Sử dụng hệ thống thanh toán của Google Play với AIDL

Cảnh báo: AIDL không còn được dùng nữa và sẽ bị xoá trong một bản phát hành sau này. Để triển khai các tính năng liên quan đến thanh toán, hãy sử dụng Thư viện Google Play Billing.

Bạn có thể sử dụng giao diện Ngôn ngữ định nghĩa giao diện Android (AIDL) để triển khai một số tính năng của hệ thống thanh toán Google Play.

Mua sản phẩm

Hình 1. Trình tự cơ bản cho yêu cầu mua hàng.

Quy trình mua điển hình với API Google Play Billing AIDL như sau:

  1. Ứng dụng gửi yêu cầu isBillingSupported tới Google Play để xác định hệ thống có hỗ trợ phiên bản mục tiêu của API Google Play Billing AIDL mà bạn đang sử dụng. Yêu cầu này cũng xác minh rằng Google Play hỗ trợ thanh toán tại quốc gia của người dùng.
  2. Khi ứng dụng khởi động hoặc khi người dùng đăng nhập, bạn nên kiểm tra với Google Play để xác định mặt hàng nào thuộc sở hữu của người dùng. Để truy vấn giao dịch mua của người dùng, hãy gửi một yêu cầu getPurchases. Nếu yêu cầu thành công, Google Play sẽ trả về một Bundle chứa một danh sách ID sản phẩm của mặt hàng đã mua, một danh sách giao dịch mua riêng lẻ và một danh sách chữ ký của giao dịch mua.
  3. Thông thường, bạn nên thông báo cho người dùng về các sản phẩm họ có thể mua. Để truy vấn thông tin chi tiết của sản phẩm trong ứng dụng mà bạn đã xác định trong Google Play, ứng dụng có thể gửi một yêu cầu getSkuDetails. Bạn phải chỉ định một danh sách ID sản phẩm trong yêu cầu truy vấn. Nếu yêu cầu thành công, Google Play sẽ trả về một Bundle chứa thông tin chi tiết về sản phẩm, bao gồm giá, tiêu đề, phần mô tả và loại giao dịch mua hàng của sản phẩm.
  4. Nếu một sản phẩm trong ứng dụng không thuộc quyền sở hữu của người dùng, bạn có thể bắt đầu một giao dịch mua sản phẩm đó. Để bắt đầu một yêu cầu mua hàng, ứng dụng của bạn sẽ gửi một yêu cầu getBuyIntent, trong đó ghi rõ mã sản phẩm của mặt hàng mà bạn mua cùng với các thông số khác. Bạn nên ghi lại mã sản phẩm khi tạo một sản phẩm trong ứng dụng mới trên Google Play Console.
    1. Google Play trả về một Bundle chứa PendingIntent mà ứng dụng của bạn dùng để bắt đầu giao diện thanh toán để mua hàng.
    2. Ứng dụng của bạn kích hoạt ý định chờ xử lý bằng cách gọi hàm startIntentSenderForResult.
    3. Khi quy trình thanh toán kết thúc (nghĩa là người dùng này đã mua thành công mặt hàng hoặc huỷ giao dịch mua), Google Play sẽ gửi phản hồi Intent đến hàm onActivityResult của bạn. Mã kết quả của onActivityResult có một mã kết quả cho biết giao dịch mua đã thành công hay bị huỷ. Phản hồi Intent chứa thông tin về mặt hàng đã mua, bao gồm chuỗi purchaseToken do Google Play tạo để xác định duy nhất giao dịch mua này. Intent cũng chứa chữ ký của giao dịch mua, được ký bằng khoá nhà phát triển riêng của bạn.

Để tìm hiểu thêm về lệnh gọi API Google Play Billing và các phản hồi của máy chủ, hãy xem Tài liệu tham khảo API Google Play Billing AIDL.

Tiêu dùng sản phẩm trong ứng dụng

Bạn có thể sử dụng cơ chế tiêu dùng để theo dõi quyền sở hữu của người dùng đối với sản phẩm được quản lý.

Tất cả sản phẩm đều được quản lý trong API Google Play Billing AIDL. Điều này có nghĩa là Google Play duy trì quyền sở hữu tất cả giao dịch mua sản phẩm của người dùng và ứng dụng có thể truy vấn thông tin mua hàng của người dùng khi cần. Khi người dùng mua thành công một sản phẩm được quản lý, giao dịch mua đó sẽ được ghi lại trong Google Play. Sau khi người dùng mua một sản phẩm được quản lý, sản phẩm đó được coi là "được sở hữu". Bạn không thể mua các sản phẩm được quản lý có trạng thái "được sở hữu" từ Google Play. Bạn phải gửi một yêu cầu tiêu dùng cho sản phẩm "được sở hữu" do bạn quản lý trước khi Google Play cung cấp lại sản phẩm đó. Khi bạn tiêu dùng sản phẩm được quản lý, sản phẩm đó sẽ chuyển về trạng thái "không được sở hữu", đồng thời huỷ dữ liệu mua trước đó.

Hình 2. Trình tự cơ bản cho một yêu cầu tiêu dùng.

Để truy xuất danh sách sản phẩm do người dùng sở hữu, ứng dụng sẽ gửi một lệnh gọi getPurchases đến Google Play. Ứng dụng có thể đưa ra yêu cầu tiêu dùng bằng cách gửi một lệnh gọi consumePurchase. Trong đối số yêu cầu, bạn phải chỉ định chuỗi purchaseToken duy nhất của sản phẩm được quản lý mà bạn đã nhận được từ Google Play khi sản phẩm đó được mua. Google Play sẽ trả về mã trạng thái cho biết đã ghi lại thành công giao dịch tiêu dùng.

Sản phẩm tiêu dùng và sản phẩm không phải hàng tiêu dùng được quản lý

Bạn có thể quyết định xem bạn muốn xử lý sản phẩm được quản lý của mình như các sản phẩm tiêu dùng hay các sản phẩm không phải hàng tiêu dùng.

Sản phẩm không phải hàng tiêu dùng
Thông thường, bạn sẽ không thực hiện giao dịch tiêu dùng cho những sản phẩm được quản lý chỉ có thể được mua một lần trong ứng dụng và mang lại một lợi ích vĩnh viễn. Sau khi mua, những sản phẩm này sẽ được liên kết vĩnh viễn với tài khoản Google của người dùng. Ví dụ về sản phẩm được quản lý không phải hàng tiêu dùng có thể kể đến như bản nâng cấp cao cấp hoặc một gói cấp độ.
Sản phẩm tiêu dùng
Ngược lại, bạn có thể triển khai giao dịch tiêu dùng cho những sản phẩm có thể được bán nhiều lần. Thông thường, các sản phẩm này mang lại một số lợi ích tạm thời. Ví dụ: Nhân vật trong trò chơi của người dùng có thể kiếm điểm sinh mạng hoặc nhận thêm xu vàng trong kho tài nguyên. Việc phân phối lợi ích hoặc tác dụng của sản phẩm đã mua trong ứng dụng được gọi là cung cấp sản phẩm được quản lý. Bạn chịu trách nhiệm kiểm soát và theo dõi cách sản phẩm được quản lý được cấp phép cho người dùng.

Lưu ý quan trọng: Trước khi cấp phép cho sản phẩm tiêu dùng được quản lý trong ứng dụng, bạn phải gửi yêu cầu tiêu dùng đến Google Play và nhận được phản hồi thành công cho biết đã ghi lại việc tiêu dùng.

Quản lý giao dịch mua sản phẩm tiêu dùng trong ứng dụng

Dưới đây là quy trình cơ bản để mua một sản phẩm tiêu dùng được quản lý:

  1. Gọi phương thức getBuyIntent để bắt đầu quy trình mua.
  2. Hãy kiểm tra Bundle được trả lại từ Google Play để xác định liệu giao dịch mua đã hoàn tất hay chưa.
  3. Nếu giao dịch mua thành công, gọi hàm consumePurchase để tiêu dùng sản phẩm đó.
  4. Kiểm tra mã phản hồi từ Google Play để xác định xem đã tiêu dùng thành công hay chưa.
  5. Nếu đã tiêu dùng thành công, hãy cung cấp sản phẩm trong ứng dụng.

Sau đó, khi người dùng khởi động hoặc đăng nhập vào ứng dụng, bạn nên kiểm tra xem họ có sở hữu sản phẩm tiêu dùng nào trong ứng dụng hay không; nếu có, hãy đảm bảo tiêu dùng và cung cấp những mặt hàng đó. Dưới đây là quy trình khởi động ứng dụng được đề xuất nếu bạn triển khai sản phẩm tiêu dùng trong ứng dụng:

  1. Gửi yêu cầu getPurchases để truy vấn các sản phẩm mà người dùng sở hữu trong ứng dụng.
  2. Nếu có sản phẩm tiêu dùng nào trong ứng dụng, hãy tiêu dùng các mặt hàng này bằng cách gọi consumePurchase. Bước này là cần thiết vì ứng dụng có thể đã hoàn tất đơn đặt hàng cho sản phẩm tiêu dùng, tuy nhiên đã ngừng hoặc bị ngắt kết nối trước khi ứng dụng có cơ hội gửi yêu cầu tiêu dùng.
  3. Kiểm tra mã phản hồi từ Google Play để xác định xem đã tiêu dùng thành công hay chưa.
  4. Nếu đã tiêu dùng thành công, hãy cung cấp sản phẩm trong ứng dụng.

Định cấu hình giao dịch mua sản phẩm thưởng

Cảnh báo: Sản phẩm thưởng không còn được hỗ trợ. Để biết thêm thông tin, hãy xem phần Tạo một sản phẩm thưởng.

Khi làm việc với các sản phẩm thưởng thông qua AIDL, bạn nên lưu "Ý định" mua vào bộ nhớ đệm trước khi người dùng cần nhận phần thưởng. Bạn có thể gọi ý định mua trên chuỗi nền và lưu phản hồi "Ý định" thành công cho đến khi người dùng thực hiện hành động để nhận phần thưởng.

Liệt kê và tải SKU

Trước khi cung cấp một sản phẩm thưởng cho người dùng, hãy tải chi tiết sản phẩm bằng cách gọi getSkuDetails(). Một trường JSON mới "rewardToken" sẽ được điền sẵn cho mỗi sản phẩm thưởng trong danh sách SKU.

Để cung cấp trải nghiệm người dùng tốt nhất, bạn phải đảm bảo quảng cáo được tải sẵn và sẵn sàng trước khi cung cấp sản phẩm thưởng cho người dùng. Để làm vậy, hãy gọi getBuyIntentExtraParams() trên luồng nền. Sau khi nhận được phản hồi BILLING_RESPONSE_RESULT_OK, hãy bật sản phẩm thưởng cho người dùng và lưu đối tượng PendingIntent được trả về để sử dụng sau. Đoạn mã sau đây minh hoạ quy trình tải quảng cáo liên kết với một sản phẩm thưởng:

Kotlin

val rewardToken = skuDetailsJson.optString("rewardToken")
val extraParams = Bundle().putString("rewardToken", rewardToken)

// This call blocks the current thread, so do this in the background.
val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName,
        sku, "inapp", "", extraParams)

val response = buyIntentBundle.getInt("RESPONSE_CODE")
if (response == BILLING_RESPONSE_RESULT_OK) {
    // Enable rewarded product.

    // Save this object for use later.
    val pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT)
} else {
    // Don't offer rewarded product.
}

Java

String rewardToken = skuDetailsJson.optString("rewardToken");
Bundle extraParams = new Bundle();
extraParams.putString("rewardToken", rewardToken);

// This call blocks the current thread, so do this in the background.
Bundle buyIntentBundle = mService.getBuyIntentExtraParams(9, getPackageName(),
        sku, "inapp", "", extraParams);

int response = buyIntentBundle.getInt("RESPONSE_CODE");
if (response == BILLING_RESPONSE_RESULT_OK) {
    // Enable rewarded product.

    // Save this object for use later.
    PendingIntent pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT);
} else {
    // Don't offer rewarded product.
}

Khai báo quảng cáo phù hợp với lứa tuổi

Để tạo điều kiện tuân thủ với các nghĩa vụ pháp lý liên quan đến trẻ em và người dùng chưa đủ tuổi hợp pháp, bao gồm cả Đạo luật bảo vệ quyền riêng tư của trẻ em trên mạng (COPPA)Quy định chung về bảo vệ dữ liệu (GDPR), ứng dụng phải khai báo quảng cáo nào nên được phân loại là hướng tới trẻ em tại Hoa Kỳ và quảng cáo nào hướng đến người dùng dưới độ tuổi hợp pháp để tự quản lý tài khoản hiện hành tại quốc gia của họ. Trung tâm trợ giúp AdMob giải thích khi nào bạn nên gắn thẻ cho các yêu cầu quảng cáo là được dành cho trẻ em và khi nào nên gắn thẻ xử lý nội dung dưới độ tuổi hợp pháp để tự quản lý tài khoản, cũng như tác động của việc làm này.

Để cho biết rằng một yêu cầu có tặng thưởng là dành cho trẻ em hoặc cho người dùng chưa đủ độ tuổi hợp pháp để tự quản lý tài khoản, hãy bao gồm các thông số bổ sung childDirectedunderAgeOfConsent như hiển thị trong đoạn mã sau:

Kotlin

val rewardToken = skuDetailsJson.optString("rewardToken")
val extraParams = Bundle().putString("rewardToken", rewardToken)
        .putInt("childDirected", ChildDirected.CHILD_DIRECTED)
        .putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT)

// This call blocks the current thread, so do this in the background.
val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName,
        sku, "inapp", "", extraParams)

Java

Bundle extraParams = new Bundle();
extraParams.putString("rewardToken", rewardToken);
extraParams.putInt("childDirected", ChildDirected.CHILD_DIRECTED);
extraParams.putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT);

// This call blocks the current thread, so do this in the background.
Bundle buyIntentBundle =
  mService.getBuyIntentExtraParams(
    9, getPackageName(), sku, "inapp", "", extraParams);

Phát quảng cáo trước khi tặng thưởng cho người dùng

Sau khi người dùng nhấp vào nút để bắt đầu xem quảng cáo, ứng dụng có thể sử dụng đối tượng PendingIntent đã lưu để bắt đầu phát quảng cáo. Để thực hiện việc này, hãy gọi startIntentSenderForResult():

Kotlin

startIntentSenderForResult(
    pendingIntentToSave,
    RC_BUY, Intent(),
    0,
    0,
    0
)

Java

startIntentSenderForResult(pendingIntentToSave, RC_BUY, new Intent(),
        0, 0, 0);

Sau đó, hãy xử lý kết quả quy trình thanh toán trong onActivityResult() như hiển thị trong các đoạn mã sau. Khi xử lý quy trình phát quảng cáo, Google Play sẽ sử dụng cùng một bộ mã phản hồi máy chủ giống như các quy trình thanh toán khác.

Kotlin

fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent) {
    if (requestCode == RC_BUY) {
        int responseCode = data.getIntExtra(RESPONSE_CODE)
        String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA)
        String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE)

        // Handle reward purchase.
    }
}

Java

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RC_BUY) {
        int responseCode = data.getIntExtra(RESPONSE_CODE);
        String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
        String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);

        // Handle reward purchase.
    }
}

Lưu vào bộ nhớ đệm cục bộ

Vì ứng dụng Google Play hiện đã lưu thông tin thanh toán vào bộ nhớ đệm cục bộ trên thiết bị, do đó bạn có thể dùng API Google Play Billing AIDL để truy vấn thông tin này thường xuyên hơn. Các lệnh gọi API Google Play Billing AIDL sau đây được thực hiện thông qua hoạt động tra cứu bộ nhớ đệm thay vì yêu cầu kết nối mạng, giúp đẩy nhanh đáng kể thời gian phản hồi của API:

  • getBuyIntent
  • getPurchases
  • isBillingSupported