products.ts
產品、方案、價格顯示和購買後授予的存取權限。
config/products.ts 匯出一個 Record<string, ProductConfig> 物件。第一層 Key 是產品 ID,每個產品的 plans 再以方案 ID 作為 Key。產品 ID 和方案 ID 都可以自行定義,saavo_starter、license、startup_monthly 等名稱只是範本示例。
必須替換 Price ID
預設範本中的六個 priceId 都以 _replace_me 結尾,只是占位值。啟用 Checkout 前,必須替換成目前 Stripe 帳號中實際存在的 Price ID。介面顯示的 salePrice 不參與扣款,實際金額和計費週期以 Stripe Price 為準。
產品 Key
產品 Key 必須是非空字串,可以依專案需求新增、刪除或修改。設定中既有的產品 Key 會組成 ProductId 聯集型別,沒有產品時可以匯出空物件。
產品物件
Prop
Type
plans
plans 儲存這個產品的方案,型別為 Record<string, PlanConfig>。方案 Key 必須是非空字串,不同產品可以使用不同的 Key。設定中既有的方案 Key 會組成 PlanIdOf<P> 和 PlanId 聯集型別。
方案物件
Prop
Type
訂閱方案欄位
type 為 recurring 時,還必須填寫下列欄位:
Prop
Type
features
方案賣點陣列,型別為 LocalizedText[]。介面依陣列中的順序顯示,不需要展示方案賣點時可以省略。
presentation
購買頁面的顯示設定,只影響公開產品頁面和購買頁面中的文案,不會改變價格、購買狀態或存取權限。
Prop
Type
purchaseFacts 是 LocalizedText[],用於填寫購買須知。specifications 是規格陣列,每個項目包含 label: LocalizedText、value: LocalizedText 和選用的 tone: "default" | "positive"。highlights 是特色卡片陣列,每個項目包含 icon、title 和 description,icon 可以填入 documentation、access、source 或 payment。
填寫 presentation 時,purchaseFacts、specifications 和 highlights 都必須填寫,陣列可以為空。
couponOffers
透過 /offer/:id 連結啟用的動態優惠活動陣列。填寫後至少要有一個項目。
Prop
Type
優惠活動也可以覆寫 features 和 presentation,格式與方案欄位相同。優惠活動不能修改 priceId、計費週期、購買狀態或存取權限,也不能巢狀包含其他優惠活動。
access
購買成功後授予的角色和權益。單次購買方案可以省略,訂閱方案則必須填寫,而且 roles 和 entitlements 中至少要有一個非空陣列。
roles
角色陣列。陣列項目可以直接填入角色 Key,也可以填入含有授予參數的物件。
Prop
Type
config 可以填入 priority: number、description: string、metadata: Record<string, unknown>,以及 effective.startsAt、effective.endsAt 兩個 Unix 毫秒時間戳記。
entitlements
權益陣列。單次購買方案可以直接填入權益 Key,也可以填入物件,訂閱方案則必須使用物件寫法。
Prop
Type
訂閱方案的權益物件必須填寫 config。
Prop
Type
kind 為 numeric 時,還可以填寫下列欄位:
Prop
Type
reset 用於設定額度重設週期。alignment: "calendar" 支援日、週、月、年,alignment: "fixed" 只支援日和週,count 必須是正整數。quotaUsedStrategy 可以填入 clear、drain、keep,也可以使用 { mode: "override", quotaUsed: number } 指定已用額度。
範本預設設定
範本預設設定只包含一個產品。表中的產品 ID 和方案 ID 都是示例,可以依業務需求替換。重新命名或清空產品前,必須同步處理頁面、購買流程、聯盟行銷、升級建議等引用,不能只修改這份設定,就認為功能仍然完整。
| 產品 ID | name.value | name.key | 方案數量 |
|---|---|---|---|
saavo_starter | Sample SaaS subscription | components.billing.product.name | 6 |
description.value 為 Example monthly and yearly plans to replace with your product terms.,文案 Key 為 components.billing.product.description。
方案
| 方案 ID | 標題 | 週期 | salePrice | priceId | 標記 |
|---|---|---|---|---|---|
license | Hobby | 每月 | $19 | price_hobby_monthly_replace_me | default: true |
hobby_yearly | Hobby | 每年 | $190 | price_hobby_yearly_replace_me | — |
startup_monthly | Startup | 每月 | $49 | price_startup_monthly_replace_me | recommended: true |
startup_yearly | Startup | 每年 | $490 | price_startup_yearly_replace_me | recommended: true |
enterprise_monthly | Enterprise | 每月 | $149 | price_enterprise_monthly_replace_me | — |
enterprise_yearly | Enterprise | 每年 | $1,490 | price_enterprise_yearly_replace_me | — |
六個方案的 type 都是 recurring,intervalCount 都是 1,allowRepurchase 都是 false。三個年繳方案也填寫了「兩個月免費」的 valueHint。
存取權限
| 方案 | 角色 Key | 權益 Key | 權益型別 | 優先順序 |
|---|---|---|---|---|
license、hobby_yearly | premium | starter_download | boolean | 100 |
startup_monthly、startup_yearly | premium | starter_download | boolean | 200 |
enterprise_monthly、enterprise_yearly | premium | starter_download | boolean | 300 |
premium 和 starter_download 也只是範本預設設定中的示例 Key,分別來自 roles.ts 和 entitlements.ts。修改這些定義時,需要同步更新本檔案中的引用。