Unity 應用程式內購買
命名空間:UnityEngine.Purchasing | 安全性:UnityEngine.Purchasing.Security
套件:com.unity.purchasing
Unity IAP 擁有自己的初始化路徑:透過 UnityIAPServices.StoreController() → store.Connect()。它不需要 UnityServices.InitializeAsync(),但如果您的專案使用了其他 UGS 服務,兩者可以共存。如果存在 Analytics 且已呼叫 InitializeAsync(),IAP 將自動傳送交易事件。
開始之前
請務必先閱讀 references/pre-check.md。 它會掃描專案中是否有第三方 IAP 套件、原生 Google Billing 及現有 Unity IAP 版本,然後路由到正確的路徑。在路由解決之前,請勿閱讀任何其他參考檔案或進行任何變更。
詳細參考資料
- 專案掃描與路徑路由 (請先閱讀): 請參閱 references/pre-check.md
- API 簽章與程式碼範例: 請參閱 references/api-notes.md
- 平台擴充功能 (Apple、Google): 請參閱 references/platform-notes.md
- 編輯
IAPProductCatalog.json(結構描述、十進位序列化、重新整理): 請參閱 references/codeless-catalog.md - v4 到 v5 遷移: 請參閱 references/migration-v4-to-v5.md
- 將原生 Google BillingClient 轉換為 Unity IAP 5: 請參閱 references/path-convert-native-google-billing.md
- 將原生 iOS StoreKit 外掛程式轉換為 Unity IAP 5: 請參閱 references/path-convert-native-storekit.md
- 將 Essential Kit 計費轉換為 Unity IAP 5: 請參閱 references/convert-essentialkit.md
- UniPay (FLOBUK) — 評估與指引: 請參閱 references/convert-unipay.md
- RevenueCat — 轉換評估與指引: 請參閱 references/convert-revenuecat.md
- Adapty — 轉換評估與指引: 請參閱 references/convert-adapty.md
- 將 Unity IAP 5 新增至沒有任何現有 IAP 的專案: 請參閱 references/path-add-iap-to-new-project.md
- 實作 IAP D2C 功能 (第三方支付提供商 — Stripe/Coda,需要 v5.4+): 請參閱 references/path-implement-iap-d2c.md
請在需要特定 API 簽章、平台擴充功能詳細資訊或遷移對應時,才按需求閱讀參考檔案。
初始化流程
- 透過
UnityIAPServices.StoreController()取得StoreController(或透過DefaultStore()、DefaultProduct()、DefaultPurchase()取得個別服務) - 在呼叫
Connect()之前訂閱 所有必要事件 (請參閱下方的必要事件訂閱) await store.Connect()以連線至平台商店- 在
OnStoreConnected觸發時,呼叫store.FetchProducts(List<ProductDefinition>)以載入目錄 - 在
OnProductsFetched觸發時,商品即可顯示與購買
在 Awake() 中進行初始化 — 確保 IAP 在其他 Start() 方法之前準備就緒。
商品類型:ProductType.Consumable、ProductType.NonConsumable、ProductType.Subscription。
擷取商品
將商品定義為 List<ProductDefinition> 並傳遞給 store.FetchProducts()。當 Apple/Google 商店的商品 ID 不同時,請使用 StoreSpecificIds。對於複雜的目錄,請使用 CatalogProvider 管理商品集與商店特定 ID。
| 方法 | 行為 |
|---|---|
GetProducts() | 傳回 快取 的商品清單 (同步,如果未呼叫 FetchProducts 則可能過期) |
FetchProducts() | 向商店查詢最新的定價/可用性並更新快取 |
GetProductById(id) | 依 ID 傳回單個快取的商品 |
這些方法不可互換。在依賴 GetProducts() 之前,請務必先呼叫 FetchProducts()。
兩步驟購買流程
IAP v5 使用強制性的兩步驟流程:待確認 → 確認。
store.PurchaseProduct(product)— 啟動平台購買對話方塊OnPurchasePending觸發 — 您會收到一個PendingOrder- 驗證收據,將內容授予玩家
store.ConfirmPurchase(pendingOrder)— 完成交易OnPurchaseConfirmed觸發 — 接收Order基底類型;透過模式比對ConfirmedOrder(成功) 與FailedOrder(確認失敗)
在授予內容後,您必須呼叫 ConfirmPurchase(pendingOrder)。 未確認的購買將在下次應用程式啟動時重新傳遞,以防止購買遺失。
重複資料刪除: OnPurchasePending 可能會針對同一筆購買多次觸發 (例如在確認前重新啟動應用程式)。請務必檢查內容是否已授予。
消耗品: 已確認的消耗品購買不會被 FetchPurchases 傳回。請自行追蹤消耗品的授予 (例如在 Cloud Save 或 Economy 中)。
延遲購買: OnPurchaseDeferred 會針對 Ask-to-Buy (iOS) 和 Google Play 延遲購買觸發。請勿授予內容 — 請等待核准後觸發的 OnPurchasePending。
還原交易
store.RestoreTransactions(callback) 會重新傳遞非消耗品與訂閱購買。每次還原的購買都會觸發 OnPurchasePending。
iOS 上需要遵守 Apple App Store 規範 — 請新增一個「還原購買」按鈕。
Apple 的非續訂訂閱無法透過 RestoreTransactions 還原。請在伺服器端追蹤這些訂閱。
收據驗證
| 平台 | 方法 |
|---|---|
| Google Play | 使用 CrossPlatformValidator 搭配 GooglePlayTangle.Data() — 支援本地驗證 |
| Apple (StoreKit 2) | 本地驗證是無效操作。請使用 order.Info.Apple?.jwsRepresentation 進行伺服器端驗證 |
在 Unity 編輯器中透過 Services > In-App Purchasing > Receipt Validation Obfuscator 產生纏結資料。
資格檢查
當您沒有 Order 但想知道特定商品狀態時使用 (取代 v4 的 product.hasReceipt)。如果您已經有 Order,請改為檢查其類型:PendingOrder 對應於 EntitledUntilConsumed (消耗品) 或 EntitledButNotFinished (非消耗品/訂閱),ConfirmedOrder 對應於 FullyEntitled。
呼叫 store.CheckEntitlement(product) 並處理 store.OnCheckEntitlement。檢查 entitlement.Status == EntitlementStatus.FullyEntitled。
EntitlementStatus 的值:FullyEntitled、EntitledUntilConsumed、EntitledButNotFinished、NotEntitled、Unknown。
擷取現有購買
store.FetchPurchases() 從商店擷取所有目前的購買。在應用程式啟動時很有用。
| 方法 | 行為 |
|---|---|
GetPurchases() | 傳回快取的購買清單 |
FetchPurchases() | 向商店查詢目前的購買並覆寫快取的清單 |
每次呼叫 FetchPurchases() 都會取代整個快取的清單。只有非消耗品與訂閱會傳回。