Tích hợp Thư viện Google Play Billing vào ứng dụng | Hệ thống thanh toán của Google Play | Android Developers

Kể từ ngày 2/8/2023, toàn bộ những ứng dụng mới phải sử dụng Thư viện Billing phiên bản 5 trở lên. Chậm nhất vào ngày 1/11/2023, tổng thể những bản update cho ứng dụng hiện có đều phải sử dụng Thư viện Billing phiên bản 5 trở lên. Tìm hiểu thêmLưu ý:Trước khi đọc chủ đề này, hãy bảo vệ bạn đã đọc kỹ Tài liệu trong Trung tâm trợ giúp của Play Console miêu tả những khái niệm quan trọng tương quan đến việc mua hàng, cũng như cách tạo và thiết lập loại sản phẩm mà bạn bán. Ngoài ra, hãy nhớ thiết lập trước thông số kỹ thuật Google Play bằng cách làm theo những bước trong bài viết Chuẩn bị
Chủ đề này diễn đạt cách tích hợp Thư viện Google Play Billing vào ứng dụng để khởi đầu bán loại sản phẩm .

Chủ đề này bao gồm các mã ví dụ dựa trên ứng dụng mẫu
chính thức trên GitHub. Bạn có thể xem
các tài nguyên khác
để biết danh sách đầy đủ ứng dụng mẫu và tài nguyên khác mà bạn có thể sử dụng
trong khi tích hợp.

Vòng đời của một giao dịch mua hàng

Dưới đây là tiến trình mua nổi bật cho thanh toán giao dịch mua hàng một lần hoặc một gói thuê bao .

  1. Hiển thị cho người dùng những sản phẩm mà họ có thể mua.
  2. Khởi chạy quy trình mua để người dùng chấp nhận giao dịch mua hàng.
  3. Xác minh giao dịch mua hàng trên máy chủ.
  4. Cung cấp nội dung cho người dùng.
  5. Xác nhận việc phân phối nội dung. Đối với các sản phẩm tiêu dùng, hãy tiến hành
    giao dịch mua để người dùng có thể mua lại mặt hàng đó.

Các gói thuê bao sẽ tự động hóa gia hạn cho đến khi bị hủy. Gói thuê bao hoàn toàn có thể trải qua những trạng thái sau :

  • Đang hoạt động: Người dùng hiện ở trạng thái tốt và có quyền truy cập vào gói thuê bao.
  • Đã huỷ: Người dùng đã huỷ nhưng vẫn có quyền truy cập vào gói thuê bao cho đến khi hết hạn.
  • Trong thời gian gia hạn: Người dùng gặp phải vấn đề thanh toán nhưng vẫn có quyền truy cập trong khi Google đang thử lại phương thức thanh toán.
  • Tạm ngưng: Người dùng gặp phải vấn đề thanh toán và không còn quyền truy cập trong khi Google đang thử lại phương thức thanh toán.
  • Bị tạm dừng: Người dùng đã tạm dừng quyền truy cập và không có quyền truy cập cho đến khi họ tiếp tục.
  • Đã hết hạn: Người dùng đã huỷ và mất quyền truy cập vào gói thuê bao.
    Người dùng được coi là rời bỏ ứng dụng khi gói thuê bao hết hạn.

Khởi tạo kết nối với Google Play

Bước tiên phong để tích hợp với mạng lưới hệ thống giao dịch thanh toán của Google Play là thêm Thư viện Google Play Billing vào ứng dụng của bạn và khởi đầu liên kết .

Thêm phần phụ thuộc Thư viện Google Play Billing

Lưu ý:Nếu đã làm theo hướng dẫn Giai đoạn chuẩn bị sẵn sàng thì bạn đã thêm những phần phụ thuộc thiết yếu và hoàn toàn có thể chuyển sang phần tiếp theo .

Thêm phần phụ thuộc Thư viện Google Play Billing vào tệp build.gradle
của ứng dụng như dưới đây:

Groovy

dependencies {
    def billing_version = "6.0.0"

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

Kotlin

dependencies {
    val billing_version = "6.0.0"

    implementation("com.android.billingclient:billing:$billing_version")
}

Nếu bạn đang sử dụng Kotlin, mô-đun KTX của Thư viện Google Play Billing chứa các tiện ích và coroutine của Kotlin, cho phép bạn viết mã
Kotlin tương thích khi sử dụng Thư viện Google Play Billing. Để đưa
các tiện ích này vào dự án, hãy thêm phần phụ thuộc sau vào
tệp build.gradle của ứng dụng như dưới đây:

Groovy

dependencies {
    def billing_version = "6.0.0"

    implementation "com.android.billingclient:billing-ktx:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "6.0.0"

    implementation("com.android.billingclient:billing-ktx:$billing_version")
}

Khởi chạy BillingClient

Sau khi thêm một phần phụ thuộc vào Thư viện Google Play Billing, bạn cần
khởi chạy một bản sao của BillingClient. BillingClient là giao diện chính để giao tiếp giữa
Thư viện Google Play Billing và các phần còn lại của ứng dụng. BillingClient
cung cấp các phương thức thuận tiện (cả đồng bộ và không đồng bộ) cho
nhiều hoạt động thanh toán phổ biến. Chúng tôi đặc biệt khuyến nghị bạn chỉ nên có một
kết nối BillingClient
hiện hoạt tại một thời điểm để tránh tạo ra nhiều lệnh gọi lại PurchasesUpdatedListener cho một sự kiện duy nhất.

Để tạo BillingClient, hãy sử dụng
newBuilder().
Bạn có thể chuyển bất kỳ ngữ cảnh nào đến hàm newBuilder(), đồng thời BillingClient sử dụng hàm này để
nhận ngữ cảnh của ứng dụng. Điều đó có nghĩa là bạn không cần lo lắng về việc rò rỉ bộ nhớ. Để nhận thông tin cập nhật về giao dịch mua, bạn cũng phải gọi hàm
setListener() bằng cách truyền tham chiếu đến một
PurchasesUpdatedListener.
Trình nghe này nhận nội dung cập nhật cho tất cả giao dịch mua trong ứng dụng.

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 purchases) {
        // To be implemented in a later section.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .build();

Lưu ý:BillingResult chứa BillingResult còn chứa

Thư viện Google Play Billing sẽ trả về lỗi dưới dạng BillingResult chứa BillingResponseCode, giúp phân loại các lỗi liên quan đến việc thanh toán mà ứng dụng của bạn có thể gặp phải. Ví dụ: nếu bạn nhận được mã lỗi SERVICE_DISCONNECTED, ứng dụng phải khởi động lại kết nối với Google Play. Ngoài ra,còn chứa thông báo gỡ lỗi. Đây là một thông báo hữu ích trong quá trình phát triển để chẩn đoán lỗi.

Kết nối với Google Play

Sau khi đã tạo một BillingClient, bạn cần thiết lập kết nối với Google Play.

Để kết nối với Google Play, hãy gọi hàm
startConnection().
Quá trình kết nối không đồng bộ, và bạn phải triển khai
BillingClientStateListener
để nhận một lệnh gọi lại sau khi ứng dụng được thiết lập và sẵn sàng
tạo thêm yêu cầu.

Bạn cũng phải triển khai logic thử lại để xử lý việc mất kết nối với
Google Play. Để triển khai logic thử lại, hãy ghi đè phương pháp gọi lại
onBillingServiceDisconnected() và đảm bảo rằng BillingClient gọi phương thức
startConnection()
để kết nối lại với Google Play trước khi tạo yêu cầu tiếp theo.

Ví dụ sau đây minh họa cách khởi đầu một liên kết và kiểm tra xem liên kết đã chuẩn bị sẵn sàng để sử dụng chưa :

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

Lưu ý:BillingClient khi
thực thi bất kỳ phương thức nào.

Bạn nên triển khai logic kết nối lại của riêng mình và ghi đè phương thức onBillingServiceDisconnected(). Hãy đảm bảo bạn duy trì kết nốikhi thực thi bất kỳ phương thức nào.

Hiển thị các sản phẩm có sẵn để mua

Sau khi thiết lập liên kết với Google Play, bạn hoàn toàn có thể truy vấn những mẫu sản phẩm mà mình hiện có và cho người dùng thấy những mẫu sản phẩm đó .
Truy vấn thông tin cụ thể về loại sản phẩm là một bước quan trọng trước khi hiển thị mẫu sản phẩm cho người dùng vì việc truy vấn này sẽ trả về thông tin loại sản phẩm đã bản địa hóa. Đối với gói thuê bao, hãy bảo vệ loại sản phẩm hiển thị tuân thủ toàn bộ chủ trương của Play .

Để truy vấn thông tin chi tiết về sản phẩm trong ứng dụng, hãy gọi
queryProductDetailsAsync().

Để xử lý kết quả của hoạt động không đồng bộ, bạn cũng phải chỉ định một trình nghe có chức năng triển khai giao diện ProductDetailsResponseListener. Sau đó, bạn có thể ghi đè
onProductDetailsResponse() để thông báo cho trình nghe khi truy vấn kết thúc, như minh hoạ trong ví dụ sau:

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 productDetailsList) {
            // check billingResult
            // process returned productDetailsList
        }
    }
)

Khi truy vấn thông tin chi tiết về sản phẩm, hãy chuyển một bản sao của QueryProductDetailsParams để chỉ định danh sách các chuỗi mã sản phẩm được tạo trong Google Play Console cùng với ProductType. ProductType có thể là ProductType.INAPP đối với các sản phẩm tính phí một lần hoặc ProductType.SUBS đối với các gói thuê bao.

Truy vấn bằng tiện ích Kotlin

Nếu đang sử dụng phần mở rộng Kotlin, bạn có thể truy vấn thông tin chi tiết về sản phẩm trong ứng dụng bằng cách gọi hàm mở rộng queryProductDetails().

queryProductDetails() tận dụng coroutine của Kotlin để bạn không cần xác định một trình nghe riêng biệt. Thay vào đó, hàm này sẽ tạm ngưng cho đến khi truy vấn hoàn tất, sau đó bạn có thể xử lý kết quả:

suspend fun processPurchases() {
    val productList = ArrayList()
    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.
}

Trong một số ít trường hợp, một số thiết bị không hỗ trợ ProductDetailsqueryProductDetailsAsync(), thường là do các phiên bản Dịch vụ Google Play đã lỗi thời. Để đảm bảo nhận được sự hỗ trợ phù hợp cho trường hợp này, hãy tìm hiểu cách sử dụng tính năng tương thích ngược trong hướng dẫn di chuyển Thư viện Play Billing 5.

Xử lý kết quả

Thư viện Google Play Billing lưu trữ các kết quả truy vấn trong một List các đối tượng ProductDetails. Sau đó, bạn có thể gọi nhiều phương thức cho mỗi đối tượng ProductDetails trong danh sách để xem thông tin liên quan về một sản phẩm trong ứng dụng, chẳng hạn như giá hoặc phần mô tả. Để xem thông tin chi tiết về sản phẩm có sẵn, hãy xem danh sách các phương thức trong lớp ProductDetails.

Trước khi chào bán một mẫu sản phẩm, hãy kiểm tra để bảo vệ rằng người dùng chưa chiếm hữu loại sản phẩm đó. Nếu người dùng có một loại sản phẩm tiêu dùng vẫn còn trong thư viện mẫu sản phẩm, thì họ phải tiêu thụ trước khi hoàn toàn có thể mua lại mẫu sản phẩm đó .
Trước khi đưa ra khuyễn mãi thêm một gói thuê bao, hãy xác định rằng người dùng chưa ĐK. Ngoài ra, hãy quan tâm những điều sau :

  • queryProductDetailsAsync() trả về thông tin chi tiết của sản phẩm đăng ký và tối đa 50 ưu đãi cho mỗi gói thuê bao.
  • queryProductDetailsAsync() chỉ trả về những ưu đãi người dùng đủ điều kiện. Nếu người dùng cố gắng mua một ưu đãi mà họ không đủ điều kiện (ví dụ: nếu ứng dụng đang đưa ra danh sách ưu đãi đủ điều kiện nhưng đã hết hạn), thì Play sẽ thông báo cho người dùng việc họ không đủ điều kiện, và họ có thể chuyển sang mua gói cơ bản.

Lưu ý:

Một số thiết bị Android có thể có phiên bản ứng dụng cũ của Cửa hàng Google Play và không hỗ trợ một số loại sản phẩm, chẳng hạn như các gói thuê bao. Trước khi ứng dụng bước vào quy trình thanh toán, bạn có thể gọi hàm isFeatureSupported() để xác định xem thiết bị có hỗ trợ các sản phẩm bạn muốn bán hay không. Để biết danh sách các loại sản phẩm có thể được hỗ trợ, hãy xem BillingClient.FeatureType

Bắt đầu quy trình mua

Để bắt đầu yêu cầu mua hàng từ ứng dụng của bạn, hãy gọi phương thức
launchBillingFlow()
từ luồng chính của ứng dụng. Phương thức này tham chiếu đến đối tượng BillingFlowParams chứa đối tượng ProductDetails liên quan đã nhận được từ việc gọi queryProductDetailsAsync().
Để tạo một đối tượng BillingFlowParams, hãy dùng lớp 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 = ...;

ImmutableList productDetailsParamsList =
    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);

Phương thức launchBillingFlow() trả về một trong nhiều mã phản hồi
được liệt kê trong
BillingClient.BillingResponseCode.
Hãy kiểm tra kết quả này để đảm bảo không có lỗi khi khởi chạy
quy trình mua. BillingResponseCode OK cho biết đã khởi chạy thành công.

Khi bạn gọi hàm launchBillingFlow() thành công, hệ thống sẽ hiển thị màn hình mua hàng trên Google Play. Hình 1 hiển thị màn hình mua cho một
gói thuê bao:

màn hình mua hàng trên Google Play cho thấy gói thuê bao
            có thể mua
Hình 1. Màn hình mua hàng trên Google Play hiển thị một
gói thuê bao mà bạn có thể mua.

Google Play gọi hàm onPurchasesUpdated() để cung cấp kết quả
của thao tác mua hàng cho một trình nghe có nhiệm vụ triển khai giao diện
PurchasesUpdatedListener. Trình nghe này được chỉ định bằng phương thức
setListener() khi bạn khởi chạy ứng dụng của mình.

Bạn phải thực thi onPurchasesUpdated() để xử lý các mã phản hồi khả thi.
Ví dụ sau đây trình bày cách ghi đè onPurchasesUpdated():

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List?) {
   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 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.
    }
}

Giao dịch mua thành công xuất sắc sẽ tạo ra một màn hình hiển thị mua hàng thành công xuất sắc trên Google Play, tựa như như hình 2 .
màn hình giao dịch mua thành công trên google play
Hình 2. Màn hình giao dịch mua thành công của
Google Play.

Một lượt mua hàng thành công xuất sắc cũng tạo ra một mã mua hàng. Mã này là giá trị nhận dạng duy nhất, đại diện thay mặt cho người dùng và mã mẫu sản phẩm của mẫu sản phẩm trong ứng dụng mà họ đã mua. Ứng dụng hoàn toàn có thể tàng trữ cục bộ mã thông tin thanh toán giao dịch mua, nhưng bạn nên truyền mã thông tin này tới sever phụ trợ bảo mật thông tin của bạn. Tại sever đó, bạn hoàn toàn có thể xác định và bảo vệ thanh toán giao dịch mua khỏi hành vi gian lận. Quy trình này được miêu tả kỹ hơn trong phần tiếp theo .
Người dùng cũng sẽ nhận được biên nhận thanh toán giao dịch chứa Mã đơn hàng hoặc một mã nhận dạng duy nhất của thanh toán giao dịch qua email. Người dùng sẽ nhận được một email kèm Mã đơn hàng duy nhất cho mỗi lần mua mẫu sản phẩm tính phí một lần, cũng như thanh toán giao dịch mua gói thuê bao lần đầu và những lần gia hạn tự động hóa định kỳ tiếp theo. Bạn hoàn toàn có thể sử dụng Mã đơn hàng để quản trị tiền hoàn trả trong Google Play Console .

Báo giá dành riêng cho bạn

Nếu bạn có thể phân phối ứng dụng cho người dùng ở Liên minh Châu Âu, hãy sử dụng phương thức setIsOfferPersonalized() để cho người dùng biết rằng giá của mặt hàng đã được cá nhân hoá bằng tính năng ra quyết định tự động.

Màn hình mua hàng trên Google Play cho biết cho biết rằng giá đã được điều chỉnh để phù hợp với người dùng.
Hình 3. Màn hình mua hàng trên Google Play cho biết giá này được điều chỉnh cho phù hợp với người dùng.

Bạn phải tìm hiểu thêm qua Art. 6 ( 1 ) ( ea ) CRD của Chỉ thị về quyền của người tiêu dùng ( 2011 / 83 / EU ) để xác lập xem giá bạn cung ứng cho người dùng có được cá thể hóa hay không .

setIsOfferPersonalized() nhận giá trị nhập boolean. Khi true, giao diện người dùng Play có bao gồm thông tin công bố. Khi false, giao diện người dùng bỏ qua thông tin công bố. Giá trị mặc định là false.

Hãy truy cập vào Trung tâm trợ giúp người tiêu dùng để biết thêm thông tin.

Xử lý giao dịch mua hàng

Sau khi người dùng hoàn tất giao dịch mua, ứng dụng cần xử lý
giao dịch mua đó. Trong hầu hết các trường hợp, ứng dụng sẽ nhận được thông báo về giao dịch mua hàng thông qua PurchasesUpdatedListener.
Tuy nhiên, trong một số trường hợp, ứng dụng sẽ ghi nhận giao dịch mua hàng bằng cách gọi BillingClient.queryPurchasesAsync() như mô tả trong phần Tìm nạp các giao dịch mua hàng.

Ngoài ra, nếu có ứng dụng Thông báo theo thời gian thực dành cho nhà phát triển trong phần phụ trợ bảo mật, bạn có thể đăng ký giao dịch mua hàng mới bằng cách nhận subscriptionNotification hoặc oneTimeProductNotification (chỉ dành cho các giao dịch mua hàng đang chờ xử lý) thông báo cho bạn về giao dịch mua hàng mới. Sau khi nhận được những thông báo này, hãy gọi API Nhà phát triển Google Play để nhận trạng thái đầy đủ và cập nhật trạng thái phụ trợ của riêng bạn.

Ứng dụng nên giải quyết và xử lý thanh toán giao dịch mua hàng theo cách sau :

  1. Xác minh giao dịch mua hàng.
  2. Cung cấp nội dung cho người dùng và xác nhận việc phân phối nội dung.
    Đánh dấu mặt hàng là đã tiêu thụ để người dùng có thể mua lại (không bắt buộc).

Để xác minh một giao dịch mua hàng, trước tiên hãy kiểm tra xem
trạng thái mua hàng
có phải là PURCHASED hay không.
Nếu giao dịch mua là PENDING, thì bạn nên xử lý giao dịch mua như được mô tả trong phần Xử lý các giao dịch đang chờ. Đối với các giao dịch mua nhận được qua
onPurchasesUpdated()
hoặc queryPurchasesAsync(),
bạn nên xác minh thêm để đảm bảo tính hợp pháp của giao dịch mua trước khi
cấp quyền cho ứng dụng. Để tìm hiểu cách xác minh giao dịch mua một cách chính xác, hãy xem phần
Xác minh giao dịch mua trước khi cấp quyền.

Sau khi xác minh giao dịch mua hàng, ứng dụng sẽ sẵn sàng cấp quyền cho người dùng. Tài khoản người dùng liên kết với giao dịch mua hàng có thể được xác định bằng ProductPurchase.obfuscatedExternalAccountId do Purchases.products:get trả về trong các giao dịch mua sản phẩm trong ứng dụng và SubscriptionPurchase.obfuscatedExternalAccountId do Purchases.subscriptions:get trả về đối với các gói thuê bao ở phía máy chủ hoặc obfuscatedAccountId từ Purchase.getAccountIdentifiers() ở phía máy khách, nếu được đặt với setObfuscatedAccountId khi giao dịch mua hàng được thực hiện.

Sau khi cấp quyền, ứng dụng phải xác nhận thanh toán giao dịch mua hàng. Việc xác nhận này cho Google Play biết rằng bạn đã cấp quyền cho thanh toán giao dịch mua hàng .
Lưu ý:Nếu bạn không xác nhận thanh toán giao dịch mua hàng trong vòng 3 ngày, người dùng sẽ tự động hóa được hoàn tiền và Google Play sẽ tịch thu thanh toán giao dịch mua hàng đó .
Quy trình cấp quyền và xác nhận thanh toán giao dịch mua hàng nhờ vào vào việc mẫu sản phẩm được mua là loại sản phẩm tiêu dùng, mẫu sản phẩm không phải hàng tiêu dùng hay gói thuê bao .

Sản phẩm tiêu dùng

Đối với sản phẩm tiêu dùng, nếu ứng dụng có phần phụ trợ bảo mật, bạn nên dùng Purchases.products:consume để sử dụng sản phẩm được mua một cách đáng tin cậy. Đảm bảo sản phẩm được mua chưa được sử dụng bằng cách kiểm tra consumptionState trong kết quả của lệnh gọi Purchases.products:get.
Nếu ứng dụng của bạn chỉ dành cho máy khách không có phần phụ trợ, hãy sử dụng consumeAsync() từ Thư viện Google Play Billing. Cả hai phương thức đều đáp ứng yêu cầu xác nhận và cho biết rằng ứng dụng đã cấp quyền cho người dùng. Các phương thức này cũng cho phép ứng dụng tạo sản phẩm tính phí một lần tương ứng với mã thông báo giao dịch mua hàng đầu vào để mua lại. Với consumeAsync(), bạn cũng phải truyền một đối tượng sẽ triển khai giao diện ConsumeResponseListener. Đối tượng này xử lý kết quả của hoạt động tiêu thụ. Bạn có thể ghi đè phương thức onConsumeResponse() mà Thư viện Google Play Billing này sẽ dùng khi hoạt động hoàn tất.

Ví dụ sau minh họa việc tiêu thụ một mẫu sản phẩm bằng Thư viện Google Play Billing bằng mã mua hàng được link :

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

Lưu ý:Đôi khi, nhu yếu tiêu thụ hoàn toàn có thể không thành công xuất sắc, do đó bạn phải kiểm tra sever phụ trợ bảo mật thông tin để bảo vệ rằng mọi mã thông tin thanh toán giao dịch mua hàng đều chưa được sử dụng và ngăn ứng dụng cấp quyền nhiều lần cho cùng một thanh toán giao dịch mua hàng. Hoặc ứng dụng hoàn toàn có thể chờ cho đến khi bạn nhận được phản hồi tiêu thụ thành công xuất sắc từ Google Play trước khi cấp quyền. Nếu chọn giữ lại những thanh toán giao dịch mua hàng của người dùng cho đến khi Google Play gửi phản hồi tiêu thụ thành công xuất sắc, bạn phải rất là cẩn trọng để không mất dấu những thanh toán giao dịch mua hàng mà bạn đã gửi nhu yếu tiêu thụ .

Sản phẩm không phải hàng tiêu dùng

Để xác nhận giao dịch mua sản phẩm không phải hàng tiêu dùng, nếu ứng dụng có phần phụ trợ bảo mật, bạn nên sử dụng Purchases.products:acknowledge để xác nhận giao dịch mua hàng một cách đáng tin cậy.
Đảm bảo giao dịch mua hàng chưa được xác nhận trước đó bằng cách kiểm tra acknowledgementState trong kết quả của lệnh gọi Purchases.products:get.

Nếu ứng dụng của bạn chỉ dành cho máy khách, hãy dùng BillingClient.acknowledgePurchase() từ Thư viện Google Play Billing trong ứng dụng của bạn. Trước khi xác nhận giao dịch mua hàng, ứng dụng của bạn phải kiểm tra xem giao dịch đã được xác nhận hay chưa bằng cách dùng phương thức isAcknowledged() trong Thư viện Google Play Billing.

Ví dụ sau cho biết cách xác nhận thanh toán giao dịch mua hàng bằng cách sử dụng Thư viện Google Play Billing :

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

Gói thuê bao

Gói thuê bao được xử lý tương tự như sản phẩm không phải hàng tiêu dùng. Nếu có thể, hãy sử dụng Purchases.subscriptions.acknowledge từ API Nhà phát triển Google Play để xác nhận một cách đáng tin cậy giao dịch mua hàng từ phần phụ trợ bảo mật của bạn. Xác minh rằng giao dịch mua hàng chưa được xác nhận trước đó bằng cách kiểm tra acknowledgementState trong tài nguyên giao dịch mua hàng từ Purchases.subscriptions:get.
Nếu không, bạn có thể xác nhận gói thuê bao bằng cách sử dụng BillingClient.acknowledgePurchase() từ Thư viện Google Play Billing sau khi kiểm tra isAcknowledged().
Bạn cần xác nhận tất cả các giao dịch mua gói thuê bao ban đầu. Bạn không cần xác nhận việc gia hạn gói thuê bao.
Để biết thêm thông tin về thời điểm cần xác nhận gói thuê bao, hãy xem chủ đề Bán gói thuê bao.

Tìm nạp các giao dịch mua hàng

Theo dõi thông tin cập nhật về giao dịch mua bằng cách sử dụng
PurchasesUpdatedListener
là không đủ để đảm bảo rằng ứng dụng sẽ xử lý tất cả giao dịch mua. Có thể
ứng dụng không biết tất cả giao dịch mua mà người dùng đã thực hiện. Dưới đây là một số trường hợp ứng dụng có thể bị mất dấu hoặc không biết về giao dịch mua:

  • Các vấn đề về mạng trong khi mua hàng: Người dùng mua hàng thành công và nhận được xác nhận của Google, nhưng thiết bị của họ bị mất
    kết nối mạng trước khi nhận được thông báo
    về giao dịch mua thông qua PurchasesUpdatedListener.
  • Nhiều thiết bị: Người dùng mua một mặt hàng trên một thiết bị và kỳ vọng thấy mặt hàng đó khi chuyển đổi thiết bị.
  • Xử lý giao dịch mua thực hiện bên ngoài ứng dụng: Người dùng có thể thực hiện một số giao dịch mua (như sử dụng các mã khuyến mãi) bên ngoài ứng dụng của bạn.

Để xử lý những trường hợp này, hãy đảm bảo ứng dụng gọi hàm BillingClient.queryPurchasesAsync() trong phương thức onResume() để đảm bảo rằng tất cả giao dịch mua đều được xử lý thành công như mô tả trong phần xử lý giao dịch mua.

Ví dụ sau đây cho thấy cách tìm nạp giao dịch mua gói thuê bao của người dùng.
Lưu ý queryPurchasesAsync() chỉ trả về thuê bao đang hoạt động và không truy vấn được các giao dịch mua hàng một lần.

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, List purchases) {
        // check billingResult
        // process returned purchase list, e.g. display the plans user owns

      }
    }
);

Tìm nạp nhật ký mua

queryPurchaseHistoryAsync() trả về giao dịch mua gần đây nhất của người dùng đối với từng sản phẩm, ngay cả khi giao dịch mua đó đã hết hạn, bị huỷ hoặc đã hoàn tất.

Nếu đang sử dụng tiện ích Kotlin, bạn có thể dùng hàm mở rộng 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, List purchasesHistoryList) {
          // check billingResult
          // process returned purchase history list, e.g. display purchase history
        }
    }
);

Xử lý giao dịch mua hàng được thực hiện bên ngoài ứng dụng

Một số thanh toán giao dịch mua như sử dụng những mã tặng thêm hoàn toàn có thể diễn ra bên ngoài ứng dụng của bạn. Khi người dùng mua hàng bên ngoài ứng dụng, họ muốn ứng dụng đưa ra thông tin trong ứng dụng hoặc sử dụng 1 số ít chính sách thông tin để người dùng biết rằng ứng dụng đã nhận và giải quyết và xử lý thanh toán giao dịch mua một cách đúng mực. Một số chính sách được đồng ý là :

  • Hiển thị một cửa sổ bật lên trong ứng dụng.
  • Chuyển thông báo tới hộp thông báo trong ứng dụng và nêu rõ rằng có một tin nhắn mới trong hộp thông báo trong ứng dụng.
  • Sử dụng một nội dung thông báo trên hệ điều hành.

Xin chú ý quan tâm rằng ứng dụng hoàn toàn có thể ở bất kể trạng thái nào khi phát hiện thanh toán giao dịch mua. Thậm chí ứng dụng hoàn toàn có thể không được thiết lập khi thanh toán giao dịch mua hàng được thực thi. Người dùng mong ước nhận thông tin về thanh toán giao dịch mua khi liên tục sử dụng ứng dụng, bất kể ứng dụng đó đang trong trạng thái sử dụng nào .
Bạn phải phát hiện những thanh toán giao dịch mua hàng bất kể ứng dụng đang trong trạng thái nào tại thời gian người dùng mua hàng. Tuy nhiên, đôi lúc cũng có những ngoại lệ hoàn toàn có thể gật đầu về việc không thông tin ngay lập tức cho người dùng rằng họ đã nhận được mẫu sản phẩm. Ví dụ :

  • Khi họ đang tham gia vào phần hành động của một trò chơi, thông báo hiển thị có thể khiến người dùng mất tập trung. Trong trường hợp này, bạn phải thông báo cho người dùng sau khi phần hành động này kết thúc.
  • Khi đoạn phim cắt cảnh đang chạy, việc hiển thị thông báo có thể khiến người dùng bị phân tâm. Trong trường hợp này, bạn phải thông báo cho người dùng sau khi đoạn phim cắt cảnh chạy hết.
  • Trong quá trình hướng dẫn ban đầu và thiết lập người dùng của trò chơi. Bạn nên
    thông báo cho người dùng mới về phần thưởng ngay sau khi họ mở trò chơi hoặc trong
    quá trình thiết lập người dùng ban đầu. Tuy nhiên, bạn có thể đợi cho đến khi cảnh chính trong trò chơi
    xuất hiện để thông báo cho người dùng.

Hãy luôn nghĩ tới trải nghiệm của người dùng khi quyết định thời điểm và cách thông báo cho họ về
giao dịch mua được thực hiện bên ngoài ứng dụng. Bất cứ khi nào người dùng không nhận được
thông báo ngay lập tức, họ có thể cảm thấy hoang mang, từ đó ngừng sử dụng ứng dụng, liên hệ với bộ phận hỗ trợ người dùng hoặc than phiền về việc đó trên mạng xã hội.
Lưu ý: PurchasesUpdatedListener đăng ký ngữ cảnh cho ứng dụng của bạn để xử lý thông tin cập nhật về giao dịch mua, bao gồm cả giao dịch mua thực hiện bên ngoài ứng dụng của bạn. Tức là nếu quy trình đăng ký của bạn không tồn tại, PurchasesUpdatedListener sẽ không được thông báo. Đây là lý do ứng dụng của bạn nên gọi BillingClient.queryPurchasesAsync() trong phương thức onResume() như đã đề cập trong Tìm nạp giao dịch.

Xử lý các giao dịch đang chờ

Lưu ý:

Bạn phải xử lý các Giao dịch đang chờ xử lý trong Thư viện Google Play Billing phiên bản 2.0 trở lên. Bạn nên xử lý các giao dịch đang chờ xử lý một cách rõ ràng.

Lưu ý:Bạn không hề sử dụng phương pháp giao dịch thanh toán bổ trợ cho những thanh toán giao dịch mua gói thuê bao .
Google Play tương hỗ thanh toán giao dịch đang chờ giải quyết và xử lý hoặc thanh toán giao dịch nhu yếu một hoặc nhiều bước bổ trợ giữa thời gian người dùng triển khai thanh toán giao dịch mua và khi phương pháp giao dịch thanh toán cho thanh toán giao dịch mua được giải quyết và xử lý. Ứng dụng không được cấp quyền cho những thanh toán giao dịch mua này cho đến khi Google thông tin cho bạn rằng đã tính phí thành công xuất sắc phương pháp giao dịch thanh toán của người dùng .

Ví dụ: người dùng có thể tạo một giao dịch mua mặt hàng PENDING trong ứng dụng bằng cách
chọn phương thức thanh toán là tiền mặt. Sau đó, người dùng có thể chọn một cửa hàng
thực tế để hoàn tất giao dịch và nhận mã thông qua cả
thông báo và email. Khi đến cửa hàng thực tế, người dùng
có thể sử dụng mã này và thanh toán cho thu ngân bằng tiền mặt. Sau đó, Google sẽ thông báo cho
cả bạn và người dùng rằng đã nhận được tiền mặt. Sau đó, ứng dụng có thể cấp quyền cho người dùng.

Ứng dụng phải hỗ trợ các giao dịch đang chờ xử lý bằng cách gọi hàm
enablePendingPurchases()
trong khi khởi chạy ứng dụng.

Khi ứng dụng nhận được một giao dịch mua mới, thông qua PurchasesUpdatedListener hoặc từ việc gọi hàm queryPurchasesAsync(), hãy sử dụng phương thức getPurchaseState() để xác định trạng thái mua hàng là PURCHASED hay PENDING.

Lưu ý:

Bạn chỉ nên cấp quyền khi trạng thái là PURCHASED. Hãy sử dụng hàm
getPurchaseState() thay vì hàm getOriginaljson() và đảm bảo
xử lý giao dịch PENDING một cách phù hợp.

Nếu ứng dụng đang chạy khi người dùng hoàn tất giao dịch mua, PurchasesUpdatedListener
sẽ được gọi lại và PurchaseState hiện là PURCHASED. Tại thời điểm này,
ứng dụng có thể xử lý giao dịch mua hàng bằng cách sử dụng phương thức tiêu chuẩn để
xử lý giao dịch mua hàng một lần. Ứng dụng cũng nên gọi hàm
queryPurchasesAsync() trong phương thức onResume() của ứng dụng để
xử lý những giao dịch mua đã chuyển sang trạng thái PURCHASED trong khi
ứng dụng không chạy.

Lưu ý:

Bạn chỉ nên xác nhận giao dịch mua hàng khi trạng thái là PURCHASED, tức là không xác nhận giao dịch mua hàng ở trạng thái PENDING. Thời hạn xác nhận
ba ngày chỉ bắt đầu khi trạng thái mua hàng chuyển đổi từ
“PENDING” (ĐANG CHỜ XỬ LÝ) thành “PURCHASED” (ĐÃ MUA).

Ứng dụng cũng có thể sử dụng
Thông báo theo thời gian thực dành cho nhà phát triển
cho các giao dịch mua đang chờ xử lý bằng cách lắng nghe
OneTimeProductNotifications. Khi giao dịch mua chuyển từ trạng thái PENDING
sang PURCHASED, ứng dụng sẽ nhận được
thông báo ONE_TIME_PRODUCT_PURCHASED. Nếu giao dịch mua bị huỷ,
ứng dụng sẽ nhận được thông báo ONE_TIME_PRODUCT_CANCELED. Điều này có thể xảy ra nếu khách hàng không hoàn tất việc thanh toán trong khung thời gian yêu cầu.
Khi nhận được những thông báo này, bạn có thể sử dụng API Nhà phát triển Google Play, bao gồm trạng thái PENDING cho
Purchases.products.

Lưu ý:Bạn hoàn toàn có thể kiểm tra những thanh toán giao dịch đang chờ giải quyết và xử lý bằng cách sử dụng trình kiểm thử giấy phép. Ngoài hai thẻ tín dụng thanh toán kiểm thử, trình kiểm thử được cấp phép có quyền truy vấn vào hai công cụ kiểm thử cho những phương pháp thanh toán giao dịch bị trì hoãn do khoản thanh toán giao dịch tự động hóa triển khai xong hoặc hủy sau vài phút. Trong quy trình kiểm thử ứng dụng, bạn nên xác định rằng ứng dụng không cấp quyền hoặc xác nhận thanh toán giao dịch mua ngay sau khi mua bằng một trong hai công cụ này. Khi mua hàng bằng công cụ kiểm thử tự động hóa hoàn tất, bạn nên xác định rằng ứng dụng cấp quyền và xác nhận thanh toán giao dịch mua hàng sau khi hoàn tất .
Bạn hoàn toàn có thể tìm thấy những bước chi tiết cụ thể về cách kiểm thử trường hợp này trong phần Kiểm thử thanh toán giao dịch mua hàng đang chờ giải quyết và xử lý .

Xử lý giao dịch mua số lượng nhiều

Được tương hỗ trong phiên bản 4.0 trở lên của Thư viện Google Play Billing, Google Play được cho phép người mua mua nhiều lần cùng một mẫu sản phẩm trong ứng dụng trong một thanh toán giao dịch bằng cách chỉ định số lượng trong giỏ hàng. Ứng dụng cần giải quyết và xử lý những thanh toán giao dịch mua hàng số lượng nhiều và cấp quyền dựa trên số lượng mẫu sản phẩm đã chỉ định .
Lưu ý:

Số lượng nhiều dành cho các sản phẩm tiêu dùng trong ứng dụng, tức là các mặt hàng
có thể mua, tiêu dùng và mua lại. Không bật tính năng này cho
những sản phẩm chỉ mua một lần.

Để xử lý các giao dịch mua với số lượng nhiều, logic cấp phép của ứng dụng cần
kiểm tra số lượng mặt hàng. Bạn có thể truy cập trường quantity qua một trong
các API sau:

  • getQuantity()
    trong Thư viện Google Play Billing.
  • Purchases.products.quantity
    từ API Nhà phát triển Google Play.

Sau khi thêm logic để giải quyết và xử lý thanh toán giao dịch mua số lượng nhiều, bạn cần bật tính năng số lượng lớn cho mẫu sản phẩm tương ứng trên trang quản trị loại sản phẩm trong ứng dụng trong Google Play Console .

Lưu ý:Hãy bảo vệ rằng ứng dụng của bạn được cho phép thực thi thanh toán giao dịch mua với số lượng nhiều trước khi bật tính năng này trong bảng điều khiển và tinh chỉnh. Có thể bạn buộc phải update lên phiên bản ứng dụng tương hỗ tính năng này trước khi hoàn toàn có thể bật tính năng trên mẫu sản phẩm .

Tích hợp Thư viện Google Play Billing vào ứng dụng | Hệ thống thanh toán của Google Play | Android Developers

Bài viết liên quan
Hotline 24/7: O984.666.352
Alternate Text Gọi ngay