UPI 开放 API

程序化提交账号 · 出码 · 查询充值状态

鉴权与签名(所有接口通用)
每个调用方持有一对密钥:API Key(公开标识 uk_…)+ Secret(私钥 us_…,仅签发时显示一次,请妥善保存)。每个请求需带以下请求头:
X-Api-Key:    uk_xxxxxxxx
X-Timestamp:  1718351999000        # 毫秒时间戳,服务端校验 ±5 分钟
X-Nonce:      <每次随机字符串>       # 防重放,同一值只能用一次
X-Signature:  <HMAC-SHA256 签名,hex>
签名串 = METHOD + "\n" + PATH + "\n" + BODY + "\n" + TIMESTAMP + "\n" + NONCE,其中 PATH 为含 query 的完整路径,BODY 为原始请求体(GET 为空串)。用 Secret 做 HMAC-SHA256:
// Node.js 示例
const crypto = require("crypto");
function sign(secret, method, path, body, ts, nonce) {
  const base = [method, path, body, ts, nonce].join("\n");
  return crypto.createHmac("sha256", secret).update(base).digest("hex");
}
const ts = Date.now().toString();
const nonce = crypto.randomBytes(12).toString("hex");
const body = JSON.stringify({ session: "<完整 session JSON 或 access token>" });
const sig = sign(SECRET, "POST", "/api/v1/upi/self/generate", body, ts, nonce);
// 带上 4 个头发起请求
安全:session/access token 仅用于出码,服务端绝不回显;代理等内部信息绝不下发。所有调用全程审计可追溯。限流默认每分钟 60 次,超出返回 429。
自营 Key:自己上传 session → 系统直接出码 → 自己扫码支付。预付余额计费:开通时由平台充值额度(次数),必须有余额才能调用,扣完即停、可随时补充。计费口径两种(开通时设定):按成功=账号真升 Plus 才扣 1 次;按出码=每生成一个支付码扣 1 次。计费只看本 Key 余额,不受所绑渠道的额度/单价设置影响(那是渠道网页后台上传的口径,与 API 互不干扰)。余额查询见 /self/quota。
POST/api/v1/upi/self/generate· 提交 session,异步出码
请求体: { "session": "<完整 session JSON 或 access token>" }
返回:   { "ok": true, "order_id": "upt_xxx", "status": "generating" }
说明:   立即返回 order_id 并后台出码,随后轮询 status 取支付码。
        仅纯手机号、有0元资格、登录态有效的账号会受理。
GET/api/v1/upi/self/status?order_id=upt_xxx· 轮询支付码/升级结果
返回: {
  "ok": true, "order_id": "upt_xxx",
  "status": "code_ready",          // generating|code_ready|paid|plus_success|gen_failed|failed
  "account": "+91****512",
  "qr_svg": "https://...",          // 支付二维码(SVG优先)
  "upi_link": "upi://...",          // 唤起 UPI App 的链接
  "cs_id": "cs_live_...",
  "expires_at": 1718352299000,
  "plan": "free",                   // 升级成功后为 plus
  "fail_reason": "", "fail_detail": ""
}
POST/api/v1/upi/self/paid· 标记已支付,触发加速检测
请求体: { "order_id": "upt_xxx" }
返回:   { "ok": true, "status": "paid" }
POST/api/v1/upi/self/retry· 出码失败/充值失败 → 同单重新生成新码
请求体: { "order_id": "upt_xxx" }
返回:   { "ok": true, "order_id": "upt_xxx", "status": "generating" }
说明:   同一订单重新出一张新码,不新建订单。
        ▸ 仅 gen_failed(出码失败)/failed(充值失败)/code_ready(旧码) 可重试,其它状态返回 409 not_retryable。
        ▸ 不重复扣费:已计费的订单(已付费)免费重试;未计费订单重试需有可用余额。
        ▸ 提交后轮询 /self/status 取新码(status 由 generating → code_ready)。
GET/api/v1/upi/self/quota· 查余额/计费口径/用量
返回: {
  "ok": true,
  "balance": 200,          // 当前剩余额度(次数),扣完即停
  "available": 197,        // 可用额度 = 余额 − 在途占用
  "pending": 3,            // 在途占用(已提交未结算的任务)
  "bill_basis": "success", // success=按成功升级扣 | generated=按出码扣
  "uploaded": 120, "success": 88   // 渠道侧累计统计
}
错误码
401 no_api_key / invalid_key      Key 缺失或已停用
401 no_signature / bad_signature  签名缺失或错误
401 timestamp_invalid             时间戳过期(±5min)
401 nonce_replay                  nonce 重复(重放)
403 mode_mismatch / no_channel    Key 类型不符 / 未绑定渠道
402 insufficient_balance          余额不足,请先充值额度(公共池/自营)
429 rate_limited                  超过每分钟调用限流
422 email_account                 邮箱注册账号不支持
422 token_invalid                 登录态已失效
422 no_zero                       无 0 元升级资格
409 duplicate                     同账号已成功/处理中
409 not_retryable                 当前状态不可重试(仅失败/旧码可重新生成)
404 not_found                     订单不存在或不属于此 Key
需要 API Key 请联系平台开通。