docs: 完整中英双语 README + Docker Hub 发布 Compose 文件
- README.md:中文主文档(功能、环境变量、部署、集成说明) - README.en.md:英文版本,内容与中文对应 - docker-compose.hub.yml:从 Docker Hub 拉取镜像,含自带 PostgreSQL - docker-compose.app.yml:仅应用容器,适配外部数据库 - 镜像已发布至 touwaeriol/sub2apipay:latest
This commit is contained in:
316
README.en.md
Normal file
316
README.en.md
Normal file
@@ -0,0 +1,316 @@
|
||||
# Sub2ApiPay
|
||||
|
||||
**Language**: [中文](./README.md) | English (current)
|
||||
|
||||
Sub2ApiPay is a self-hosted recharge payment gateway built for the [Sub2API](https://sub2api.com) platform. It supports Alipay, WeChat Pay (via EasyPay aggregator), and Stripe. Once a payment is confirmed, the system automatically calls the Sub2API management API to credit the user's balance — no manual intervention required.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Features](#features)
|
||||
- [Tech Stack](#tech-stack)
|
||||
- [Quick Start](#quick-start)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [Deployment](#deployment)
|
||||
- [Sub2API Integration](#sub2api-integration)
|
||||
- [Admin Panel](#admin-panel)
|
||||
- [Payment Flow](#payment-flow)
|
||||
- [Development](#development)
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Multiple Payment Methods** — Alipay, WeChat Pay (EasyPay), Stripe credit card
|
||||
- **Auto Balance Credit** — Automatically calls Sub2API after payment verification, fully hands-free
|
||||
- **Full Order Lifecycle** — Auto-expiry, user cancellation, admin cancellation, refunds
|
||||
- **Limit Controls** — Configurable per-transaction cap and daily cumulative cap per user
|
||||
- **Security** — Token auth, MD5/Webhook signature verification, timing-safe comparison, full audit log
|
||||
- **Responsive UI** — PC + mobile adaptive layout, dark mode support, iframe embed support
|
||||
- **Admin Panel** — Order list (pagination/filtering), order details, retry recharge, refunds
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Category | Technology |
|
||||
|----------|------------|
|
||||
| Framework | Next.js 16 (App Router) |
|
||||
| Language | TypeScript 5 + React 19 |
|
||||
| Styling | TailwindCSS 4 |
|
||||
| ORM | Prisma 7 (adapter-pg mode) |
|
||||
| Database | PostgreSQL 16 |
|
||||
| Container | Docker + Docker Compose |
|
||||
| Package Manager | pnpm |
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Docker Hub Image (Recommended)
|
||||
|
||||
No Node.js or pnpm required on the server — just Docker.
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/sub2apipay && cd /opt/sub2apipay
|
||||
|
||||
# Download Compose file and env template
|
||||
curl -O https://raw.githubusercontent.com/touwaeriol/sub2apipay/main/docker-compose.hub.yml
|
||||
curl -O https://raw.githubusercontent.com/touwaeriol/sub2apipay/main/.env.example
|
||||
cp .env.example .env
|
||||
|
||||
# Fill in required environment variables
|
||||
nano .env
|
||||
|
||||
# Start (includes bundled PostgreSQL)
|
||||
docker compose -f docker-compose.hub.yml up -d
|
||||
```
|
||||
|
||||
### Build from Source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/touwaeriol/sub2apipay.git
|
||||
cd sub2apipay
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
See [`.env.example`](./.env.example) for the full template.
|
||||
|
||||
### Core (Required)
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `SUB2API_BASE_URL` | Sub2API service URL, e.g. `https://sub2api.com` |
|
||||
| `SUB2API_ADMIN_API_KEY` | Sub2API admin API key |
|
||||
| `ADMIN_TOKEN` | Admin panel access token (use a strong random string) |
|
||||
| `NEXT_PUBLIC_APP_URL` | Public URL of this service, e.g. `https://pay.example.com` |
|
||||
|
||||
> `DATABASE_URL` is automatically injected by Docker Compose when using the bundled database.
|
||||
|
||||
### Payment Methods
|
||||
|
||||
Control which payment methods are enabled via `ENABLED_PAYMENT_TYPES` (comma-separated):
|
||||
|
||||
```env
|
||||
ENABLED_PAYMENT_TYPES=alipay,wxpay,stripe
|
||||
```
|
||||
|
||||
#### EasyPay (Alipay / WeChat Pay)
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `EASY_PAY_PID` | EasyPay merchant ID |
|
||||
| `EASY_PAY_PKEY` | EasyPay merchant secret key |
|
||||
| `EASY_PAY_API_BASE` | EasyPay API base URL |
|
||||
| `EASY_PAY_NOTIFY_URL` | Async callback URL: `${NEXT_PUBLIC_APP_URL}/api/easy-pay/notify` |
|
||||
| `EASY_PAY_RETURN_URL` | Redirect URL after payment: `${NEXT_PUBLIC_APP_URL}/pay` |
|
||||
| `EASY_PAY_CID_ALIPAY` | Alipay channel ID (optional) |
|
||||
| `EASY_PAY_CID_WXPAY` | WeChat Pay channel ID (optional) |
|
||||
|
||||
#### Stripe
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `STRIPE_SECRET_KEY` | Stripe secret key (`sk_live_...`) |
|
||||
| `STRIPE_PUBLISHABLE_KEY` | Stripe publishable key (`pk_live_...`) |
|
||||
| `STRIPE_WEBHOOK_SECRET` | Stripe webhook signing secret (`whsec_...`) |
|
||||
|
||||
> Stripe webhook endpoint: `${NEXT_PUBLIC_APP_URL}/api/stripe/webhook`
|
||||
> Subscribe to: `checkout.session.completed`, `checkout.session.expired`
|
||||
|
||||
### Business Rules
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `MIN_RECHARGE_AMOUNT` | Minimum amount per transaction (CNY) | `1` |
|
||||
| `MAX_RECHARGE_AMOUNT` | Maximum amount per transaction (CNY) | `1000` |
|
||||
| `MAX_DAILY_RECHARGE_AMOUNT` | Daily cumulative max per user (`0` = unlimited) | `10000` |
|
||||
| `ORDER_TIMEOUT_MINUTES` | Order expiry in minutes | `5` |
|
||||
| `PRODUCT_NAME` | Product name shown on payment page | `Sub2API Balance Recharge` |
|
||||
|
||||
### UI Customization (Optional)
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `NEXT_PUBLIC_PAY_HELP_IMAGE_URL` | Help image URL (e.g. customer service QR code) |
|
||||
| `NEXT_PUBLIC_PAY_HELP_TEXT` | Help text displayed on payment page |
|
||||
|
||||
### Docker Compose Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `APP_PORT` | Host port mapping | `3001` |
|
||||
| `DB_PASSWORD` | PostgreSQL password (bundled DB) | `password` (**change in production**) |
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
### Option 1: Docker Hub Image + Bundled Database
|
||||
|
||||
Use `docker-compose.hub.yml` — the simplest deployment:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.hub.yml up -d
|
||||
```
|
||||
|
||||
Image: [`touwaeriol/sub2apipay:latest`](https://hub.docker.com/r/touwaeriol/sub2apipay)
|
||||
|
||||
### Option 2: Docker Hub Image + External Database
|
||||
|
||||
For existing PostgreSQL instances (shared with other services):
|
||||
|
||||
1. Set `DATABASE_URL` in `.env`
|
||||
2. Use `docker-compose.app.yml` (app only, no DB):
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.app.yml up -d
|
||||
```
|
||||
|
||||
### Option 3: Build from Source
|
||||
|
||||
For custom builds after modifications:
|
||||
|
||||
```bash
|
||||
# On the build server
|
||||
docker compose build
|
||||
docker tag sub2apipay-app:latest touwaeriol/sub2apipay:latest
|
||||
docker push touwaeriol/sub2apipay:latest
|
||||
|
||||
# On the deploy server
|
||||
docker compose -f docker-compose.hub.yml pull
|
||||
docker compose -f docker-compose.hub.yml up -d
|
||||
```
|
||||
|
||||
### Reverse Proxy
|
||||
|
||||
The default host port is `3001` (configurable via `APP_PORT`). Use Nginx or Caddy as a reverse proxy with HTTPS:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name pay.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Database Migrations
|
||||
|
||||
Migrations run automatically on container startup via `prisma migrate deploy`. To run manually:
|
||||
|
||||
```bash
|
||||
docker compose exec app npx prisma migrate deploy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sub2API Integration
|
||||
|
||||
Configure the recharge URL in the Sub2API admin panel:
|
||||
|
||||
```
|
||||
https://pay.example.com/pay?user_id={USER_ID}&token={TOKEN}&theme={THEME}
|
||||
```
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `user_id` | Sub2API user ID (required) |
|
||||
| `token` | User login token (optional — required to view order history) |
|
||||
| `theme` | `light` (default) or `dark` |
|
||||
| `ui_mode` | `standalone` (default) or `embedded` (for iframe) |
|
||||
|
||||
---
|
||||
|
||||
## Admin Panel
|
||||
|
||||
Access: `https://pay.example.com/admin?token=YOUR_ADMIN_TOKEN`
|
||||
|
||||
| Feature | Description |
|
||||
|---------|-------------|
|
||||
| Order List | Filter by status, paginate, choose 20/50/100 per page |
|
||||
| Order Detail | View all fields and audit log timeline |
|
||||
| Retry Recharge | Re-trigger recharge for paid-but-failed orders |
|
||||
| Cancel Order | Force-cancel pending orders |
|
||||
| Refund | Issue refund and deduct Sub2API balance |
|
||||
|
||||
---
|
||||
|
||||
## Payment Flow
|
||||
|
||||
```
|
||||
User submits recharge amount
|
||||
│
|
||||
▼
|
||||
Create Order (PENDING)
|
||||
├─ Validate user status / pending order count / daily limit
|
||||
└─ Call payment provider to get payment link
|
||||
│
|
||||
▼
|
||||
User completes payment
|
||||
├─ EasyPay → QR code / H5 redirect
|
||||
└─ Stripe → Checkout Session
|
||||
│
|
||||
▼
|
||||
Payment callback (signature verified) → Order PAID
|
||||
│
|
||||
▼
|
||||
Auto-call Sub2API recharge API
|
||||
├─ Success → COMPLETED, balance credited automatically
|
||||
└─ Failure → FAILED (admin can retry)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
### Requirements
|
||||
|
||||
- Node.js 22+
|
||||
- pnpm
|
||||
- PostgreSQL 16+
|
||||
|
||||
### Local Setup
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
cp .env.example .env
|
||||
# Edit .env with DATABASE_URL and other required values
|
||||
pnpm prisma migrate dev
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
pnpm dev # Dev server with hot reload
|
||||
pnpm build # Production build
|
||||
pnpm test # Run tests
|
||||
pnpm typecheck # TypeScript type check
|
||||
pnpm lint # ESLint
|
||||
pnpm format # Prettier format
|
||||
|
||||
pnpm prisma generate # Generate Prisma client
|
||||
pnpm prisma migrate dev # Create and apply migration (dev)
|
||||
pnpm prisma migrate deploy # Apply migrations (production)
|
||||
pnpm prisma studio # Visual database browser
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
322
README.md
322
README.md
@@ -1,36 +1,316 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
# Sub2ApiPay
|
||||
|
||||
## Getting Started
|
||||
**语言 / Language**: 中文(当前)| [English](./README.en.md)
|
||||
|
||||
First, run the development server:
|
||||
Sub2ApiPay 是为 [Sub2API](https://sub2api.com) 平台构建的自托管充值支付网关。支持支付宝、微信支付(通过 EasyPay 聚合)和 Stripe,订单支付成功后自动调用 Sub2API 管理接口完成余额到账,无需人工干预。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
- [功能特性](#功能特性)
|
||||
- [技术栈](#技术栈)
|
||||
- [快速开始](#快速开始)
|
||||
- [环境变量](#环境变量)
|
||||
- [部署指南](#部署指南)
|
||||
- [集成到 Sub2API](#集成到-sub2api)
|
||||
- [管理后台](#管理后台)
|
||||
- [支付流程](#支付流程)
|
||||
- [开发指南](#开发指南)
|
||||
|
||||
---
|
||||
|
||||
## 功能特性
|
||||
|
||||
- **多支付方式** — 支付宝、微信支付(EasyPay 聚合)、Stripe 信用卡
|
||||
- **自动到账** — 支付回调验签后自动调用 Sub2API 充值接口,全程无需人工
|
||||
- **订单全生命周期** — 超时自动取消、用户主动取消、管理员取消、退款
|
||||
- **限额控制** — 可配置单笔上限与每日累计上限,按用户维度统计
|
||||
- **安全设计** — Token 鉴权、MD5/Webhook 签名验证、时序安全对比、完整审计日志
|
||||
- **响应式 UI** — PC + 移动端自适应,支持深色模式,支持 iframe 嵌入
|
||||
- **管理后台** — 订单列表(分页/筛选)、订单详情、重试充值、退款
|
||||
|
||||
---
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 类别 | 技术 |
|
||||
|------|------|
|
||||
| 框架 | Next.js 16 (App Router) |
|
||||
| 语言 | TypeScript 5 + React 19 |
|
||||
| 样式 | TailwindCSS 4 |
|
||||
| ORM | Prisma 7(adapter-pg 模式) |
|
||||
| 数据库 | PostgreSQL 16 |
|
||||
| 容器 | Docker + Docker Compose |
|
||||
| 包管理 | pnpm |
|
||||
|
||||
---
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 使用 Docker Hub 镜像(推荐)
|
||||
|
||||
无需本地安装 Node.js 或 pnpm,服务器上只需 Docker。
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
mkdir -p /opt/sub2apipay && cd /opt/sub2apipay
|
||||
|
||||
# 下载 Compose 文件和环境变量模板
|
||||
curl -O https://raw.githubusercontent.com/touwaeriol/sub2apipay/main/docker-compose.hub.yml
|
||||
curl -O https://raw.githubusercontent.com/touwaeriol/sub2apipay/main/.env.example
|
||||
cp .env.example .env
|
||||
|
||||
# 填写必填环境变量
|
||||
nano .env
|
||||
|
||||
# 启动(含自带 PostgreSQL)
|
||||
docker compose -f docker-compose.hub.yml up -d
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
### 从源码构建
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
```bash
|
||||
git clone https://github.com/touwaeriol/sub2apipay.git
|
||||
cd sub2apipay
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
---
|
||||
|
||||
## Learn More
|
||||
## 环境变量
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
完整模板见 [`.env.example`](./.env.example)。
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
### 核心(必填)
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `SUB2API_BASE_URL` | Sub2API 服务地址,如 `https://sub2api.com` |
|
||||
| `SUB2API_ADMIN_API_KEY` | Sub2API 管理 API 密钥 |
|
||||
| `ADMIN_TOKEN` | 管理后台访问令牌(自定义强密码) |
|
||||
| `NEXT_PUBLIC_APP_URL` | 本服务的公网地址,如 `https://pay.example.com` |
|
||||
|
||||
## Deploy on Vercel
|
||||
> `DATABASE_URL` 使用自带数据库时由 Compose 自动注入,无需手动填写。
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
### 支付方式
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
通过 `ENABLED_PAYMENT_TYPES` 控制开启哪些支付方式(逗号分隔):
|
||||
|
||||
```env
|
||||
ENABLED_PAYMENT_TYPES=alipay,wxpay,stripe
|
||||
```
|
||||
|
||||
#### EasyPay(支付宝 / 微信支付)
|
||||
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `EASY_PAY_PID` | EasyPay 商户 ID |
|
||||
| `EASY_PAY_PKEY` | EasyPay 商户密钥 |
|
||||
| `EASY_PAY_API_BASE` | EasyPay API 地址 |
|
||||
| `EASY_PAY_NOTIFY_URL` | 异步回调地址,填 `${NEXT_PUBLIC_APP_URL}/api/easy-pay/notify` |
|
||||
| `EASY_PAY_RETURN_URL` | 支付完成跳转地址,填 `${NEXT_PUBLIC_APP_URL}/pay` |
|
||||
| `EASY_PAY_CID_ALIPAY` | 支付宝通道 ID(可选) |
|
||||
| `EASY_PAY_CID_WXPAY` | 微信支付通道 ID(可选) |
|
||||
|
||||
#### Stripe
|
||||
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `STRIPE_SECRET_KEY` | Stripe 密钥(`sk_live_...`) |
|
||||
| `STRIPE_PUBLISHABLE_KEY` | Stripe 可公开密钥(`pk_live_...`) |
|
||||
| `STRIPE_WEBHOOK_SECRET` | Stripe Webhook 签名密钥(`whsec_...`) |
|
||||
|
||||
> Stripe Webhook 端点:`${NEXT_PUBLIC_APP_URL}/api/stripe/webhook`
|
||||
> 需订阅事件:`checkout.session.completed`、`checkout.session.expired`
|
||||
|
||||
### 业务规则
|
||||
|
||||
| 变量 | 说明 | 默认值 |
|
||||
|------|------|--------|
|
||||
| `MIN_RECHARGE_AMOUNT` | 单笔最低充值金额(元) | `1` |
|
||||
| `MAX_RECHARGE_AMOUNT` | 单笔最高充值金额(元) | `1000` |
|
||||
| `MAX_DAILY_RECHARGE_AMOUNT` | 每日累计最高充值(元,`0` = 不限) | `10000` |
|
||||
| `ORDER_TIMEOUT_MINUTES` | 订单超时分钟数 | `5` |
|
||||
| `PRODUCT_NAME` | 充值商品名称(显示在支付页) | `Sub2API Balance Recharge` |
|
||||
|
||||
### UI 定制(可选)
|
||||
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `NEXT_PUBLIC_PAY_HELP_IMAGE_URL` | 帮助图片 URL(如客服二维码) |
|
||||
| `NEXT_PUBLIC_PAY_HELP_TEXT` | 帮助说明文字 |
|
||||
|
||||
### Docker Compose 专用
|
||||
|
||||
| 变量 | 说明 | 默认值 |
|
||||
|------|------|--------|
|
||||
| `APP_PORT` | 宿主机映射端口 | `3001` |
|
||||
| `DB_PASSWORD` | PostgreSQL 密码(使用自带数据库时) | `password`(**生产请修改**) |
|
||||
|
||||
---
|
||||
|
||||
## 部署指南
|
||||
|
||||
### 方案一:Docker Hub 镜像 + 自带数据库
|
||||
|
||||
使用 `docker-compose.hub.yml`,最省事的部署方式:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.hub.yml up -d
|
||||
```
|
||||
|
||||
镜像:[`touwaeriol/sub2apipay:latest`](https://hub.docker.com/r/touwaeriol/sub2apipay)
|
||||
|
||||
### 方案二:Docker Hub 镜像 + 外部数据库
|
||||
|
||||
适用于已有 PostgreSQL 实例(如与其他服务共用):
|
||||
|
||||
1. 在 `.env` 中填写 `DATABASE_URL`
|
||||
2. 使用 `docker-compose.app.yml`(仅启动应用,不含 DB):
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.app.yml up -d
|
||||
```
|
||||
|
||||
### 方案三:从源码构建
|
||||
|
||||
适用于自定义修改后自行构建:
|
||||
|
||||
```bash
|
||||
# 在构建服务器上
|
||||
docker compose build
|
||||
docker tag sub2apipay-app:latest touwaeriol/sub2apipay:latest
|
||||
docker push touwaeriol/sub2apipay:latest
|
||||
|
||||
# 在部署服务器上
|
||||
docker compose -f docker-compose.hub.yml pull
|
||||
docker compose -f docker-compose.hub.yml up -d
|
||||
```
|
||||
|
||||
### 端口与反向代理
|
||||
|
||||
默认宿主机端口为 `3001`(可通过 `APP_PORT` 修改)。建议使用 Nginx/Caddy 作反向代理并配置 HTTPS:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name pay.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 数据库迁移
|
||||
|
||||
容器启动时自动执行 `prisma migrate deploy`,无需手动操作。如需手动执行:
|
||||
|
||||
```bash
|
||||
docker compose exec app npx prisma migrate deploy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 集成到 Sub2API
|
||||
|
||||
在 Sub2API 管理后台将充值链接配置为:
|
||||
|
||||
```
|
||||
https://pay.example.com/pay?user_id={USER_ID}&token={TOKEN}&theme={THEME}
|
||||
```
|
||||
|
||||
| 参数 | 说明 |
|
||||
|------|------|
|
||||
| `user_id` | Sub2API 用户 ID(必填) |
|
||||
| `token` | 用户登录 Token(可选,有 token 才能查看订单历史) |
|
||||
| `theme` | `light`(默认)或 `dark` |
|
||||
| `ui_mode` | `standalone`(默认)或 `embedded`(iframe 嵌入) |
|
||||
|
||||
---
|
||||
|
||||
## 管理后台
|
||||
|
||||
访问:`https://pay.example.com/admin?token=YOUR_ADMIN_TOKEN`
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| 订单列表 | 按状态筛选、分页浏览,支持每页 20/50/100 条 |
|
||||
| 订单详情 | 查看完整字段与操作审计日志 |
|
||||
| 重试充值 | 对已支付但充值失败的订单重新发起充值 |
|
||||
| 取消订单 | 强制取消待支付订单 |
|
||||
| 退款 | 对已完成订单发起退款并扣减 Sub2API 余额 |
|
||||
|
||||
---
|
||||
|
||||
## 支付流程
|
||||
|
||||
```
|
||||
用户提交充值金额
|
||||
│
|
||||
▼
|
||||
创建订单 (PENDING)
|
||||
├─ 校验用户状态 / 待支付订单数 / 每日限额
|
||||
└─ 调用支付提供商获取支付链接
|
||||
│
|
||||
▼
|
||||
用户完成支付
|
||||
├─ EasyPay → 扫码 / H5 跳转
|
||||
└─ Stripe → Checkout Session
|
||||
│
|
||||
▼
|
||||
支付回调(签名验证)→ 订单 PAID
|
||||
│
|
||||
▼
|
||||
自动调用 Sub2API 充值接口
|
||||
├─ 成功 → COMPLETED,余额自动到账
|
||||
└─ 失败 → FAILED(管理员可重试)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 开发指南
|
||||
|
||||
### 环境要求
|
||||
|
||||
- Node.js 22+
|
||||
- pnpm
|
||||
- PostgreSQL 16+
|
||||
|
||||
### 本地启动
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
cp .env.example .env
|
||||
# 编辑 .env,填写 DATABASE_URL 和其他必填项
|
||||
pnpm prisma migrate dev
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### 常用命令
|
||||
|
||||
```bash
|
||||
pnpm dev # 开发服务器(热重载)
|
||||
pnpm build # 生产构建
|
||||
pnpm test # 运行测试
|
||||
pnpm typecheck # TypeScript 类型检查
|
||||
pnpm lint # ESLint 代码检查
|
||||
pnpm format # Prettier 格式化
|
||||
|
||||
pnpm prisma generate # 生成 Prisma 客户端
|
||||
pnpm prisma migrate dev # 创建迁移(开发)
|
||||
pnpm prisma migrate deploy # 应用迁移(生产)
|
||||
pnpm prisma studio # 可视化数据库管理
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
14
docker-compose.app.yml
Normal file
14
docker-compose.app.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
# docker-compose.app.yml
|
||||
# 使用 Docker Hub 镜像部署(仅应用,外部数据库)
|
||||
# 适合:已有 PostgreSQL 实例,将 DATABASE_URL 填入 .env
|
||||
#
|
||||
# 启动:docker compose -f docker-compose.app.yml up -d
|
||||
# 更新:docker compose -f docker-compose.app.yml pull && docker compose -f docker-compose.app.yml up -d
|
||||
|
||||
services:
|
||||
app:
|
||||
image: touwaeriol/sub2apipay:latest
|
||||
ports:
|
||||
- '${APP_PORT:-3001}:3000'
|
||||
env_file: .env
|
||||
restart: unless-stopped
|
||||
37
docker-compose.hub.yml
Normal file
37
docker-compose.hub.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
# docker-compose.hub.yml
|
||||
# 使用 Docker Hub 镜像部署(含自带 PostgreSQL)
|
||||
# 适合:全新服务器,无现有数据库
|
||||
#
|
||||
# 启动:docker compose -f docker-compose.hub.yml up -d
|
||||
# 更新:docker compose -f docker-compose.hub.yml pull && docker compose -f docker-compose.hub.yml up -d
|
||||
|
||||
services:
|
||||
app:
|
||||
image: touwaeriol/sub2apipay:latest
|
||||
ports:
|
||||
- '${APP_PORT:-3001}:3000'
|
||||
env_file: .env
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://sub2apipay:${DB_PASSWORD:-password}@db:5432/sub2apipay
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: sub2apipay
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-password}
|
||||
POSTGRES_DB: sub2apipay
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U sub2apipay']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
Reference in New Issue
Block a user