Lưu ý: Kể từ ngày 2 tháng 8 năm 2022, tất cả các ứng dụng mới phải sử dụng Thư viện Billing phiên bản 4 trở lên. Chậm nhất vào ngày 1 tháng 11 năm 2022, tất cả các bản cập nhật cho ứng dụng hiện có đều phải sử dụng Thư viện Billing phiên bản 4 trở lên. Tìm hiểu thêm.

Hướng dẫn di chuyển Thư viện Google Play Billing 4 sang 5

Chủ đề này mô tả cách di chuyển từ Thư viện Google Play Billing 4 sang Thư viện Google Play Billing 5 và cách sử dụng các tính năng thuê bao mới.

Tổng quan

Thư viện Google Play Billing phiên bản 5 đã giới thiệu các thuê bao cơ bản và thuê bao ưu đãi. Các tính năng này mở rộng cách thức bạn có thể bán gói thuê bao và giảm độ phức tạp của quá trình tích hợp so với các phiên bản trước.

Bằng cách sử dụng API Play Developer Console hoặc API Nhà phát triển Play, bạn có thể thiết lập một gói thuê bao với nhiều gói cơ bản, mỗi gói có nhiều ưu đãi. Các gói ưu đãi có mô hình định giá và cách thiết lập tính đủ điều kiện một cách linh hoạt. Bạn có thể tạo chương trình ưu đãi trong suốt thời gian đăng ký bằng cách sử dụng nhiều gói tự động gia hạn và trả trước. Để biết thêm thông tin, hãy xem hướng dẫn tích hợp.

Các bước di chuyển

Cập nhật Thư viện Google Play Billing

Thay thế phần phụ thuộc Thư viện Play Billing hiện có bằng phiên bản cập nhật cho tệp build.gradle của ứng dụng.

dependencies {
    def billingVersion = "5.0.0"

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

Dự án của bạn sẽ được tạo ngay lập tức, ngay cả khi bạn chưa sửa đổi bất kỳ lệnh gọi nào đối với các phương thức, vì chúng tôi đã xây dựng khả năng tương thích ngược trên Thư viện Play Billing 5. Tuy nhiên, khái niệm SKU đã không còn được dùng nữa.

Khởi tạo Ứng dụng thanh toán và thiết lập kết nối với Google Play

Các bước đầu tiên để tạo giao dịch mua từ một ứng dụng Android không thay đổi:

Hiển thị những sản phẩm có thể mua

Cách nhận tất cả ưu đãi người dùng đủ điều kiện để mua:

  • Thay thế SkuDetailsParams bằng QueryProductDetailsParams.
  • Chuyển lệnh gọi BillingClient.querySkuDetailsAsync() để sử dụng BillingClient.queryProductDetailsAsync()

Lưu ý kết quả truy vấn giờ đây sẽ là ProductDetails thay vì SkuDetails. Mỗi mặt hàng ProductDetails chứa thông tin về sản phẩm (mã nhận dạng, tiêu đề, loại, v.v.). Đối với các sản phẩm thuê bao, ProductDetails chứa List<ProductDetails.SubscriptionOfferDetails>, là danh sách thông tin chi tiết về ưu đãi cho thuê bao. Đối với các sản phẩm mua một lần, ProductDetails chứa ProductDetails.OneTimePurchaseOfferDetails. Bạn có thể dùng thông tin này để quyết định ưu đãi nào sẽ hiển thị cho người dùng.

Ví dụ sau cho thấy ứng dụng của bạn trông như thế nào trước và sau khi thực hiện những thay đổi này:

Trước

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.
        }
    }
);

Sau

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
                }
        }
);

Lệnh gọi lại cho queryProductDetailsAsync trả về List<ProductDetails>. Mỗi mặt hàng ProductDetails chứa thông tin về sản phẩm (mã nhận dạng, tiêu đề, loại, v.v.). Điểm khác biệt chính là các sản phẩm thuê bao hiện cũng chứa List<ProductDetails.SubscriptionOfferDetails> chứa tất cả các ưu đãi người dùng có thể sử dụng.

Vì các phiên bản trước của Thư viện Play Billing không hỗ trợ các đối tượng mới (gói thuê bao, gói cơ bản, ưu đãi, v.v.), nên hệ thống mới sẽ chuyển đổi từng SKU thuê bao thành một gói cơ bản có khả năng tương thích ngược và ưu đãi. Các sản phẩm mua một lần cũng được chuyển đến đối tượng ProductDetails. Bạn có thể truy cập thông tin chi tiết về ưu đãi của một sản phẩm mua một lần bằng phương thức getOneTimePurchaseOfferDetails().

Ra mắt quy trình mua ưu đãi

Việc bắt đầu một quy trình mua hàng cho một ưu đãi rất giống với việc ra mắt một quy trình cho SKU. Để bắt đầu một yêu cầu mua hàng bằng phiên bản 5, hãy làm như sau:

  • Thay vì dùng SkuDetails cho BillingFlowParams, hãy dùng ProductDetailsParams.
  • Bạn có thể lấy thông tin chi tiết về(các) ưu đãi này bằng cách sử dụng đối tượng SubscriptionOfferDetails.

Để mua sản phẩm bằng ưu đãi đã chọn của người dùng, hãy lấy offerToken của ưu đãi đã chọn và chuyển ưu đãi đó vào đối tượng ProductDetailsParams.

Sau khi bạn tạo đối tượng BillingFlowParams, việc chạy luồng thanh toán với BillingClient vẫn giữ nguyên.

Ví dụ sau cho bạn thấy ứng dụng sẽ trông như thế nào trước và sau khi thực hiện các thay đổi này:

Trước

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)

Sau

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);

Xử lý các giao dịch mua

Việc xử lý các giao dịch mua bằng Thư viện Google Play Billing 5 vẫn tương tự như các phiên bản trước.

Để lấy tất cả các giao dịch mua đang hoạt động thuộc sở hữu của người dùng và truy vấn các giao dịch mua mới, hãy làm như sau:

  • Thay vì chuyển giá trị BillingClient.SkuType đến queryPurchasesAsync(), hãy chuyển đối tượng QueryPurchasesParams chứa giá trị BillingClient.ProductType.

Ví dụ sau cho bạn thấy ứng dụng sẽ trông như thế nào trước và sau khi thực hiện các thay đổi này:

Trước

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&lt;Purchase> purchases) {
            // process the result
        }
    }
);

Sau

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
        }
    }
);

Các bước để quản lý giao dịch mua ngoài ứng dụnggiao dịch đang chờ xử lý không thay đổi.

Quản lý trạng thái của gói thuê bao

Nếu bạn có một thành phần quản lý trạng thái gói thuê bao trong phần phụ trợ để kiểm tra trạng thái và quản lý các giao dịch mua gói thuê bao, bạn sẽ cần sử dụng API mua gói thuê bao. Để biết thông tin chi tiết về những thay đổi so với các phiên bản trước, hãy xem hướng dẫn cho các tính năng thuê bao mới trong tháng 5 năm 2022.