--- title: "變更與查詢" description: "訂閱相關端點分為兩類。" source: "https://docs.tokenz.one/zh-TW/v2/subscriptions/modification" api_version: "v2" locale: "zh-TW" version_status: "current" docs_stage: "prod" --- # 變更與查詢 訂閱相關端點分為兩類。 **直接查詢與變更。** 這類呼叫不經過 Checkout Session。可用來顯示訂閱、其訂單紀錄與發票連結,以及尚未完成的方案變更;當由您主動發起時,也可用來取消訂閱或待生效的方案變更。直接取消會立即生效。 - [列出訂閱](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E8%A8%82%E9%96%B1)和[取得單一訂閱](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E5%8F%96%E5%BE%97%E5%96%AE%E4%B8%80%E8%A8%82%E9%96%B1):顯示訂閱。 - [列出訂閱的訂單](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E8%A8%82%E9%96%B1%E7%9A%84%E8%A8%82%E5%96%AE)和[發票連結](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E7%99%BC%E7%A5%A8%E9%80%A3%E7%B5%90):顯示訂單紀錄與發票。 - [列出方案變更](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E6%96%B9%E6%A1%88%E8%AE%8A%E6%9B%B4):顯示尚未完成的方案變更。 - [取消訂閱](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E5%8F%96%E6%B6%88%E8%A8%82%E9%96%B1)和[取消方案變更](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E5%8F%96%E6%B6%88%E6%96%B9%E6%A1%88%E8%AE%8A%E6%9B%B4):由您這端取消訂閱或待生效的變更。 **需由消費者確認的請求。** 這類呼叫會回傳 Checkout Session,請將消費者重新導向至其 `url`。在消費者確認之前,訂閱不會有任何變動。當變更需要消費者操作或同意時使用:消費者要求取消、需要消費者核准方案變更,或需要消費者提供新的付款方式。 - [要求消費者確認取消](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E8%A6%81%E6%B1%82%E6%B6%88%E8%B2%BB%E8%80%85%E7%A2%BA%E8%AA%8D%E5%8F%96%E6%B6%88):因消費者要求而取消。 - [要求變更方案](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E8%A6%81%E6%B1%82%E8%AE%8A%E6%9B%B4%E6%96%B9%E6%A1%88):由消費者核准新方案。 - [要求變更付款方式](https://docs.tokenz.one/zh-TW/v2/subscriptions/modification#%E8%A6%81%E6%B1%82%E8%AE%8A%E6%9B%B4%E4%BB%98%E6%AC%BE%E6%96%B9%E5%BC%8F):由消費者提供新卡片。 **金額格式:** 金額(例如 `amount` 欄位)以各貨幣的最小輔助單位表示。請參閱[支援的貨幣](https://docs.tokenz.one/zh-TW/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-TW/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-TW/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-TW/v2/subscriptions/modification#%E5%88%97%E5%87%BA%E8%A8%82%E9%96%B1)相同:將 `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 產生後才會出現。請將顧客重新導向至完整網址,包括帶有 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-TW/v2/subscriptions/webhooks)。