1. Giới thiệu
Lớp học lập trình này hướng dẫn bạn cách sử dụng Google Play Billing Library (PBL) để quản lý các thay đổi đối với gói thuê bao. Bạn sẽ khám phá cách các chế độ thay thế khác nhau ảnh hưởng đến giá và quyền của người dùng trong khi tìm hiểu cách xử lý Thông báo theo thời gian thực dành cho nhà phát triển (RTDN) ở phía phụ trợ.
Đố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, cung cấp hướng dẫn về cách triển khai các tính năng quản lý gói thuê bao phức tạp. Hướng dẫn này giúp bạn mang đến cho người dùng trải nghiệm liền mạch khi nâng cấp, hạ cấp hoặc chuyển đổi giữa các gói thuê bao khác nhau.
Kiến thức bạn sẽ học được...
- Cách tạo Gói thuê bao trong Play Developer Console.
- Cách chọn
ReplacementModechính xác (ví dụ:WITH_TIME_PRORATIONso vớiDEFERRED) để phù hợp với chính sách nâng cấp và hạ cấp của ứng dụng. - Cách định cấu hình
BillingFlowParamstronglaunchBillingFlowđể kích hoạt quy trình mua hàng trên Google Play cho một yêu cầu thay thế gói thuê bao. - Cách sử dụng Thông báo theo thời gian thực dành cho nhà phát triển (RTDN) và API
purchases.subscriptionsv2để thu hồi quyền truy cập cũ và cấp quyền truy cập mới một cách an toàn trên phần phụ trợ
Bạn cần có
- 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.
- Ứ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
Lớp học lập trình này sử dụng một ứng dụng Android mẫu để cho bạn thấy cách triển khai tính năng thay thế gói thuê bao trong PBL. Ứng dụng mẫu được thiết kế để trở thành một ứng dụng Android có đầy đủ chức năng và mã nguồn hoàn chỉnh, cho thấy các khía cạnh sau:
- Tích hợp ứng dụng với PBL
- Triển khai tính năng thay thế gói thuê bao
Nếu đã quen với tính năng thay thế gói thuê bao và PBL, bạn có thể tải ứng dụng mẫu xuống và dùng thử.
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 và bật các tính năng kiếm tiền. Ngoài ra, bạn có thể sử dụng một ứng dụng hiện có trong Play Console. Nếu ứng dụng của bạn chưa bật các tính năng kiếm tiền, hãy làm theo các bước này để thiết lập.
- Cài đặt Android Studio.
Tạo
Cách tạo ứng dụng mẫu theo yêu cầu để làm theo lớp học lập trình:
- Tải ứng dụng mẫu xuống từ GitHub.
- Cập nhật
applicationIdtrongbuild.gradlecủa ứng dụng mẫu để phản ánh Application Id của ứng dụng trong Play Developer Console. - Tạo ứng dụng mẫu.
Lưu ý: Thao tác này sẽ tạo thành công ứng 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ì bạn chưa tạo các gói thuê bao bắt buộc trong Play Console. Phần tiếp theo sẽ đề cập đến việc tạo gói thuê bao trong Developer Console.
3. Tạo gói thuê bao trong Play Console
Hệ thống gói thuê bao trên Google Play giúp bạn linh hoạt trong cách tạo, quản lý và bán gói thuê bao. Trong Play Console, bạn có thể thiết lập các gói thuê bao có nhiều gói cơ bản, mỗi gói cơ bản có nhiều ưu đãi. Mỗi gói thuê bao có thể áp dụng nhiều mô hình tính giá và điều kiện tham gia. Trong lớp học lập trình này, bạn sẽ tạo 3 gói thuê bao: Gói Premium, Gói cơ bản và Gói Lite, mô phỏng một gói thuê bao điển hình ở nhiều mức giá. Mỗi gói thuê bao sẽ có một gói cơ bản định kỳ hằng tháng.
Đăng ký nhận tin
Cách tạo một gói thuê bao mới
- Mở Play Console rồi chuyển đến trang Gói thuê bao (Kiếm tiền qua Play > Sản phẩm > Gói thuê bao)
- Nhấp vào Tạo gói thuê bao.
- Nhập thông tin chi tiết về gói thuê bao của bạn:
- ProductID : Nhập một mã sản phẩm riêng biệt. Nhập
premium_plan. - Tên : Nhập một tên ngắn cho gói thuê bao. Ví dụ:
Premium Plan.
- ProductID : Nhập một mã sản phẩm riêng biệt. Nhập
- Nhấp vào Tạo.
Tạo gói Base Plan
- Mở Play Console rồi chuyển đến trang Gói thuê bao (Kiếm tiền qua Play > Sản phẩm > Gói thuê bao)
- Nhấp vào mũi tên phải bên cạnh gói thuê bao mà bạn muốn tạo gói cơ bản để xem chi tiết về gói thuê bao đó.
- Nhấp vào Thêm gói cơ bản.
- Nhập mã gói cơ bản. Ví dụ:
monthly-auto-renewing. - Chọn loại hình là Tự động gia hạn.
- Đối với gói cơ bản Tự động gia hạn, hãy đặt những thông tin sau:
- Kỳ thanh toán: Hằng tháng.
- Thời gian gia hạn: 7 ngày.
- Thay đổi về ưu đãi và gói thanh toán: Tính phí vào ngày lập hoá đơn.
- Đăng ký lại: Cho phép.
- Trong phần Giá và phạm vi cung cấp, hãy nhấp vào Đặt giá để đặt giá cho gói cơ bản.
- Chọn tất cả quốc gia và khu vực rồi nhấp vào Đặt giá.
- Đặt giá là 10 USD cho gói cơ bản này rồi nhấp vào Cập nhật.
- Sau khi bạn đặt giá cho gói cơ bản, hãy nhấp vào Lưu rồi nhấp vào Kích hoạt ở dưới cùng bên phải.
Tạo gói thuê bao cho ứng dụng mẫu
Để phục vụ mục đích của lớp học lập trình này, hãy tạo thêm 2 gói thuê bao có cấu hình như sau:
- Gói cơ bản
- Mã sản phẩm: basic_plan
- Tên: Gói cơ bản
- Mã gói cơ bản: monthly-auto-renewing
- Giá: 5 USD
- Gói Lite
- Mã sản phẩm: lite_plan
- Tên: Gói Lite
- Mã gói cơ bản: monthly-auto-renewing
- Giá: 3000 VND
Ứng dụng mẫu được định cấu hình để sử dụng các mã sản phẩm và mã gói cơ bản này. Bạn có thể tạo nhiều gói thuê bao với nhiều cấu hình. 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 đã tạo.
Video hướng dẫn tạo gói thuê bao
Video sau đây minh hoạ các bước đã mô tả trước đó để tạo gói thuê bao trong Play Developer Console.
4. Thay thế gói thuê bao
Nhà phát triển tích hợp với PBL có thể cung cấp nhiều lựa chọn thay đổi gói thuê bao cho những người đăng ký hiện tại để phù hợp hơn với nhu cầu của họ:
- Nếu bán nhiều cấp thuê bao, chẳng hạn như gói thuê bao cơ bản và cao cấp, thì bạn có thể cho phép người dùng chuyển đổi giữa các cấp bằng cách mua gói ưu đãi hoặc gói cơ bản của một gói thuê bao khác.
- Bạn có thể cho phép người dùng thay đổi kỳ thanh toán hiện tại, chẳng hạn như chuyển từ gói hằng tháng sang Gói hằng năm.
- Bạn cũng có thể cho phép người dùng chuyển đổi giữa gói tự động gia hạn và gói trả trước.
Khi người dùng quyết định nâng cấp, hạ cấp hoặc thay đổi gói thuê bao, bạn sẽ chỉ định một chế độ thay thế giúp xác định cách áp dụng giá trị chia theo tỷ lệ của kỳ thanh toán hiện tại và thời điểm diễn ra thay đổi về quyền đối với người dùng.
Thư viện Play Billing cung cấp một số lựa chọn ReplacementMode để kiểm soát hành vi này.
Các chế độ thay thế hiện có
WITH_TIME_PRORATION: Gói thuê bao được nâng cấp hoặc hạ cấp ngay lập tức. Hệ thống sẽ điều chỉnh thời gian còn lại dựa trên mức chênh lệch giá và cấp một khoản tín dụng tương đương vào gói thuê bao mới bằng cách cập nhật ngày thanh toán tiếp theo. Đây là hành vi mặc định.CHARGE_PRORATED_PRICE: Mặt hàng thuê bao được nâng cấp ngay lập tức và chu kỳ thanh toán vẫn giữ nguyên. Sau đó, hệ thống sẽ tính mức chênh lệch giá cho khoảng thời gian còn lại của người dùng.CHARGE_FULL_PRICE: Gói thuê bao được nâng cấp hoặc hạ cấp ngay lập tức và hệ thống sẽ tính phí người dùng ở mức giá đầy đủ đối với quyền mới này ngay lập tức. Hệ thống sẽ chuyển giá trị còn lại của gói thuê bao trước đó sang mức quyền tương tự hoặc sẽ chia thời gian theo tỷ lệ khi chuyển sang một quyền khác.WITHOUT_PRORATION: Gói thuê bao được nâng cấp hoặc hạ cấp ngay lập tức, đồng thời hệ thống sẽ tính giá mới khi người dùng gia hạn gói thuê bao. Chu kỳ thanh toán vẫn giữ nguyên.DEFERRED: Gói thuê bao chỉ được nâng cấp hoặc hạ cấp khi người dùng gia hạn gói thuê bao.
5. WITH_TIME_PRORATION
Trong chế độ thay thế này, mặt hàng thuê bao sẽ được nâng cấp hoặc hạ cấp ngay lập tức. Hệ thống sẽ điều chỉnh thời gian còn lại dựa trên mức chênh lệch giá và cấp một khoản tín dụng tương đương vào gói thuê bao mới bằng cách dời ngày thanh toán tiếp theo. Đây là hành vi mặc định.
Tình huống ví dụ
Một người dùng chuyển từ gói Basic (4,99 USD/tháng) sang gói Premium (9,99 USD/tháng) vào ngày 15 tháng 4, tức là giữa chu kỳ thanh toán hằng tháng.
Trong tình huống này:
- Người dùng sẽ có quyền sử dụng gói Premium ngay lập tức.
- Google Play tự động tính toán khoảng thời gian tính phí theo tỷ lệ. Giả sử nếu Play tính toán rằng 15 ngày còn lại của gói Cơ bản tương đương với 7 ngày của gói Cao cấp, thì ngày lập hóa đơn tiếp theo sẽ được chuyển sang ngày 21 tháng 4.
- Người dùng không cần thanh toán ngay.
Đoạn mã
// ProductDetails for the plan to be switched to
ProductDetails productDetails = ...;
// The specific offer token for the toBeSwitched plan's base plan
String offerToken = "...";
// The purchase token of the user's current subscription
String oldPurchaseToken = "...";
// The productId for the user's current subscription
String oldProductId = "...";
// The replacementMode to replace the user's subscription
int replacementMode = SubscriptionProductReplacementParams.ReplacementMode.WITH_TIME_PRORATION;
SubscriptionProductReplacementParams subscriptionProductReplacementParams =
SubscriptionProductReplacementParams.newBuilder()
.setOldProductId(oldProductId)
.setReplacementMode(replacementMode)
.build();
ProductDetailsParams productDetailsParams =
ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.setSubscriptionProductReplacementParams(subscriptionProductReplacementParams)
.setOfferToken(offerToken)
.build();
List<ProductDetailsParams> productDetailsParamsList = ImmutableList.of(productDetailsParams);
BillingFlowParams billingFlowParams =
BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.setSubscriptionUpdateParams(
SubscriptionUpdateParams.newBuilder().setOldPurchaseToken(oldPurchaseToken).build())
.build();
billingClient.launchBillingFlow(activity, billingFlowParams);
Nâng cấp với WITH_TIME_PRORATION
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.WITH_TIME_PRORATION. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Premium.
Quyền của người dùng sẽ được nâng cấp lên gói Premium ngay lập tức. Số tiền mà người dùng phải thanh toán ngay là 0 USD. Giá trị còn lại của gói Cơ bản được tính theo tỷ lệ thành thời gian sử dụng gói Cao cấp, do đó, ngày gia hạn tiếp theo sẽ được dời lên. Người dùng sẽ bị tính phí gia hạn là 9,99 USD vào ngày thanh toán mới được điều chỉnh.
Hạ cấp với WITH_TIME_PRORATION
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.WITH_TIME_PRORATION. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Lite.
Quyền của người dùng sẽ bị hạ cấp xuống gói Lite ngay lập tức. Số tiền phải thanh toán ngay là 0 USD. Giá trị còn lại của gói Cơ bản được tính theo tỷ lệ thời gian cho gói Lite, giúp kéo dài đáng kể ngày gia hạn tiếp theo. Người dùng sẽ bị tính phí gia hạn là 2,99 USD vào ngày thanh toán mới được điều chỉnh.
Kết luận
Trong phần này, bạn đã tìm hiểu cách WITH_TIME_PRORATION sửa đổi quyền của người dùng mà không tính phí ngay bằng cách điều chỉnh thời gian cho đến lần gia hạn tiếp theo dựa trên chênh lệch giá. Đây là một chiến lược mặc định hiệu quả để nâng cấp hoặc hạ cấp người dùng.
6. CHARGE_PRORATED_PRICE
Ở chế độ thay thế này, mặt hàng thuê bao sẽ được nâng cấp ngay lập tức và chu kỳ thanh toán vẫn giữ nguyên. Sau đó, hệ thống sẽ tính mức chênh lệch giá cho khoảng thời gian còn lại của người dùng.
Lưu ý: Lựa chọn này chỉ dành cho việc nâng cấp gói thuê bao, trong đó, giá mỗi đơn vị thời gian sẽ tăng lên.
Tình huống ví dụ
Một người dùng gói Cơ bản (4,99 USD/tháng) quyết định nâng cấp lên gói Premium (9,99 USD/tháng) vào ngày 20 tháng 4 khi còn khoảng 10 ngày nữa là hết chu kỳ thanh toán hằng tháng.
Trong tình huống này:
- Người dùng sẽ có quyền sử dụng gói Premium ngay lập tức.
- Người dùng sẽ bị tính ngay phần chênh lệch theo tỷ lệ cho 10 ngày còn lại của chu kỳ thanh toán hiện tại. Số tiền này tương đương với khoảng 2,99 USD, tức là giá trị của gói Premium trong 10 ngày.
- Ngày thanh toán của người dùng không thay đổi.
Đoạn mã
// ProductDetails for the plan to be switched to
ProductDetails productDetails = ...;
// The specific offer token for the toBeSwitched plan's base plan
String offerToken = "...";
// The purchase token of the user's current subscription
String oldPurchaseToken = "...";
// The productId for the user's current subscription
String oldProductId = "...";
// The replacementMode to replace the user's subscription
int replacementMode = SubscriptionProductReplacementParams.ReplacementMode.CHARGE_PRORATED_PRICE;
SubscriptionProductReplacementParams subscriptionProductReplacementParams =
SubscriptionProductReplacementParams.newBuilder()
.setOldProductId(oldProductId)
.setReplacementMode(replacementMode)
.build();
ProductDetailsParams productDetailsParams =
ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.setSubscriptionProductReplacementParams(subscriptionProductReplacementParams)
.setOfferToken(offerToken)
.build();
List<ProductDetailsParams> productDetailsParamsList = ImmutableList.of(productDetailsParams);
BillingFlowParams billingFlowParams =
BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.setSubscriptionUpdateParams(
SubscriptionUpdateParams.newBuilder().setOldPurchaseToken(oldPurchaseToken).build())
.build();
billingClient.launchBillingFlow(activity, billingFlowParams);
Nâng cấp với CHARGE_PRORATED_PRICE
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.CHARGE_PRORATED_PRICE. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Premium.
Người dùng sẽ được nâng cấp lên gói Premium ngay lập tức và vẫn giữ nguyên ngày gia hạn ban đầu. Số tiền bạn phải trả ngay là phần chênh lệch theo tỷ lệ giữa giá của gói Premium và gói Basic cho số ngày còn lại của chu kỳ hiện tại. Vào ngày gia hạn, người dùng sẽ bị tính phí gia hạn Premium đầy đủ là 9,99 USD.
Hạ cấp với CHARGE_PRORATED_PRICE
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.CHARGE_PRORATED_PRICE. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Lite.
Chế độ thay thế này sẽ gây ra lỗi trong quá trình hạ cấp vì chế độ này chỉ dùng được cho việc nâng cấp mặt hàng thuê bao khi giá mỗi đơn vị thời gian tăng lên. Quy trình thanh toán sẽ không thành công và hiển thị lỗi cho người dùng, cho biết rằng chế độ chia theo tỷ lệ không được hỗ trợ cho việc hạ cấp.
Kết luận
Phần này giải thích cách CHARGE_PRORATED_PRICE cho phép nâng cấp ngay lập tức bằng cách tính cho người dùng chính xác mức chênh lệch giá cho kỳ thanh toán còn lại mà vẫn giữ nguyên chu kỳ thanh toán. Trường hợp này hữu ích khi người dùng muốn nâng cấp lên một cấp đắt tiền hơn mà không thay đổi ngày thanh toán.
7. CHARGE_FULL_PRICE
Trong chế độ thay thế này, gói thuê bao được nâng cấp hoặc hạ cấp ngay lập tức và hệ thống sẽ tính phí người dùng ở mức giá đầy đủ đối với quyền mới ngay lập tức. Hệ thống sẽ chuyển giá trị còn lại của gói thuê bao trước đó sang mức quyền tương tự hoặc sẽ chia thời gian theo tỷ lệ khi chuyển sang một quyền khác.
Tình huống ví dụ
Một người dùng đang sử dụng gói Basic (4,99 USD/tháng kể từ ngày 1 tháng 4). Vào ngày 20 tháng 4, người dùng muốn chuyển sang gói Premium (9,99 USD/tháng).
Trong tình huống này:
- Người dùng sẽ bị tính ngay mức giá đầy đủ của gói Premium (9,99 USD).
- Giá trị còn lại của gói Cơ bản (ví dụ: 10 ngày) sẽ được chuyển đổi thành thời gian tương đương cho gói Cao cấp. Trong ví dụ này, 10 ngày sử dụng gói Cơ bản tương đương với 5 ngày sử dụng gói Cao cấp.
- Ngày gia hạn tiếp theo của người dùng sẽ được điều chỉnh để bao gồm khoảng thời gian tính phí theo tỷ lệ này. Vì vậy, ngày gia hạn sẽ là ngày 25 tháng 5 (ngày 20 tháng 4 + 1 tháng + 5 ngày).
- Các lần gia hạn tiếp theo sẽ diễn ra hằng tháng, bắt đầu từ ngày 25 tháng 5.
Đoạn mã
// ProductDetails for the plan to be switched to
ProductDetails productDetails = ...;
// The specific offer token for the toBeSwitched plan's base plan
String offerToken = "...";
// The purchase token of the user's current subscription
String oldPurchaseToken = "...";
// The productId for the user's current subscription
String oldProductId = "...";
// The replacementMode to replace the user's subscription
int replacementMode = SubscriptionProductReplacementParams.ReplacementMode.CHARGE_FULL_PRICE;
SubscriptionProductReplacementParams subscriptionProductReplacementParams =
SubscriptionProductReplacementParams.newBuilder()
.setOldProductId(oldProductId)
.setReplacementMode(replacementMode)
.build();
ProductDetailsParams productDetailsParams =
ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.setSubscriptionProductReplacementParams(subscriptionProductReplacementParams)
.setOfferToken(offerToken)
.build();
List<ProductDetailsParams> productDetailsParamsList = ImmutableList.of(productDetailsParams);
BillingFlowParams billingFlowParams =
BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.setSubscriptionUpdateParams(
SubscriptionUpdateParams.newBuilder().setOldPurchaseToken(oldPurchaseToken).build())
.build();
billingClient.launchBillingFlow(activity, billingFlowParams);
Nâng cấp với CHARGE_FULL_PRICE
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.CHARGE_FULL_PRICE. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Premium.
Người dùng sẽ được nâng cấp lên gói Premium ngay lập tức. Số tiền bạn phải thanh toán ngay là giá đầy đủ của gói Premium – 9,99 USD. Mọi giá trị còn lại của gói Basic sẽ được chuyển đổi thành thời gian sử dụng gói Premium mới, giúp kéo dài thêm một chút ngày gia hạn đầu tiên. Sau đó, số tiền gia hạn sẽ là 9,99 USD cho mỗi chu kỳ.
Hạ cấp với CHARGE_FULL_PRICE
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.CHARGE_FULL_PRICE. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Lite.
Người dùng sẽ được hạ cấp xuống gói Lite ngay lập tức và một chu kỳ thanh toán mới sẽ bắt đầu. Số tiền phải trả ngay là giá mục tiêu đầy đủ là 2,99 USD. Phần chưa sử dụng của gói Cơ bản sẽ được tính theo tỷ lệ vào thời gian của gói Lite mới, kéo dài ngày gia hạn đầu tiên. Sau đó, số tiền gia hạn sẽ là 2,99 USD mỗi chu kỳ.
Kết luận
Trong phần này, chúng ta đã đề cập đến cách CHARGE_FULL_PRICE tính phí đầy đủ cho người dùng vào ngày chuyển đổi, bắt đầu một chu kỳ thanh toán mới ngay lập tức. Mọi số dư còn lại của gói trước đó sẽ được áp dụng theo tỷ lệ cho đến ngày gia hạn tiếp theo.
8. WITHOUT_PRORATION
Ở chế độ thay thế này, gói thuê bao được nâng cấp hoặc hạ cấp ngay lập tức và hệ thống sẽ tính giá mới khi người dùng gia hạn gói thuê bao.
Tình huống ví dụ
Một người dùng đang sử dụng gói Basic (4,99 USD/tháng kể từ ngày 1 tháng 4). Vào ngày 20 tháng 4, người dùng muốn chuyển sang gói Premium (9,99 USD/tháng).
Trong tình huống này:
- Người dùng sẽ có quyền sử dụng gói Premium ngay lập tức.
- Người dùng sẽ không phải trả mức giá cao hơn là 9,99 USD cho đến ngày gia hạn gói thuê bao tiếp theo (ngày 1 tháng 5).
Đoạn mã
// ProductDetails for the plan to be switched to
ProductDetails productDetails = ...;
// The specific offer token for the toBeSwitched plan's base plan
String offerToken = "...";
// The purchase token of the user's current subscription
String oldPurchaseToken = "...";
// The productId for the user's current subscription
String oldProductId = "...";
// The replacementMode to replace the user's subscription
int replacementMode = SubscriptionProductReplacementParams.ReplacementMode.WITHOUT_PRORATION;
SubscriptionProductReplacementParams subscriptionProductReplacementParams =
SubscriptionProductReplacementParams.newBuilder()
.setOldProductId(oldProductId)
.setReplacementMode(replacementMode)
.build();
ProductDetailsParams productDetailsParams =
ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.setSubscriptionProductReplacementParams(subscriptionProductReplacementParams)
.setOfferToken(offerToken)
.build();
List<ProductDetailsParams> productDetailsParamsList = ImmutableList.of(productDetailsParams);
BillingFlowParams billingFlowParams =
BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.setSubscriptionUpdateParams(
SubscriptionUpdateParams.newBuilder().setOldPurchaseToken(oldPurchaseToken).build())
.build();
billingClient.launchBillingFlow(activity, billingFlowParams);
Nâng cấp mà KHÔNG_TÍNH_PHẦN_CHÊNH_LỆCH
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.WITHOUT_PRORATION. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Premium.
Người dùng sẽ được nâng cấp lên gói Premium ngay lập tức mà vẫn giữ nguyên ngày gia hạn hiện tại. Số tiền phải thanh toán ngay là 0 USD. Người dùng có quyền sử dụng gói Premium trong thời gian còn lại của chu kỳ đã cho, trước khi chuyển sang mức gia hạn mới là 9,99 USD vào ngày thanh toán tiếp theo.
Hạ cấp mà KHÔNG TÍNH PHÍ THEO TỶ LỆ
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.WITHOUT_PRORATION. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Lite.
Người dùng sẽ bị hạ cấp xuống gói Lite ngay lập tức và mất các tính năng của gói Basic mà họ đã thanh toán. Số tiền phải thanh toán ngay là 0 USD. Chu kỳ thanh toán vẫn diễn ra bình thường và người dùng sẽ thanh toán mức giá mới thấp hơn là 2,99 USD vào lần gia hạn theo lịch tiếp theo.
Kết luận
Phần này minh hoạ cách WITHOUT_PRORATION ngay lập tức hoán đổi các quyền của người dùng mà không tính phí thanh toán trong khi vẫn giữ nguyên chu kỳ thanh toán.
9. DEFERRED
Ở chế độ thay thế này, gói thuê bao chỉ được nâng cấp hoặc hạ cấp khi người dùng gia hạn gói đó, nhưng giao dịch mua mới sẽ diễn ra ngay lập tức. Mặt hàng hiện tại được đặt thành không gia hạn và hết hạn vào cuối chu kỳ thanh toán hiện tại, trong khi quyền mới được yêu cầu bắt đầu ngay sau đó.
Tình huống ví dụ
Một người dùng đang sử dụng gói Basic (4,99 USD/tháng kể từ ngày 1 tháng 4). Vào ngày 20 tháng 4, người dùng muốn chuyển sang gói Premium (9,99 USD/tháng).
Trong tình huống này:
- Người dùng không phải trả phí ngay lập tức.
- Người dùng vẫn có thể sử dụng các tính năng của gói Basic cho đến hết chu kỳ thanh toán hiện tại (ngày 30 tháng 4).
- Gói thuê bao sẽ tự động nâng cấp lên gói Premium vào ngày gia hạn tiếp theo (ngày 1 tháng 5).
Đoạn mã
// ProductDetails for the plan to be switched to
ProductDetails productDetails = ...;
// The specific offer token for the toBeSwitched plan's base plan
String offerToken = "...";
// The purchase token of the user's current subscription
String oldPurchaseToken = "...";
// The productId for the user's current subscription
String oldProductId = "...";
// The replacementMode to replace the user's subscription
int replacementMode = SubscriptionProductReplacementParams.ReplacementMode.DEFERRED;
SubscriptionProductReplacementParams subscriptionProductReplacementParams =
SubscriptionProductReplacementParams.newBuilder()
.setOldProductId(oldProductId)
.setReplacementMode(replacementMode)
.build();
ProductDetailsParams productDetailsParams =
ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.setSubscriptionProductReplacementParams(subscriptionProductReplacementParams)
.setOfferToken(offerToken)
.build();
List<ProductDetailsParams> productDetailsParamsList = ImmutableList.of(productDetailsParams);
BillingFlowParams billingFlowParams =
BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.setSubscriptionUpdateParams(
SubscriptionUpdateParams.newBuilder().setOldPurchaseToken(oldPurchaseToken).build())
.build();
billingClient.launchBillingFlow(activity, billingFlowParams);
Nâng cấp bằng DEFERRED
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.DEFERRED. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Premium.
Người dùng sẽ tiếp tục sử dụng gói Basic cho đến hết chu kỳ thanh toán hiện tại. Số tiền phải thanh toán ngay là 0 USD. Vào ngày gia hạn, quyền của họ sẽ được nâng cấp lên gói Premium và họ sẽ phải trả khoản phí gia hạn mới là 9,99 USD.
Hạ cấp bằng DEFERRED
Cách mô phỏng tình huống này:
- Trong
MainActivitycủa ứng dụng mẫu, hãy cập nhậtreplacementModetrong đoạn mã thànhSubscriptionProductReplacementParams.ReplacementMode.DEFERRED. - Tạo lại và chạy ứng dụng.
- Huỷ các gói thuê bao hiện có (nếu có) trong Cửa hàng Google Play và gói thuê bao đó sẽ hết hạn.
- Mua gói Cơ bản.
- Chuyển sang gói Lite.
Người dùng sẽ tiếp tục sử dụng gói Basic cho đến hết chu kỳ thanh toán hiện tại. Số tiền phải thanh toán ngay là 0 USD. Vào ngày gia hạn, quyền của họ sẽ được nâng cấp lên gói Lite và họ sẽ phải trả khoản phí gia hạn mới là 2,99 USD.
Kết luận
Phần này giải thích cách chế độ thay thế DEFERRED hoãn việc nâng cấp hoặc hạ cấp cho đến khi hết thời gian có tính phí của người dùng đang hoạt động. Điều này đặc biệt lý tưởng cho việc hạ cấp để tránh mất các tính năng đã mua.
10. Xử lý phụ trợ và phía máy khách
Sau khi người dùng kích hoạt thành công việc thay thế gói thuê bao, hãy đảm bảo cả ứng dụng và phần phụ trợ của bạn đều xử lý chính xác thay đổi này để tránh các vấn đề như gián đoạn dịch vụ hoặc tính phí trùng lặp.
Tình huống ví dụ
- Người dùng có gói Cơ bản hằng tháng (product_id
basic_planvà purchase_tokenbasic_purchase_token_123). - Người dùng chuyển sang gói Premium bằng chế độ thay thế ngay lập tức (một trong các chế độ
WITHOUT_PRORATION,WITH_TIME_PRORATION,CHARGE_PRORATED_PRICE,CHARGE_FULL_PRICE) - Sau khi chuyển đổi gói thuê bao thành công, Google sẽ coi đây là một gói thuê bao MỚI và tạo một mã thông báo giao dịch mua mới, khác biệt cho gói Premium (product_id
premium_planvà purchase_tokenpremium_purchase_token_123).
Xử lý phía máy khách
onPurchasesUpdated
Khi giao dịch mua thay thế hoàn tất, sự kiện PurchasesUpdatedListener sẽ được kích hoạt. Mặc dù đây là một lần chuyển đổi, nhưng Google Play coi gói Premium này là một giao dịch mua hoàn toàn mới.
Ứng dụng sẽ nhận được một đối tượng Purchase chứa mã thông báo giao dịch mua premium_purchase_token_123 và product_id premium_plan. Bạn phải xử lý yêu cầu này giống như một yêu cầu của người đăng ký mới: xác minh mã thông báo và chuẩn bị cấp quyền truy cập
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) {
for (Purchase purchase : purchases) {
// purchase.getPurchaseToken() = premium_purchase_token_123
// purchase.getProducts() will contain premium_plan
// Verify the purchase and grant entitlement
handleNewPurchase(purchase);
}
}
}
queryPurchasesAsync
queryPurchasesAsync chỉ trả về những gói thuê bao đang hoạt động được mua qua ứng dụng của bạn. Bạn nên dựa vào phương thức này để xác định quyền nào sẽ hiển thị cho người dùng. Để thay thế ngay lập tức, queryPurchasesAsync() sẽ ngừng trả về mã thông báo giao dịch mua CƠ BẢN cũ và giờ đây sẽ chỉ trả về mã thông báo giao dịch mua PREMIUM mới.
Bất cứ khi nào ứng dụng của bạn tiếp tục hoạt động hoặc một giao dịch mua hoàn tất, hãy gọi phương thức này. Nếu có mã thông báo Premium, hãy cấp quyền sử dụng các tính năng Premium ngay lập tức và xoá các tính năng cơ bản.
Xử lý phụ trợ (RTDN)
Khi có một yêu cầu thay thế, Google Play sẽ gửi Thông báo theo thời gian thực dành cho nhà phát triển (RTDN) đến chủ đề pub/sub mà bạn đã định cấu hình.
- Trong trường hợp thay thế ngay lập tức, Google sẽ gửi một RTDN
SUBSCRIPTION_PURCHASEDkèm theo mã thông báo giao dịch mua mới.Tải trọng RTDN mẫu{ "version":"1.0", "packageName":"com.google.play.billing.samples.subscriptions", "eventTimeMillis":"...", "subscriptionNotification": { "version":"1.0", "notificationType":4, // SUBSCRIPTION_PURCHASED "purchaseToken":"premium_purchase_token_123" //purchase token for the new subscription } } - Khi máy chủ của bạn nhận được mã thông báo giao dịch mua mới từ RTDN, hãy gọi API
purchases.subscriptionsV2bằng mã thông báo giao dịch mua mới để tìm nạp thông tin chi tiết về giao dịch mua. Phản hồi API chứa trườnglinkedPurchaseTokendùng để xác định xem mã thông báo giao dịch mua có liên quan đến giao dịch mua gói thuê bao mới hay giao dịch thay thế gói thuê bao. - Trong trường hợp thay thế gói thuê bao,
linkedPurchaseTokenđề cập đến mã thông báo giao dịch mua của gói thuê bao cũ. Trong trường hợp này, câu trả lời sẽ làbasic_purchase_token_123.Câu trả lời mẫuGET purchases.subscriptionsV2curl \ 'https://androidpublisher.googleapis.com/androidpublisher/v3/applications/<application_id>/purchases/subscriptionsv2/tokens/premium_purchase_token_123' \ --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \ --header 'Accept: application/json' { "kind": "androidpublisher#subscriptionPurchaseV2", "startTime": "...", "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE", "latestOrderId": "GPA.<order_id>", "linkedPurchaseToken": "basic_purchase_token_123", // The purchase token of the subscription that was replaced (Basic Plan in this case) "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED", "lineItems": [ { "productId": "premium_plan", // productID of the new subscription (Premium Plan in this case) "expiryTime": "....", "autoRenewingPlan": {...}, "offerDetails": { "basePlanId": "monthly-auto-renewing" // base plan ID of the new subscription }, "itemReplacement": { // Details about the subscription replacement "productId": "subscription_basic", // productID of the old subscription (Basic Plan in this case) "replacementMode": "CHARGE_PRORATED_PRICE", // Replacement strategy used for this subscription change "basePlanId": "monthly-auto-renewing" // base plan ID of the old subscription }, "offerPhase": {...} } ], "etag": "<etag_value>" } - Bạn phải xác nhận giao dịch mua gói Premium mới. Bạn có thể thực hiện việc này trong ứng dụng hoặc trên phần phụ trợ. Nếu bạn không xác nhận giao dịch mua trong vòng 3 ngày, giao dịch mua sẽ được hoàn tiền và quyền sẽ bị thu hồi. Để biết thêm thông tin về cách xử lý và xác nhận giao dịch mua, hãy tham khảo tài liệu dành cho nhà phát triển.
Kết luận
Phần này trình bày các bước xử lý việc thay thế gói thuê bao ngay lập tức trên cả ứng dụng và máy chủ phụ trợ của bạn. Bạn đã biết rằng Google Play coi gói mới là một giao dịch mua hoàn toàn mới và sẽ phát hành một mã thông báo giao dịch mua mới. Trên ứng dụng, bạn phải xử lý giao dịch mua mới này bằng cách sử dụng PurchasesUpdatedListener và cập nhật quyền dựa trên phản hồi từ queryPurchasesAsync. Ở phần phụ trợ, bạn nên lắng nghe các RTDN SUBSCRIPTION_PURCHASED cho mã thông báo mới, sử dụng API purchases.subscriptionsv2 để xác định linkedPurchaseToken của gói thuê bao cũ và nhanh chóng thu hồi quyền truy cập liên kết với mã thông báo cũ trong khi cấp quyền mới. Hãy nhớ luôn xác nhận giao dịch mua mới.
11. Xử lý các thao tác thay thế BỊ HOÃN
Không giống như các chế độ thay thế ngay lập tức, ReplacementMode.DEFERRED sẽ hoãn việc thay đổi gói thuê bao và cập nhật quyền cho đến khi kết thúc chu kỳ thanh toán hiện tại. Việc xử lý các yêu cầu thay thế bị hoãn lại đòi hỏi phải có logic cụ thể để đảm bảo người dùng nhận được quyền phù hợp vào thời điểm thích hợp.
Tình huống ví dụ
- Người dùng có gói Cơ bản hằng tháng (product_id
basic_planvà purchase_tokenbasic_purchase_token_123) gia hạn vào ngày 15 tháng 4. - Vào ngày 1 tháng 4, người dùng quyết định chuyển sang gói Premium bằng cách sử dụng
ReplacementMode.DEFERRED. - Google sẽ tạo một mã thông báo giao dịch mua MỚI cho gói Premium (product_id
premium_planvà purchase_tokenpremium_purchase_123) ngay lập tức, nhưng số tiền sẽ tính cho người dùng và quyền được lên lịch vào ngày 15 tháng 4.
Xử lý chế độ thay thế bị hoãn
1. Ngay sau khi quy trình mua thành công (ứng dụng)
PurchasesUpdatedListenerđược gọi sau khi quy trình mua hoàn tất. Ứng dụng sẽ nhận được một đối tượngPurchasechứa mã thông báo giao dịch mua mớipremium_purchase_token_123, tuy nhiên product_id vẫn sẽ đề cập đếnbasic_plancũ vì người dùng chỉ có quyền sử dụng gói Cơ bản. Bạn phải coi đây là một giao dịch mua mới và xác nhận mã thông báo.@Override public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { // purchase.getPurchaseToken() = premium_purchase_token_123 // purchase.getProducts() will contain basic_plan // Verify and acknowledge the purchase handleNewPurchase(purchase); } } }queryPurchasesAsyncsẽ ngay lập tức trả về giao dịch mua có mã thông báo giao dịch mua mới (premium_purchase_token_123) và quyền gốc (basic_plan) liên kết với giao dịch mua đó. Bạn có thể dựa vào thông tin này để tiếp tục cấp quyền sử dụng gói Cơ bản cho người dùng.
2. Ngay sau khi quy trình mua thành công (máy chủ phụ trợ)
- RTDN SUBSCRIPTION_PURCHASED được gửi ngay sau quy trình mua của mã thông báo giao dịch mua mới (
premium_purchase_token_123).Tải trọng RTDN mẫu{ "version":"1.0", "packageName":"com.google.play.billing.samples.subscriptions", "eventTimeMillis":"...", "subscriptionNotification": { "version":"1.0", "notificationType":4, // SUBSCRIPTION_PURCHASED "purchaseToken":"premium_purchase_token_123" //purchase token for the new subscription } } - Gọi
GET purchases.subscriptionsv2bằng mã thông báo giao dịch mua mới để tìm nạp thông tin chi tiết về giao dịch mua. Phản hồi chứa 2 mục hàng.- Một mục riêng thể hiện gói thuê bao cũ (gói cơ bản) và có
expiryTimetrong tương lai. Gói thuê bao cũ sẽ không được gia hạn và códeferredItemReplacementchứa gói thuê bao mới (gói cao cấp). Điều này cho biết một quyền cũ đang chờ được thay thế khi hết hạn. - Một mã thông báo đại diện cho gói thuê bao mới mua. Không có giá trị nào được đặt cho "expiryTime"
{ "kind": "androidpublisher#subscriptionPurchaseV2", "startTime": "2026-05-07T15:50:11.383Z", "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE", "latestOrderId": "GPA.<order_id>", "linkedPurchaseToken": "basic_purchase_token_123", "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED", "lineItems": [ { "productId": "premium_plan", // Premium Plan has no expiry time "autoRenewingPlan": {...}, "offerDetails": {...}, "itemReplacement": {. // Subscription replacement details "productId": "basic_plan", "replacementMode": "DEFERRED", "basePlanId": "monthly-auto-renewing" }, "offerPhase": {} }, { "productId": "basic_plan", // Subscription to be replaced "expiryTime": "2026-05-07T15:54:34.768Z", // Expiry time in the future "autoRenewingPlan": {}, "offerDetails": {...}, "deferredItemReplacement": { // identifier indicating this subscription will be replaced upon renewal "productId": "subscription_premium" }, "latestSuccessfulOrderId": "GPA.<order_id>", "itemReplacement": {...}, } ], "etag": "<etag>" } - Một mục riêng thể hiện gói thuê bao cũ (gói cơ bản) và có
- Bạn phải xác nhận mã thông báo giao dịch mua mới. Bạn có thể thực hiện việc này trong ứng dụng hoặc trên phần phụ trợ. Để biết thêm thông tin về cách xử lý và xác nhận giao dịch mua, hãy tham khảo tài liệu dành cho nhà phát triển.
- RTDN SUBSCRIPTION_EXPIRED được gửi cho mã thông báo giao dịch mua cũ (
basic_purchase_token_123).Tải trọng RTDN mẫu{ "version":"1.0", "packageName":"com.google.play.billing.samples.subscriptions", "eventTimeMillis":"...", "subscriptionNotification": { "version":"1.0", "notificationType":13, // SUBSCRIPTION_EXPIRED "purchaseToken":"basic_purchase_token_123" //purchase token for the old subscription } } - Khi gọi API
GET purchases.subscriptionsv2bằng mã thông báo giao dịch mua cũ, API này có vẻ như đã hết hạn (SUBSCRIPTION_STATE_EXPIRED). Quyền của gói cũ được chuyển sang giao dịch mua mới trong thời gian còn lại.
3. Vào ngày thay thế – lần gia hạn đầu tiên sau quy trình mua (ứng dụng)
queryPurchasesAsyncsẽ trả về giao dịch mua có mã thông báo giao dịch mua mới (premium_purchase_token_123) và gói thuê bao mới liên kết với giao dịch mua đó (premium_plan).- Giao dịch mua mới chắc hẳn đã được xử lý khi quy trình mua thành công, bạn không phải thực hiện bất kỳ hành động đặc biệt nào ngoài việc đảm bảo cấp cho người dùng quyền truy cập vào gói thuê bao phù hợp.
4. Vào ngày thay thế – lần gia hạn đầu tiên sau quy trình mua (máy chủ phụ trợ)
- Với
ReplacementMode.DEFERRED, các lần gia hạn đầu tiên sẽ tuân theo hành vi tiêu chuẩn của mọi lần gia hạn khác đang xử lýSUBSCRIPTION_RENEWEDRTDN. Bạn không cần có logic đặc biệt nào cho việc thay thế khi sự kiện này diễn ra. - Gọi
GET purchases.subscriptionsv2bằng mã thông báo giao dịch mua mới để tìm nạp thông tin chi tiết về giao dịch mua. Phản hồi chứa 2 mục hàng.- Một mục riêng thể hiện gói thuê bao cũ (gói cơ bản) và có
expiryTimetrong quá khứ. Gói thuê bao cũ sẽ không còn có giá trị được đặt cho trườngdeferredItemReplacementnữa. - Một mục riêng thể hiện gói thuê bao mới có
expiryTimetrong tương lai và trườngautoRenewEnabledđược đặt thànhtrue.
{ "kind": "androidpublisher#subscriptionPurchaseV2", "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE", "latestOrderId": "GPA.<order_id>..0", "linkedPurchaseToken": "basic_purchase_token_123", // purchase token of the old subscription "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED", "lineItems": [ { "productId": "premium_plan", // New subscription "expiryTime": "2026-05-07T16:00:09.437Z", // Expiry time set in the future "autoRenewingPlan": { "autoRenewEnabled": true, // Auto Renewing Flag set to True "recurringPrice": {...} }, "offerDetails": {...}, "latestSuccessfulOrderId": "GPA.<order_id>..0", "itemReplacement": {. // Details of the subscription replacement "productId": "basic_plan", "replacementMode": "DEFERRED", "basePlanId": "monthly-auto-renewing" }, "offerPhase": {...} }, { "productId": "basic_plan", // Old subscription, Does not contains the deferredItemReplacement field "expiryTime": "2026-05-07T15:54:34.768Z", // Expiry time set in the past "autoRenewingPlan": {}, "offerDetails": {...}, "latestSuccessfulOrderId": "GPA.<order_id>..0", "itemReplacement": {...}, } ], "etag": "<etag>" } - Một mục riêng thể hiện gói thuê bao cũ (gói cơ bản) và có
Kết luận
Phần này trình bày chi tiết cách xử lý riêng biệt cần thiết cho ReplacementMode.DEFERRED. Bạn đã biết rằng không giống như chế độ ngay lập tức, thay đổi về quyền chỉ xảy ra khi kết thúc chu kỳ thanh toán hiện tại. Phần này trình bày các bước cần thiết để cả ứng dụng và phần phụ trợ của bạn đều xử lý chính xác giao dịch mua ban đầu, xác nhận mã thông báo mới và quản lý việc chuyển đổi quyền khi gói thuê bao cũ hết hạn và gói thuê bao mới bắt đầu hoạt động.
12. Sân chơi thay thế gói thuê bao
Tính năng Replacement Playground trong ứng dụng mẫu cho phép bạn kiểm thử việc nâng cấp và hạ cấp gói thuê bao cho các sản phẩm thuê bao được thiết lập trong tài khoản Google Play Console. Phần này mô tả cách sử dụng tính năng Replacement Playground (Sân chơi thay thế).
Thiết lập
Để sử dụng tính năng Playground thay thế, hãy đảm bảo rằng bạn:
packageIdtrong tệpbuild.gradlecủa bạn khớp với ứng dụng được định cấu hình trong Google Play Console.- Tài khoản người dùng thử nghiệm của bạn được đăng ký làm người kiểm thử được cấp phép trong Google Play Console. Để tìm hiểu thêm về kiểm thử cấp phép, hãy xem bài viết Kiểm thử việc triển khai tính năng thanh toán của ứng dụng.
Sân chơi thay thế gói thuê bao
Ứng dụng mẫu có thẻ Replacement Playground (Sân chơi thay thế) cho phép bạn mô phỏng các thay đổi đối với gói thuê bao. Bạn có thể truy vấn các gói thuê bao được xác định trong Play Console và kiểm thử việc chuyển đổi giữa các gói này bằng nhiều chế độ thay thế. Sân chơi này giúp bạn hiểu cách các chế độ khác nhau ảnh hưởng đến chu kỳ thanh toán và các quyền của gói thuê bao, nhờ đó, bạn có thể xác định lựa chọn phù hợp nhất với nhu cầu kinh doanh của mình.
Để mô phỏng việc thay thế bằng hộp cát, hãy làm theo các bước sau:
- Chuyển đến thẻ Playground.
- Nếu bạn có một gói thuê bao đang hoạt động: Gói đó sẽ được đánh dấu. Đây là gói thuê bao sẽ được thay thế.

- Nếu bạn không có gói thuê bao đang hoạt động: Trước tiên, bạn cần mua một gói thuê bao.
- Theo mặc định, Playground liệt kê các gói Cơ bản, Premium và Lite được tạo cho lớp học lập trình này.
- Để kiểm thử với các kế hoạch khác được định cấu hình trong Play Console, hãy nhấp vào Thêm kế hoạch tuỳ chỉnh, tìm kiếm theo
productIdvàbasePlanId. - Mua gói thuê bao đã chọn.
- Gói thuê bao đang hoạt động mà người dùng mới mua sẽ xuất hiện.

- Chọn gói thuê bao mà người dùng muốn chuyển sang.
- Chọn một Chế độ thay thế cho hiệu ứng chuyển đổi.

- Nhấp vào nút Kiểm thử việc thay thế để mô phỏng việc thay thế gói thuê bao.
- Bạn sẽ thấy bảng dưới cùng về dịch vụ thanh toán của Google Play, trong đó có thông tin chi tiết đã tính toán về việc thay thế gói thuê bao (chẳng hạn như các khoản phí ngay lập tức và điều chỉnh chu kỳ thanh toán).

- Hoàn tất giao dịch mua.
- Chuyển đến trang Quản lý gói thuê bao trong ứng dụng Cửa hàng Play để xem các thay đổi đối với gói thuê bao đang hoạt động, cùng với thông tin chi tiết về ngày gia hạn và giá mới.

13. 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ợ 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
14. Xin chúc mừng
Xin chúc mừng! Bạn đã triển khai thành công tính năng thay thế gói thuê bao bằng nhiều chế độ tính phí theo tỷ lệ và định cấu hình quy trình xử lý phụ trợ cho các lượt chuyển đổi gói.
Kiến thức bạn học được
- Cách định cấu hình
SubscriptionProductReplacementParamsbằng các chế độ thay thế cụ thể. - Sự khác biệt giữa việc nâng cấp ngay lập tức và hạ cấp có trì hoãn.
- Cách ngừng sử dụng mã thông báo thuê bao cũ bằng
linkedPurchaseTokenthông qua RTDN.
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.