314 lines
7.4 KiB
Markdown
314 lines
7.4 KiB
Markdown
# Sub2API Admin API: Payment Integration / 支付集成接口文档
|
||
|
||
## 中文
|
||
|
||
### 概述
|
||
|
||
本文档描述外部支付系统(例如 sub2apipay)对接 Sub2API 时的最小 Admin API 集合,用于完成充值发放与对账。
|
||
|
||
### 基础地址
|
||
|
||
- 生产环境:`https://<your-domain>`
|
||
- Beta 环境:`http://<your-server-ip>:8084`
|
||
|
||
### 认证方式
|
||
|
||
以下接口均建议使用:
|
||
|
||
- 请求头:`x-api-key: admin-<64hex>`(服务间调用推荐)
|
||
- 请求头:`Content-Type: application/json`
|
||
|
||
说明:管理员 JWT 也可访问 admin 路由,但机器对机器调用建议使用 Admin API Key。
|
||
|
||
### 1) 一步完成:创建兑换码并兑换
|
||
|
||
`POST /api/v1/admin/redeem-codes/create-and-redeem`
|
||
|
||
用途:
|
||
|
||
- 原子化完成“创建固定兑换码 + 兑换给指定用户”。
|
||
- 常用于支付回调成功后的自动充值。
|
||
|
||
必需请求头:
|
||
|
||
- `x-api-key`
|
||
- `Idempotency-Key`
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"code": "s2p_cm1234567890",
|
||
"type": "balance",
|
||
"value": 100.0,
|
||
"user_id": 123,
|
||
"notes": "sub2apipay order: cm1234567890"
|
||
}
|
||
```
|
||
|
||
规则:
|
||
|
||
- `code`:外部订单映射的确定性兑换码。
|
||
- `type`:当前推荐使用 `balance`。
|
||
- `value`:必须大于 0。
|
||
- `user_id`:目标用户 ID。
|
||
|
||
幂等语义:
|
||
|
||
- 同一 `code` 且 `used_by` 一致:返回 `200`(幂等回放)。
|
||
- 同一 `code` 但 `used_by` 不一致:返回 `409`(冲突)。
|
||
- 缺少 `Idempotency-Key`:返回 `400`(`IDEMPOTENCY_KEY_REQUIRED`)。
|
||
|
||
示例:
|
||
|
||
```bash
|
||
curl -X POST "${BASE}/api/v1/admin/redeem-codes/create-and-redeem" \
|
||
-H "x-api-key: ${KEY}" \
|
||
-H "Idempotency-Key: pay-cm1234567890-success" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"code":"s2p_cm1234567890",
|
||
"type":"balance",
|
||
"value":100.00,
|
||
"user_id":123,
|
||
"notes":"sub2apipay order: cm1234567890"
|
||
}'
|
||
```
|
||
|
||
### 2) 查询用户(可选前置检查)
|
||
|
||
`GET /api/v1/admin/users/:id`
|
||
|
||
用途:
|
||
|
||
- 支付成功后充值前,确认目标用户是否存在。
|
||
|
||
示例:
|
||
|
||
```bash
|
||
curl -s "${BASE}/api/v1/admin/users/123" \
|
||
-H "x-api-key: ${KEY}"
|
||
```
|
||
|
||
### 3) 余额调整(已存在接口)
|
||
|
||
`POST /api/v1/admin/users/:id/balance`
|
||
|
||
用途:
|
||
|
||
- 复用现有管理员接口做人工纠偏。
|
||
- 支持 `set`、`add`、`subtract`。
|
||
|
||
示例(扣减):
|
||
|
||
```json
|
||
{
|
||
"balance": 100.0,
|
||
"operation": "subtract",
|
||
"notes": "manual correction"
|
||
}
|
||
```
|
||
|
||
```bash
|
||
curl -X POST "${BASE}/api/v1/admin/users/123/balance" \
|
||
-H "x-api-key: ${KEY}" \
|
||
-H "Idempotency-Key: balance-subtract-cm1234567890" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"balance":100.00,
|
||
"operation":"subtract",
|
||
"notes":"manual correction"
|
||
}'
|
||
```
|
||
|
||
### 4) 购买页跳转 URL Query 参数(iframe 与新窗口统一)
|
||
|
||
Sub2API 前端在打开 `purchase_subscription_url` 时,会给 iframe 和“新窗口打开”统一追加 query 参数,确保外部支付页拿到一致上下文。
|
||
|
||
追加参数:
|
||
|
||
- `user_id`:当前登录用户 ID
|
||
- `token`:当前登录 JWT token
|
||
- `theme`:当前主题(`light` / `dark`)
|
||
- `ui_mode`:当前 UI 模式(固定 `embedded`)
|
||
|
||
示例:
|
||
|
||
```text
|
||
https://pay.example.com/pay?user_id=123&token=<jwt>&theme=light&ui_mode=embedded
|
||
```
|
||
|
||
### 5) 失败处理建议
|
||
|
||
- 支付状态与充值状态分开落库。
|
||
- 收到并验证支付回调后,立即标记“支付成功”。
|
||
- 支付成功但充值失败的订单应允许后续重试。
|
||
- 重试时继续使用同一 `code`,并使用新的 `Idempotency-Key`。
|
||
|
||
### 6) `doc_url` 配置建议
|
||
|
||
Sub2API 已支持系统设置中的 `doc_url` 字段。
|
||
|
||
推荐配置:
|
||
|
||
- 查看链接:`https://github.com/Wei-Shaw/sub2api/blob/main/ADMIN_PAYMENT_INTEGRATION_API.md`
|
||
- 下载链接:`https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/ADMIN_PAYMENT_INTEGRATION_API.md`
|
||
|
||
---
|
||
|
||
## English
|
||
|
||
### Overview
|
||
|
||
This document defines the minimum Admin API surface for integrating external payment systems (for example, sub2apipay) with Sub2API for recharge fulfillment and reconciliation.
|
||
|
||
### Base URL
|
||
|
||
- Production: `https://<your-domain>`
|
||
- Beta: `http://<your-server-ip>:8084`
|
||
|
||
### Authentication
|
||
|
||
Recommended headers:
|
||
|
||
- `x-api-key: admin-<64hex>` (recommended for server-to-server calls)
|
||
- `Content-Type: application/json`
|
||
|
||
Note: Admin JWT is also accepted by admin routes, but Admin API key is recommended for machine integrations.
|
||
|
||
### 1) One-step Create + Redeem
|
||
|
||
`POST /api/v1/admin/redeem-codes/create-and-redeem`
|
||
|
||
Purpose:
|
||
|
||
- Atomically create a deterministic redeem code and redeem it to the target user.
|
||
- Typical usage: called right after payment callback success.
|
||
|
||
Required headers:
|
||
|
||
- `x-api-key`
|
||
- `Idempotency-Key`
|
||
|
||
Request body:
|
||
|
||
```json
|
||
{
|
||
"code": "s2p_cm1234567890",
|
||
"type": "balance",
|
||
"value": 100.0,
|
||
"user_id": 123,
|
||
"notes": "sub2apipay order: cm1234567890"
|
||
}
|
||
```
|
||
|
||
Rules:
|
||
|
||
- `code`: deterministic code mapped from external order id.
|
||
- `type`: `balance` is the recommended type.
|
||
- `value`: must be greater than 0.
|
||
- `user_id`: target user id.
|
||
|
||
Idempotency behavior:
|
||
|
||
- Same `code` and same `used_by`: `200` (idempotent replay).
|
||
- Same `code` and different `used_by`: `409` (conflict).
|
||
- Missing `Idempotency-Key`: `400` (`IDEMPOTENCY_KEY_REQUIRED`).
|
||
|
||
Example:
|
||
|
||
```bash
|
||
curl -X POST "${BASE}/api/v1/admin/redeem-codes/create-and-redeem" \
|
||
-H "x-api-key: ${KEY}" \
|
||
-H "Idempotency-Key: pay-cm1234567890-success" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"code":"s2p_cm1234567890",
|
||
"type":"balance",
|
||
"value":100.00,
|
||
"user_id":123,
|
||
"notes":"sub2apipay order: cm1234567890"
|
||
}'
|
||
```
|
||
|
||
### 2) Query User (Optional Pre-check)
|
||
|
||
`GET /api/v1/admin/users/:id`
|
||
|
||
Purpose:
|
||
|
||
- Verify target user existence before final recharge/retry.
|
||
|
||
Example:
|
||
|
||
```bash
|
||
curl -s "${BASE}/api/v1/admin/users/123" \
|
||
-H "x-api-key: ${KEY}"
|
||
```
|
||
|
||
### 3) Balance Adjustment (Existing API)
|
||
|
||
`POST /api/v1/admin/users/:id/balance`
|
||
|
||
Purpose:
|
||
|
||
- Reuse existing admin endpoint for manual reconciliation.
|
||
- Supports `set`, `add`, `subtract`.
|
||
|
||
Request body example (`subtract`):
|
||
|
||
```json
|
||
{
|
||
"balance": 100.0,
|
||
"operation": "subtract",
|
||
"notes": "manual correction"
|
||
}
|
||
```
|
||
|
||
Example:
|
||
|
||
```bash
|
||
curl -X POST "${BASE}/api/v1/admin/users/123/balance" \
|
||
-H "x-api-key: ${KEY}" \
|
||
-H "Idempotency-Key: balance-subtract-cm1234567890" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"balance":100.00,
|
||
"operation":"subtract",
|
||
"notes":"manual correction"
|
||
}'
|
||
```
|
||
|
||
### 4) Purchase URL Query Parameters (Iframe + New Tab)
|
||
|
||
When Sub2API frontend opens `purchase_subscription_url`, it appends the same query parameters for both iframe and “open in new tab” to keep context consistent.
|
||
|
||
Appended parameters:
|
||
|
||
- `user_id`: current logged-in user id
|
||
- `token`: current logged-in JWT token
|
||
- `theme`: current theme (`light` / `dark`)
|
||
- `ui_mode`: UI mode (fixed `embedded`)
|
||
|
||
Example:
|
||
|
||
```text
|
||
https://pay.example.com/pay?user_id=123&token=<jwt>&theme=light&ui_mode=embedded
|
||
```
|
||
|
||
### 5) Failure Handling Recommendations
|
||
|
||
- Store payment state and recharge state separately.
|
||
- Mark payment success immediately after callback verification.
|
||
- Keep orders retryable when payment succeeded but recharge failed.
|
||
- Reuse the same deterministic `code` and a new `Idempotency-Key` when retrying.
|
||
|
||
### 6) Suggested `doc_url` Value
|
||
|
||
Sub2API already supports `doc_url` in system settings.
|
||
|
||
Recommended values:
|
||
|
||
- View URL: `https://github.com/Wei-Shaw/sub2api/blob/main/ADMIN_PAYMENT_INTEGRATION_API.md`
|
||
- Download URL: `https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/ADMIN_PAYMENT_INTEGRATION_API.md`
|