開發者指南React Hooks
useSubscribe
發起訂閱結帳、管理付款狀態的 React Hook
useSubscribe
useSubscribe 是發起結帳的主要 Hook,封裝了 useRecur().checkout() 並提供自動狀態管理。
需要在 RecurProvider 內使用。
基本用法
import { useSubscribe } from 'recur-tw';
function SubscribeButton() {
const { subscribe, isLoading, error } = useSubscribe({
onPaymentComplete: (subscription) => {
console.log('付款成功!', subscription.id);
window.location.href = '/welcome';
},
});
return (
<div>
<button
onClick={() => subscribe({
productId: 'prod_xxx',
customerEmail: 'user@example.com',
})}
disabled={isLoading}
>
{isLoading ? '處理中...' : '立即訂閱'}
</button>
{error && <p className="text-red-500">{error.message}</p>}
</div>
);
}Options(初始化參數)
傳入 useSubscribe() 的 callback 設定:
| 參數 | 類型 | 說明 |
|---|---|---|
onSuccess | (result) => void | Checkout session 建立成功(卡片表單已準備好) |
onPaymentComplete | (subscription) => void | 付款完成、訂閱已啟用 |
onError | (error) => void | 發生錯誤 |
onPaymentFailed | (error) => PaymentFailedAction | void | 付款失敗(卡號錯誤等),可回傳自訂行為 |
onPaymentCancel | () => void | 用戶取消付款 |
subscribe() 參數
呼叫 subscribe() 時傳入的結帳選項:
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
productId | string | 是* | 產品 ID |
productSlug | string | 是* | 或用產品 slug(二擇一) |
customerEmail | string | 是 | 顧客 email |
customerName | string | 否 | 顧客名稱 |
externalCustomerId | string | 否 | 您系統中的客戶 ID |
promoCode | string | 否 | 優惠碼(搭配 usePromoCode 使用) |
trialDays | number | 否 | 覆蓋預設試用天數 |
quantity | number | 否 | 數量(預設 1) |
metadata | object | 否 | 自訂資料(最多 10 key) |
collectPaymentMethod | string | 否 | 'always' 或 'if_required' |
Return 值
| 屬性 | 類型 | 說明 |
|---|---|---|
subscribe | (options) => Promise<void> | 發起結帳 |
mutate | (options) => Promise<void> | subscribe 的別名 |
isLoading | boolean | 結帳流程進行中 |
error | CheckoutError | null | 錯誤物件 |
reset | () => void | 清除錯誤狀態 |
useSubscribe vs useRecur
useSubscribe | useRecur | |
|---|---|---|
| 狀態管理 | 內建(isLoading, error, reset) | 需自己管理 |
| Callbacks | 透過 options 設定 | 在 checkout() 內設定 |
| 推薦場景 | 大多數情境 | 需要完整控制流程時 |
搭配優惠碼
import { useSubscribe, usePromoCode } from 'recur-tw';
function Checkout({ userId, userEmail }) {
const promo = usePromoCode({ customerId: userId });
const { subscribe, isLoading } = useSubscribe();
return (
<div>
<input onBlur={(e) => promo.apply(e.target.value)} />
<button onClick={() => subscribe({
productId: 'prod_xxx',
customerEmail: userEmail,
promoCode: promo.code, // null = 不帶優惠碼
})}>
訂閱
</button>
</div>
);
}錯誤處理
const { subscribe, error, reset } = useSubscribe({
onError: (err) => {
if (err.code === 'DUPLICATE_SUBSCRIPTION') {
alert('您已經訂閱了此方案');
}
},
onPaymentFailed: (err) => {
// 自訂付款失敗行為
if (err.details?.failureCode === 'INSUFFICIENT_FUNDS') {
return { action: 'show_message', message: '餘額不足,請更換付款方式' };
}
// 回傳 undefined 使用預設處理
},
});詳細的錯誤碼說明請參考 錯誤處理指南。
Last updated on