变更与查询
订阅相关的接口分为两类。
直接查询与变更。 这些调用不使用 Checkout Session。可用于展示订阅、订单历史与发票链接以及未完成的方案变更;当操作由您发起时,也可用于取消订阅或待生效的方案变更。直接取消会立即生效。
需由消费者确认的请求。 这些调用会返回一个 Checkout Session。请将消费者重定向到其 url。在消费者确认之前,订阅不会发生任何变化。当变更需要消费者操作或同意时使用这些调用:消费者主动要求取消、消费者需要批准方案变更,或消费者需要提供新的支付方式。
金额格式: amount 等金额字段以每种货币的最小辅助单位表示。请参见支持的货币。
返回结果仅限于该 API 密钥所属的商户及其测试模式。
列出订阅
GET /v2/subscription 返回已认证商户的订阅,按 id 从新到旧排列。
reference 和 customerId 均为精确匹配,同时传入时按 AND 组合。limit 取值 1–100,默认 20。请求第一页时省略 cursor;请求下一页时,将 pagination.nextCursor 原样作为 cursor 传回。
curl --request GET \
--url 'https://api.tokenz.one/v2/subscription?customerId=customer_123&limit=20' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
响应
{
"data": [
{
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active",
"test": true,
"reference": "Pro Plan (Monthly)",
"customerId": "customer_123",
"items": [
{
"id": "item_1p4LS47fB1i_t",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"interval": { "unit": "MONTH", "count": 1 },
"provideAccess": true,
"currentBillingPeriodEnd": "2026-08-01T00:00:00Z",
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-01T00:00:00Z"
}
],
"pagination": {
"nextCursor": "subscription_1p4LC47fB2a_t"
}
}
到达最后一页时,响应中不包含 pagination.nextCursor。
获取订阅
GET /v2/subscription/{id} 返回单个订阅。如果该 id 不存在、属于其他商户,或与 API 密钥的测试模式不一致,调用将返回 404。
curl --request GET \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
响应
{
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active",
"test": true,
"reference": "Pro Plan (Monthly)",
"customerId": "customer_123",
"items": [
{
"id": "item_1p4LS47fB1i_t",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"interval": { "unit": "MONTH", "count": 1 },
"provideAccess": true,
"currentBillingPeriodEnd": "2026-08-01T00:00:00Z",
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-01T00:00:00Z"
}
取消订阅
POST /v2/subscription/{id}/cancel 会立即取消订阅,无需请求体。 只有处于 trialing、active 或 unpaid 状态的订阅才能被取消。已经是 canceled 的订阅不受影响,其他状态会返回 422,错误代码为 subscription.status-invalid。
取消操作会设置 canceledAt、停止生成后续的续订订单,并发送 subscription.canceled。取消是最终操作。关于访问权限和处理中订单会如何处理,请参见生命周期与计费。
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/cancel \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
响应
{
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "canceled",
"test": true,
"items": [
{
"id": "item_1p4LS47fB1i_t",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"interval": { "unit": "MONTH", "count": 1 },
"provideAccess": true,
"provideAccessUntil": "2026-08-01T00:00:00Z",
"canceledAt": "2026-07-15T12:00:00Z",
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
请求消费者确认取消
POST /v2/subscription/{id}/request/cancel 本身不会取消订阅,而是创建一个供消费者确认取消的 Checkout Session。请将消费者重定向到返回的 url。消费者确认后,订阅会按与直接取消相同的方式被取消,同样会发送 subscription.canceled webhook。
必填的请求体字段:
successUrl:消费者确认后跳转到的地址。pendingUrl:确认仍在处理中时消费者跳转到的地址。cancelUrl:消费者放弃该流程时跳转到的地址。
theme 为可选字段(LIGHT 或 DARK)。
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/cancel \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel"
}'
响应
返回 201 及该 Checkout Session。在消费者确认之前,订阅保持当前状态不变。
{
"id": "checkoutsession_1p4LC47fB2a_t",
"object": "checkoutsession",
"url": "https://checkout.tokenz.one/1p4LC47fB2a_t",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel",
"test": true,
"subscription": {
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active"
},
"createdAt": "2026-07-15T12:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
请求更换支付方式
POST /v2/subscription/{id}/request/payment-method-change 会创建一个 Checkout Session,供消费者提供新卡。请将消费者重定向到 url。新卡的授权会在该托管页面上获取;参见支付方式与授权。
请求体与请求消费者确认取消相同,包含三个重定向地址(successUrl、pendingUrl、cancelUrl),以及可选的 theme。
如果订阅处于 unpaid 状态,返回的会话是未付订单的结账会话。支付该订单后,订阅的支付方式会被替换,订阅也会重新激活。成功后,Tokenz 会发送 subscription.activated webhook。
如果订阅处于 active 或 trialing 状态,返回的是用于更新支付方式的 Checkout Session。成功后,Tokenz 会发送 subscription.payment_method_updated webhook。
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/payment-method-change \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel"
}'
响应
{
"id": "checkoutsession_1p4LP47fB3b_t",
"object": "checkoutsession",
"url": "https://checkout.tokenz.one/1p4LP47fB3b_t",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel",
"test": true,
"subscription": {
"id": "subscription_1p4LS47fB1h_t",
"object": "subscription",
"status": "active"
},
"createdAt": "2026-07-15T12:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
请求方案变更
POST /v2/subscription/{id}/request/plan-change 请求消费者批准新的商品和计费间隔。 在消费者通过返回的 Checkout Session 批准之前,变更不会生效。
订阅必须处于 active 或 trialing 状态,其他状态会返回 422,错误代码为 subscription.status-invalid。 请求体必须包含 itemDetails、replacementMode、successUrl、pendingUrl 和 cancelUrl。 itemDetails 会替换订阅当前的商品:必须且只能包含一个未打折、quantity 为 1 的商品。 该商品的货币必须与订阅的货币一致,否则会返回 400,错误代码为 currency.inconsistent。 interval 用于设置新的计费间隔,格式为 { "unit": "WEEK" | "MONTH" | "YEAR", "count": <integer ≥ 1> }。 立即生效的变更应用后使用 successUrl,延后生效的变更获批后使用 pendingUrl。
replacementMode:
IMMEDIATE_PRORATION:适用于按时间提供权益的订阅(例如高级会员方案),在消费者授权订单后立即应用变更。 如果订阅处于 active 状态,当前计费周期剩余部分的价值会按比例折算并抵扣给消费者,计费锚点也会改为授权当天的日期。 如果订阅处于 trialing 状态,试用期会立即结束且不提供额外抵扣,订阅随即以新方案开始。 如果计算出的抵扣金额超过新商品的价格,会返回422,错误代码为subscription.plan-replacement-invalid。 请勿对按商品发放的订阅(例如每月购买游戏货币)使用此模式。如果您需要为按商品发放的订阅提供升级选项,请联系 Tokenz。DEFERRED:在当前计费周期结束后应用变更。消费者批准后会发送subscription.plan_change_scheduled;方案本身会在下一个计费周期的订单支付成功时变更。
方案生效时(无论是立即生效还是在下一个周期生效),Tokenz 都会发送 subscription.plan_changed webhook。
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/plan-change \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \
--data '{
"itemDetails": [{
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"],
"taxCategory": "SAAS"
}
}],
"interval": { "unit": "YEAR", "count": 1 },
"replacementMode": "DEFERRED",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel"
}'
如需在消费者批准后立即应用同一方案,请使用 "replacementMode": "IMMEDIATE_PRORATION"。此模式适用于按时间提供权益的订阅,不适用于按商品发放的订阅。
响应
返回 201 及该 Checkout Session 和待处理的变更。
{
"id": "checkoutsession_1p4LR47fB4c_t",
"object": "checkoutsession",
"url": "https://checkout.tokenz.one/1p4LR47fB4c_t",
"successUrl": "https://example.com/success",
"pendingUrl": "https://example.com/pending",
"cancelUrl": "https://example.com/cancel",
"test": true,
"subscriptionChange": {
"id": "subscriptionchange_1p4LC9aB2cD_t",
"object": "subscriptionchange",
"status": "pending",
"replacementMode": "DEFERRED",
"interval": { "unit": "YEAR", "count": 1 },
"items": [
{
"id": "item_1p4LS47fB1j_t",
"detail": {
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
]
},
"createdAt": "2026-07-15T12:00:00Z",
"updatedAt": "2026-07-15T12:00:00Z"
}
请将消费者重定向到 url。如果之后需要列出或取消该变更,请保存 subscriptionChange.id。
列出方案变更
GET /v2/subscription/{id}/plan-change 返回订阅中未完成的变更,即处于 pending 或 approved 状态的变更。不包含 canceled 和 applied 状态的变更。
变更会依次经历 pending(等待消费者处理)、approved(已接受;对于延后生效的变更,表示尚未应用),最终变为 applied 或 canceled。
curl --request GET \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
响应
{
"data": [
{
"id": "subscriptionchange_1p4LC9aB2cD_t",
"object": "subscriptionchange",
"status": "approved",
"replacementMode": "DEFERRED",
"interval": { "unit": "YEAR", "count": 1 },
"items": [
{
"id": "item_1p4LS47fB1j_t",
"detail": {
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
]
}
]
}
取消方案变更
POST /v2/subscription/{id}/plan-change/{changeId}/cancel 会在 pending 或 approved 状态的变更生效前将其取消,无需请求体。 取消 applied、expired 或 canceled 状态的变更会返回 422,错误代码为 subscription.change-status-invalid。 一旦下一个计费周期的订单已创建,延后生效的变更即使状态仍为 approved 也无法再取消,此时尝试取消会返回 422,错误代码为 subscription.change-status-invalid。
取消一个已获批准的延后生效变更时,会发送 subscription.plan_change_canceled。
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change/subscriptionchange_1p4LC9aB2cD_t/cancel \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
响应
{
"id": "subscriptionchange_1p4LC9aB2cD_t",
"object": "subscriptionchange",
"status": "canceled",
"replacementMode": "DEFERRED",
"interval": { "unit": "YEAR", "count": 1 },
"items": [
{
"id": "item_1p4LS47fB1j_t",
"detail": {
"product": {
"price": { "amount": 2000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Yearly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
]
}
列出订阅的订单
Order 服务的 GET /v2/order 会列出为某个订阅创建的订单,subscriptionId 为必填参数。limit(1–100,默认 20)和 cursor 的分页方式与列出订阅相同:将 pagination.nextCursor 原样作为 cursor 传回。订单按 id 从新到旧排列,且只返回与 API 密钥测试模式一致的订单。
每个订单都包含 subscriptionId。商品可能包含 billedPeriodStart(含)和 billedPeriodEnd(不含),表示该订单覆盖的计费周期。
curl --request GET \
--url 'https://api.tokenz.one/v2/order?subscriptionId=subscription_1p4LS47fB1h_t&limit=20' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
响应
{
"data": [
{
"id": "order_1D5xA9BnKfv_t",
"object": "order",
"status": "succeeded",
"test": true,
"subscriptionId": "subscription_1p4LS47fB1h_t",
"amount": { "amount": 1000, "currency": "USD" },
"items": [
{
"id": "item_1p4LO47fB1k_t",
"billedPeriodStart": "2026-07-01T00:00:00Z",
"billedPeriodEnd": "2026-08-01T00:00:00Z",
"detail": {
"product": {
"price": { "amount": 1000, "currency": "USD" },
"quantity": 1,
"label": "Pro Plan (Monthly)",
"images": ["https://example.com/pro-plan.png"]
}
}
}
],
"createdAt": "2026-07-01T00:00:00Z",
"updatedAt": "2026-07-01T00:00:05Z"
}
],
"pagination": {
"nextCursor": "order_1p4LC47fB2a_t"
}
}
发票链接
GET /v2/order/{id}/invoice 返回某个订单(包括订阅续订订单)面向买家的托管发票链接。displayUrl 是托管发票页面。downloadUrl 是 PDF 文件,仅在 PDF 生成后才会返回。将客户重定向时,请使用完整的 URL,包括其中带有 Tokenz 生成签名的片段(fragment)部分。
curl --request GET \
--url https://api.tokenz.one/v2/order/order_1D5xA9BnKfv_t/invoice \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
响应
{
"displayUrl": "https://invoice.tokenz.one/i/1D5xA9BnKfv_t#generated-invoice-signature",
"downloadUrl": "https://invoice.tokenz.one/i/1D5xA9BnKfv_t/download#generated-invoice-signature"
}
在 PDF 生成之前,响应中仅包含 displayUrl。
Webhook
请通过 webhook 同步您自己的记录,而不是轮询这些接口。本页各项操作对应的事件如下:
subscription.canceled——直接取消或经消费者确认的取消已完成。subscription.payment_method_updated——消费者确认了新卡。subscription.plan_change_scheduled——消费者批准了一项延后生效的方案变更。subscription.plan_change_canceled——一项已排期的延后方案变更在生效前被取消。subscription.plan_changed——一项立即或延后生效的方案变更已应用。负载中的items和interval即为新方案。
负载结构请参见 Webhook。