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 sản phẩm tính phí một lần, tích hợp ứng dụng với Thư viện Play Billing (PBL) và phân tích lý do khiến người dùng bỏ qua giao dịch mua.
Lưu ý: Để hoàn tất lớp học lập trình này thành công, bạn cần có quyền truy cập vào tính năng Nhiều lựa chọn mua và ưu đãi cho sản phẩm tính phí một lần. Tính năng này nằm trong chương trình tiếp cận sớm (EAP). Các sản phẩm và tính năng trong EAP được cung cấp "nguyên trạng" và có thể có phạm vi hỗ trợ hạn chế. Để truy cập vào tính năng EAP, hãy gửi yêu cầu bằng Biểu mẫu bày tỏ sự quan tâm với EAP cho sản phẩm tính phí một lần. Tuy nhiên, nếu bạn chỉ muốn tìm hiểu cách phân tích tình trạng người dùng bỏ qua giao dịch mua bằng cách sử dụng mã phản hồi của Play Billing, hãy chuyển trực tiếp đến phần Phân tích tình trạng người dùng bỏ qua giao dịch mua của lớp học lập trình này.
Đối tượng người xem
Lớp học lập trình này nhắm đến các 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 tính phí một lần.
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 với PBL.
- Cách xử lý các giao dịch mua sản phẩm tính phí một lần có thể tiêu thụ và không thể tiêu thụ trong PBL.
- Cách phân tích tình trạng người dùng bỏ qua giao dịch mua.
Những điều bạn cần...
- 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 hoạt động đầy đủ, có mã nguồn hoàn chỉnh thể hiện 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 các sản phẩm tính phí một lần
- Các tình huống mua dẫn đến các phản hồi thanh toán sau:
BILLING_UNAVAILABLEUSER_CANCELLEDOKITEM_ALREADY_OWNED
Video minh hoạ sau đây cho thấy ứng dụng mẫu sẽ trông như thế nào và hoạt động ra sao sau khi được triển khai và chạy.
Điều kiện tiên quyết
Trước khi 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 ứng dụng, bạn có thể chỉ định bất kỳ tên ứng dụng nào 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 gói ứng dụng Android 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 ứ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 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 sẽ 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 sau trong lớp học lập trình này. - Tạo gói ứng dụng Android có chữ 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 có chữ ký đã 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.
- Nhấp vào Create app (Tạo ứng dụng). Thao tác này sẽ mở trang Create app (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 chi tiết khác liên quan đến ứng dụng.
- Nhấp vào Create app (Tạo ứng dụng). Thao tác này sẽ tạo một ứng dụng trong Google Play Console.
Bây giờ, bạn có thể tải gói ứng dụng có chữ ký của ứng dụng mẫu lên.
Tải gói ứng dụng có chữ ký lên
- Tải gói ứng dụng có chữ ký lên kênh thử nghiệm nội bộ của Google Play Console. Chỉ sau khi tải lên, bạn mới 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.
- Nhấp vào Test and release > Testing > Internal release > Create new release (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 và tải tệp gói ứng dụng có chữ ký lên.
- Nhấp vào Next (Tiếp theo), sau đó nhấp vào Save and publish (Lưu và phát hành).
Bây giờ, 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 Monetize with Play (Kiếm tiền bằng Play) > Products (Sản phẩm) > One-time products (Sản phẩm tính phí một lần).
- Nhấp vào Create one-time product (Tạo sản phẩm tính phí một lần).
- Nhập thông tin chi tiết về sản phẩm sau:
- Product ID (Mã sản phẩm): Nhập mã sản phẩm duy nhất. Nhập
one_time_product_01. - (Không bắt buộc) Thẻ: Thêm các thẻ có liên quan.
- Name (Tên): Nhập tên sản phẩm. Ví dụ:
Product name(Tên sản phẩm). - Description (Mô tả): Nhập nội dung mô tả sản phẩm. Ví dụ:
Product description(Mô tả sản phẩm). - (Không bắt buộc) Thêm hình ảnh biểu tượng: Tải biểu tượng đại diện cho sản phẩm của bạn lên.
- Product ID (Mã sản phẩm): Nhập mã sản phẩm duy nhất. Nhập
- Nhấp vào Next (Tiếp theo).
- Thêm lựa chọn mua và định cấu hình 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, xác định cách cấp quyền sử dụng, giá và phạm vi cung cấp theo khu vực. Đối với lớp học lập trình này, chúng ta sẽ thêm lựa chọn Buy (Mua) tiêu chuẩn cho sản phẩm.Trong phần Purchase option (Lựa chọn mua), hãy nhập các thông tin sau:
- Purchase Option ID (Mã lựa chọn mua): Nhập mã lựa chọn mua. Ví dụ:
buy. - Purchase type (Loại giao dịch mua): Chọn Buy (Mua).
- (Không bắt buộc) Thẻ: Thêm các thẻ dành riêng cho lựa chọn mua này.
- (Không bắt buộc) Nhấp vào Advanced options (Tuỳ chọn nâng cao) để định cấu hình các tuỳ chọn nâng cao. Để phục vụ mục đích của lớp học lập trình này, bạn có thể bỏ qua việc định cấu hình các tuỳ chọn nâng cao.
- Purchase Option ID (Mã lựa chọn mua): Nhập mã lựa chọn mua. Ví dụ:
- Trong phần Availability and pricing (Phạm vi cung cấp và giá), hãy nhấp vào Set prices (Đặt giá) > Bulk edit pricing (Chỉnh sửa giá hàng loạt).
- Chọn tuỳ chọn Country / region (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 Continue (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 Apply (Áp dụng).
- Nhấp vào Save (Lưu) rồi nhấp vào Activate (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 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 các mã sản phẩm khác. Trong trường hợp đó, 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 Monetize with Play (Kiếm tiền bằng Play) > Products (Sản phẩm) > One-time products (Sản phẩm tính phí một lần). Sau đó, nhấp vào Create one-time product (Tạo sản phẩm tính phí một lần) và lặp lại các bước từ 3 đến 9.
Video về cách tạo sản phẩm tính phí một lần
Video mẫu sau đây cho thấy các bước tạo sản phẩm tính phí một lần đã được mô tả trước đó.
4. Tích hợp với PBL
Bây giờ, chúng ta sẽ xem cách tích hợp ứng dụng với Thư viện Play Billing (PBL). Phần này mô tả các bước tích hợp cấp cao và cung cấp một đoạn mã cho từng bước. Bạn có thể sử dụng các đ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 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 nằm trên ứng dụng của bạn và giao tiếp với Thư viện Play Billing. Đoạn mã sau đây cho biết cách khởi động ứ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 cho biết 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 chi tiết 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 chi tiết sản phẩm tính phí một lần vào ứng dụng. Đoạn mã sau đây cho biết cách tìm nạp chi tiết sản phẩm tính phí một lần trong ứng dụng.
Việc 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); } }); }ProductDetailssẽ cung cấp 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:
- Xác minh giao dịch mua
- Cấp quyền sử dụng 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
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 tình trạng người dùng bỏ qua giao dịch mua
Cho đến nay trong lớp học lập trình này, các phản hồi của Play Billing tập trung vào các tình huống hạn chế như phản hồi USER_CANCELLED, BILLING_UNAVAILABLE, OK và ITEM_ALREADY_OWNED. Tuy nhiên, Play Billing 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ố trong thế giới thực.
Phần này trình bày chi tiết về nguyên nhân gây ra các phản hồi lỗi USER_CANCELLED và BILLING_UNAVAILABLE, đồng thời đề xuất các hành động khắc phục có thể triển khai.
Mã lỗi phản hồi USER_CANCELED
Mã phản hồi này cho biết người dùng đã bỏ qua 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 đang ở một 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 thanh toán của 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
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ỳ thuộc vào bối cảnh, chẳng hạn như tương tác của người dùng trong phiên (như trong quá trình mua) so với các thao tác trong nền (chẳng hạn như truy vấn giao dịch mua khi tiếp tục ứng dụng). Việc triển khai các chiến lược này là rất quan trọng vì một số giá trị BillingResponseCode biểu thị các vấn đề tạm thời có thể được giải quyết bằng cách thử lại, trong khi các 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 trong nề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), exponential backoff (thời gian chờ luỹ thừa) là phương pháp được đề xuất.
Để 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 bài viết 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á hiệu quả của việc tích hợp Google Play Billing.
- 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ợ an toàn của bạn sau khi người dùng bắt đầu mua các 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 đã điều hướng thành công Google Play Console để tạo một sản phẩm tính phí một lần mới, kiểm thử mã phản hồi thanh toán, phân tích tình trạng người dùng bỏ qua giao dịch mua.
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 dành vài phút để hoàn thành bản khảo sát của chúng tôi.