Files
ViGent2/Docs/ALIPAY_DEPLOY.md
Kevin Wong bc0fe9326a 更新
2026-02-11 17:48:38 +08:00

9.3 KiB
Raw Blame History

支付宝付费开通会员 — 部署指南

本文档涵盖支付宝电脑网站支付功能的完整部署流程。用户注册后通过支付宝付费自动激活会员,有效期 1 年。


前置条件

  • 支付宝企业/个体商户账号
  • 已在 支付宝开放平台 创建应用并获取 APPID
  • 应用已开通 「电脑网站支付」 产品权限(alipay.trade.page.pay 接口)
  • 服务器域名已配置 HTTPS支付宝回调要求公网可达

第一部分:支付宝开放平台配置

1. 创建应用

登录 https://open.alipay.com → 控制台 → 创建应用(或使用已有应用)。

2. 开通「电脑网站支付」产品

进入应用详情 → 产品绑定/产品管理 → 添加 「电脑网站支付」 → 提交审核。

注意:未开通此产品会导致 ACQ.ACCESS_FORBIDDEN 错误。

3. 生成密钥对

进入应用详情 → 开发设置 → 接口加签方式 → 选择 RSA2(SHA256)

  1. 使用支付宝官方密钥工具生成 RSA2048 密钥对
  2. 应用公钥 上传到开放平台
  3. 上传后平台会显示 支付宝公钥alipayPublicKey_RSA2

最终你会得到两样东西:

  • 应用私钥:你本地保存,代码用来签名请求
  • 支付宝公钥:平台返回给你,代码用来验证回调签名

应用公钥只是上传用的中间产物,代码中不需要。


第二部分:服务器配置

1. 放置密钥文件

将密钥保存为标准 PEM 格式,放到 backend/keys/ 目录:

mkdir -p /home/rongye/ProgramFiles/ViGent2/backend/keys

backend/keys/app_private_key.pem(应用私钥):

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...(你的私钥内容)
...
-----END PRIVATE KEY-----

backend/keys/alipay_public_key.pem(支付宝公钥):

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...(支付宝公钥内容)
...
-----END PUBLIC KEY-----

PEM 格式要求

支付宝密钥工具导出的是一行纯文本,需要转换为标准 PEM 格式:

  • 必须有头尾标记(-----BEGIN/END ...-----
  • 密钥内容每 64 字符换行
  • 私钥头标记为 -----BEGIN PRIVATE KEY-----PKCS#8 格式)
  • 公钥头标记为 -----BEGIN PUBLIC KEY-----

如果你拿到的是一行裸密钥,用以下命令转换:

# 私钥格式化(假设裸密钥在 raw_private.txt 中)
echo "-----BEGIN PRIVATE KEY-----" > app_private_key.pem
cat raw_private.txt | fold -w 64 >> app_private_key.pem
echo "-----END PRIVATE KEY-----" >> app_private_key.pem

# 公钥格式化
echo "-----BEGIN PUBLIC KEY-----" > alipay_public_key.pem
cat raw_public.txt | fold -w 64 >> alipay_public_key.pem
echo "-----END PUBLIC KEY-----" >> alipay_public_key.pem

backend/keys/ 目录已加入 .gitignore,不会被提交到仓库。

2. 配置环境变量

backend/.env 中添加:

# =============== 支付宝配置 ===============
ALIPAY_APP_ID=你的应用APPID
ALIPAY_PRIVATE_KEY_PATH=/home/rongye/ProgramFiles/ViGent2/backend/keys/app_private_key.pem
ALIPAY_PUBLIC_KEY_PATH=/home/rongye/ProgramFiles/ViGent2/backend/keys/alipay_public_key.pem
ALIPAY_NOTIFY_URL=https://vigent.hbyrkj.top/api/payment/notify
ALIPAY_RETURN_URL=https://vigent.hbyrkj.top/pay
变量 说明
ALIPAY_APP_ID 支付宝开放平台应用 APPID
ALIPAY_PRIVATE_KEY_PATH 应用私钥 PEM 文件绝对路径
ALIPAY_PUBLIC_KEY_PATH 支付宝公钥 PEM 文件绝对路径
ALIPAY_NOTIFY_URL 异步回调地址(服务器间通信),必须公网 HTTPS 可达
ALIPAY_RETURN_URL 同步跳转地址(用户支付完成后浏览器跳转回的页面)

config.py 中还有几个可调参数(已有默认值,一般不需要加到 .env

变量 默认值 说明
ALIPAY_SANDBOX false 是否使用沙箱环境
PAYMENT_AMOUNT 999.00 会员价格(元)
PAYMENT_EXPIRE_DAYS 365 会员有效天数

3. 创建数据库表

通过 Docker 在本地 Supabase 中执行:

docker exec -i supabase-db psql -U postgres -c "
CREATE TABLE IF NOT EXISTS orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES users(id) ON DELETE CASCADE,
    out_trade_no TEXT UNIQUE NOT NULL,
    amount DECIMAL(10, 2) NOT NULL DEFAULT 999.00,
    status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'paid', 'failed')),
    trade_no TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    paid_at TIMESTAMP WITH TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id);
CREATE INDEX IF NOT EXISTS idx_orders_out_trade_no ON orders(out_trade_no);
"

4. 安装依赖

# 后端(在 venv 中)
cd /home/rongye/ProgramFiles/ViGent2/backend
venv/bin/pip install python-alipay-sdk

前端无额外依赖需要安装。

5. Nginx 配置

确保 Nginx 将 /api/payment/notify 代理到后端。如果现有配置已覆盖 /api/ 前缀,则无需额外修改:

location /api/ {
    proxy_pass http://localhost:8006;
    # ... 现有配置
}

6. 重启服务

# 构建前端
cd /home/rongye/ProgramFiles/ViGent2/frontend
npx next build

# 重启
pm2 restart vigent2-backend
pm2 restart vigent2-frontend

第三部分:正式上线

测试通过后,将 backend/app/core/config.py 中的测试金额改为正式价格:

PAYMENT_AMOUNT: float = 999.00      # 正式价格

或在 backend/.env 中添加覆盖:

PAYMENT_AMOUNT=999.00

然后重启后端:

pm2 restart vigent2-backend

支付流程说明

用户注册 → 登录(密码正确但 is_active=false
         → 后端返回 403 + payment_token
         → 前端跳转 /pay 页面
         → POST /api/payment/create-order → 返回支付宝收银台 URL
         → 前端重定向到支付宝收银台页面(支持扫码、账号登录、余额等多种支付方式)
         → 用户完成支付
         → 支付宝异步回调 POST /api/payment/notify
         → 后端验签 → 更新订单 → 激活用户is_active=true, expires_at=+365天
         → 支付宝同步跳转回 /pay?out_trade_no=xxx
         → 前端轮询 GET /api/payment/status/{out_trade_no}
         → 轮询到 paid → 提示成功 → 跳转登录页
         → 用户重新登录 → 成功进入系统

电脑网站支付 vs 当面付:电脑网站支付(alipay.trade.page.pay)会跳转到支付宝官方收银台页面,用户可以选择扫码、支付宝账号登录、余额等多种方式支付,体验更好。当面付(alipay.trade.precreate)仅生成一个二维码,只能扫码支付。

会员到期续费同流程:登录时检测到过期 → 返回 PAYMENT_REQUIRED → 跳转 /pay。

管理员手动激活功能不受影响,两种方式并存。


涉及文件

文件 变更类型 说明
backend/requirements.txt 修改 添加 python-alipay-sdk
backend/database/schema.sql 修改 新增 orders
backend/app/core/config.py 修改 支付宝配置项
backend/app/core/security.py 修改 payment_token 函数
backend/app/core/deps.py 修改 is_active 安全兜底
backend/app/repositories/orders.py 新建 orders 数据层
backend/app/modules/payment/__init__.py 新建 模块初始化
backend/app/modules/payment/schemas.py 新建 请求/响应模型
backend/app/modules/payment/service.py 新建 支付业务逻辑(电脑网站支付)
backend/app/modules/payment/router.py 新建 3 个 API 端点
backend/app/modules/auth/router.py 修改 登录返回 PAYMENT_REQUIRED
backend/app/main.py 修改 注册 payment_router
backend/.env 修改 支付宝环境变量
backend/keys/ 新建 PEM 密钥文件
frontend/src/shared/lib/auth.ts 修改 login() 处理 paymentToken
frontend/src/shared/api/axios.ts 修改 PUBLIC_PATHS 加 /pay
frontend/src/app/login/page.tsx 修改 paymentToken 跳转
frontend/src/app/register/page.tsx 修改 注册成功提示文案
frontend/src/app/pay/page.tsx 新建 付费页面(重定向到支付宝收银台)

常见问题

RSA key format is not supported

密钥文件缺少 PEM 头尾标记或未按 64 字符换行。参考「PEM 格式要求」重新格式化。

ACQ.ACCESS_FORBIDDEN

应用未开通「电脑网站支付」产品。在支付宝开放平台 → 应用详情 → 产品管理中添加并开通。

支付宝回调不到

  1. 检查 ALIPAY_NOTIFY_URL 是否公网 HTTPS 可达
  2. 检查 Nginx 是否将 /api/payment/notify 代理到后端
  3. 支付宝回调超时15s 未响应)会重试,共重试 8 次,持续 24 小时

支付完成后页面未跳转回来

检查 ALIPAY_RETURN_URL 配置是否正确,必须是前端 /pay 页面的完整 URLhttps://vigent.hbyrkj.top/pay)。支付宝会在用户支付完成后将浏览器重定向到此地址,并附带 out_trade_no 等参数。

前端显示"网络错误"而非具体错误

API 函数缺少 try/catch 捕获 axios 异常。已在 auth.tsregister()login() 中修复。