Nếu PWA của bạn được đăng trên Google Play và bạn muốn kiếm tiền từ PWA đó bằng cách bán sản phẩm hoặc gói thuê bao trong ứng dụng, thì chính sách của Play sẽ yêu cầu bạn triển khai Play Billing. Bạn sẽ cần triển khai 2 API trong PWA của mình: Digital Goods API và Payment Request API.
Digital Goods API
Digital Goods API là một giao diện giữa ứng dụng của bạn và Google Play. API này cho phép bạn truy xuất các sản phẩm kỹ thuật số và thông tin chi tiết mà bạn đã nhập cho sản phẩm trong ứng dụng và gói thuê bao trong Play Console, cũng như truy xuất các giao dịch mua hiện có mà người dùng đã thực hiện. Nếu bạn chưa thêm sản phẩm trong ứng dụng hoặc gói thuê bao trong Play Console, hãy nhớ làm theo hướng dẫn Thiết lập Play Console cho dịch vụ Thanh toán qua Play.
Vào ngày 30 tháng 11 năm 2021, ChromeOS 96 đã được phát hành cùng với việc triển khai Digital Goods API 2.0.
Bản dùng thử theo nguyên gốc cho phiên bản đầu tiên của Digital Goods API đã kết thúc vào ngày 30 tháng 1 năm 2022. Do đó, API này hiện không được dùng nữa và chỉ có API phiên bản 2.
Vào ngày 23 tháng 6 năm 2022, ChromeOS 103 đã được phát hành cùng với việc triển khai Digital Goods API 2.1. Bản phát hành này không có thay đổi nào có thể gây lỗi và chỉ bao gồm các phương thức mới và trường bổ sung: listPurchaseHistory() và itemType.
Đăng ký tham gia chương trình dùng thử theo nguyên gốc
Lưu ý: Digital Goods API hiện có sẵn thông qua Origin Trial (Thử nghiệm nguồn gốc) – một cơ chế cho phép nhà phát triển tiếp cận sớm các API Web mới. Bạn sẽ cần đăng ký thử nghiệm nguồn gốc Digital Goods API phiên bản 2 và yêu cầu một mã thông báo mà bạn sẽ cần cung cấp trên mọi trang trong nguồn gốc của mình.
Sau khi đăng ký dùng thử nguồn gốc, bạn sẽ thấy ngày "Có hiệu lực đến". Đây là ngày mà mã thông báo của bạn chắc chắn sẽ hoạt động. Hãy nhớ gia hạn mã thông báo khi đến gần ngày đó để tiếp tục tham gia dùng thử. Các API được cung cấp dưới dạng bản dùng thử theo nguyên gốc có thể thay đổi, vì vậy, hãy nhớ cập nhật những thay đổi mới nhất đối với mọi bản dùng thử theo nguyên gốc mà bạn đang tham gia. Trong trường hợp có vấn đề, hãy tham khảo tài liệu về Digital Goods API.
Payment Request API
Payment Request API xử lý giao dịch thanh toán thực tế khi người dùng thực hiện giao dịch mua. Thư viện này sử dụng thông tin chi tiết về mặt hàng mà Digital Goods API cung cấp để thực hiện giao dịch mua hàng trong ứng dụng bằng phương thức thanh toán phù hợp, trong trường hợp này là Google Play Billing.
Phát hiện tính năng Digital Goods API
Bạn có thể phát hiện xem mình đã bật API đúng cách trên trang web thông qua chương trình dùng thử ban đầu hay chưa bằng cách kiểm tra phương thức getDigitalGoodsService trong đối tượng window.
if ('getDigitalGoodsService' in window) { // Digital Goods API is supported! } else { console.log('DigitalGoodsService is not available.'); // Use another payment method }
Kết nối với dịch vụ Google Play Billing
Digital Goods API được thiết kế để tương thích với nhiều trình duyệt và cửa hàng kỹ thuật số, tương tự như cách Payment Request API không phụ thuộc vào trình duyệt và có thể dùng với nhiều nhà cung cấp dịch vụ thanh toán. Để lấy một phiên bản của dịch vụ liên kết với Google Play Billing, hãy truyền chuỗi "https://play.google.com/billing" làm phương thức thanh toán đến getDigitalGoodsService().
Nếu phương thức này gặp lỗi, thì phương thức thanh toán Google Play Billing sẽ không dùng được (ví dụ: người dùng đang truy cập vào PWA của bạn thông qua trình duyệt). Thay vào đó, bạn nên cung cấp một phương thức thanh toán khác cho các giao dịch.
if ('getDigitalGoodsService' in window) { // Digital Goods API is supported! try { const service = await window.getDigitalGoodsService('https://play.google.com/billing'); // Google Play Billing service is available } catch (error) { // Google Play Billing service is not available. Use another payment flow. } }
Lấy thông tin về mặt hàng
Sau khi kết nối dịch vụ Hàng hoá kỹ thuật số với Google Play, bạn có thể dùng API này để truy xuất thông tin về sản phẩm và giao dịch mua.
Phương thức getDetails() cho phép bạn nhận thông tin về những mặt hàng mà bạn đã thiết lập trong Play Console. Thông tin như tiêu đề, nội dung mô tả và giá sản phẩm phải được hiển thị cho người dùng trong giao diện người dùng của ứng dụng để họ biết những sản phẩm có thể mua và giá của sản phẩm.
Phương thức getDetails() sẽ cần một danh sách mã mặt hàng tương ứng với mã sản phẩm của các sản phẩm trong ứng dụng và gói thuê bao mà bạn đã tạo trong Play Console.
const itemDetails = await service.getDetails(['product_1', 'product_2', 'product_3']); for (const item of itemDetails) { // Display item information to user displayItem(item.title, item.description, item.price); }
Để nhận được mức giá phù hợp với ngôn ngữ của người dùng, bạn cần định dạng thêm một số thông tin:
const localePrice = new Intl.NumberFormat(navigator.language, { style: 'currency', currency: item.price.currency, }).format(item.price.value);
Lưu ý: Digital Goods API không cung cấp cho bạn phương thức để lấy danh sách mã nhận dạng mặt hàng. Thay vào đó, bạn sẽ cần mã hoá cứng các giá trị này vào ứng dụng hoặc tìm nạp các giá trị này từ máy chủ phụ trợ. API Nhà phát triển Google Play cho phép bạn truy vấn danh sách mã nhận dạng mặt hàng từ một phần phụ trợ. (Tìm hiểu thêm về cách triển khai các thành phần chính của Play Billing trong máy chủ phụ trợ. Dù bạn chọn giải pháp nào, hãy nhớ giữ mã mặt hàng nhất quán với mã mặt hàng trong Play Console.
Trong phiên bản 2.1 của API, một trong các trường do getDetails() trả về là itemType. Đây là một enum có giá trị là ”product” hoặc ”subscription” để biểu thị tương ứng rằng mặt hàng tương ứng là sản phẩm trong ứng dụng hay gói thuê bao. Việc phân biệt được hai loại sản phẩm này có thể hữu ích nếu bạn cần áp dụng các phương pháp xử lý khác nhau cho từng loại sản phẩm. Ví dụ: bạn có thể có một trang cụ thể để người dùng đăng ký và một trang khác cho các sản phẩm không phải là sản phẩm đăng ký. Thông tin này cũng hữu ích khi bạn muốn biết tài nguyên REST API Nhà phát triển Google Play phù hợp để sử dụng trong phần phụ trợ (purchases.products hoặc purchases.subscriptions).
Mua một mặt hàng
Sau khi sản phẩm và thông tin chi tiết của bạn xuất hiện với người dùng, bạn có thể tạo quy trình mua hàng bằng Payment Request API. Khi dùng cùng với Digital Goods API, bạn chỉ cần một tham số đầu vào: methodData.
Dịch vụ Thanh toán qua Play chỉ cho phép mua một mặt hàng tại một thời điểm; máy chủ Play đã biết giá và thông tin chi tiết của mặt hàng, nên không cần tham số details. Hãy xem tài liệu giải thích để biết nội dung giải thích chi tiết hơn.
Sử dụng thành phần supportedMethods của tham số methodData trong PaymentRequest để xác định Google Play Billing là phương thức thanh toán bằng chuỗi "https://play.google.com/billing". Sau đó, trong thành phần data, hãy truyền mã mặt hàng dưới dạng sku.
const paymentMethodData = [ { supportedMethods: 'https://play.google.com/billing', data: { sku: item.itemId, }, }, ];
Sau đó, hãy tạo yêu cầu thanh toán và gọi show() để bắt đầu quy trình thanh toán:
const request = new PaymentRequest(paymentMethodData); const paymentResponse = await request.show();
Thao tác này sẽ hiển thị giao diện người dùng mua hàng trên Play cho người dùng, nơi họ sẽ thấy thông tin chi tiết về sản phẩm mà họ đang cố gắng mua. Họ có thể bỏ ngang giao dịch hoặc tiếp tục thanh toán. Nếu người dùng huỷ thanh toán, thì lời hứa do show() trả về sẽ bị từ chối kèm theo một lỗi. Nếu họ thanh toán và hoàn tất giao dịch mua thành công, thì lời hứa sẽ được thực hiện bằng một PaymentResponse. Trong thuộc tính details của phản hồi thanh toán, một mã thông báo mua hàng sẽ được trả về.
Để ngăn chặn hành vi gian lận, bạn cần xác minh giao dịch mua và mã thông báo giao dịch mua trên máy chủ phụ trợ. Bạn cũng nên theo dõi người dùng và mã thông báo mua hàng liên kết với họ. Tìm hiểu cách triển khai quy trình xác minh trên máy chủ phụ trợ.
Sau khi xác thực giao dịch mua, hãy gọi complete() trên phản hồi thanh toán để hoàn tất quy trình thanh toán và đóng giao diện người dùng thanh toán. Bạn cũng có thể truyền vào một chuỗi result không bắt buộc để cho biết trạng thái của quy trình thanh toán. Trình duyệt sẽ quyết định có cung cấp thông tin nào về kết quả này cho người dùng hay không. Chrome không tạo bất kỳ tín hiệu nào mà người dùng có thể thấy, vì vậy, bạn nên hiển thị thông báo lỗi hoặc thông báo thành công của riêng mình trong PWA.
/* Changes were recently made so that the PaymentResponse `details` property returns the purchase token as `purchaseToken` instead of `token`. Note that `token` will be deprecated at some point in the future. To ensure that your app won't be affected by this, make the change to `purchaseToken` in your client code and use the latest version of Bubblewrap (v1.13.5 and later) to update and generate a new app package to upload to the Play Console. */ const { purchaseToken } = paymentResponse.details; let paymentComplete; if (validatePurchaseOnBackend(purchaseToken)) { paymentComplete = await paymentResponse.complete('success'); // Let user know their purchase transaction has successfully completed and been verified } else { paymentComplete = await paymentResponse.complete('fail'); // Let user know their purchase transaction failed to verify }
Nâng cấp và hạ cấp gói thuê bao
Quy trình mua này giống nhau cho cả giao dịch mua sản phẩm trong ứng dụng và giao dịch mua gói thuê bao. Tuy nhiên, đối với gói thuê bao, Google Play có các lựa chọn mua bổ sung mà bạn có thể triển khai: nâng cấp và hạ cấp. Khi tạo data cho phương thức thanh toán, bạn sẽ cần truyền các thông tin sau để bắt đầu quy trình nâng cấp hoặc hạ cấp:
sku: Đây là mã mặt hàng của gói thuê bao mới mà bạn muốn nâng cấp hoặc hạ cấp.oldSku: Đây là mã mặt hàng của gói thuê bao hiện tại của người dùng.purchaseToken: Đây là mã thông báo mua hàng cho gói thuê bao hiện tại của người dùng. Như đã lưu ý trước đó, bạn nên theo dõi mã thông báo mua hàng trong phần phụ trợ. Đối với trường hợp này và các trường hợp khác, bạn cũng nên liên kết người dùng với các giao dịch mua và mã thông báo mua hàng hiện tại của họ.prorationMode: Đây là cách tính phí gói thuê bao mới khi gói này thay thế gói thuê bao hiện tại của người dùng.
| Chế độ chia theo tỷ lệ | Mô tả |
|---|---|
immediateAndChargeProratedPrice |
Gói 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. |
immediateAndChargeFullPrice |
Gói thuê bao được nâng cấp hoặc hạ cấp và hệ thống sẽ tính phí người dùng ở mức giá đầy đủ đối với quyền truy cập mới ngay lập tức. Hệ thống sẽ chia giá trị còn lại của gói thuê bao trước đó theo tỷ lệ thời gian cho gói thuê bao mới. Chế độ tính phí theo tỷ lệ này mới được thêm vào trong bản phát hành Thư viện Google Play Billing 4.0. Hiện tại, bạn có thể sử dụng tính năng này thông qua Bubblewrap, bắt đầu từ phiên bản 1.13.5. |
immediateWithoutProration |
TẠM THỜI TẮT Có một lỗ hổng gian lận tiềm ẩn trong chế độ tính phí theo tỷ lệ này, trong đó người dùng có thể nâng cấp gói thuê bao mà không phải trả thêm phí cho một chu kỳ thanh toán. Xin lưu ý rằng chúng tôi đã tạm thời tắt chế độ này trong khi tìm cách khắc phục. |
immediateWithTimeProration |
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 dời ngày thanh toán tiếp theo. Đây là hành vi mặc định. |
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. Điều này đặc biệt hữu ích khi hạ cấp. |
unknownSubscriptionUpgradeDowngradePolicy |
Chưa đặt chính sách. Bạn không nên làm vậy. |
Tìm hiểu thêm về các chế độ tính phí theo tỷ lệ trong tài liệu tham khảo của Thư viện Google Play Billing. Hãy xem tài liệu dành cho nhà phát triển Android để biết thêm thông tin về việc nâng cấp và hạ cấp gói thuê bao cũng như các đề xuất về chế độ tính phí theo tỷ lệ.
Việc sử dụng các trường bổ sung này sẽ có dạng như sau:
const paymentMethod = [ { supportedMethods: 'https://play.google.com/billing', data: { sku: item.itemId, oldSku: oldPurchase.itemId, purchaseToken: oldPurchase.purchaseToken, prorationMode: 'immediateAndChargeProratedPrice', }, }, ];
Trong đó, item là ItemDetails của gói thuê bao mới mà người dùng đang cố gắng nâng cấp hoặc hạ cấp, còn oldPurchase là PurchaseDetails của gói thuê bao hiện tại của người dùng.
Xác nhận giao dịch mua
Sau khi người dùng mua một mặt hàng, bạn nên cấp cho họ các quyền thích hợp (quyền truy cập vào mặt hàng hoặc nội dung mà họ vừa mua). Sau đó, hãy xác nhận giao dịch mua. Khi bạn xác nhận một giao dịch mua, Google Play sẽ biết rằng bạn đã nhận và xử lý giao dịch mua đó một cách thích hợp.
Lưu ý: Nếu giao dịch mua không được xác nhận trong vòng 72 giờ kể từ thời điểm mua, thì khoản thanh toán sẽ được hoàn lại cho người dùng và giao dịch mua sẽ bị thu hồi. Mã thông báo mua hàng sẽ không còn hợp lệ nữa, vì vậy khi bạn truy vấn các giao dịch mua hiện có, giao dịch mua đã bị thu hồi sẽ không được trả về. Điều này đảm bảo rằng người dùng không bị tính phí không đúng cách trong trường hợp xảy ra lỗi mạng khiến họ không được cấp quyền sử dụng mặt hàng của mình.
Bạn nên xác nhận giao dịch mua từ máy chủ phụ trợ bằng API Nhà phát triển Google Play. Bạn nên cấp quyền và sau đó xác nhận giao dịch mua cùng nhau trong máy chủ phụ trợ.
- Sau khi người dùng mua hàng phía máy khách, hãy gửi mã thông báo mua hàng và mã mặt hàng trong một yêu cầu đến máy chủ phụ trợ của bạn.
- Trên phần phụ trợ, để biết thông tin chi tiết về giao dịch mua nhằm xác minh giao dịch đó, hãy gọi:
- purchases.products.get cho các mặt hàng trong ứng dụng.
- purchases.subscriptions.get cho gói thuê bao.
- Cấp quyền thích hợp trong cơ sở dữ liệu phụ trợ.
- Sau đó, xác nhận giao dịch mua bằng cách gọi:
- purchases.products.acknowledge cho các mặt hàng trong ứng dụng.
- purchases.subscriptions.acknowledge cho gói thuê bao.
Tiêu thụ giao dịch mua
Khi bạn xác nhận một giao dịch mua, Google Play sẽ biết rằng người dùng hiện sở hữu mặt hàng đó và không được phép mua lại. Nếu đây là một mặt hàng mà người dùng chỉ cần mua một lần và sẽ sở hữu vĩnh viễn (ví dụ: giao diện nhân vật trong trò chơi), thì mặt hàng đó không phải là mặt hàng tiêu dùng.
Ngoài ra, mặt hàng có thể là thứ mà bạn giới hạn mỗi người dùng chỉ được dùng một lần tại một thời điểm. Sau đó, người dùng cần sử dụng mặt hàng đó thì mới có thể mua một mặt hàng khác. Khi người dùng "sử dụng" mặt hàng, để cho Google Play biết rằng người dùng đã sử dụng mặt hàng đó, bạn nên gọi phương thức consume(). Sau đó, Google Play sẽ cho phép người dùng mua lại mặt hàng đó.
Đối với những mặt hàng mà bạn cho phép người dùng sở hữu nhiều lần, họ phải có thể mua nhiều lần mà không cần phải sử dụng trước (chúng tôi gọi đây là mặt hàng có thể mua nhiều lần). Tương tự, người dùng cần "tiêu thụ" những mặt hàng này trước khi Google Play cho phép họ mua lại. Do đó, ngay cả khi người dùng chưa sử dụng mặt hàng, bạn vẫn cần gọi phương thức consume() để đánh dấu mặt hàng là đã sử dụng.
// After the user purchases the item, send the purchase token and item ID to your backend to grant the entitlement and acknowledge it right away . . . // When the user uses the item or if it is a repeatable item, consume it so it’s available for purchase again. service.consume(purchaseToken); }
Kiểm tra các giao dịch mua hiện có
Luồng người dùng chính cuối cùng là kiểm tra các giao dịch mua hiện có (sản phẩm trong ứng dụng chưa được sử dụng và gói thuê bao đang diễn ra) để cho người dùng biết họ hiện sở hữu gói thuê bao hoặc mặt hàng nào. Những giao dịch mua hiện có này là những giao dịch mua trước đây trên Google Play trên mọi thiết bị, được thực hiện trong ứng dụng hoặc trên Cửa hàng Play. Các giao dịch mua được thực hiện bên ngoài ứng dụng trong Cửa hàng Play được gọi là giao dịch mua bên ngoài ứng dụng.
Khi truy xuất các giao dịch mua hiện có, bạn cũng nên kiểm tra trạng thái xác nhận và xác nhận mọi giao dịch mua đã được thực hiện trước đó nhưng chưa được xác nhận đúng cách. Bạn nên xác nhận giao dịch mua hàng càng sớm càng tốt để các quyền của người dùng luôn được cập nhật và phản ánh đúng trong ứng dụng.
Phương thức listPurchases() của Digital Goods API sẽ trả về một danh sách PurchaseDetails chứa itemId và purchaseToken cho từng giao dịch mua. Bạn sẽ cần sử dụng API Nhà phát triển Google Play trên máy chủ phụ trợ để kiểm tra trạng thái của giao dịch mua và xác nhận các giao dịch đó một cách thích hợp. Bạn nên:
- Gọi phương thức
listPurchases()của Digital Goods API phía máy khách để truy xuất danh sách giao dịch mua của người dùng. - Đối với mỗi giao dịch mua, hãy truyền
purchaseTokenvàitemIdđến phần phụ trợ của bạn. - Nếu phù hợp, hãy cấp quyền trong cơ sở dữ liệu phụ trợ của bạn.
- Sau đó, hãy gọi và kiểm tra
acknowledgementState.- purchases.products.get cho các mặt hàng trong ứng dụng.
- purchases.subscriptions.get cho gói thuê bao.
- Nếu giá trị là 0 (chưa được xác nhận), hãy gọi:
- purchases.products.acknowledge cho các mặt hàng trong ứng dụng.
- purchases.subscriptions.acknowledge cho gói thuê bao.
Tìm hiểu thêm về cách xác minh giao dịch mua trên máy chủ phụ trợ trước khi cấp quyền.
Nhật ký mua
Mặc dù listPurchases sẽ trả về thông tin về các giao dịch mua hiện có của người dùng, nhưng phương thức listPurchaseHistory() (trong phiên bản 2.1 của API) sẽ trả về giao dịch mua gần đây nhất của người dùng đối với từng mặt hàng, bất kể giao dịch mua đó đã hết hạn, bị huỷ hay đã hoàn tất. Phương thức listPurchaseHistory() trả về một danh sách PurchaseDetails chứa itemId và purchaseToken cho mỗi giao dịch mua. Bạn sẽ cần sử dụng danh sách này với API Nhà phát triển Google Play trên máy chủ phụ trợ để truy xuất thêm thông tin.
Giao dịch mua ngoài ứng dụng
Giao dịch mua ngoài ứng dụng là giao dịch mua không được thực hiện trong quy trình mua hàng thông thường trong ứng dụng. Các giao dịch này thường diễn ra trong Cửa hàng Play thay vì trong ứng dụng của bạn. Có 2 cách chính để người dùng có thể thực hiện giao dịch mua bên ngoài ứng dụng:
- Đổi mã khuyến mãi: Trong trình đơn người dùng của Play Store, trong phần "Ưu đãi và thông báo" -> "Đổi mã khuyến mãi" hoặc trong phần "Thanh toán và gói thuê bao" -> "Đổi mã quà tặng".
- Đăng ký lại: Trong trình đơn người dùng của Cửa hàng Play, trong phần "Thanh toán và gói thuê bao" -> "Gói thuê bao". Tại đây, người dùng có thể quản lý tất cả các gói thuê bao của họ trên nhiều ứng dụng. Đối với gói thuê bao đã hết hạn hoặc bị huỷ, người dùng có thể chọn "Đăng ký lại".
Khi người dùng đăng ký lại qua Cửa hàng Play, giao dịch mua của họ sẽ không được xác nhận tự động, điều này có thể dẫn đến việc họ được hoàn tiền. Hành vi này là có chủ ý vì người dùng chỉ bị tính phí cho gói thuê bao nếu họ mở ứng dụng để sử dụng. Người dùng có thể thấy thông báo "Xác nhận đăng ký" như sau, nhắc họ mở ứng dụng.
Bạn là nhà phát triển nên có trách nhiệm triển khai cơ chế xác nhận những giao dịch mua này sau khi người dùng khởi chạy ứng dụng. Đó là lý do bạn nên kiểm tra các giao dịch mua hiện có (thường là khi ứng dụng khởi chạy lần đầu) và xác nhận mọi giao dịch mua chưa được xác nhận.
Cho phép người dùng quản lý gói thuê bao
Để mang lại trải nghiệm tốt cho người dùng, bạn cần cung cấp cho người dùng cách quản lý và huỷ gói thuê bao trong ứng dụng. Bạn nên tạo một đường liên kết sâu trên trang hoặc trình đơn cài đặt để chuyển hướng người dùng đến trang quản lý gói thuê bao của ứng dụng trên Cửa hàng Play. Hãy thay thế URL sau bằng "sub-product-id" và "app-package-name" phù hợp:
https://play.google.com/store/account/subscriptions?sku=sub-product-id&package=app-package-nameCác bước tiếp theo
Các quy trình và đoạn mã này là một cách triển khai cơ bản để minh hoạ cách sử dụng Digital Goods API và Payment Request API trong PWA để triển khai Play Billing. Bạn nên sử dụng các API này khi phù hợp với bối cảnh và trường hợp sử dụng của ứng dụng. Để xem ví dụ về cách triển khai toàn diện, hãy xem mẫu mã nguồn mở của chúng tôi.
Sau đó, hãy xem cách triển khai các thành phần quan trọng của Play Billing trong máy chủ phụ trợ để giữ cho ứng dụng của bạn luôn an toàn và cập nhật các quyền của người dùng.