--- title: "变更与查询" description: "订阅相关的接口分为两类。" source: "https://docs.tokenz.one/zh-CN/v2/subscriptions/modification" api_version: "v2" locale: "zh-CN" version_status: "current" docs_stage: "prod" --- # 变更与查询 订阅相关的接口分为两类。 **直接查询与变更。** 这些调用不使用 Checkout Session。可用于展示订阅、订单历史与发票链接以及未完成的方案变更;当操作由您发起时,也可用于取消订阅或待生效的方案变更。直接取消会立即生效。 - [列出订阅](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E8%AE%A2%E9%98%85)和[获取订阅](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E8%8E%B7%E5%8F%96%E8%AE%A2%E9%98%85)——展示订阅。 - [列出订阅的订单](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E8%AE%A2%E9%98%85%E7%9A%84%E8%AE%A2%E5%8D%95)和[发票链接](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E5%8F%91%E7%A5%A8%E9%93%BE%E6%8E%A5)——展示订单历史和发票。 - [列出方案变更](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E6%96%B9%E6%A1%88%E5%8F%98%E6%9B%B4)——展示未完成的方案变更。 - [取消订阅](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E5%8F%96%E6%B6%88%E8%AE%A2%E9%98%85)和[取消方案变更](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E5%8F%96%E6%B6%88%E6%96%B9%E6%A1%88%E5%8F%98%E6%9B%B4)——由您这一方取消订阅或待生效的变更。 **需由消费者确认的请求。** 这些调用会返回一个 Checkout Session。请将消费者重定向到其 `url`。在消费者确认之前,订阅不会发生任何变化。当变更需要消费者操作或同意时使用这些调用:消费者主动要求取消、消费者需要批准方案变更,或消费者需要提供新的支付方式。 - [请求消费者确认取消](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E8%AF%B7%E6%B1%82%E6%B6%88%E8%B4%B9%E8%80%85%E7%A1%AE%E8%AE%A4%E5%8F%96%E6%B6%88)——因消费者要求而取消。 - [请求方案变更](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E8%AF%B7%E6%B1%82%E6%96%B9%E6%A1%88%E5%8F%98%E6%9B%B4)——由消费者批准新方案。 - [请求更换支付方式](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E8%AF%B7%E6%B1%82%E6%9B%B4%E6%8D%A2%E6%94%AF%E4%BB%98%E6%96%B9%E5%BC%8F)——由消费者提供新卡。 **金额格式:** `amount` 等金额字段以每种货币的最小辅助单位表示。请参见[支持的货币](https://docs.tokenz.one/zh-CN/v2/checkout/currency)。 返回结果仅限于该 API 密钥所属的商户及其测试模式。 ## 列出订阅 `GET /v2/subscription` 返回已认证商户的订阅,按 id 从新到旧排列。 `reference` 和 `customerId` 均为精确匹配,同时传入时按 AND 组合。`limit` 取值 1–100,默认 20。请求第一页时省略 `cursor`;请求下一页时,将 `pagination.nextCursor` 原样作为 `cursor` 传回。 ```bash curl --request GET \ --url 'https://api.tokenz.one/v2/subscription?customerId=customer_123&limit=20' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 响应 ```json { "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`。 ```bash curl --request GET \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 响应 ```json { "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`。取消是最终操作。关于访问权限和处理中订单会如何处理,请参见[生命周期与计费](https://docs.tokenz.one/zh-CN/v2/subscriptions/lifecycle#%E5%8F%96%E6%B6%88)。 ```bash curl --request POST \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/cancel \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 响应 ```json { "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`)。 ```bash 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。在消费者确认之前,订阅保持当前状态不变。 ```json { "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`。新卡的授权会在该托管页面上获取;参见[支付方式与授权](https://docs.tokenz.one/zh-CN/v2/subscriptions/payment-methods)。 请求体与请求消费者确认取消相同,包含三个重定向地址(`successUrl`、`pendingUrl`、`cancelUrl`),以及可选的 `theme`。 如果订阅处于 `unpaid` 状态,返回的会话是未付订单的结账会话。支付该订单后,订阅的支付方式会被替换,订阅也会重新激活。成功后,Tokenz 会发送 `subscription.activated` webhook。 如果订阅处于 `active` 或 `trialing` 状态,返回的是用于更新支付方式的 Checkout Session。成功后,Tokenz 会发送 `subscription.payment_method_updated` webhook。 ```bash 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" }' ``` ### 响应 ```json { "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": }`。 立即生效的变更应用后使用 `successUrl`,延后生效的变更获批后使用 `pendingUrl`。 `replacementMode`: - `IMMEDIATE_PRORATION`:适用于按时间提供权益的订阅(例如高级会员方案),在消费者授权订单后立即应用变更。 如果订阅处于 active 状态,当前计费周期剩余部分的价值会按比例折算并抵扣给消费者,计费锚点也会改为授权当天的日期。 如果订阅处于 trialing 状态,试用期会立即结束且不提供额外抵扣,订阅随即以新方案开始。 如果计算出的抵扣金额超过新商品的价格,会返回 `422`,错误代码为 `subscription.plan-replacement-invalid`。 请勿对按商品发放的订阅(例如每月购买游戏货币)使用此模式。如果您需要为按商品发放的订阅提供升级选项,请联系 Tokenz。 - `DEFERRED`:在当前计费周期结束后应用变更。消费者批准后会发送 `subscription.plan_change_scheduled`;方案本身会在下一个计费周期的订单支付成功时变更。 方案生效时(无论是立即生效还是在下一个周期生效),Tokenz 都会发送 `subscription.plan_changed` webhook。 ```bash 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 和待处理的变更。 ```json { "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`。 ```bash curl --request GET \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 响应 ```json { "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`。 ```bash 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' ``` ### 响应 ```json { "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` 的分页方式与[列出订阅](https://docs.tokenz.one/zh-CN/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E8%AE%A2%E9%98%85)相同:将 `pagination.nextCursor` 原样作为 `cursor` 传回。订单按 id 从新到旧排列,且只返回与 API 密钥测试模式一致的订单。 每个订单都包含 `subscriptionId`。商品可能包含 `billedPeriodStart`(含)和 `billedPeriodEnd`(不含),表示该订单覆盖的计费周期。 ```bash curl --request GET \ --url 'https://api.tokenz.one/v2/order?subscriptionId=subscription_1p4LS47fB1h_t&limit=20' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 响应 ```json { "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)部分。 ```bash curl --request GET \ --url https://api.tokenz.one/v2/order/order_1D5xA9BnKfv_t/invoice \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### 响应 ```json { "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](https://docs.tokenz.one/zh-CN/v2/subscriptions/webhooks)。