1. Cấu hình Google Play Billing trong ứng dụng Android
Tích hợp Google Play Billing: Trước tiên, tích hợp thư viện Google Play Billing vào ứng dụng Android của bạn. Thêm dependency thích hợp (ví dụ: com.android.billingclient:billing:5.0.0
hoặc phiên bản mới nhất) vào Gradle. Đảm bảo bạn đã tạo các sản phẩm in-app (sản phẩm mua một lần) và gói thuê bao (subscription) trên Google Play Console cho ứng dụng của mình.
Thiết lập BillingClient: Khởi tạo BillingClient
trong ứng dụng và kết nối đến Google Play. Sử dụng PurchasesUpdatedListener để nhận callback kết quả giao dịch. Ví dụ, khi người dùng mua hàng thành công, Google sẽ trả về một đối tượng Purchase
chứa thông tin giao dịch. Từ đó, bạn có thể lấy được purchaseToken – một mã duy nhất đại diện cho giao dịch này
rossbulat.medium.com. Ngoài ra, Purchase
còn có các thuộc tính như purchaseTime
, orderId
, danh sách products
(hoặc sku
), trạng thái purchaseState
…
Gửi thông tin giao dịch về server: Trong hàm callback khi purchase thành công, gửi dữ liệu giao dịch lên server Node.js của bạn để xác minh. Bạn nên gửi ít nhất các thông tin sau: purchaseToken
, mã sản phẩm (productId
hoặc SKU), loại giao dịch (phân biệt giữa sản phẩm mua một lần hay gói thuê bao), và định danh người dùng (ví dụ user ID hoặc token đăng nhập) để server biết ai thực hiện giao dịch. Ví dụ minh họa bằng pseudo-code trong Android:
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
for (Purchase purchase : purchases) {
String purchaseToken = purchase.getPurchaseToken();
String productId = purchase.getProducts().get(0); // SKU của sản phẩm/thuê bao
// Gửi purchaseToken, productId, userId... lên server qua HTTPS
sendPurchaseToServer(userId, productId, purchaseToken, purchase.getPurchaseState());
// (Tùy chọn) Tạm thời cấp quyền truy cập nội dung premium cho người dùng
// hoặc chờ đến khi server xác minh xong rồi mới cấp.
}
}
}
Ở bước này, không tiêu thụ (consume) hoặc xác nhận (acknowledge) giao dịch ngay lập tức trên ứng dụng. Thay vào đó, hãy chờ kết quả xác minh từ server để đảm bảo giao dịch hợp lệ. Sau khi nhận phản hồi thành công từ server, ứng dụng có thể gọi acknowledgePurchase() (cho non-consumable hoặc subscription) hoặc consumeAsync() (cho consumable) để hoàn tất giao dịch. Việc acknowledge là bắt buộc trong vòng 3 ngày đối với các giao dịch mua không tiêu thụ và thuê bao, nếu không Google sẽ tự hoàn tiền giao dịch đó
developer.android.com
developer.android.com
. Bạn có thể thực hiện việc xác nhận này từ phía client hoặc server: Google khuyến nghị nếu có backend an toàn thì dùng API phía server để xác nhận giao dịch một cách đáng tin cậy
developer.android.com
. (Lưu ý: các lần gia hạn subscription tự động về sau không cần xác nhận thủ công)
developer.android.com
.
2. Xác minh receipt / purchase token với Google từ server Node.js
Thiết lập quyền truy cập Google Play Developer API: Server Node.js cần quyền gọi Google Play Developer API để kiểm tra hóa đơn. Trên Google Play Console, vào Settings > API access và liên kết một Google Cloud Project với tài khoản của bạn. Sau đó, tạo một Service Account trong Google Cloud Project đó và cấp quyền “View financial data” (hoặc quyền Android Publisher tương ứng) cho tài khoản dịch vụ này trên Play Console
github.com
. Tải về tệp JSON chứa khóa riêng tư của Service Account để sử dụng trong code Node.js.
Sử dụng Google Play Developer API để xác minh: Google cung cấp API REST để kiểm tra trạng thái giao dịch dựa trên package name, product ID (hoặc subscription ID) và purchase token. Cú pháp REST như sau:
Đối với sản phẩm in-app (mua một lần): GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}
developers.google.com
Đối với thuê bao: GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token} (tương tự, khác ở path)
Lời gọi này yêu cầu server phải gửi kèm OAuth2 access token của service account với scope https://www.googleapis.com/auth/androidpublisher
developers.google.com
. Thư viện Node.js chính thức của Google (googleapis) có thể hỗ trợ bạn thực hiện dễ dàng. Ví dụ minh họa dùng Node.js và thư viện googleapis:
const { google } = require('googleapis');
const authClient = new google.auth.GoogleAuth({
keyFile: 'keys/service-account.json', // path tới khóa JSON của Service Account
scopes: ['https://www.googleapis.com/auth/androidpublisher']
});
const publisher = google.androidpublisher({ version: 'v3', auth: authClient });
// Giả sử ta nhận được request từ app với purchaseToken, productId, loại giao dịch:
app.post('/api/verifyPurchase', async (req, res) => {
const { userId, productId, purchaseToken, purchaseType } = req.body;
try {
let result;
if (purchaseType === 'subscription') {
result = await publisher.purchases.subscriptions.get({
packageName: "com.yourapp.package",
subscriptionId: productId,
token: purchaseToken
});
} else {
result = await publisher.purchases.products.get({
packageName: "com.yourapp.package",
productId: productId,
token: purchaseToken
});
}
const purchaseData = result.data;
// Kiểm tra các trường trong purchaseData để xác định tính hợp lệ...
if (purchaseType === 'subscription') {
// Ví dụ: kiểm tra trạng thái thanh toán và hạn hết hạn
if (purchaseData.paymentState === 1 && Number(purchaseData.expiryTimeMillis) > Date.now()) {
// Xác minh thành công: cập nhật DB, phản hồi OK
}
} else {
if (purchaseData.purchaseState === 0) {
// Giao dịch mua một lần hợp lệ (0 = purchased)
}
}
// ... (cập nhật DB, xử lý logic ứng dụng)
return res.sendStatus(200);
} catch (error) {
// Token không hợp lệ hoặc lỗi kết nối
return res.sendStatus(400);
}
});
Trong ví dụ trên, server gọi trực tiếp Google API để lấy thông tin giao dịch. Bạn cũng có thể dùng các thư viện có sẵn như google-play-billing-validator
(npm) để đơn giản hóa việc xác minh. Thư viện này cho phép tạo đối tượng Verifier
với email và private key của service account, sau đó gọi verifyINAPP()
hoặc verifySub()
với receipt
(gồm packageName, productId, purchaseToken) để nhận về kết quả hứa (Promise) xác thực
github.com. Dù dùng cách nào, mục tiêu là gửi purchaseToken tới Google để xác minh tính hợp lệ
Diễn giải kết quả từ Google: Google sẽ trả về thông tin chi tiết về giao dịch dưới dạng JSON. Với sản phẩm mua một lần, kết quả sẽ bao gồm các trường như purchaseState
(trạng thái giao dịch: 0 = đã mua, 1 = đã hủy/refund, 2 = đang pending) và consumptionState
(0 = chưa tiêu thụ, 1 = đã tiêu thụ)
developers.google.com. Ví dụ payload cho sản phẩm in-app như sau: {"purchaseTimeMillis": 1630000000000, "purchaseState": 0, "consumptionState": 0, "orderId": "...", ...}
github.com. Với gói thuê bao, JSON trả về sẽ có expiryTimeMillis
(thời điểm hết hạn), autoRenewing
(boolean cho biết có tự động gia hạn không), paymentState
(trạng thái thanh toán: 0 = đang chờ, 1 = đã thanh toán, 2 = trong giai đoạn dùng thử, 3 = chờ nâng/hạ cấp)
developers.google.com, và cancelReason
nếu bị hủy (0 = người dùng tự hủy, 1 = hệ thống hủy do lỗi thanh toán, 2 = thay thế bằng gói khác, 3 = nhà phát triển hủy)
developers.google.com. Ví dụ payload thuê bao: {"startTimeMillis": 1630000000000, "expiryTimeMillis": 1632688400000, "autoRenewing": true, "paymentState": 1, "cancelReason": null, ...}
github.com. Server cần kiểm tra các thông tin này: Nếu hợp lệ (ví dụ purchaseState=0
cho sản phẩm thường, hoặc paymentState=1
và expiryTimeMillis
còn hạn cho thuê bao), thì tiến hành xử lý giao dịch; nếu không (token sai, đã dùng hoặc giao dịch bị hủy/refund), thì từ chối và có thể trả về lỗi cho ứng dụng.
Xác nhận giao dịch (acknowledge/consume): Sau khi xác minh hợp lệ, server có thể gọi tiếp API để acknowledge giao dịch. Google Play yêu cầu tất cả giao dịch không tiêu thụ và thuê bao phải được acknowledge trong vòng 3 ngày
developer.android.com. Bạn có thể sử dụng phương thức purchases.products.acknowledge
hoặc purchases.subscriptions.acknowledge
của API để xác nhận giao dịch đó (kèm tham số purchaseToken)
developer.android.com. Thao tác này thông báo cho Google rằng bạn đã cấp hàng hóa/dịch vụ cho người dùng, tránh việc giao dịch bị hoàn tiền. Đối với sản phẩm tiêu thụ (consumable), thay vì acknowledge, bạn gọi purchases.products.consume
hoặc đơn giản gọi consumeAsync()
từ app. (Nếu bạn chọn để app thực hiện acknowledge/consume sau khi server báo thành công, hãy chắc chắn xử lý logic này đồng bộ để không quên acknowledge.)
3. Thiết kế API endpoint để nhận giao dịch từ app và xác minh
Trên server Node.js, bạn sẽ cần một API endpoint (ví dụ: /api/verifyPurchase
như minh họa ở trên) để ứng dụng gọi tới khi có giao dịch mới. Thiết kế endpoint như sau:
- Phương thức: Sử dụng
POST
(bảo mật hơn GET vì dữ liệu giao dịch có thể nhạy cảm). - Yêu cầu client gửi: userID (hoặc thông tin xác thực người dùng), productId (hoặc subscriptionId), purchaseToken, loại giao dịch (subscription hay in-app) và bất cứ thông tin cần thiết nào khác. Bạn có thể yêu cầu kèm một token xác thực (ví dụ JWT của người dùng) để đảm bảo request tới từ người dùng hợp lệ đã đăng nhập.
- Xử lý phía server:
- Xác thực request (ví dụ kiểm tra chữ ký hoặc token của người dùng để chống giả mạo request từ bên thứ ba).
- Kiểm tra nhanh các tham số: productId có thuộc danh sách sản phẩm hợp lệ trong ứng dụng không, định dạng token có hợp lệ không, v.v. (Các bước này giúp loại bỏ request không hợp lệ trước khi gọi Google).
- Gửi purchaseToken tới Google Play API để xác minh (như mô tả ở phần 2). Đảm bảo gọi đúng endpoint theo purchaseType.
- Nhận kết quả từ Google và kiểm tra trạng thái giao dịch:
- Nếu hợp lệ và chưa được xử lý trước đó: tiến hành cập nhật trạng thái người dùng (ví dụ nâng cấp tài khoản Premium, thêm vật phẩm, hoặc kích hoạt thuê bao trong hệ thống của bạn), đồng thời phản hồi cho app là thành công (HTTP 200 + nội dung cần thiết).
- Nếu không hợp lệ (Google trả lỗi hoặc trạng thái cho thấy giao dịch không thành công/hết hạn): phản hồi lỗi cho app (ví dụ HTTP 400 hoặc mã lỗi tùy chỉnh) để app biết giao dịch không được chấp nhận.
- (Tùy chọn) Sau khi xử lý thành công, thực hiện acknowledge/consume như đã nêu.
- Phản hồi phía server: Gửi về JSON hoặc mã trạng thái để app biết kết quả. Thông thường chỉ cần báo thành công/ thất bại. Nếu thành công, có thể gửi kèm thông tin về quyền lợi vừa được kích hoạt (như loại gói thuê bao và thời hạn hết hạn) để app cập nhật giao diện.
Lưu ý khi thiết kế: Endpoint này nên chỉ chấp nhận các request từ ứng dụng đã được xác thực. Không nên để bất kỳ ai có thể tùy ý gọi tới API xác minh (ví dụ kẻ gian gửi token giả mạo). Vì vậy, hãy sử dụng xác thực người dùng (như JWT, OAuth) và có thể kiểm tra một số yếu tố như userID gửi lên phải khớp với người đang đăng nhập trên server. Ngoài ra, implement idempotency (tính không lặp) cho endpoint: cùng một giao dịch (cùng purchaseToken) nếu gửi nhiều lần thì server cũng chỉ xử lý một lần. Bạn có thể kiểm tra trong DB, nếu token đã tồn tại thì bỏ qua hoặc trả về kết quả đã có, tránh cấp quyền lợi trùng lặp.
Một điểm quan trọng: Không tin tưởng dữ liệu từ app gửi lên hoàn toàn. Luôn kiểm tra chéo với kết quả từ Google. App chỉ nên đóng vai trò chuyển tiếp “hóa đơn” (purchase token) về server. Toàn bộ quyết định giao dịch hợp lệ phải dựa trên phản hồi từ Google Play Developer API
4. Lưu trữ dữ liệu giao dịch trên server
Bạn cần thiết kế cơ sở dữ liệu để lưu lại các thông tin giao dịch đã xác minh thành công. Việc lưu trữ này giúp bạn theo dõi trạng thái mua hàng của người dùng, cũng như tránh phải gọi Google API lặp lại nhiều lần (Google cũng khuyến cáo lưu thông tin thuê bao trên server để hạn chế gọi API không cần thiết)
developer.android.com. Dưới đây là những dữ liệu quan trọng nên lưu:
- User ID: Người dùng thực hiện giao dịch (để ràng buộc giao dịch với tài khoản trong hệ thống của bạn).
- Loại giao dịch: Phân biệt mua hàng một lần (in-app product) hay thuê bao (subscription), để xử lý và kiểm tra gia hạn cho phù hợp.
- Product ID / Subscription ID: Mã định danh của gói mà người dùng mua (ví dụ:
premium_upgrade
hoặccom.yourapp.subscription.gold
). - Purchase Token: Mã giao dịch duy nhất do Google cấp. Token này đóng vai trò như “biên lai” dùng để kiểm chứng về saurossbulat.medium.com. Hãy lưu bền vững và gắn nó với user ID tương ứngrossbulat.medium.com. (Mỗi lần gia hạn thuê bao thường sẽ dùng lại token cũ hoặc nhận token mới tùy trường hợp; nếu token mới, có thể lưu cả chuỗi liên kết token cũ mới trong trường hợp upgrade/downgrade gói).
- Order ID: Mã đơn hàng (ví dụ GPA.XXX-XXX-XXX) – hữu ích cho việc tra soát hoặc đối soát giao dịch, và phát hiện hoàn tiền (một order ID có thể xuất hiện trong danh sách hoàn tiền nếu bị refund).
- Thời gian giao dịch: Thời điểm mua (
purchaseTime
) để biết khi nào giao dịch diễn ra. - Trạng thái thanh toán: Trạng thái hiện tại của giao dịch theo Google. Đối với thuê bao, bạn có
paymentState
(0,1,2,3 như giải thích ở trên)developers.google.com; với in-app, bạn cópurchaseState
(0,1,2)developers.google.com. Trạng thái này cho biết giao dịch đã thanh toán thành công chưa, có bị hủy hay đang chờ xử lý. - Trạng thái hiệu lực: Đối với thuê bao, lưu thời hạn hết hạn (
expiryTimeMillis
) của lần gia hạn hiện tạigithub.com, và cờ autoRenewing để biết thuê bao có đang cài tự động gia hạn không. Nhờ đó, server có thể biết user còn quyền lợi đến ngày nào. - Acknowledgement/Consumption: Lưu trạng thái xem giao dịch đã được acknowledged hoặc consumed hay chưa, để tránh acknowledge lặp hoặc đảm bảo consumable không được tiêu thụ hai lần. (Trường
acknowledgementState
hoặcconsumptionState
có thể lưu hoặc suy ra từ việc bạn đã gọi API acknowledge/consume)developers.google.com. - Các thông tin khác: Ví dụ giá tiền, đơn vị tiền tệ, quốc gia (có trong kết quả Google trả về) – có thể lưu để tham khảo hoặc báo cáo. Đối với thuê bao, có thể lưu
cancelReason
nếu có, hoặcuserCancellationTime
nếu user đã huỷ để biết thời điểm hủy.
Cấu trúc lưu trữ có thể là một bảng Purchases với các cột: userId, productId, purchaseToken, orderId, purchaseTime, expiryTime (có thể null cho non-subscription), isAutoRenewing, purchaseState/paymentState, acknowledged(boolean), … Bạn cũng có thể tách thành hai bảng cho thuê bao và giao dịch thường nếu muốn, nhưng quản lý một bảng chung với các trường linh hoạt cũng được.
Sử dụng dữ liệu đã lưu: Khi người dùng mở app, thay vì mỗi lần đều gọi Google API (tốn thời gian và giới hạn rate limit), app của bạn có thể gọi server để lấy trạng thái gói mua từ DB. Ví dụ, trả về “user A có premium đến ngày X”. Chỉ khi cần đồng bộ với Google (như khi gần hết hạn hoặc nhận được thông báo thay đổi), server mới gọi lại Google API để cập nhật. Việc này tuân theo khuyến nghị của Google: cache thông tin thuê bao trên server và chỉ gọi API khi thực sự cần
5. Bảo mật và xử lý gia hạn tự động, hoàn tiền
Khi triển khai hệ thống thanh toán, cần lưu ý các vấn đề bảo mật và các trường hợp đặc thù như gia hạn thuê bao tự động hay hoàn tiền:
Xác thực và chống giả mạo: Luôn coi dữ liệu từ ứng dụng gửi lên là không tin cậy. Kẻ xấu có thể can thiệp ứng dụng hoặc gửi request giả mạo. Do đó, chỉ tin tưởng kết quả từ Google API. Mỗi purchaseToken
rất khó giả mạo vì là chuỗi do Google cấp, nhưng bạn vẫn nên kiểm tra: token phải thuộc về app (Google API sẽ báo lỗi nếu token không khớp packageName), và mỗi token chỉ nên dùng một lần cho một user. Nếu phát hiện token đã dùng cho user khác hoặc dùng lại nhiều lần, đó có thể là dấu hiệu gian lận. Hãy đảm bảo endpoint của bạn được bảo vệ (sử dụng HTTPS, xác thực người dùng, và có thể áp dụng thêm các cơ chế như xác minh chữ ký của thông báo nếu dùng Real-time developer notifications).
Acknowledge an toàn: Như đã đề cập, đừng quên acknowledge/consume. Việc này không chỉ tuân thủ quy định của Google, mà còn ngăn chặn người dùng lợi dụng: nếu bạn không acknowledge, Google hoàn tiền -> user có thể được dịch vụ miễn phí. Do đó, hãy thiết kế sao cho sau khi xác minh xong trên server, giao dịch được acknowledge ngay (từ server hoặc báo về app để app ack). Google có cung cấp trường acknowledgementState
trong dữ liệu giao dịch để bạn biết giao dịch đã được xác nhận chưa
Giám sát gia hạn tự động: Với thuê bao, khi người dùng đăng ký, Google sẽ tự động gia hạn và tính tiền theo chu kỳ. Trường hợp gia hạn thành công:
- Thông thường, purchaseToken cho thuê bao sẽ giữ nguyên trong các kỳ gia hạn (trừ khi user hủy và đăng ký lại hoặc thay đổi gói). Bạn cần cập nhật expiryTimeMillis mới cho thuê bao sau mỗi lần gia hạn. Google Play không tự động gọi API của bạn, do đó bạn phải chủ động cập nhật. Có hai cách:
- Real-time Developer Notifications (RTDN): Thiết lập thông báo thời gian thực từ Google Play qua Cloud Pub/Sub. Khi có sự kiện thuê bao (gia hạn, hủy, payment failed…), Google sẽ gửi một thông báo tới topic Pub/Sub của bạn. Server của bạn có thể lắng nghe thông báo này, sau đó gọi Google API để lấy chi tiết và cập nhật trạng thái thuê bao. RTDN giúp bạn cập nhật ngay lập tức và chính xác các thay đổi.
- Lập lịch kiểm tra định kỳ: Nếu không dùng RTDN, bạn nên lên lịch (ví dụ dùng cron job hoặc hàng đợi) để kiểm tra lại trạng thái thuê bao gần thời điểm hết hạn. Như một câu trả lời gợi ý, hãy đặt lịch tái xác minh vào thời điểm
expiryTimeMillis
của thuê baostackoverflow.com. Khi đến hạn, gọi Google API: nếu thuê bao đã gia hạn (expiryTime mới lớn hơn), cập nhật DB và lên lịch lại cho kỳ tiếp theo; nếu không (hết hạn hoặc bị hủy), thì cập nhật trạng thái không còn hiệu lực (hủy quyền Premium của user).
- Trường hợp người dùng hủy (cancel): Nếu người dùng chủ động hủy thuê bao, trường
autoRenewing
sẽ chuyển thành false vàcancelReason=0
(user canceled)developers.google.com. Thuê bao vẫn có hiệu lực đến hếtexpiryTime
, nhưng sẽ không gia hạn nữa. Bạn nên lưu thông tin này và vẫn cho user sử dụng dịch vụ đến hết thời hạn đã trả tiền, đồng thời không gia hạn thêm sau đó. - Trường hợp gia hạn thất bại: Nếu tới kỳ gia hạn mà thu phí không thành công (ví dụ thẻ hết hạn, không đủ số dư), Google có thể cho phép khoảng thời gian gia hạn (grace period) hoặc tạm dừng tùy chính sách. Khi đó
cancelReason
có thể là 1 (hệ thống hủy do vấn đề thanh toán)developers.google.com. Bạn cần lắng nghe RTDN hoặc kiểm tra thủ công để biết và vô hiệu hóa quyền lợi khi thuê bao thực sự hết hạn (sau grace period nếu có).
Xử lý hoàn tiền (refund): Hoàn tiền có thể xảy ra nếu: người dùng yêu cầu hoàn tiền qua Play Store, giao dịch bị Google phát hiện gian lận, hoặc bạn (nhà phát triển) chủ động hoàn tiền từ Play Console. Khi hoàn tiền, tùy trường hợp, giao dịch sẽ bị hủy bỏ hiệu lực:
- Đối với sản phẩm mua một lần, nếu hoàn tiền,
purchaseState
có thể chuyển thành 1 (đã hủy) – tức là quyền lợi không còn. Những token đã hoàn tiền không thể dùng lại để xác minh hợp lệ. Bạn nên gỡ bỏ hoặc vô hiệu hóa nội dung mà người dùng đã nhận từ giao dịch đó. - Đối với thuê bao, nếu hoàn tiền toàn bộ, thuê bao có thể bị hủy ngay lập tức (dù chưa hết kỳ hạn). Trường
cancelReason
có thể là 3 (developer canceled) nếu do bạn hoàn từ phía bạndevelopers.google.com, hoặc 0 nếu do người dùng hủy và được hoàn trong 48h. Trong trường hợp hoàn tiền, tốt nhất bạn nên coi thuê bao đó như đã hết hạn và tước quyền lợi ngay khi biết thông tin.
Phát hiện hoàn tiền: Google cung cấp Voided Purchases API để liệt kê các đơn hàng bị hủy/hoàn tiền
developer.android.com. Bạn có thể định kỳ gọi API này để lấy danh sách giao dịch bị void (hoàn tiền, chargeback, hủy) và đối chiếu với DB của bạn (dựa trên orderId hoặc token) để cập nhật trạng thái. Ngoài ra, RTDN cũng gửi thông báo cho sự kiện refund/chargeback (thuộc loại “SUBSCRIPTION_CANCELED” cho thuê bao nếu bị hủy do refund, hoặc “ONE_TIME_PRODUCT_CANCELED” cho sản phẩm một lần). Sau khi nhận, bạn vẫn cần gọi Google API để lấy chi tiết và xác nhận tình trạng rồi cập nhật DB
Tóm lại về bảo mật: Hãy luôn đảm bảo các giao tiếp đều qua HTTPS, sử dụng các cơ chế xác thực (API key, JWT…) để bảo vệ endpoint. Mã private key của service account dùng để gọi Google API cần được bảo quản cẩn thận trên server (không đưa vào app). Hạn chế tối đa việc chia sẻ các thông tin nhạy cảm (như purchase token hoặc orderId) trừ khi cần thiết. Việc triển khai xác minh phía server giúp ứng dụng của bạn an toàn hơn trước các can thiệp client – ví dụ, người dùng đã root máy hoặc dùng bản đã bị sửa của app sẽ không thể giả mạo giao dịch, vì server chỉ tin kết quả từ Google.
Cuối cùng, xây dựng hệ thống này đòi hỏi bạn kiểm soát được vòng đời giao dịch từ lúc mua đến khi kết thúc. Với cách tiếp cận trên, mỗi giao dịch đều được ghi nhận và kiểm chứng rõ ràng. Bạn có thể tham khảo thêm tài liệu chính thức và mã mẫu từ Google để đảm bảo tuân thủ các yêu cầu mới nhất về Google Play Billing và subscriptions (ví dụ: tài liệu Google Play Developer API, mẫu code xác minh trên GitHub) để hoàn thiện hệ thống của mình.