本主題說明了如何將 Google Play 帳款服務程式庫整合至您的應用程式,以便開始販售產品。
本主題提供的程式碼範例是以 GitHub 上的官方範例應用程式為基礎。如需整合時可使用的範例應用程式和其他資源的完整清單,請參閱「其他資源」。
購買流程
以下是一次性消費或訂閱項目的一般購買流程。
- 向使用者說明可以購買的內容。
- 啟動購買流程,以便使用者接受購買。
- 在伺服器上驗證購買交易。
- 將內容提供給使用者。
- 確認提交內容。如果是消費性產品,請先消耗購買項目,讓使用者可以再次購買該商品。
訂閱會自動續約,直到取消為止。訂閱可呈現下列狀態:
- 有效:使用者記錄良好,有權存取訂閱。
- 已取消:使用者已取消訂閱,但在到期前仍擁有存取權。
- 寬限期:使用者遇到付款問題,但仍擁有存取權,同時 Google 正在重試付款方式以扣除款項。
- 保留中:使用者因遇到付款問題而不再擁有存取權,同時 Google 正在重試以該付款方式扣除款項。
- 已暫停:使用者已暫停存取權,取消暫停後才可繼續存取。
- 已到期:使用者已取消訂閱並失去存取權。 訂閱到期後,系統會將使用者視為「已流失」。
啟動與 Google Play 的連線
如要整合 Google Play 的帳單系統,首先請將 Google Play 帳款服務程式庫新增至應用程式並啟動連線。
新增 Google Play 帳款服務程式庫依附元件
將 Google Play 帳款服務程式庫依附元件新增至應用程式的 build.gradle
檔案,如下所示:
Groovy
dependencies { def billing_version = "6.0.1" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "6.0.1" implementation("com.android.billingclient:billing:$billing_version") }
如果您使用的是 Kotlin,Google Play 帳款服務程式庫 KTX 模組會包含 Kotlin 擴充功能和協同程式支援,可讓您在使用 Google Play 帳款服務程式庫時編寫慣用的 Kotlin 程式碼。如要在專案中加入這些擴充功能,請將下列依附元件新增至應用程式的 build.gradle
檔案,如下所示:
Groovy
dependencies { def billing_version = "6.0.1" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "6.0.1" implementation("com.android.billingclient:billing-ktx:$billing_version") }
初始化 BillingClient
在 Google Play 帳款服務程式庫中加入依附元件後,您必須初始化 BillingClient
執行個體。BillingClient
是 Google Play 帳款服務程式庫與您其他應用程式之間通訊的主要介面。BillingClient
提供同步和非同步的便利方法,適用於許多常見的結帳作業。強烈建議您一次啟用一組 BillingClient
連線,以免單一事件發生多次 PurchasesUpdatedListener
回呼。
如要建立 BillingClient
,請使用 newBuilder()
。
您可以將任何結構定義傳遞至 newBuilder()
,BillingClient
就可透過該程式碼取得應用程式結構定義。因此,您不必擔心記憶體流失的問題。如要接收購買交易的最新動態,您也必須呼叫 setListener()
,並將參照傳遞至 PurchasesUpdatedListener
。
這個事件監聽器會收到應用程式內所有購買交易的最新動態。
Kotlin
private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases -> // To be implemented in a later section. } private var billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) .enablePendingPurchases() .build()
Java
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() { @Override public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { // To be implemented in a later section. } }; private BillingClient billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) .enablePendingPurchases() .build();
連線至 Google Play
建立 BillingClient
後,您需要與 Google Play 建立連線。
如要連線至 Google Play,請呼叫 startConnection()
。
連線程序為非同步,在用戶端完成設定並準備好提出進一步要求後,您必須實作 BillingClientStateListener
才能收到回呼。
您還必須執行重試邏輯,處理與 Google Play 連線中斷的問題。如要執行重試邏輯,請覆寫 onBillingServiceDisconnected()
回呼方法,並確認 BillingClient
會呼叫 startConnection()
方法重新以重新連線 Google Play,然後再提出其他請求。
以下範例說明了如何發起連線,並測試是否可供使用:
Kotlin
billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } override fun onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } })
Java
billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } @Override public void onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } });
顯示可供購買的產品
與 Google Play 建立連線後,您就可以開始查詢適用的產品,並向使用者顯示。
向使用者顯示產品之前,查詢產品詳細資料是非常重要的步驟,因為這會傳回本地化的產品資訊。如果是訂閱項目,請確認您的產品顯示「遵守所有 Play 政策」字樣。
如要查詢應用程式內產品的詳細資料,請呼叫 queryProductDetailsAsync()
。
如要處理非同步作業的結果,您必須一併指定實作 ProductDetailsResponseListener
介面的事件監聽器。接著,您可以覆寫 onProductDetailsResponse()
,這會在查詢完成時通知事件監聽器,如以下範例所示:
Kotlin
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build() billingClient.queryProductDetailsAsync(queryProductDetailsParams) { billingResult, productDetailsList -> // check billingResult // process returned productDetailsList } )
Java
QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) { // check billingResult // process returned productDetailsList } } )
查詢產品詳細資料時,請傳遞 QueryProductDetailsParams
例項,此例項可指定在 Google Play 管理中心內建立的產品 ID 字串清單以及 ProductType
。ProductType
可以是一次性產品的 ProductType.INAPP
,也可以是訂閱項目的 ProductType.SUBS
。
使用 Kotlin 擴充功能進行查詢
如果您使用 Kotlin 擴充功能,則可以透過呼叫 queryProductDetails()
擴充功能函式,查詢應用程式內產品的詳細資料。
queryProductDetails()
會利用 Kotlin 協同程式,因此您無需定義單獨的事件監聽器。相對的,函式會先暫停直到查詢完成為止,之後您可以處理結果:
suspend fun processPurchases() {
val productList = ArrayList<String>()
productList.add(
QueryProductDetailsParams.Product.newBuilder()
.setProductId("product_id_example")
.setProductType(BillingClient.ProductType.SUBS)
.build()
)
val params = QueryProductDetailsParams.newBuilder()
params.setProductList(productList)
// leverage queryProductDetails Kotlin extension function
val productDetailsResult = withContext(Dispatchers.IO) {
billingClient.queryProductDetails(params.build())
}
// Process the result.
}
在極少數的情況下,某些裝置無法支援 ProductDetails
和 queryProductDetailsAsync()
,這通常是因為 Google Play 服務版本過舊。為確保能對此情境妥善支援,請參閱「Play 帳款服務程式庫 5 遷移指南」,瞭解如何使用回溯相容性功能。
處理結果
Google Play 帳款服務程式庫會將查詢結果儲存在 ProductDetails
物件的 List
中。接著,您可以在清單中的每個 ProductDetails
物件上呼叫各種方法,以便查看應用程式內產品的相關資訊,例如價格或說明。如要查看可用產品的詳細資訊,請參閱 ProductDetails
類別中的方法清單。
在提供待售項目之前,請先檢查使用者是否尚未擁有該項目。如果使用者的商品庫中仍有消耗性產品,他們必須先消耗該商品才能再次購買。
提供訂閱項目前,請先確認使用者尚未訂閱。此外,也請注意下列事項:
queryProductDetailsAsync()
會傳回訂閱產品詳細資料,每個訂閱項目最多 50 項優惠。queryProductDetailsAsync()
只會傳回使用者有資格享有的優惠。如果使用者嘗試購買無資格享有的優惠方案 (例如應用程式顯示過舊的優惠清單),Play 會將不符資格的消息告知使用者,讓他們可以選擇改為購買基本方案。
啟動購買流程
如要透過應用程式提出購買請求,請從應用程式的主要執行緒呼叫 launchBillingFlow()
方法。這個方法會參照 BillingFlowParams
物件,該物件包含透過呼叫 queryProductDetailsAsync()
取得的相關 ProductDetails
物件。
如要建立 BillingFlowParams
物件,請用 BillingFlowParams.Builder
類別。
Kotlin
// An activity reference from which the billing flow will be launched. val activity : Activity = ...; val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // to get an offer token, call ProductDetails.subscriptionOfferDetails() // for a list of offers that are available to the user .setOfferToken(selectedOfferToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build() // Launch the billing flow val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Java
// An activity reference from which the billing flow will be launched. Activity activity = ...; ImmutableListproductDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // to get an offer token, call ProductDetails.getSubscriptionOfferDetails() // for a list of offers that are available to the user .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
launchBillingFlow()
方法會傳回 BillingClient.BillingResponseCode
中列出的其中一個回應代碼。請務必查看這項結果,確認啟動時購買流程沒有發生錯誤。OK
的 BillingResponseCode
表示啟動成功。
成功呼叫 launchBillingFlow()
時,系統會顯示 Google Play 購買畫面。圖 1 顯示了訂閱項目的購買畫面:

Google Play 會呼叫 onPurchasesUpdated()
,將購物作業的結果提供給實作 PurchasesUpdatedListener
介面的事件監聽器。在初始化用戶端時,請使用 setListener()
方法指定事件監聽器。
您必須執行 onPurchasesUpdated()
來處理可能的回應代碼。
以下範例說明了如何覆寫 onPurchasesUpdated()
:
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { handlePurchase(purchase) } } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
Java
@Override void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
購買成功後,系統會產生與圖 2 類似的 Google Play 購買成功畫面。

購物成功後還會產生購買憑證,這是一個不重複 ID,代表已購買應用程式內產品的使用者和產品 ID。應用程式可在使用者的裝置上儲存購買憑證。不過,建議您將該憑證傳遞至安全的後端伺服器,以便驗證購買交易並防範詐欺行為。下一節會說明這項程序。
使用者也會收到隨附交易收據的電子郵件,收據內含該筆交易的訂單 ID 或專屬 ID。使用者每次購買一次性產品、購買初始訂閱項目和後續的定期自動續訂時,都會收到內含專屬訂單 ID 的電子郵件。您可以在 Google Play 管理中心使用這組訂單 ID 管理退款。
顯示個人化的價格
如果您的應用程式可以發布給歐盟使用者,請使用 setIsOfferPersonalized()
方法向使用者揭露商品價格是以自動化決策功能進行個人化。

您必須查閱《消費者權益指令》(2011/83/EU) 6 (1) (ea) CRD 條款,確定您為使用者提供的價格是否經過個人化處理。
setIsOfferPersonalized()
接受布林輸入。如果為 true
,Play UI 會包含揭露事項。如果為 false
,UI 會省略揭露事項。預設值為 false
。
詳情請參閱消費者說明中心。
處理購買交易
使用者完成購買後,您的應用程式就需要處理該筆購買交易。在大多數情況下,系統會透過 PurchasesUpdatedListener
傳送購買通知給應用程式。但在某些情況下,您的應用程式會藉由呼叫 BillingClient.queryPurchasesAsync()
得知購買交易,如「擷取購買交易」所述。
此外,如果您在安全後端設有即時開發人員通知用戶端,可以接收 subscriptionNotification
或 oneTimeProductNotification
(僅適用於未完成的購買交易) 來註冊新交易。這兩者都會在有新的購買交易時通知您。收到這類通知後,請呼叫 Google Play Developer API,藉此取得完整狀態並更新您自己的後端狀態。
您的應用程式應以下列方式處理購買交易:
- 驗證購買交易。
- 將內容提供給使用者,並確認內容的交付程序。 視需要將項目標示為「已消耗」,以便使用者再次購買。
如要驗證購買交易,請先確認「購買狀態」是否為 PURCHASED
,
如果購買狀態為 PENDING
,請按照處理未完成交易的說明處理購買程序。對於從 onPurchasesUpdated()
或 queryPurchasesAsync()
收到的購買交易,在應用程式授權之前,您應進一步驗證購買交易以確保合法性。如要瞭解如何正確驗證購買交易,請參閱「在授權前驗證購買交易」。
驗證購買交易後,您的應用程式就可以開始將權限授予使用者。如要確認與購買交易相關聯的使用者帳戶,您可以使用 Purchases.products:get
傳回的 ProductPurchase.obfuscatedExternalAccountId
(用於應用程式內產品的購買交易) 和 Purchases.subscriptions:get
傳回的 SubscriptionPurchase.obfuscatedExternalAccountId
(適用於伺服器端的訂閱項目),或是 Purchase.getAccountIdentifiers()
從用戶端傳回的 obfuscatedAccountId
(如果在交易時以 setObfuscatedAccountId
設定即可這麼做)。
授權後,您的應用程式就必須確認購買交易。這項確認作業會通知 Google Play 您已授予購買交易的權限。
授權和確認購買交易的程序會因該交易的購買項目 (非消耗性產品、消耗性產品或訂閱項目) 而有所不同。
消耗性產品
針對消耗性產品,如果您的應用程式具有安全的後端,建議您透過 Purchases.products:consume
確實消耗購買交易。請確保購買交易須未經消耗,方法是根據呼叫 Purchases.products:get
的結果檢查 consumptionState
。如果您的應用程式只有用戶端而沒有後端,請使用 Google Play 帳款服務程式庫的 consumeAsync()
。這兩種方法都符合確認要求,且會表明您的應用程式已將權限授予使用者。這類方法也能讓應用程式提供與輸入購買憑證相對應的一次性產品,以供使用者再次購買。如果使用 consumeAsync()
,您也必須傳遞實作 consumeAsync()
ConsumeResponseListener
介面的物件,這個物件會處理消耗作業的結果。您可以覆寫 onConsumeResponse()
方法,等到作業完成後,Google Play 帳款服務程式庫就會呼叫此方法。
以下範例示範如何使用相關聯的購買憑證,透過 Google Play 帳款服務程式庫消耗產品:
Kotlin
suspend fun handlePurchase(purchase: Purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. val purchase : Purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() val consumeResult = withContext(Dispatchers.IO) { client.consumePurchase(consumeParams) } }
Java
void handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. Purchase purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); ConsumeResponseListener listener = new ConsumeResponseListener() { @Override public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Handle the success of the consume operation. } } }; billingClient.consumeAsync(consumeParams, listener); }
非消耗性產品
如果您想確認非消耗性產品的購買交易,而應用程式具有安全的後端,建議您使用 Purchases.products:acknowledge
切實地確認購買交易。請根據呼叫 Purchases.products:get
的結果檢查 acknowledgementState
,確認購買交易先前未經確認。
如果您的應用程式只有用戶端,請使用 Google Play 帳款服務程式庫的 BillingClient.acknowledgePurchase()
。在確認購買交易之前,您應檢查應用程式是否已透過 Google Play 帳款服務程式庫的 isAcknowledged()
方法進行確認。
以下範例說明了如何透過 Google Play 帳款服務程式庫確認購買交易:
Kotlin
val client: BillingClient = ... val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ... suspend fun handlePurchase() { if (purchase.purchaseState === PurchaseState.PURCHASED) { if (!purchase.isAcknowledged) { val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) val ackPurchaseResult = withContext(Dispatchers.IO) { client.acknowledgePurchase(acknowledgePurchaseParams.build()) } } } }
Java
BillingClient client = ... AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ... void handlePurchase(Purchase purchase) { if (purchase.getPurchaseState() == PurchaseState.PURCHASED) { if (!purchase.isAcknowledged()) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
訂閱項目
處理訂閱項目的方式與非消耗產品類似。如果可以的話,請使用 Google Play Developer API 中的 Purchases.subscriptions.acknowledge
,切實地透過安全後端確認購買交易。請驗證購買交易尚未經過確認,方法是從 Purchases.subscriptions:get
檢查購買資源中的 acknowledgementState
。不然,您也可以在檢查 isAcknowledged()
後,使用 Google Play 帳款服務程式庫的 BillingClient.acknowledgePurchase()
確認訂閱。所有初始訂閱項目的購買交易都必須獲得確認,訂閱項目的續訂則無需確認。如要進一步瞭解確認訂閱項目的時機,請參閱「販售訂閱項目」主題。
擷取購買交易
使用 PurchasesUpdatedListener
監聽購買狀態更新不足以確保應用程式可以順利處理所有購買交易。您的應用程式可能並不瞭解使用者進行的所有購買交易。在以下情況中,您的應用程式可能會無法掌握或無法得知購買狀態:
- 購物期間的網路問題:使用者成功完成購買交易且收到 Google 的確認通知,但使用者的裝置在透過
PurchasesUpdatedListener
收到購買通知前失去網路連線。 - 多部裝置:使用者在某部裝置上購買商品,並且希望切換裝置後也能查看該商品。
- 處理應用程式外的購買交易:某些購買交易可在應用程式外完成,例如促銷兌換。
如要處理這類情況,請務必讓應用程式使用 onResume()
方法呼叫 BillingClient.queryPurchasesAsync()
,以確保所有購買交易的處理程序都按照這篇文章的說明順利完成。
以下範例說明如何擷取使用者的訂閱交易。請注意,queryPurchasesAsync()
只會傳回有效的訂閱項目,以及非消耗的一次性消費。
Kotlin
val params = QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) // uses queryPurchasesAsync Kotlin extension function val purchasesResult = billingClient.queryPurchasesAsync(params.build()) // check purchasesResult.billingResult // process returned purchasesResult.purchasesList, e.g. display the plans user owns
Java
billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) .build(), new PurchasesResponseListener() { public void onQueryPurchasesResponse(BillingResult billingResult, Listpurchases) { // check billingResult // process returned purchase list, e.g. display the plans user owns } } );
擷取購買記錄
queryPurchaseHistoryAsync()
會傳回使用者針對各個產品最近一次的購買交易,即使購買交易已過期、取消或消耗。
如果您使用 Kotlin 擴充功能,可以採用 queryPurchaseHistory()
擴充功能函式。
Kotlin
val params = QueryPurchaseHistoryParams.newBuilder() .setProductType(ProductType.SUBS) // uses queryPurchaseHistory Kotlin extension function val purchaseHistoryResult = billingClient.queryPurchaseHistory(params.build()) // check purchaseHistoryResult.billingResult // process returned purchaseHistoryResult.purchaseHistoryRecordList, e.g. display purchase
Java
billingClient.queryPurchaseHistoryAsync( QueryPurchaseHistoryParams.newBuilder() .setProductType(ProductType.SUBS) .build(), new PurchaseHistoryResponseListener() { public void onPurchaseHistoryResponse( BillingResult billingResult, ListpurchasesHistoryList) { // check billingResult // process returned purchase history list, e.g. display purchase history } } );
處理應用程式外的購買交易
某些購買交易 (例如促銷兌換) 可能會在應用程式外進行。使用者在應用程式外購物時,會希望應用程式顯示應用程式內通訊訊息,或透過某種通知機制讓他們瞭解應用程式已正確接收並處理購買交易。可接受的機制如下:
- 顯示應用程式內彈出式視窗。
- 將訊息傳送至應用程式內通訊訊息方塊,並清楚說明應用程式內通訊訊息方塊中有新訊息。
- 使用作業系統通知訊息。
請注意,即使您的應用程式辨識出購買交易,應用程式仍可能處於任何狀態,使用者甚至可能在購買後仍未安裝您的應用程式。無論應用程式處於何種狀態,使用者都希望重新啟用應用程式時收到購買項目。
在購買發生時,無論應用程式處於何種狀態,您都必須偵測出購買交易。然而,在某些例外情況下,我們可能不會立即通知使用者已收到項目。例如:
- 在遊戲需要大量操作的部分中,顯示訊息可能會分散使用者的注意力。在此情況下,您必須在操作結束後通知使用者。
- 在剪輯過程中,顯示訊息可能會分散使用者的注意力。在此情況下,您必須在剪輯結束後通知使用者。
- 遊戲的初始教學課程和使用者設定期間。建議您在使用者開啟遊戲後或初次進行使用者設定期間,立即向新使用者發出獎勵通知。不過,也可以等到主要遊戲序列可通知使用者為止。
如果您正在決定要於何時 (及如何) 向使用者發出應用程式外購物通知,請一律將使用者納入考量。如果使用者沒有立即收到通知,他們可能會感到困惑,而且可能會因此停止使用您的應用程式、聯絡使用者支援團隊,或在社群媒體上投訴。注意:PurchasesUpdatedListener
已註冊您的應用程式結構定義,以便處理購買交易更新資訊,包含在應用程式外發起的購買交易。也就是說,如果應用程式程序不存在,PurchasesUpdatedListener
就不會收到通知。因此,應用程式應呼叫 onResume()
方法中的 BillingClient.queryPurchasesAsync()
,如「擷取購買交易」一節中所述。
處理未完成的交易
Google Play 支援「未完成的交易」,這類交易程序從使用者發起購買交易開始,到系統處理購買交易付款方式的這段期間,需要完成其他一或多個步驟。除非 Google 通知您已透過使用者的付款方式成功扣款,否則應用程式不應向這類購買交易授權。
舉例來說,使用者可以選擇使用現金付款,建立狀態為 PENDING
的應用程式內產品購買交易。使用者可以選擇在實體商店完成交易,並透過通知和電子郵件接收代碼。當使用者來到實體商店時,就可以向收銀員兌換代碼,再用現金付款。接著,Google 會通知您和使用者已收到現金,您的應用程式就可以向使用者授權。
應用程式必須在初始化的過程中呼叫 enablePendingPurchases()
,以便支援未完成的交易。
無論應用程式是透過 PurchasesUpdatedListener
還是由於呼叫 queryPurchasesAsync()
而收到新的購買交易,都請使用 getPurchaseState()
方法來判斷購買狀態是 PURCHASED
還是 PENDING
。
如果使用者完成購買時您的應用程式正在運作,系統會再次呼叫 PurchasesUpdatedListener
,而 PurchaseState
現已變為 PURCHASED
。這時,應用程式可按照一次性消費的標準處理方法處理購買交易。應用程式還應呼叫應用程式 onResume()
方法中的 queryPurchasesAsync()
,處理已於應用程式未運作時轉換為 PURCHASED
狀態的購買交易。
應用程式也可以監聽 OneTimeProductNotifications
,將「即時開發人員通知」用於未完成購買交易。當購買交易從 PENDING
變為 PURCHASED
時,應用程式會收到 ONE_TIME_PRODUCT_PURCHASED
通知。如果購買交易被取消,應用程式會收到 ONE_TIME_PRODUCT_CANCELED
通知,如果客戶在指定的時間範圍內未完成付款,就可能發生這種情況。
收到這類通知時,您可以使用 Google Play Developer API,其中包含 Purchases.products
的 PENDING
狀態。
如需測試此情境的詳細步驟,請參閱「測試未完成的購買交易」。
處理多件購買交易
在 Google Play 帳款服務程式庫 4.0 以上版本中,Google Play 允許客戶在購物車中指定購買數量,藉此在同一筆交易中購買多件相同的應用程式內產品。應用程式應處理多件購買交易,並按照指定的購買數量授予權限。
為了滿足多件購買交易的需求,應用程式的佈建邏輯需要檢查項目數量。您可以透過下列任一 API 存取「quantity
」欄位:
- Google Play 帳款服務程式庫的
getQuantity()
。 - Google Play Developer API 的
Purchases.products.quantity
。
新增了處理多項購買交易的邏輯後,您需要在 Google Play 管理中心的應用程式內產品管理頁面中,為對應的產品啟用多項交易的功能。