提醒:自 2023 年 8 月 2 日起,所有新應用程式都必須採用帳款服務程式庫 5.0 以上版本 自 2023 年 11 月 1 日起,現有應用程式的所有更新都必須採用帳款服務程式庫 5.0 以上版本。瞭解詳情

Google Play 帳款服務程式庫遷移指南 (從第 4 版升級到第 5 版)

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

總覽

Google Play 帳款服務程式庫第 5 版推出了「訂閱方案和訂閱優惠」,這些功能可消除建立和管理逐漸新增 SKU 數量的需求,進而擴大您販售訂閱項目的方式,並減少作業成本。詳情請參閱 Play 管理中心最近的訂閱異動

在 2022 年 5 月發布的 Play 帳款服務程式庫第 5 版和新的訂閱平台中,所有現有的訂閱產品都會自動轉換為這個新範例。如要進一步瞭解此轉換作業,請參閱 Play 管理中心說明文章的「使用較舊的訂閱項目」一節。

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

不過,如果不打算立即採用這些新功能,只要產品目錄保持回溯相容的設定,您仍可先將應用程式遷移至 Play 帳款服務程式庫第 5 版,之後再規劃後端元件遷移事宜。

遷移步驟

建立後端產品目錄

建議您在遷移應用程式前,依照新訂閱平台中的實體結構建立新產品,以便處理 Play 帳款服務程式庫第 5 版的整合作業。您可以在單一訂閱方案下,具有相同訂閱權限的舊目錄中整合重複的產品,並使用基本方案和優惠設定代表您要提供的所有選項。如要進一步瞭解這項建議,請參閱 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 = "5.0.0"

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

即使您尚未修改任何方法的呼叫,系統也應該會立即建構您的專案,因為我們在 Play 帳款服務程式庫第 5 版中建立了回溯相容性的功能,但 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)

billingClient.querySkuDetailsAsync(params.build()) {
    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);

billingClient.querySkuDetailsAsync(params.build(),
    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)

billingClient.queryProductDetailsAsync(params.build()) {
    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() 要求可用的回溯相容性產品資訊。如要進一步瞭解如何使用 Play 帳款服務程式庫第 5 版的回溯相容性功能,請參閱 2022 年 5 月 訂閱功能指南

啟動優惠購買流程

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

  • 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 = ...;
// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken

val productDetailsParamsList =
    listOf(
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .setOfferToken(offerToken)
            .build()
    )
val billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .build()

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

Java

// Retrieve a value for "productDetails" by calling queryProductDetailsAsync()
// Get the offerToken of the selected offer
String offerToken = productDetails
                     .getSubscriptionOfferDetails()
                     .get(selectedOfferIndex)
                     .getOfferToken();
// Set the parameters for the offer that will be presented
// in the billing flow creating separate productDetailsParamsList variable
ImmutableList<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
                 ProductDetailsParams.newBuilder()
                     .setProductDetails(productDetails)
                     .setOfferToken(offerToken)
                     .build()
        );

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

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

正在處理購買交易

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

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

  • 請改為傳送包含 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 月版本前後),因此在遷移後,您僅需要這個版本的訂閱購買狀態管理模組。