订阅 API
概述
- Base URL:
https://api.stablepay.co - API 前缀:
/api/v1 - 协议: HTTPS
- 数据格式: JSON
- 字符编码: UTF-8
端点
订阅管理
| 方法 | 端点 | 描述 |
|---|---|---|
| POST | /api/v1/subscriptions/create | 创建订阅 |
| GET | /api/v1/subscriptions/:subscription_id | 查询订阅 |
| GET | /api/v1/subscriptions/ | 列出订阅 |
| POST | /api/v1/subscriptions/:subscription_id/cancel | 取消订阅 |
账单管理
| 方法 | 端点 | 描述 |
|---|---|---|
| GET | /api/v1/invoices/:invoice_id | 查询账单 |
| GET | /api/v1/invoices/ | 列出账单 |
支付查询
| 方法 | 端点 | 描述 |
|---|---|---|
| GET | /api/v1/payment/:payment_id | 查询支付会话(payment_id) |
| GET | /api/v1/payment_method/:payment_method_id | 查询支付方式 |
退款管理
| 方法 | 端点 | 描述 |
|---|---|---|
| POST | /api/v1/refunds/create | 创建退款 |
| GET | /api/v1/refunds/:refund_id | 查询退款 |
| POST | /api/v1/refunds/:refund_id/cancel | 取消退款 |
接口列表
订阅管理
1. 创建订阅
接口地址
POST /api/v1/subscriptions/create
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| items | array | 是 | 订阅项数组(当前仅支持 1 个) |
| items[].price_data.price_id | string | 是 | 价格 ID |
| items[].price_data.currency | string | 是 | 币种(USD) |
| items[].price_data.product | string | 是 | 产品名 |
| items[].price_data.unit_amount | int64 | 是 | 单价(最小货币单位) |
| items[].price_data.recurring.interval | string | 是 | 周期:day/week/month/year |
| items[].quantity | int | 否 | 数量,默认 1 |
| customer | string | 是 | 客户外部 ID |
| customer_email | string | 否 | 客户邮箱 |
| customer_phone | string | 否 | 客户手机号 |
| customer_name | string | 否 | 客户姓名 |
| currency | string | 否 | 订阅币种(USD) |
| description | string | 否 | 订阅描述 |
| success_url | string | 否 | 支付成功跳转地址 |
| cancel_url | string | 否 | 支付取消跳转地址 |
| trial_end | int64 | 否 | 试用结束时间(Unix 秒) |
| billing_cycle_anchor | int64 | 否 | 账期锚点(Unix 秒) |
| cancel_at | int64 | 否 | 自动取消时间(Unix 秒),与 iterations 互斥 |
| iterations | int | 否 | 运行 N 个周期后自动取消,与 cancel_at 互斥 |
| metadata | object | 否 | 业务扩展字段 |
cancel_at 和 iterations 不能同时传入。
请求示例
{
"items": [
{
"price_data": {
"price_id": "price_monthly_001",
"currency": "USD",
"product": "Pro Plan",
"unit_amount": 1999,
"recurring": {
"interval": "month"
}
},
"quantity": 1,
"metadata": {
"seat_plan": "pro"
}
}
],
"customer": "cust_001",
"customer_email": "alice@example.com",
"customer_name": "Alice",
"currency": "USD",
"description": "Pro Monthly Plan",
"success_url": "https://merchant.example/success",
"cancel_url": "https://merchant.example/cancel",
"metadata": {
"merchant_order_no": "sub_order_1001"
}
}
响应示例
{
"id": "202603311103103101010000000001",
"object": "subscription",
"customer": "cust_001",
"store_id": "store_001",
"currency": "USD",
"description": "Pro Monthly Plan",
"status": "incomplete",
"items": [
{
"price_data": {
"price_id": "price_monthly_001",
"currency": "USD",
"product": "Pro Plan",
"unit_amount": 1999,
"recurring": {
"interval": "month"
}
},
"quantity": 1
}
],
"payment_method_id": "202603311103101003010000000001",
"billing_cycle_anchor": 1774886400,
"current_period_start": 1774886400,
"current_period_end": 1777478400,
"latest_invoice": "202603311103103103010000000001",
"checkout_url": "https://cashier.stablepay.co/subscription/202603311103103101010000000001",
"metadata": {
"merchant_order_no": "sub_order_1001"
},
"created": 1774924800
}
状态码
200 OK: 创建成功400 Bad Request: 参数错误409 Conflict: 幂等冲突
2. 查询订阅
接口地址
GET /api/v1/subscriptions/:subscription_id
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| subscription_id | string | 是 | 订阅 ID |
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| expand | string / array | 否 | 可选:latest_invoice、customer、payment_method |
请求示例
{
"subscription_id": "202603311103103101010000000001",
"expand": ["latest_invoice", "payment_method"]
}
响应示例
{
"id": "202603311103103101010000000001",
"object": "subscription",
"customer": "cust_001",
"currency": "USD",
"status": "active",
"current_period_start": 1774886400,
"current_period_end": 1777478400,
"latest_invoice": "202603311103103103010000000001",
"latest_invoice_object": {
"id": "202603311103103103010000000001",
"status": "paid",
"amount_due": 1999,
"amount_paid": 1999,
"currency": "USD"
},
"payment_method_object": {
"id": "202603311103101003010000000001",
"type": "crypto_wallet",
"status": "active"
},
"created": 1774924800
}
状态码
200 OK: 查询成功404 Not Found: 订阅不存在
3. 列出订阅
接口地址
GET /api/v1/subscriptions/
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| customer | string | 否 | 客户 ID |
| status | string | 否 | 订阅状态过滤 |
| limit | int | 否 | 返回条数,默认 10,最大 100 |
| starting_after | string | 否 | 向后分页游标 |
| ending_before | string | 否 | 向前分页游标 |
请求示例
{
"customer": "cust_001",
"status": "active",
"limit": 2
}
响应示例
{
"object": "list",
"data": [
{
"id": "202603311103103101010000000001",
"object": "subscription",
"customer": "cust_001",
"currency": "USD",
"status": "active",
"current_period_start": 1774886400,
"current_period_end": 1777478400,
"created": 1774924800
},
{
"id": "202603311103103101010000000002",
"object": "subscription",
"customer": "cust_001",
"currency": "USD",
"status": "trialing",
"current_period_start": 1774928400,
"current_period_end": 1777520400,
"created": 1774928400
}
],
"has_more": false,
"url": "/api/v1/subscriptions/?customer=cust_001&status=active&limit=2"
}
4. 取消订阅
接口地址
POST /api/v1/subscriptions/:subscription_id/cancel
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| subscription_id | string | 是 | 订阅 ID |
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cancel_at_period_end | bool | 否 | 是否账期结束后取消 |
| cancellation_reason | string | 否 | 取消原因 |
| cancellation_comment | string | 否 | 取消备注 |
请求示例
{
"subscription_id": "202603311103103101010000000001",
"cancel_at_period_end": true,
"cancellation_reason": "user_requested",
"cancellation_comment": "downgrade next month"
}
响应示例
{
"id": "202603311103103101010000000001",
"object": "subscription",
"status": "active",
"cancel_at": 1777478400,
"canceled_at": null,
"current_period_end": 1777478400,
"updated": 1774929000
}
账单管理
5. 查询账单
接口地址
GET /api/v1/invoices/:invoice_id
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| invoice_id | string | 是 | 账单 ID |
请求示例
{
"invoice_id": "202603311103103103010000000001"
}
响应示例
{
"id": "202603311103103103010000000001",
"object": "invoice",
"subscription_id": "202603311103103101010000000001",
"customer": "cust_001",
"amount_due": 1999,
"amount_paid": 1999,
"amount_remaining": 0,
"currency": "USD",
"status": "paid",
"payment_status": "paid",
"billing_reason": "subscription_cycle",
"period_start": 1774886400,
"period_end": 1777478400,
"payment_id": "202603311103101001010000000001",
"paid_at": 1774925100,
"due_date": 1775011200,
"metadata": {
"cycle": "2026-04"
},
"created": 1774924800
}
6. 列出账单
接口地址
GET /api/v1/invoices/
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| subscription_id | string | 否 | 订阅 ID |
| customer | string | 否 | 客户 ID |
| status | string | 否 | open / paid / void |
| limit | int | 否 | 返回条数,默认 10,最大 100 |
| starting_after | string | 否 | 向后分页游标 |
| ending_before | string | 否 | 向前分页游标 |
请求示例
{
"subscription_id": "202603311103103101010000000001",
"status": "paid",
"limit": 2
}
响应示例
{
"object": "list",
"data": [
{
"id": "202603311103103103010000000001",
"object": "invoice",
"subscription_id": "202603311103103101010000000001",
"customer": "cust_001",
"amount_due": 1999,
"amount_paid": 1999,
"currency": "USD",
"status": "paid",
"payment_status": "paid",
"created": 1774924800
}
],
"has_more": false,
"url": "/api/v1/invoices/?subscription_id=202603311103103101010000000001&status=paid&limit=2"
}
支付查询
7. 查询支付会话(payment_id)
接口地址
GET /api/v1/payment/:payment_id
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| payment_id | string | 是 | 支付 ID |
请求示例
{
"payment_id": "202603311103101001010000000001"
}
响应示例
{
"id": "202603311103101001010000000001",
"amount_total": 1999,
"currency": "USD",
"payment_status": "paid",
"created": 1774924800,
"expires_at": 1774928400,
"url": "https://cashier.stablepay.co/pay/202603311103101001010000000001",
"line_items": [
{
"price_data": {
"currency": "USD",
"unit_amount": 1999,
"product_data": {
"name": "Pro Plan"
}
},
"quantity": 1
}
],
"tax_amount": 0,
"shipping_amount": 0,
"exchange_rate": "1.0000",
"target_currency": "USDT",
"target_amount_total": 1999,
"rate_locked_at": 1774924800,
"subscription_id": "202603311103103101010000000001",
"invoice_id": "202603311103103103010000000001"
}
8. 查询支付方式
接口地址
GET /api/v1/payment_method/:payment_method_id
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| payment_method_id | string | 是 | 支付方式 ID |
请求示例
{
"payment_method_id": "202603311103101003010000000001"
}
响应示例
{
"id": "202603311103101003010000000001",
"customer_id": "cust_001",
"merchant_id": "mch_001",
"type": "crypto_wallet",
"address": "TXYZ***********abcd",
"status": "active",
"metadata": {
"network": "TRON"
},
"created_at": 1774920000,
"updated_at": 1774924800
}
退款管理
9. 创建退款
接口地址
POST /api/v1/refunds/create
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| payment_id | string | 是 | 支付 ID(服务端映射会话) |
| refund_id | string | 是 | 退款 ID(幂等) |
| amount | int64 | 是 | 退款金额(最小货币单位) |
| currency | string | 是 | USDT / USDC |
| reason | string | 否 | 退款原因 |
| description | string | 否 | 退款描述 |
| metadata | object | 否 | 业务扩展字段 |
请求示例
{
"payment_id": "202603311103101101010000000001",
"refund_id": "merchant_refund_20260331_0001",
"amount": 999,
"currency": "USDT",
"reason": "requested_by_customer",
"description": "partial refund",
"metadata": {
"ticket_id": "cs_12345"
}
}
响应示例
{
"refund_id": "merchant_refund_20260331_0001",
"payment_id": "202603311103101101010000000001",
"order_id": "order_202603310001",
"amount": 999,
"currency": "USDT",
"status": "pending",
"reason": "requested_by_customer",
"description": "partial refund",
"created_at": 1774929600,
"invoice_id": "202603311103103103010000000001",
"subscription_id": "202603311103103101010000000001",
"metadata": {
"ticket_id": "cs_12345"
}
}
10. 查询退款
接口地址
GET /api/v1/refunds/:refund_id
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| refund_id | string | 是 | 退款 ID |
请求示例
{
"refund_id": "merchant_refund_20260331_0001"
}
响应示例
{
"refund_id": "merchant_refund_20260331_0001",
"payment_id": "202603311103101101010000000001",
"order_id": "order_202603310001",
"amount": 999,
"currency": "USDT",
"status": "succeeded",
"reason": "requested_by_customer",
"description": "partial refund",
"failure_reason": "",
"transaction_hash": "0xdef456abc789",
"receipt_number": "rcpt_10001",
"created_at": 1774929600,
"processed_at": 1774930200,
"metadata": {
"ticket_id": "cs_12345"
}
}
11. 取消退款
接口地址
POST /api/v1/refunds/:refund_id/cancel
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| refund_id | string | 是 | 退款 ID |
请求示例
{
"refund_id": "merchant_refund_20260331_0001"
}
响应示例
{
"refund_id": "merchant_refund_20260331_0001",
"status": "canceled",
"canceled_at": 1774930800
}
Webhook 事件
Webhook 请求头
| Header | 说明 |
|---|---|
Content-Type | 固定为 application/json |
X-StablePay-Signature | Webhook 签名值(HMAC-SHA256) |
X-StablePay-Timestamp | 签名时间戳(Unix 秒) |
X-StablePay-Nonce | 随机串(防重放) |
X-StablePay-Event-Type | 事件类型(如 subscription.active) |
X-StablePay-Event-ID | 事件唯一 ID(通知记录 ID) |
User-Agent | 固定 StablePay-Webhook/1.0 |
签名串(来自 stablepay-notification 实现):
sign_payload = nonce + "." + request_body
订阅事件(逐条)
| 事件类型 | 触发条件 | data.object.status | 主要字段 |
|---|---|---|---|
subscription.created | 订阅创建成功后 | incomplete(常见) | subscription_id、customer_id、items、checkout_url |
subscription.trialing | 完成授权且进入试用 | trialing | subscription_id、current_period_start/end |
subscription.active | 首次/续费支付成功后激活 | active | subscription_id、current_period_start/end |
subscription.past_due | 续费失败进入催缴 | past_due | subscription_id、current_period_start/end |
subscription.canceled | 主动取消或重试耗尽自动取消 | canceled | subscription_id、canceled_at |
subscription.updated | 订阅对象发生更新 | 按实际状态 | subscription_id、可变字段 |
subscription.incomplete_expired | 初次授权超时失效 | incomplete_expired | subscription_id |
订阅事件 body(API 渠道最终推送)字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 事件 ID(evt_ 前缀) |
type | string | 上表事件类型 |
created_at | int64 | 订阅创建时间戳(秒) |
data.object.subscription_id | string | 订阅 ID |
data.object.customer_id | string | 客户 ID |
data.object.status | string | 订阅状态 |
data.object.cancel_at_period_end | bool | 是否账期结束取消 |
data.object.current_period_start | int64 | 当前周期开始(可选) |
data.object.current_period_end | int64 | 当前周期结束(可选) |
data.object.checkout_url | string | 订阅支付链接(可选) |
data.object.canceled_at | int64 | 实际取消时间(可选) |
data.object.source | string | 来源系统(api/shopify/...) |
data.object.items[] | array | 订阅项列表 |
data.object.items[].price_id | string | 价格 ID |
data.object.items[].quantity | int64 | 数量 |
data.object.items[].currency | string | 币种 |
data.object.items[].product_id | string | 产品名 |
data.object.items[].interval | string | 周期(day/week/month/year) |
data.object.items[].interval_count | int64 | 周期间隔数 |
data.object.items[].amount | int64 | 金额(最小货币单位) |
订阅事件示例
{
"id": "evt_1774924800123456789",
"type": "subscription.active",
"created_at": 1774924800,
"data": {
"object": {
"subscription_id": "202603311103103101010000000001",
"customer_id": "cust_001",
"status": "active",
"cancel_at_period_end": false,
"current_period_start": 1774886400,
"current_period_end": 1777478400,
"checkout_url": "https://cashier.stablepay.co/subscription/202603311103103101010000000001",
"source": "api",
"items": [
{
"price_id": "price_monthly_001",
"quantity": 1,
"currency": "USD",
"product_id": "Pro Plan",
"interval": "month",
"interval_count": 1,
"amount": 1999
}
]
}
}
}
账单事件(逐条)
| 事件类型 | 触发条件 | data.object.status | 主要字段 |
|---|---|---|---|
invoice.created | 生成新账单(首期/续费) | open / draft | invoice_id、amount_due、period_start/end |
invoice.paid | 账单支付成功 | paid | invoice_id、amount_paid、paid_at |
invoice.payment_failed | 账单支付失败 | open / payment_failed | invoice_id、amount_remaining |
账单事件 body(API 渠道最终推送)字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 事件 ID(evt_ 前缀) |
type | string | invoice.created / invoice.paid / invoice.payment_failed |
created_at | int64 | 账单创建时间戳(秒) |
data.object.invoice_id | string | 账单 ID |
data.object.subscription_id | string | 订阅 ID |
data.object.customer_id | string | 客户 ID |
data.object.amount_due | int64 | 应付金额 |
data.object.amount_paid | int64 | 已付金额 |
data.object.amount_remaining | int64 | 未付金额 |
data.object.currency | string | 币种 |
data.object.status | string | 账单状态 |
data.object.payment_status | string | 支付状态 |
data.object.billing_reason | string | 账单生成原因 |
data.object.period_start | int64 | 账期开始 |
data.object.period_end | int64 | 账期结束 |
data.object.paid_at | int64 | 付款时间(可选) |
data.object.source | string | 来源系统 |
账单事件示例
{
"id": "evt_1774924900123456789",
"type": "invoice.paid",
"created_at": 1774924800,
"data": {
"object": {
"invoice_id": "202603311103103103010000000001",
"subscription_id": "202603311103103101010000000001",
"customer_id": "cust_001",
"amount_due": 1999,
"amount_paid": 1999,
"amount_remaining": 0,
"currency": "USD",
"status": "paid",
"payment_status": "paid",
"billing_reason": "subscription_cycle",
"period_start": 1774886400,
"period_end": 1777478400,
"paid_at": 1774925100,
"source": "api"
}
}
}
退款事件(逐条)
| 事件类型 | 触发条件 | data.object.status | 主要字段 |
|---|---|---|---|
refund.succeeded | 退款处理成功 | completed | refund_id、refund_amount、refund_currency |
refund.failed | 退款处理失败 | failed | refund_id、refund_amount、refund_currency |
退款事件 body(API 渠道最终推送)字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 事件 ID(evt_ 前缀) |
type | string | refund.succeeded / refund.failed |
created_at | int64 | 退款状态更新时间戳(秒) |
data.object.session_id | string | 原支付会话 ID |
data.object.order_id | string | 商户订单 ID |
data.object.refund_id | string | 系统退款 ID |
data.object.external_refund_id | string | 商户退款 ID(可选) |
data.object.refund_amount | int64 | 退款金额(最小货币单位) |
data.object.refund_currency | string | 退款币种 |
data.object.original_currency | string | 原订单币种(可选) |
data.object.status | string | 退款状态(completed / failed) |
data.object.source | string | 来源系统 |
退款事件示例
{
"id": "evt_1774925000123456789",
"type": "refund.succeeded",
"created_at": 1774929600,
"data": {
"object": {
"session_id": "202603311103101001010000000001",
"order_id": "order_202603310001",
"refund_id": "202603311103101003010000000099",
"external_refund_id": "merchant_refund_20260331_0001",
"refund_amount": 999,
"refund_currency": "USDT",
"original_currency": "USD",
"status": "completed",
"source": "api"
}
}
}
错误响应
{
"error": "subscription_id is required"
}
{
"error": {
"code": "resource_not_found",
"message": "invoice not found",
"param": "invoice_id",
"type": "invalid_request_error"
}
}
{
"error": {
"type": "invalid_request_error",
"code": "parameter_missing",
"message": "Missing required parameter: merchant_id",
"param": "merchant_id",
"doc_url": "https://docs.stablepay.co/errors#parameter_missing"
},
"request_id": "req_xxx",
"timestamp": 1774924800
}