erio 55756744a1 feat: 集成支付宝电脑网站支付(alipay direct)
- 新增 src/lib/alipay/ 模块:RSA2 签名、网关客户端、AlipayProvider
- 新增 /api/alipay/notify 异步通知回调路由
- config.ts 添加 ALIPAY_* 环境变量
- payment/index.ts 注册 alipaydirect 提供商
- 27 个单元测试全部通过
2026-03-05 01:48:10 +08:00
2026-03-03 22:00:44 +08:00
2026-03-04 17:06:27 +08:00
2026-03-04 17:06:27 +08:00

Sub2ApiPay

Language: 中文 | English (current)

Sub2ApiPay is a self-hosted recharge payment gateway built for the Sub2API 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

  • 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

No Node.js or pnpm required on the server — just Docker.

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

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 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 Providers & Methods

Step 1: Declare which payment providers to load via PAYMENT_PROVIDERS (comma-separated):

# EasyPay only
PAYMENT_PROVIDERS=easypay
# Stripe only
PAYMENT_PROVIDERS=stripe
# Both
PAYMENT_PROVIDERS=easypay,stripe

Step 2: Control which channels are shown to users via ENABLED_PAYMENT_TYPES:

# EasyPay supports: alipay, wxpay  |  Stripe supports: stripe
ENABLED_PAYMENT_TYPES=alipay,wxpay

EasyPay (Alipay / WeChat Pay)

Any payment provider compatible with the EasyPay protocol can be used, such as ZPay (https://z-pay.cn/?uid=23808) (this link contains the author's referral code — feel free to remove it).

ZPay Registration QR Code

ZPay Preview

Disclaimer: Please evaluate the security, reliability, and compliance of any third-party payment provider on your own. This project does not endorse or guarantee any specific provider.

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: payment_intent.succeeded, payment_intent.payment_failed

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)

Display a support contact image and description on the right side of the payment page.

Variable Description
PAY_HELP_IMAGE_URL Help image URL — external URL or local path (see below)
PAY_HELP_TEXT Help text; use \n for line breaks, e.g. Scan to add WeChat\nMonFri 9am6pm

Two ways to provide the image:

  • External URL (recommended — no Compose changes needed): any publicly accessible image link (CDN, OSS, image hosting).

    PAY_HELP_IMAGE_URL=https://cdn.example.com/help-qr.jpg
    
  • Local file: place the image in ./uploads/ and reference it as /uploads/<filename>. The directory must be mounted in docker-compose.app.yml (included by default):

    volumes:
      - ./uploads:/app/public/uploads:ro
    
    PAY_HELP_IMAGE_URL=/uploads/help-qr.jpg
    

Clicking the help image opens it full-screen in the center of the screen.

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:

docker compose -f docker-compose.hub.yml up -d

Image: touwaeriol/sub2apipay:latest

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):
docker compose -f docker-compose.app.yml up -d

Option 3: Build from Source

For custom builds after modifications:

# 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:

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:

docker compose exec app npx prisma migrate deploy

Sub2API Integration

The following page URLs can be configured in the Sub2API admin panel:

Page URL Description
Payment https://pay.example.com/pay User recharge entry
My Orders https://pay.example.com/pay/orders User views their own recharge history
Order Management https://pay.example.com/admin Sub2API admin only

Sub2API v0.1.88 and above will automatically append the following parameters — no manual query string needed:

Parameter Description
user_id Sub2API user ID
token User login token (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  → Payment Element (PaymentIntent)
         │
         ▼
  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

pnpm install
cp .env.example .env
# Edit .env with DATABASE_URL and other required values
pnpm prisma migrate dev
pnpm dev

Commands

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

Description
No description provided
Readme MIT 1.7 MiB
Languages
TypeScript 99%
Shell 0.5%
Dockerfile 0.2%
CSS 0.2%