# Sub2API Admin API: Payment Integration / 支付集成接口文档 ## 中文 ### 概述 本文档描述外部支付系统(例如 sub2apipay)对接 Sub2API 时的最小 Admin API 集合,用于完成充值发放与对账。 ### 基础地址 - 生产环境:`https://` - Beta 环境:`http://: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=&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://` - Beta: `http://: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=&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`