從 Google Play 帳款服務程式庫第 4 或第 5 版改用第 6 版

本主題說明如何從 Google Play 帳款服務程式庫第 4 或 5 版改用第 6 版,以及如何使用新的訂閱功能。

如需第 6.0.0 版的完整異動清單,請參閱「版本資訊」。

總覽

Google Play 帳款服務程式庫第 6 版是以第 5 版的新訂閱功能為基礎,並加入更多改善項目。這些功能可讓您不必建立及管理逐漸增加的 SKU 數量,進而擴充販售訂閱項目的方式,並降低作業成本。

如要進一步瞭解 Play 帳款服務程式庫第 5 版中的新功能,請參閱「Play 管理中心訂閱項目的近期異動」。

回溯相容的 Play 帳款服務程式庫升級

在 2022 年 5 月發布的 Play 帳款服務程式庫第 5 版和新的訂閱平台中,所有現有的訂閱產品都會自動轉換為這個新範例。也就是說,您無須變更訂閱產品設定,即可擁有與新版 Play 帳款服務程式庫相容的目錄。如要進一步瞭解如何將訂閱 SKU 轉換為可回溯相容的訂閱項目,請參閱 Play 管理中心說明文章的「使用較舊的訂閱項目」一節。

舊版應用程式仍可正常運作

如果您的訂閱產品目錄可回溯相容,則所有現有的應用程式版本應該都可搭配這些產品正常運作。一次性產品購買交易應該也能繼續在舊版中正常運作。

如果應用程式版本使用已淘汰的方法 (例如 querySkuDetailsAsync()),將無法販售不回溯相容的基本方案或優惠。如要瞭解回溯相容的優惠,請參閱 Play 管理中心說明中心文章

升級至 Play 帳款服務程式庫第 5 或第 6 版

Play 帳款服務程式庫第 5 和第 6 版包含已淘汰的方法 querySkuDetailsAsyncBillingFlowParams.Builder.setSkuDetails,這些方法的結帳流程參數為 SkuDetails。也就是說,您可以規劃不同的遷移階段,逐步改用 Play 帳款服務程式庫第 6 版。

如要遷移,請先更新程式庫版本,但不必變更目錄和後端,然後在應用程式仍使用已淘汰方法時測試。如果不是使用 queryPurchaseslaunchPriceChangeFlowsetVrPurchaseFlow,則應仍可正常運作。之後,您可以逐步採用 2022 年 5 月推出的新訂閱功能

如果您已透過 Google Play 帳款服務程式庫第 5 版的遷移作業採用這些功能,則可以直接跳至「更新 Google Play 帳款服務程式庫」和「變更使用者的訂閱購買交易」等章節。如要從更舊的版本開始遷移,或尚未完全採用新功能,請參閱「完整遷移步驟」,瞭解如何採用這些功能。

完整遷移步驟

在後端產品目錄中建立新訂閱項目

您現在可以使用 Play 管理中心或 Play Developer API,設定含有多項基本方案的單一訂閱項目,而且每個方案都能提供多種優惠。訂閱優惠具有靈活彈性的計費模式和資格條件選項。您可以使用各種自動續訂和預付方案,在訂閱項目的生命週期間建立優惠。

建議您在遷移應用程式前,依照新訂閱平台中的實體結構建立新產品,以便處理 Play 帳款服務程式庫第 6 版的整合作業。您可以在單一訂閱方案下,為具有相同訂閱權限的舊目錄整合重複的產品,並使用基本方案和優惠設定來代表您要提供的所有選項。如要進一步瞭解這項建議,請參閱 Play 管理中心說明文章的「使用舊版訂閱項目」一節。

建議您不要在 2022 年 5 月的版本後修改已轉換的訂閱產品。您應保留這些產品,因為這些產品會在販售時使用已淘汰的方法 (例如 querySkuDetailsAsync()),卻未導入可能影響這些舊版本的變更項目。

轉換程序會將您目錄中 2022 年 5 月前的訂閱產品設為唯讀狀態,以免意外變更導致現有整合作業發生問題。雖然您可以變更這些訂閱項目,但可能會影響前端和後端整合功能:

  • 在前端,如果應用程式版本是使用 querySkuDetailsAsync() 取得訂閱產品詳細資料,就只能販售可回溯相容的基本方案和優惠,而且只可以有一個回溯相容的基本方案和優惠組合。因此,如果在已轉換的訂閱產品中新增方案或優惠,將無法在舊版應用程式上販售這些新增的基本方案或優惠。

  • 在後端,如果您在 Play 管理中心使用者介面中編輯您轉換的訂閱項目,您無法使用 inappproducts 端點管理它們 (如果您為此呼叫端點)。如要管理這些訂閱購買交易,您也應改用新的訂閱購買交易狀態端點 (purchases.subscriptionsv2.get),因為舊有的購買交易狀態端點 (purchases.subscriptions.get) 只會傳回必要的資料,用於處理回溯相容性基本方案和優惠購買交易。詳情請參閱「管理訂閱購買狀態」一節。

使用新 API 管理後端訂閱目錄

如果您使用 Google Play Developer API 自動管理訂閱產品目錄,就需要使用新的訂閱產品定義端點,建立及管理訂閱項目、基本方案和優惠。如要進一步瞭解此版本的產品目錄 API 異動,請參閱 2022 年 5 月訂閱功能指南

如要遷移 Google Play 帳款服務訂閱的自動產品目錄管理模組,請將 inappproducts API 換成新的 Subscription Publishing API,以管理和發布您的訂閱目錄。有三個新端點:

這些新端點具備所有必要的功能,以運用您目錄中的所有新功能:基本方案和優惠標記、指定區域、預付方案等。

您仍應使用 inappproducts API 管理一次性消費產品的應用程式內產品目錄。

如果應用程式版本使用已淘汰的方法 (例如 querySkuDetailsAsync()),將無法販售不回溯相容的基本方案或優惠。回溯相容優惠的相關資訊請參閱此處

更新 Google Play 帳款服務程式庫

建立新的訂閱產品目錄後,您可以將應用程式遷移至 Google 帳款服務程式庫第 5 版。將現有的 Play 帳款服務程式庫依附元件改為更新版應用程式的 build.gradle 檔案。

dependencies {
    def billingVersion = "6.0.0"

    implementation "com.android.billingclient:billing:$billingVersion"
}

即使您尚未修改任何方法的呼叫,系統也應該會立即建構您的專案,因為 Play 帳款服務程式庫第 6 版可回溯相容。我們認為 SKU 的概念已不適用,但仍會繼續使用,以便提供更簡單漸進的應用程式遷移程序。

初始化帳款服務用戶端並與 Google Play 建立連線

從 Android 應用程式啟動購買流程的第一步如下:

顯示可供購買的產品

如何取得使用者有資格購買的所有優惠:

  • QueryProductDetailsParams 取代 SkuDetailsParams
  • 切換 BillingClient.querySkuDetailsAsync() 呼叫,以使用 BillingClient.queryProductDetailsAsync()

請注意,查詢結果現在是 ProductDetails,而不是 SkuDetails。各個 ProductDetails 項目都含有產品相關資訊 (ID、名稱、類型等等)。如果是訂閱產品,ProductDetails 則包含 List<ProductDetails.SubscriptionOfferDetails>,這是訂閱項目優惠詳細資料的清單。針對一次性購買產品,ProductDetails 包含 ProductDetails.OneTimePurchaseOfferDetails。這些屬性可用來決定要向使用者顯示哪些優惠。

您可以參考以下範例,比較應用程式變更前與變更後的差異:

變更前

Kotlin

val skuList = ArrayList<String>()

skuList.add("up_basic_sub")

val params = SkuDetailsParams.newBuilder()

params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS).build()

billingClient.querySkuDetailsAsync(params) {
    billingResult,
    skuDetailsList ->
    // Process the result
}

Java

List<String> skuList = new ArrayList<>();

skuList.add("up_basic_sub");

SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();

params.setSkusList(skuList).setType(SkuType.SUBS).build();

billingClient.querySkuDetailsAsync(params,
    new SkuDetailsResponseListener() {
        @Override
        public void onSkuDetailsResponse(BillingResult billingResult,
                List<SkuDetails> skuDetailsList) {
            // Process the result.
        }
    }
);

變更後

Kotlin

val productList =
    listOf(
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId("up_basic_sub")
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    )

val params = QueryProductDetailsParams.newBuilder().setProductList(productList).build()

billingClient.queryProductDetailsAsync(params) {
    billingResult,
    productDetailsList ->
    // Process the result
}

Java

ImmutableList<Product> productList = ImmutableList.of(Product.newBuilder()
                                            .setProductId("up_basic_sub")
                                            .setProductType(ProductType.SUBS)
                                            .build());

QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
    .setProductList(productList)
    .build();

billingClient.queryProductDetailsAsync(
        params,
        new ProductDetailsResponseListener() {
                public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) {
                    // Process the result
                }
        }
);

queryProductDetailsAsync 的回呼會回傳 List<ProductDetails>。各個 ProductDetails 項目都含有產品相關資訊 (ID、名稱、類型等等)。主要差異在於訂閱項目產品現在包含 List<ProductDetails.SubscriptionOfferDetails>,其中包含使用者可用的所有優惠。

由於舊版 Play 帳款服務程式庫不支援新的物件,例如訂閱項目、基礎方案、優惠等等,因此新系統會將各個訂閱 SKU 轉換成單個可回溯相容的基本方案和優惠。可用的一次性購買產品也會轉移至 ProductDetails 物件。一次性購買產品的優惠詳細資料可透過 getOneTimePurchaseOfferDetails() 方法存取。

在極少數情況下,某些裝置無法支援 ProductDetailsqueryProductDetailsAsync(),這通常是因為 Google Play 服務版本過舊。為確保能對此情境妥善支援,請在呼叫 queryProductDetailsAsync 前先呼叫 PRODUCT_DETAILS 功能的 isFeatureSupported()。如果回應是 OK,代表裝置支援這項功能,因此您可以繼續呼叫 queryProductDetailsAsync()。如果回應是 FEATURE_NOT_SUPPORTED,您可以改用 querySkuDetailsAsync(),要求可用的回溯相容性產品清單。如要進一步瞭解如何使用回溯相容性功能,請參閱 2022 年 5 月訂閱功能指南

啟動優惠購買流程

啟動優惠的購買流程與啟動 SKU 流程非常類似。如要使用第 6 版提出購買要求,請按照下列步驟操作:

  • BillingFlowParams 使用 ProductDetailsParams 而非 SkuDetails
  • 如優惠 ID、基本方案 ID 等優惠詳細資料可以使用 SubscriptionOfferDetails 物件取得。

如要購買使用者所選優惠的產品,請取得所選優惠的 offerToken 並將其傳送到 ProductDetailsParams 物件。

建立 BillingFlowParams 物件後,使用 BillingClient 啟動計費流程將維持不變。

您可以參考以下範例,比較應用程式變更前與變更後的差異:

變更前

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
val billingFlowParams = BillingFlowParams.newBuilder()
                            .setSkuDetails(skuDetails)
                            .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// An activity reference from which the billing flow will be launched.
Activity activity = ...;
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

變更後

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)
        // For One-time product, "setOfferToken" method shouldn't be called.
        // For subscriptions, to get the offer token corresponding to the selected
        // offer call productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken
        .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 = ...;

ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // For one-time products, "setOfferToken" method shouldn't be called.
            // For subscriptions, to get the offer token corresponding to the selected
            // offer call productDetails.getSubscriptionOfferDetails().get(selectedOfferIndex).getOfferToken()
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

處理購買交易

使用 Google Play 帳款服務程式庫第 6 版處理交易的方式與先前版本類似。

如要提取使用者擁有的所有有效購買交易,並查詢新購買,請執行下列操作:

  • 請改為傳送包含 BillingClient.ProductType 值的 QueryPurchasesParams 物件,而不是將 BillingClient.SkuType 值傳送至 queryPurchasesAsync()

您可以參考以下範例,比較應用程式在變更前後的差異:

變更前

Kotlin

billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) {
    billingResult,
    purchaseList -> {
        // Process the result
    }
}

Java


billingClient.queryPurchasesAsync(
    BillingClient.SkuType.SUBS,
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // process the result
        }
    }
);

變更後

Kotlin

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
        .setProductType(BillingClient.ProductType.SUBS)
        .build()
) { billingResult, purchaseList ->
    // Process the result
}

Java

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder().setProductType(ProductType.SUBS).build(),
    new PurchasesResponseListener() {
        public void onQueryPurchasesResponse(
                BillingResult billingResult,
                List<Purchase> purchases) {
            // Process the result
        }
    }
);

管理應用程式外購交易未完成交易的步驟並未變更。

在後端使用新 API 管理訂閱項目購買狀態

您應該在後端遷移訂閱項目購買狀態管理元件,才能處理先前步驟中所建立新產品的購買交易。對於 2022 年 5 月推出前定義的已轉換訂閱產品,您目前的訂閱購買狀態管理元件應仍然照常運作,且應足以管理回溯相容的優惠,但不支援任何新功能。

您必須為訂閱購買狀態管理模組實作新的 Subscription Purchases API,以檢查購買狀態並在後端管理 Play 帳款服務訂閱授權。舊版 API 不會傳回管理新平台中的購買項目所需的所有詳細資料。如要詳細瞭解先前版本所做的變更,請參閱 2022 年 5 月全新訂閱功能指南

每次收到 SubscriptionNotification 即時開發人員通知 時一般會呼叫 Subscription Purchases API,以提取訂閱狀態的最新資訊。您必須將 purchases.subscriptions.get 的呼叫換成新版 Subscription Purchases API (purchases.subscriptionsv2.get)。有一個名為 SubscriptionPurchaseV2 的新資源可提供足管理新模型中訂閱購買授權的足夠資訊。

這個新端點會傳回所有訂閱產品和購買交易的狀態,不論販售產品的應用程式版本和定義產品的時間 (2022 年 5 月版本前後) 為何,都會照常傳回狀態。因此在遷移後,您只需要這個版本的訂閱購買交易狀態管理模組。

變更使用者的訂閱購買交易

在 Play 帳款服務程式庫 5 以下版本中,ProrationMode 是用來對使用者的訂閱購買交易套用變更,例如升級或降級。這個項目已淘汰,並在第 6 版中替換為 ReplacementMode

處理訂閱價格異動

先前淘汰的 launchPriceConfirmationFlow API 已從 Play 帳款服務程式庫第 6 版中移除。如需替代方案,請參閱價格異動指南

處理 Play 帳款服務程式庫錯誤

Play 帳款服務程式庫第 6 版新增了 NETWORK_ERROR 代碼,可指出使用者裝置與 Google Play 系統之間的網路連線問題。此外,代碼 SERVICE_TIMEOUTSERVICE_UNAVAILABLE 也有所變更。詳情請參閱「處理 BillingResult 回應代碼」。

處理未完成的交易

從第 6.0.0 版開始,Play 帳款服務程式庫不會為未完成的購買交易建立訂單 ID,必須等到購買交易移至 PURCHASED 狀態後,系統才會為這類購買交易填入訂單 ID。請確保您的整合功能只預期在交易完成後取得訂單 ID。您仍然可以將購買憑證用於記錄。如要進一步瞭解如何處理未完成的購買交易,請參閱 Play 帳款服務程式庫整合指南購買交易生命週期管理指南