跳转到主要内容

Documentation Index

Fetch the complete documentation index at: https://docs.stablepayfi.ai/llms.txt

Use this file to discover all available pages before exploring further.

本文档介绍集成 StablePay API 前需要完成的准备工作,包括账号与密钥获取、请求签名算法、Webhook 事件通知机制,以及每个接口需要携带的请求头。

基础信息

项目
生产环境 Base URLhttps://api.stablepay.co
API 前缀/api/v1
协议HTTPS
数据格式JSON
字符编码UTF-8

前置条件

开始接入前,请确认你已经:
  1. 注册 StablePay 商户账号并完成资质审核
  2. 在商户后台创建店铺,渠道类型选择 API,等待审核通过
  3. 在店铺的「密钥管理」菜单中生成并获取:
    • API Key:用于 Authorization 请求头,标识调用方身份
    • Secret Key:用于生成请求签名,请妥善保管,切勿提交到公开代码仓库或分享给他人

认证与签名

请求头清单

所有 API 请求都必须携带以下请求头:
请求头是否必填说明
Authorization格式:Bearer {api_key}
Content-TypePOST/PUT 必填固定为 application/json。GET 请求不必携带
X-StablePay-TimestampUnix 时间戳(秒),与服务器时间相差不得超过 5 分钟
X-StablePay-Nonce随机字符串(建议 UUID v4),用于防重放,每次请求必须唯一
X-StablePay-Signature使用 Secret Key 对签名串做 HMAC-SHA256 运算后的小写十六进制字符串

签名串拼接规则

sign_payload = {timestamp} + "." + {nonce} + "." + {requestBody}
  • {requestBody}:POST / PUT 请求为原始 JSON 字符串(不要再次序列化、不要格式化)
  • GET / DELETE 等没有请求体的方法:{requestBody}空字符串
  • 签名算法:HMAC-SHA256(sign_payload, secret_key) → 小写 hex 字符串

示例代码

TIMESTAMP=$(date +%s)
NONCE=$(uuidgen)
BODY='{"amount":1999,"currency":"USD"}'
SIGN_PAYLOAD="${TIMESTAMP}.${NONCE}.${BODY}"
SIGNATURE=$(echo -n "${SIGN_PAYLOAD}" | openssl dgst -sha256 -hmac "${SECRET_KEY}" | awk '{print $2}')

curl -X POST https://api.stablepay.co/api/v1/checkout/sessions/create \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "X-StablePay-Timestamp: ${TIMESTAMP}" \
  -H "X-StablePay-Nonce: ${NONCE}" \
  -H "X-StablePay-Signature: ${SIGNATURE}" \
  -H "Content-Type: application/json" \
  -d "${BODY}"
签名串中的 requestBody 必须是实际发送的原始字节。不要在计算签名后再对 JSON 进行格式化或重排字段,否则签名会校验失败。

每个接口所需的请求头

接口分类路径示例Authorization签名三件套
支付POST /api/v1/checkout/sessions/create
支付GET /api/v1/checkout/sessions/{session_id}✅(body 为空串)
支付POST /api/v1/checkout/sessions/{session_id}/cancel
退款POST /api/v1/refunds/create
退款GET /api/v1/refunds/{refund_id}✅(body 为空串)
退款POST /api/v1/refunds/{refund_id}/cancel
订阅POST /api/v1/subscriptions/create
订阅GET /api/v1/subscriptions/{subscription_id}✅(body 为空串)
订阅GET /api/v1/subscriptions✅(body 为空串)
订阅POST /api/v1/subscriptions/{subscription_id}/cancel
发票GET /api/v1/invoices/{invoice_id}✅(body 为空串)
发票GET /api/v1/invoices✅(body 为空串)
支付查询GET /api/v1/payment/{payment_id}✅(body 为空串)
支付方式GET /api/v1/payment_method/{payment_method_id}✅(body 为空串)
POST /api/v1/subscriptions/create 还必须额外携带 Idempotency-Key 请求头。使用相同键重试时,服务端会返回首次创建的订阅对象。

幂等性

以下接口支持幂等,商户自定义 ID 作为幂等键:
接口幂等键
创建退款请求体 refund_id
创建订阅请求头 Idempotency-Key
使用相同幂等键重复提交时,服务端返回首次创建的资源,不会产生重复数据。

Webhook 通知

StablePay 通过 Webhook 将关键事件异步推送到你在商户后台配置的回调 URL。

事件类型

类别事件类型
支付payment.completedpayment.failedpayment.expiredpayment.cancelled
退款refund.succeededrefund.failed
订阅subscription.createdsubscription.trialingsubscription.activesubscription.past_duesubscription.canceledsubscription.updatedsubscription.incomplete_expired
发票invoice.createdinvoice.paidinvoice.payment_failed

Webhook 请求头

请求头说明
Content-Type固定 application/json
User-AgentStablePay-Webhook/1.0
X-StablePay-Signature{timestamp}.{raw_body} 做 HMAC-SHA256 后得到的小写 hex 签名
X-StablePay-TimestampUnix 时间戳(秒)
X-StablePay-Nonce随机字符串,可用于接收方额外防重放或日志追踪;不参与签名计算
X-StablePay-Event-Type事件类型,例如 payment.completed
X-StablePay-Event-ID事件唯一 ID,用于幂等去重

签名校验步骤

  1. 从请求头取出 X-StablePay-SignatureX-StablePay-Timestamp;如需额外防重放或日志追踪,也可记录 X-StablePay-Nonce
  2. 校验时间戳与当前时间相差不超过 5 分钟(防重放)
  3. 原始请求体字节不要解析后再序列化),按下列格式拼接:
    sign_payload = {timestamp} + "." + {raw_body}
    
  4. 使用商户 Secret Key 做 HMAC-SHA256,得到小写 hex 字符串
  5. 使用恒定时间比较(如 hmac.compare_digest)与请求头中的签名对比

校验示例(Python)

import hmac, hashlib, time

def verify_webhook(headers, raw_body: bytes, secret_key: str) -> bool:
    ts = headers["X-StablePay-Timestamp"]
    sig = headers["X-StablePay-Signature"]

    if abs(int(time.time()) - int(ts)) > 300:
        return False

    sign_payload = f"{ts}.".encode() + raw_body
    expected = hmac.new(
        secret_key.encode(), sign_payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, sig)

响应要求与重试策略

  • 商户服务需在 30 秒内返回 HTTP 2xx
  • 返回 4295xx 会进入重试队列,其他 4xx 不重试
  • 最多重试 10 次,采用指数退避间隔(分钟):2, 4, 8, 16, 32, 64, 128, 256, 512, 1024

幂等消费

请使用 X-StablePay-Event-ID(或请求体中的 id 字段)作为幂等键,处理前检查事件是否已被处理过,避免重复下发带来的副作用。

错误响应

错误统一使用 HTTP 状态码 + JSON 响应体返回。error 字段可能是字符串或结构化对象:
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "Missing required parameter: refund_id",
    "param": "refund_id",
    "doc_url": "https://docs.stablepayfi.ai/errors#parameter_missing"
  },
  "request_id": "req_xxx",
  "timestamp": 1774924800
}
常见错误码:
HTTPcode含义
400parameter_missing / invalid_request_error参数缺失或格式不合法
401invalid_api_keyAPI Key 无效或签名校验失败
403无权限访问该资源
404resource_not_found资源不存在
409conflict幂等冲突(同一幂等键不同参数)
429DAILY_REFUND_LIMIT_EXCEEDED达到频次或额度限制

安全建议

  • Secret Key 只在服务端使用,不得出现在前端代码、APK、小程序包、日志中
  • 建议在 CI/CD 中用密钥管理服务(KMS/Vault/SSM)注入 Secret Key
  • Webhook 回调 URL 必须使用 HTTPS
  • 对每个收到的 Webhook 做签名校验 + 幂等去重 + 业务状态校验(例如订单必须为「已支付」才允许退款)
  • 定期在商户后台轮换 API Key 与 Secret Key
Last modified on April 30, 2026