1. Giới thiệu
Trong lớp học lập trình này, bạn sẽ tập trung vào việc tạo một sản phẩm mua một lần, tích hợp ứng dụng của bạn với Thư viện Play Billing (PBL) và phân tích lý do khiến giao dịch mua bị huỷ ngang.
Đối tượng người xem
Lớp học lập trình này dành cho nhà phát triển ứng dụng Android đang sử dụng Thư viện Play Billing (PBL) hoặc muốn sử dụng PBL để kiếm tiền từ các sản phẩm mua một lần.
Kiến thức bạn sẽ học được...
- Cách tạo sản phẩm tính phí một lần trong Google Play Console.
- Cách tích hợp ứng dụng của bạn với PBL.
- Cách xử lý giao dịch mua sản phẩm tiêu hao và sản phẩm không tiêu hao tính phí một lần trong PBL.
- Cách phân tích tình trạng bỏ ngang giao dịch mua.
Những thứ bạn cần...
- Có quyền truy cập vào Google Play Console bằng tài khoản nhà phát triển. Nếu chưa có tài khoản nhà phát triển, bạn cần tạo một tài khoản.
- Một ứng dụng mẫu cho lớp học lập trình này mà bạn có thể tải xuống từ GitHub.
- Android Studio.
2. Tạo ứng dụng mẫu
Ứng dụng mẫu được thiết kế để trở thành một ứng dụng Android có đầy đủ chức năng, có mã nguồn hoàn chỉnh minh hoạ các khía cạnh sau:
- Tích hợp ứng dụng với PBL
- Tìm nạp sản phẩm tính phí một lần
- Bắt đầu quy trình mua cho sản phẩm tính phí một lần
- Các trường hợp mua hàng dẫn đến những phản hồi thanh toán sau đây:
BILLING_UNAVAILABLE
USER_CANCELLED
OK
ITEM_ALREADY_OWNED
Video minh hoạ sau đây cho thấy giao diện và cách hoạt động của ứng dụng mẫu sau khi được triển khai và chạy.
Điều kiện tiên quyết
Trước khi bạn tạo và triển khai ứng dụng mẫu, hãy làm như sau:
- Tạo tài khoản nhà phát triển trên Google Play Console. Nếu bạn đã có tài khoản nhà phát triển, hãy bỏ qua bước này.
- Tạo một ứng dụng mới trong Play Console. Khi tạo một ứng dụng, bạn có thể chỉ định tên ứng dụng bất kỳ cho ứng dụng mẫu.
- Cài đặt Android Studio.
Tạo
Mục tiêu của bước tạo này là tạo một tệp Android App Bundle có chữ ký của ứng dụng mẫu.
Để tạo gói ứng dụng Android, hãy làm theo các bước sau:
- Tải ứng dụng mẫu xuống từ GitHub.
- Tạo ứng dụng mẫu. Trước khi tạo, hãy thay đổi tên gói của ứng dụng mẫu rồi tạo. Nếu bạn có các gói của những ứng dụng khác trong Play Console, hãy đảm bảo tên gói mà bạn cung cấp cho ứng dụng mẫu là duy nhất.
Lưu ý: Việc tạo ứng dụng mẫu chỉ tạo ra một tệp APK mà bạn có thể dùng để kiểm thử cục bộ. Tuy nhiên, việc chạy ứng dụng không tìm nạp sản phẩm và giá vì các sản phẩm chưa được định cấu hình trong Play Console. Bạn sẽ thực hiện việc này trong phần tiếp theo của lớp học lập trình này. - Tạo một Android App Bundle đã ký.
Bước tiếp theo là tải gói ứng dụng Android lên Google Play Console.
3. Tạo sản phẩm tính phí một lần trong Play Console
Để tạo sản phẩm tính phí một lần trong Google Play Console, bạn cần có một ứng dụng trong Play Console. Tạo một ứng dụng trong Play Console, sau đó tải gói ứng dụng đã ký mà bạn tạo trước đó lên.
Tạo ứng dụng
Cách tạo ứng dụng:
- Đăng nhập vào Google Play Console bằng tài khoản nhà phát triển của bạn.
- Nhấp vào Tạo ứng dụng. Thao tác này sẽ mở trang Tạo ứng dụng.
- Nhập tên ứng dụng, chọn ngôn ngữ mặc định và các thông tin khác liên quan đến ứng dụng.
- Nhấp vào Tạo ứng dụng. Thao tác này sẽ tạo một ứng dụng trong Google Play Console.
Giờ đây, bạn có thể tải gói ứng dụng đã ký của ứng dụng mẫu lên.
Tải gói ứng dụng đã ký lên
- Tải gói ứng dụng đã ký lên kênh kiểm thử nội bộ của Google Play Console. Bạn chỉ có thể định cấu hình các tính năng liên quan đến việc kiếm tiền trong Play Console sau khi tải lên.
- Nhấp vào Kiểm thử và phát hành > Kiểm thử > Bản phát hành nội bộ > Tạo bản phát hành mới.
- Nhập tên bản phát hành rồi tải tệp gói ứng dụng đã ký lên.
- Nhấp vào Tiếp theo, rồi nhấp vào Lưu và xuất bản.
Giờ đây, bạn có thể tạo sản phẩm tính phí một lần.
Tạo sản phẩm tính phí một lần
Cách tạo sản phẩm tính phí một lần:
- Trong Google Play Console, trên trình đơn điều hướng bên trái, hãy chuyển đến Kiếm tiền qua Play > Sản phẩm > Sản phẩm tính phí một lần.
- Nhấp vào Tạo sản phẩm tính phí một lần.
- Nhập các thông tin chi tiết sau về sản phẩm:
- Mã sản phẩm: Nhập một mã sản phẩm riêng biệt. Nhập
one_time_product_01
. - (Không bắt buộc) Thẻ: Thêm các thẻ có liên quan.
- Tên: Nhập tên sản phẩm. Ví dụ:
Product name
. - Nội dung mô tả: Nhập nội dung mô tả sản phẩm. Ví dụ:
Product description
. - (Không bắt buộc) Thêm hình ảnh biểu tượng: Tải một biểu tượng đại diện cho sản phẩm của bạn lên.
- Mã sản phẩm: Nhập một mã sản phẩm riêng biệt. Nhập
- Nhấp vào Tiếp theo.
- Thêm một lựa chọn mua và thiết lập phạm vi cung cấp theo khu vực. Sản phẩm tính phí một lần cần có ít nhất một lựa chọn mua. Lựa chọn này xác định cách cấp quyền sử dụng, giá và phạm vi cung cấp theo khu vực. Trong lớp học lập trình này, chúng ta sẽ thêm lựa chọn Mua tiêu chuẩn cho sản phẩm.Trong phần Lựa chọn mua, hãy nhập các thông tin sau:
- Mã lựa chọn mua: Nhập mã lựa chọn mua. Ví dụ:
buy
. - Loại giao dịch mua: Chọn Mua.
- (Không bắt buộc) Thẻ: Thêm thẻ dành riêng cho lựa chọn mua này.
- (Không bắt buộc) Nhấp vào Tuỳ chọn nâng cao để định cấu hình các tuỳ chọn nâng cao. Trong phạm vi của lớp học lập trình này, bạn có thể bỏ qua bước định cấu hình các lựa chọn nâng cao.
- Mã lựa chọn mua: Nhập mã lựa chọn mua. Ví dụ:
- Trong phần Tình trạng còn hàng và giá, hãy nhấp vào Đặt giá > Chỉnh sửa giá hàng loạt.
- Chọn mục Quốc gia / khu vực. Thao tác này sẽ chọn tất cả các khu vực.
- Nhấp vào Tiếp tục. Thao tác này sẽ mở một hộp thoại để nhập giá. Nhập 10 USD rồi nhấp vào Áp dụng.
- Nhấp vào Lưu rồi nhấp vào Kích hoạt. Thao tác này sẽ tạo và kích hoạt lựa chọn mua.
Để phục vụ mục đích của lớp học lập trình này, hãy tạo thêm 3 sản phẩm tính phí một lần với các mã sản phẩm sau:
- consumable_product_01
- consumable_product_02
- consumable_product_03
Ứng dụng mẫu được định cấu hình để sử dụng các mã sản phẩm này. Bạn có thể cung cấp nhiều mã sản phẩm. Trong trường hợp này, bạn sẽ phải sửa đổi ứng dụng mẫu để sử dụng mã sản phẩm mà bạn đã cung cấp.
Mở ứng dụng mẫu trong Google Play Console, rồi chuyển đến phần Kiếm tiền bằng Play > Sản phẩm > Sản phẩm mua một lần. Sau đó, hãy nhấp vào Tạo sản phẩm tính phí một lần rồi lặp lại các bước từ 3 đến 9.
Video hướng dẫn cách tạo sản phẩm tính phí một lần
Video mẫu sau đây minh hoạ các bước tạo sản phẩm một lần như đã mô tả trước đó.
4. Tích hợp với PBL
Giờ đây, chúng ta sẽ xem cách tích hợp ứng dụng của bạn với Thư viện Play Billing (PBL). Phần này mô tả các bước tổng quát để tích hợp và cung cấp một đoạn mã cho từng bước. Bạn có thể sử dụng những đoạn mã này làm hướng dẫn để triển khai quy trình tích hợp thực tế.
Để tích hợp ứng dụng của bạn với PBL, hãy làm theo các bước sau:
- Thêm phần phụ thuộc Thư viện Play Billing vào ứng dụng mẫu.
dependencies { val billing_version = "8.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
- Khởi động BillingClient. BillingClient là SDK ứng dụng khách nằm trên ứng dụng của bạn và giao tiếp với Thư viện Google Play Billing. Đoạn mã sau đây cho biết cách khởi chạy ứng dụng thanh toán.
protected BillingClient createBillingClient() { return BillingClient.newBuilder(activity) .setListener(purchasesUpdatedListener) .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()) .enableAutoServiceReconnection() .build(); }
- Kết nối với Google Play.Đoạn mã sau đây minh hoạ cách kết nối với Google Play.
public void startBillingConnection(ImmutableList<Product> productList) { Log.i(TAG, "Product list sent: " + productList); Log.i(TAG, "Starting connection"); billingClient.startConnection( new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Query product details to get the product details list. queryProductDetails(productList); } else { // BillingClient.enableAutoServiceReconnection() will retry the connection on // transient errors automatically. // We don't need to retry on terminal errors (e.g., BILLING_UNAVAILABLE, // DEVELOPER_ERROR). Log.e(TAG, "Billing connection failed: " + billingResult.getDebugMessage()); Log.e(TAG, "Billing response code: " + billingResult.getResponseCode()); } } @Override public void onBillingServiceDisconnected() { Log.e(TAG, "Billing Service connection lost."); } }); }
- Tìm nạp thông tin chi tiết về sản phẩm tính phí một lần.Sau khi tích hợp ứng dụng với PBL, bạn phải tìm nạp thông tin chi tiết về sản phẩm tính phí một lần vào ứng dụng. Đoạn mã sau đây minh hoạ cách tìm nạp thông tin chi tiết về sản phẩm tính phí một lần trong ứng dụng.
Tìm nạpprivate void queryProductDetails(ImmutableList<Product> productList) { Log.i(TAG, "Querying products for: " + productList); QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().setProductList(productList).build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { @Override public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResponse) { // check billingResult Log.i(TAG, "Billing result after querying: " + billingResult.getResponseCode()); // process returned productDetailsList Log.i( TAG, "Print unfetched products: " + productDetailsResponse.getUnfetchedProductList()); setupProductDetailsMap(productDetailsResponse.getProductDetailsList()); billingServiceClientListener.onProductDetailsFetched(productDetailsMap); } }); }
ProductDetails
, sẽ cho bạn một phản hồi tương tự như sau:{ "productId": "consumable_product_01", "type": "inapp", "title": "Shadow Coat (Yolo's Realm | Play Samples)", "name": "Shadow Coat", "description": "A sleek, obsidian coat for stealth and ambushes", "skuDetailsToken": "<---skuDetailsToken--->", "oneTimePurchaseOfferDetails": {}, "oneTimePurchaseOfferDetailsList": [ { "priceAmountMicros": 1990000, "priceCurrencyCode": "USD", "formattedPrice": "$1.99", "offerIdToken": "<--offerIdToken-->", "purchaseOptionId": "buy", "offerTags": [] } ] }, { "productId": "consumable_product_02", "type": "inapp", "title": "Emperor Den (Yolo's Realm | Play Samples)", "name": "Emperor Den", "description": "A fair lair glowing with molten rock and embers", "skuDetailsToken": "<---skuDetailsToken--->", "oneTimePurchaseOfferDetails": {}, "oneTimePurchaseOfferDetailsList": [ { "priceAmountMicros": 2990000, "priceCurrencyCode": "USD", "formattedPrice": "$2.99", "offerIdToken": "<--offerIdToken-->", "purchaseOptionId": "buy", "offerTags": [] } ] }
- Bắt đầu quy trình thanh toán.
public void launchBillingFlow(String productId) { ProductDetails productDetails = productDetailsMap.get(productId); if (productDetails == null) { Log.e( TAG, "Cannot launch billing flow: ProductDetails not found for productId: " + productId); billingServiceClientListener.onBillingResponse( BillingResponseCode.ITEM_UNAVAILABLE, BillingResult.newBuilder().setResponseCode(BillingResponseCode.ITEM_UNAVAILABLE).build()); return; } ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder().setProductDetails(productDetails).build()); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); billingClient.launchBillingFlow(activity, billingFlowParams); }
- Phát hiện và xử lý giao dịch mua. Trong bước này, bạn cần phải:
- Xác minh giao dịch mua
- Cấp quyền cho người dùng
- Thông báo cho người dùng
- Thông báo cho Google về quy trình mua hàng
private void handlePurchase(Purchase purchase) { // Step 1: Send the purchase to your secure backend to verify the purchase following // https://developer.android.com/google/play/billing/security#verify // Step 2: Update your entitlement storage with the purchase. If purchase is // in PENDING state then ensure the entitlement is marked as pending and the // user does not receive benefits yet. It is recommended that this step is // done on your secure backend and can combine in the API call to your // backend in step 1. // Step 3: Notify the user using appropriate messaging. if (purchase.getPurchaseState() == PurchaseState.PURCHASED) { for (String product : purchase.getProducts()) { Log.d(TAG, product + " purchased successfully! "); } } // Step 4: Notify Google the purchase was processed. // For one-time products, acknowledge the purchase. // This sample app (client-only) uses billingClient.acknowledgePurchase(). // For consumable one-time products, consume the purchase // This sample app (client-only) uses billingClient.consumeAsync() // If you have a secure backend, you must acknowledge purchases on your server using the // server-side API. // See https://developer.android.com/google/play/billing/security#acknowledge if (purchase.getPurchaseState() == PurchaseState.PURCHASED && !purchase.isAcknowledged()) { if (shouldConsume(purchase)) { ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build(); billingClient.consumeAsync(consumeParams, consumeResponseListener); } else { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); billingClient.acknowledgePurchase( acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
5. Phân tích lượt bỏ ngang khi mua hàng
Cho đến nay trong lớp học lập trình, các phản hồi của Play Billing tập trung vào một số trường hợp hạn chế như phản hồi USER_CANCELLED, BILLING_UNAVAILABLE, OK và ITEM_ALREADY_OWNED. Tuy nhiên, Dịch vụ thanh toán của Play có thể trả về 13 mã phản hồi khác nhau có thể được kích hoạt bởi nhiều yếu tố thực tế.
Phần này trình bày chi tiết nguyên nhân gây ra phản hồi lỗi USER_CANCELLED
và BILLING_UNAVAILABLE
, đồng thời đề xuất các biện pháp khắc phục có thể thực hiện.
Mã lỗi phản hồi USER_CANCELED
Mã phản hồi này cho biết rằng người dùng đã rời khỏi giao diện người dùng của quy trình mua trước khi hoàn tất giao dịch mua.
Nguyên nhân có thể xảy ra | Bạn có thể làm những việc gì? |
|
|
Mã lỗi phản hồi BILLING_UNAVAILABLE
Mã phản hồi này có nghĩa là không thể hoàn tất giao dịch mua do có vấn đề với nhà cung cấp dịch vụ thanh toán của người dùng hoặc phương thức thanh toán mà họ chọn. Ví dụ: thẻ tín dụng của người dùng đã hết hạn hoặc người dùng ở quốc gia không được hỗ trợ. Mã này không cho biết lỗi với chính hệ thống Play Billing.
Nguyên nhân có thể xảy ra | Bạn có thể làm những việc gì? |
|
|
Chiến lược thử lại cho mã lỗi phản hồi
Các chiến lược thử lại hiệu quả cho lỗi có thể khôi phục từ Thư viện Play Billing (PBL) sẽ khác nhau tuỳ theo bối cảnh, chẳng hạn như các hoạt động tương tác của người dùng trong phiên (như trong khi mua hàng) so với các thao tác ở chế độ nền (chẳng hạn như truy vấn giao dịch mua khi ứng dụng tiếp tục hoạt động). Bạn cần triển khai các chiến lược này vì một số giá trị BillingResponseCode
cho biết các vấn đề tạm thời có thể giải quyết bằng cách thử lại, trong khi những giá trị khác là vĩnh viễn và không yêu cầu thử lại.
Đối với các lỗi gặp phải khi người dùng đang hoạt động, bạn nên sử dụng chiến lược thử lại đơn giản với số lần thử tối đa đã đặt để giảm thiểu sự gián đoạn cho trải nghiệm người dùng. Ngược lại, đối với các thao tác ở chế độ nền (chẳng hạn như xác nhận giao dịch mua mới) không yêu cầu thực thi ngay lập tức, bạn nên dùng phương pháp thời gian đợi luỹ thừa.
Để biết thông tin chi tiết về các mã phản hồi cụ thể và chiến lược thử lại được đề xuất tương ứng, hãy xem phần Xử lý mã phản hồi BillingResult.
6. Các bước tiếp theo
- Tìm hiểu cách tối đa hoá việc tích hợp dịch vụ thanh toán qua Play.
- Hãy nhớ làm theo các phương pháp hay nhất để xác minh và xử lý giao dịch mua trên phần phụ trợ bảo mật của bạn khi người dùng bắt đầu mua những sản phẩm này.
Tài liệu tham khảo
7. Xin chúc mừng!
Xin chúc mừng! Bạn đã thao tác thành công trên Google Play Console để tạo một sản phẩm dùng một lần mới, kiểm thử mã phản hồi thanh toán và phân tích các trường hợp giao dịch mua bị huỷ.
Khảo sát
Chúng tôi rất coi trọng ý kiến phản hồi của bạn về lớp học lập trình này. Hãy cân nhắc dành vài phút để hoàn thành bản khảo sát của chúng tôi.