跳至内容
产品与订阅变更与查询

变更与查询

订阅相关的接口分为两类。

直接查询与变更。 这些调用不使用 Checkout Session。可用于展示订阅、订单历史与发票链接以及未完成的方案变更;当操作由您发起时,也可用于取消订阅或待生效的方案变更。直接取消会立即生效。

需由消费者确认的请求。 这些调用会返回一个 Checkout Session。请将消费者重定向到其 url。在消费者确认之前,订阅不会发生任何变化。当变更需要消费者操作或同意时使用这些调用:消费者主动要求取消、消费者需要批准方案变更,或消费者需要提供新的支付方式。

金额格式: amount 等金额字段以每种货币的最小辅助单位表示。请参见支持的货币。

返回结果仅限于该 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。取消是最终操作。关于访问权限和处理中订单会如何处理,请参见生命周期与计费。

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。新卡的授权会在该托管页面上获取;参见支付方式与授权。

请求体与请求消费者确认取消相同,包含三个重定向地址(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": <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。

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 的分页方式与列出订阅相同:将 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。