Files
gitlab-instance-0a899031_pa…/README.md
2026-04-01 02:23:37 -05:00

123 lines
4.9 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PayJS API
支付 API 服务支持多支付渠道XorPay、ZPAY按项目模块化拆分。
## 路由与项目对应
| 项目 | 路由前缀 | 说明 |
|------|----------|------|
| nomadvip | `/nomadvip/*` | 固定 ZPAY独立实例 |
| digital | `/digital/*` | 使用 PAYMENT_PROVIDER |
| cnomadcna | `/cnomadcna/*` | 使用 PAYMENT_PROVIDER |
| nomadlms | `/nomadlms/*` | 使用 PAYMENT_PROVIDER |
| legacy | `/payh5``/zpay_notify` 等 | 向后兼容 |
各项目业务互不影响,可单独配置。
## 环境
本地调试:`BASE_URL` 需为 ZPAY 可访问地址(如 ngrok 暴露 8700 端口)
线上部署:`BASE_URL=https://api.hackrobot.cn`
## 模块结构
```
app/
├── config.py # 配置(环境变量)
├── main.py # FastAPI 入口,挂载路由
├── sdk/ # SDK 组件化封装
│ ├── payment/ # 支付网关ZPAY/XorPay
│ ├── pocketbase.py # PocketBase 数据库
│ ├── minio.py # MinIO 对象存储
│ └── memos.py # Memos 用户(仅 nomadvip 使用)
├── services/ # 共享业务逻辑(基于 SDK
│ ├── pb.py # PocketBase 客户端
│ ├── memos.py # Memos 用户创建
│ ├── minio.py # MinIO 上传
│ └── payment.py # 支付成功处理
├── routers/ # 项目路由
│ ├── nomadvip.py # /nomadvip/*
│ ├── digital.py # /digital/*
│ ├── cnomadcna.py # /cnomadcna/*
│ ├── nomadlms.py # /nomadlms/*
│ ├── legacy.py # /payh5 等(向后兼容)
│ └── common.py # /submit_meetup_application、/create_user
└── payment/
├── base.py # 支付抽象基类
├── xorpay.py # XorPay 实现
├── zpay.py # ZPAY 实现(易支付兼容)
└── factory.py # 渠道工厂
```
## 支付渠道
| 渠道 | 环境变量 | 说明 |
|------|----------|------|
| XorPay | `PAYMENT_PROVIDER=xorpay` | 默认 |
| ZPAY | `PAYMENT_PROVIDER=zpay` | 需配置 `ZPAY_PID``ZPAY_KEY` |
切换渠道:设置环境变量 `PAYMENT_PROVIDER=xorpay``zpay`,参考 `.env.example`
## 本地调试
```bash
# 复制配置
cp .env.example .env
# 本地调试时 BASE_URL 需 ZPAY 可访问,可用 ngrok
# ngrok http 8700 -> 将 BASE_URL 设为 ngrok 提供的 https 地址
python run.py
# 或 uvicorn app.main:app --host 0.0.0.0 --port 8700 --reload
```
## 线上部署
域名:`https://api.hackrobot.cn`
```bash
# .env 中设置
BASE_URL=https://api.hackrobot.cn
PAYMENT_PROVIDER=zpay
# 其他 ZPAY、PocketBase、Memos 配置见 .env.example
```
## 线上「支付失败」排查
本地正常、Ubuntu 部署后 api.hackrobot.cn 调用支付失败,常见原因:
1. **BASE_URL 配置错误**:必须为 ZPAY 可公网访问的地址。错误示例:`http://127.0.0.1:8700``http://localhost`。正确:`https://api.hackrobot.cn`域名需解析到本机nginx 反向代理对应端口)。
2. **服务器无法访问 zpayz.cn**防火墙、DNS 或网络限制。访问 `https://api.hackrobot.cn/health?check_zpay=1` 自检:
- `zpayz_reachable: false` → 开放出站或检查网络
- `zpayz_error` 含 "SSL" → 执行 `apt install ca-certificates` 后重启
3. **client_ip 内网导致 ZPAY 风控拒单**前端digital/cnomadcna/nomadvip通过 nginx 代理时,需配置 `proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for`,否则 payjsapi 收到 127.0.0.1 会触发风控。已做兼容:内网 IP 时自动省略 clientip 参数。
4. **启动时控制台有 BASE_URL 警告**:说明配置了内网地址,需修改 `.env` 中的 `BASE_URL` 为公网地址后重启。
5. **查看详细错误**支付失败时payjsapi 会输出 `ZPAY create_order_api 失败` 日志,含 status/code/msg便于定位。
## 自检结果2026-04-01
本次联动自检覆盖了 `nomadvip` 前端与本仓库 `nomadvip` 路由的支付闭环:
- 创建订单:`/nomadvip/payh5``/nomadvip/payh5/redirect`
- 异步通知:`/nomadvip/xorpay_notify``/nomadvip/zpay_notify`
- 支付查询:`/nomadvip/order_status`
- VIP 识别:`/nomadvip/check_vip``/nomadvip/check_vip_by_email`
### 发现问题
- 业务链路问题发生在前端 `nomadvip``/api/pay/confirm` 兜底写 `payments` 时使用默认金额,可能与实际支付金额不一致(例如测试价、活动价)。
### 处理状态
- 已在前端仓库修复confirm 兜底写库时优先使用网关返回 `pay_price`,失败才回退默认金额。
- 本仓库暂未发现新的阻断型业务 bug以静态代码审阅为准
## 维护建议
- 建议保持 `payjsapi` 为唯一支付入账源,前端 confirm 仅作为短时兜底。
- 建议为 `order_status` 返回结构固定增加字段约束(如统一返回 `pay_price` 字段),避免调用侧重复兼容。