Thông báo giao dịch bị hủy cho phép máy chủ Google Play của bạn thu hồi quyền truy cập ngay khi một khoản hoàn tiền xảy ra
Google Play có thể đẩy tới máy chủ của bạn một thông báo giao dịch bị hủy ngay lập tức khi một giao dịch được hoàn tiền, bị bồi hoàn, hoặc bị hủy. Nó mang theo purchaseToken, orderId, productType và refundType, và nó có nghĩa một điều, thu hồi quyền truy cập. Đây là cách đọc nó và kết nối nó.

Điểm chính
- Thông báo giao dịch bị hủy là một Real-time Developer Notification mà Google Play đẩy tới topic Cloud Pub/Sub của bạn ngay khi một giao dịch được hoàn tiền, bị bồi hoàn, hoặc bị hủy theo cách khác. Đó là một tín hiệu đẩy, không phải thứ bạn phải thăm dò (poll).
- Thông báo mang theo đúng bốn trường: `purchaseToken`, `orderId`, `productType` và `refundType`. Bấy nhiêu là đủ để tìm đúng giao dịch trong cơ sở dữ liệu của bạn và thu hồi quyền lợi gắn với nó.
- `productType` là `1` cho một gói đăng ký bị hủy và `2` cho một giao dịch mua một lần bị hủy. `refundType` là `1` cho hoàn tiền toàn phần và `2` cho hoàn tiền một phần theo số lượng, chỉ áp dụng cho các giao dịch mua một lần nhiều số lượng.
- Một thông báo giao dịch bị hủy có nghĩa khách hàng đã nhận lại tiền của họ. Hướng dẫn của chính Google là thu hồi quyền truy cập vào nội dung liên quan, vì người mua không còn nên giữ quyền lợi đó nữa.
- Thông báo giao dịch bị hủy sẽ tắt cho đến khi bạn bật chúng lên. Trong Play Console, dưới Monetization setup, bạn chọn hoặc gói đăng ký cùng tất cả giao dịch bị hủy, hoặc mục đó cộng thêm các sự kiện sản phẩm mua một lần. Cả hai lựa chọn đều bao gồm giao dịch bị hủy.
- Thông báo giao dịch bị hủy không phải là một trong hai luồng hoàn tiền yêu cầu bạn cung cấp bằng chứng. Nó là một thông báo sau khi sự việc đã xảy ra. Các luồng duy nhất nhận đầu vào của bạn là CONSUMPTION_REQUEST của Apple, với cửa sổ 12-hour, và quy trình xét duyệt bồi hoàn của Google Play thông qua `orders.reviewrefund`, với cửa sổ 24-hour.
- Từ August 3, 2026, Google chuyển giá mua cộng với phí ngân hàng của một khoản bồi hoàn cho nhà phát triển. Thông báo giao dịch bị hủy thường là cách máy chủ của bạn lần đầu biết rằng một khoản hủy do bồi hoàn đã xảy ra, nên việc kết nối nó là điều cho phép bạn ngừng phục vụ một khách hàng mà bạn không còn được trả tiền.
Một khoản hoàn tiền trên Google Play không nhất thiết phải là thứ bạn phát hiện sau này trong một báo cáo. Google Play có thể đẩy tới máy chủ của bạn một thông báo giao dịch bị hủy ngay lập tức khi một giao dịch bị hủy, dù người mua đã tự thực hiện hoàn tiền, một nhân viên hỗ trợ đã cấp nó, một ngân hàng đã buộc một khoản bồi hoàn, hay chính bạn đã hoàn tiền đơn hàng đó với cờ thu hồi được bật. Thông điệp rất nhỏ, nó nêu đúng giao dịch, và nó mang một chỉ dẫn, trả lại quyền lợi, vì tiền đã mất rồi.
Thông báo giao dịch bị hủy thực chất là gì
Thông báo giao dịch bị hủy là một loại trong các Real-time Developer Notifications của Google Play, hay RTDN. RTDN là một kênh đẩy. Google phát một thông điệp tới một topic Cloud Pub/Sub mà bạn sở hữu, và backend của bạn nhận được nó trong khoảnh khắc sau khi sự kiện xảy ra, thay vì biết được vào lần thăm dò theo lịch tiếp theo. Đó chính là toàn bộ điểm mấu chốt của thông báo giao dịch bị hủy so với đường pull cũ hơn: bạn biết về khoản hoàn tiền ngay khi nó xảy ra, không phải nhiều giờ sau đó.
Đường pull vẫn tồn tại và vẫn quan trọng. Voided Purchases API cho phép máy chủ của bạn hỏi, theo lịch riêng của bạn, danh sách các giao dịch đã bị hủy trong một khoảng thời gian. Hai cái này bổ trợ cho nhau. Thông báo cho bạn biết ngay khoảnh khắc một giao dịch thay đổi; API cho phép bạn đối soát hàng loạt và bù đắp bất cứ điều gì mà một thông điệp bị bỏ lỡ để lại.
Nó đi kèm bên trong một Real-time Developer Notification
Thông báo giao dịch bị hủy không bao giờ đến một mình. Nó nằm bên trong một lớp bọc DeveloperNotification, và lớp bọc đó được gửi đi dưới dạng một chuỗi mã hóa base64 duy nhất trong trường data của thông điệp Pub/Sub. Trình xử lý của bạn giải mã chuỗi đó thành JSON trước khi có thể đọc bất cứ thứ gì. Lớp bọc luôn nêu tên ứng dụng và thời điểm sự kiện, và nó chứa đúng một đối tượng thông báo trong số năm loại mà Google định nghĩa. Chúng loại trừ lẫn nhau, nên một thông điệp mang voidedPurchaseNotification sẽ không đồng thời mang một sự kiện đăng ký hay mua một lần.
| Trường lớp bọc | Nó chứa gì |
|---|---|
version | Phiên bản lược đồ thông báo, ví dụ 1.0 |
packageName | Ứng dụng mà sự kiện thuộc về, ví dụ com.acme.app |
eventTimeMillis | Thời điểm sự kiện xảy ra, tính bằng mili giây kể từ epoch |
| Một trong năm đối tượng thông báo | oneTimeProductNotification, subscriptionNotification, voidedPurchaseNotification, pendingRefundReviewNotification, hoặc testNotification. Chỉ một cái hiện diện trong mỗi thông điệp |
Bốn trường mà nó mang theo
Bóc lớp bọc ra và bản thân thông báo giao dịch bị hủy chỉ là bốn trường. Điều đó cố tình gọn nhẹ. Quan điểm của Google là nếu tất cả những gì bạn cần là tìm đúng giao dịch và điều chỉnh quyền lợi, bốn trường này là đủ, và bạn không phải gọi lại bất kỳ API nào để hành động.
| Trường | Nó là gì | Cách bạn sử dụng nó |
|---|---|---|
purchaseToken | Token được trao cho thiết bị khi món hàng được mua | Khóa chính của bạn. Khớp nó với bản ghi giao dịch bạn đã lưu lúc cấp quyền |
orderId | Id đơn hàng hiển thị cho người mua, ví dụ GS.0000-0000-0000 | Một khóa thứ hai dễ đọc cho con người, dùng cho hỗ trợ và đối soát |
productType | Món bị hủy là gói đăng ký hay giao dịch mua một lần | Định tuyến tới đúng đường thu hồi |
refundType | Khoản hủy là hoàn tiền toàn phần hay hoàn tiền một phần theo số lượng | Quyết định thu hồi tất cả hay chỉ số lượng đã được hoàn |
productType cho bạn biết cái gì đã bị hủy
productType là một số nguyên nhỏ, và nó quyết định đường thu hồi nào của bạn cần đi. Một khoản hủy gói đăng ký phải tháo gỡ quyền truy cập đang diễn ra; một khoản hủy giao dịch mua một lần chỉ cần gỡ bỏ một quyền lợi duy nhất.
| Giá trị `productType` | Hằng số | Ý nghĩa |
|---|---|---|
1 | PRODUCT_TYPE_SUBSCRIPTION | Một giao dịch đăng ký đã bị hủy |
2 | PRODUCT_TYPE_ONE_TIME | Một giao dịch mua một lần đã bị hủy |
refundType cho bạn biết bao nhiêu đã được trả lại
refundType phân tách một khoản đảo ngược toàn phần gọn gàng với một khoản một phần. Trường hợp một phần rất hẹp. Nó chỉ xuất hiện khi một giao dịch mua một lần nhiều số lượng được hoàn một phần, chứ không phải toàn bộ số lượng.
| Giá trị `refundType` | Hằng số | Ý nghĩa |
|---|---|---|
1 | REFUND_TYPE_FULL_REFUND | Giao dịch đã bị hủy hoàn toàn |
2 | REFUND_TYPE_QUANTITY_BASED_PARTIAL_REFUND | Một phần của giao dịch nhiều số lượng đã bị hủy |
Bật nó lên trước, nếu không nó sẽ không bao giờ đến
Thông báo giao dịch bị hủy không tự động chảy về. Bạn bật RTDN một lần, trong Play Console, và trỏ nó tới một topic Pub/Sub mà bạn kiểm soát. Công tắc nằm dưới Monetize, rồi Monetization setup, trong mục Real-time developer notifications ở đầu trang. Đánh dấu Enable real-time notifications, rồi dán tên topic đầy đủ của bạn theo dạng projects/{project_id}/topics/{topic_name}, và dùng Send Test Message để xác nhận đường ống hoạt động trước khi bạn tin nó.
Công tắc nội dung là nơi mọi người bỏ lỡ giao dịch bị hủy. Cả hai lựa chọn đều bao gồm chúng, nên bạn không thể vô tình từ chối hoàn tiền trong khi vẫn giữ các gói đăng ký.
- Nhận thông báo cho các gói đăng ký và tất cả giao dịch bị hủy. Bạn nhận các sự kiện đăng ký và mọi giao dịch bị hủy, nhưng không nhận các sự kiện mua sản phẩm một lần.
- Nhận tất cả thông báo cho các gói đăng ký và sản phẩm mua một lần. Bạn nhận những cái trên cộng với các sự kiện sản phẩm mua một lần như
ONE_TIME_PRODUCT_PURCHASEDvàONE_TIME_PRODUCT_CANCELED.

Nó tốn kém bao nhiêu, tính bằng tiền
Một khoản hủy là một tổn thất đã được ghi sổ vào thời điểm thông báo đến tay bạn. Giá bán đã mất, và cả những gì bạn đã chi để phục vụ khách hàng đó cũng vậy. Nếu họ đã tạo ra hình ảnh, chạy các lệnh gọi tới các mô hình của bạn, dùng dung lượng lưu trữ, hay kích hoạt một khoản chi trả cho bên thứ ba, những chi phí đó đã được trả bằng tiền thật và không quay lại cùng khoản hoàn tiền. Thông báo không thể phục hồi bất kỳ điều nào trong số đó. Điều nó có thể làm là chặn dòng chảy máu từ đây trở đi, và đó là toàn bộ lý do để hành động nhanh với nó.
Sự chảy máu tồi tệ nhất ở các gói đăng ký và tồi tệ nhất ở các khoản bồi hoàn. Một gói đăng ký mà bạn không thu hồi sẽ tiếp tục tốn kém để phục vụ, tháng này qua tháng khác, cho một khách hàng không còn trả tiền. Và một khoản bồi hoàn là loại hủy đắt đỏ nhất. Từ August 3, 2026, tài liệu của Google nêu rằng một khoản bồi hoàn chuyển giá mua cộng với phí của ngân hàng cho nhà phát triển. Thông báo giao dịch bị hủy thường là nơi đầu tiên mà chính các hệ thống của bạn nghe được rằng một khoản bồi hoàn đã hoàn tất, nên một trình xử lý thu hồi ngay tại chỗ là điều giữ cho một khoản bán bị mất không biến thành một khoản bán bị mất cộng với nhiều tuần phục vụ miễn phí.
Cách xử lý một thông báo giao dịch bị hủy, từng bước
Xác minh và loại trùng lặp thông điệp
- Xác nhận thông điệp Pub/Sub đến từ Google và nhắm tới topic bạn đã cấu hình, rồi giải mã trường
database64 để lấy JSONDeveloperNotification. - Dùng
messageIdcủa Pub/Sub để loại bỏ bản trùng. Google cảnh báo rằng cùng một thông báo có thể được gửi nhiều hơn một lần, nên hãy coi việc phát lại là bình thường và làm cho trình xử lý của bạn có tính idempotent. - Chỉ xác nhận (acknowledge) thông điệp sau khi bạn đã ghi lại nó an toàn, để một sự cố giữa chừng trình xử lý không làm mất sự kiện.
Tra cứu giao dịch
- Khớp
purchaseTokenvới giao dịch bạn đã lưu khi lần đầu cấp quyền lợi. DùngorderIdlàm phương án dự phòng cho tra cứu hỗ trợ và đối soát thủ công. - Đọc
productTypeđể chọn đường thu hồi gói đăng ký hoặc mua một lần, và đọcrefundTypeđể quyết định giữa thu hồi toàn phần và một phần.
Thu hồi và ghi lại
- Gỡ bỏ quyền lợi. Với hoàn tiền toàn phần, cắt quyền truy cập vào món hàng. Với hoàn tiền một phần theo số lượng, giảm số lượng đã cấp đi đúng lượng đã hoàn và giữ nguyên phần còn lại.
- Ghi lại bạn đã làm gì và khi nào, khóa theo
purchaseTokenvàorderId. Bản ghi đó là thứ cho phép bạn trả lời một phiếu hỗ trợ về sau, và là thứ cho phép Voided Purchases API đối soát gọn gàng với trạng thái của chính bạn.
Nó nằm ở đâu giữa các tín hiệu hoàn tiền khác
Một thông báo giao dịch bị hủy là một thông báo, không phải một cuộc thương lượng. Nó cho bạn biết một kết quả đã được quyết định. Đáng để đặt nó bên cạnh các tín hiệu dễ bị nhầm lẫn với nó, vì chỉ một số trong chúng từng hỏi phía câu chuyện của bạn.
| Tín hiệu | Hướng | Nó có nhận đầu vào của bạn không |
|---|---|---|
| Thông báo giao dịch bị hủy (RTDN) | Google đẩy tới máy chủ của bạn | Không. Nó báo cáo một khoản hủy đã xảy ra |
| Voided Purchases API | Máy chủ của bạn kéo về từ Google | Không. Nó là một danh sách chỉ đọc các khoản hủy trong quá khứ |
pendingRefundReviewNotification (RTDN) | Google đẩy tới máy chủ của bạn | Có, một cách gián tiếp. Nó gắn cờ một khoản bồi hoàn mà sau đó bạn phản đối thông qua orders.reviewrefund trong vòng 24 giờ |
| Apple CONSUMPTION_REQUEST | Apple hỏi máy chủ của bạn | Có. Bạn trả lời bằng Send Consumption Information trong vòng 12 giờ |
Điều cần ghi nhớ rất đơn giản. Trên cả hai cửa hàng có đúng hai luồng hoàn tiền mà nhà phát triển có tiếng nói, CONSUMPTION_REQUEST của Apple và quy trình xét duyệt bồi hoàn của Google Play. Một thông báo giao dịch bị hủy không phải là cái nào cả. Đến lúc nó tới tay bạn, quyết định đã ở sau lưng bạn và điều duy nhất còn lại trong tay bạn là bạn thu hồi nhanh đến mức nào.
Câu hỏi thường gặp
- Thông báo giao dịch bị hủy trên Google Play có nghĩa là gì?
- Nó có nghĩa một giao dịch đã được hoàn tiền, bị bồi hoàn, hoặc bị hủy theo cách khác, và khách hàng đã nhận lại tiền của họ. Hướng dẫn của Google là thu hồi quyền truy cập vào nội dung liên quan, vì người mua không còn nên giữ quyền lợi đó nữa. Thông báo nêu đúng giao dịch qua `purchaseToken` và `orderId` của nó.
- Một thông báo giao dịch Google Play bị hủy chứa những trường nào?
- Bốn: `purchaseToken`, `orderId`, `productType` và `refundType`. `productType` là `1` cho một gói đăng ký và `2` cho một giao dịch mua một lần. `refundType` là `1` cho hoàn tiền toàn phần và `2` cho hoàn tiền một phần theo số lượng trên một giao dịch nhiều số lượng.
- Làm thế nào để bật thông báo giao dịch bị hủy?
- Trong Play Console, mở Monetize rồi Monetization setup, và trong mục Real-time developer notifications, đánh dấu Enable real-time notifications, rồi nhập tên topic Cloud Pub/Sub của bạn. Cả hai lựa chọn nội dung, gói đăng ký cùng tất cả giao dịch bị hủy, và mục đó cộng thêm các sự kiện sản phẩm mua một lần, đều bao gồm giao dịch bị hủy.
- Sự khác biệt giữa thông báo giao dịch bị hủy và Voided Purchases API là gì?
- Thông báo là một tín hiệu đẩy được gửi theo thời gian thực qua Cloud Pub/Sub ngay khi một giao dịch bị hủy. Voided Purchases API là một đường pull mà máy chủ của bạn truy vấn theo lịch riêng của nó để liệt kê các khoản hủy trong một khoảng thời gian. Dùng thông báo để phản ứng tức thì và API để đối soát và bù đắp.
- Thông báo giao dịch bị hủy có cho phép tôi phản đối khoản hoàn tiền không?
- Không. Nó là một thông báo sau khi sự việc đã xảy ra về một quyết định đã được đưa ra. Luồng Google Play duy nhất nhận đầu vào của bạn là quy trình xét duyệt bồi hoàn thông qua `orders.reviewrefund`, mà bạn có 24 giờ để trả lời, và trên Apple đó là CONSUMPTION_REQUEST với cửa sổ 12-hour.
Nguồn và tài liệu đọc thêm
- Android Developers: Real-time developer notifications reference guide
- Google Play Developer API: Voided Purchases API
- Google Play Developer API: REST Resource purchases.voidedpurchases
- Android Developers: Purchase lifecycle and RTDNs
- Google Play Console Help: refund protection and chargeback cost responsibility
- Google Play Developer API: Method orders.reviewrefund
RefundHalt
Chế độ tự động xử lý hoàn tiền cho App Store và Google Play
Đọc tiếp
Bạn có thể tự hoàn tiền một đơn hàng Google Play, và làm việc đó trước khi có chargeback giúp bạn tiết kiệm phí ngân hàng
Bạn có thể hoàn tiền bất kỳ đơn hàng Google Play nào dưới ba năm tuổi chỉ với một lệnh gọi API, có hoặc không thu hồi quyền truy cập. Tự làm việc đó trước khi một tranh chấp biến thành chargeback giúp bạn tiết kiệm khoản phí ngân hàng đổ lên nhà phát triển kể từ ngày 3 tháng 8 năm 2026. Đây là cách orders.refund hoạt động.
Send Consumption Information của Apple giờ yêu cầu năm trường, không phải mười hai, và đây là từng trường một
Khi một khách hàng yêu cầu Apple hoàn tiền, payload Send Consumption Information là câu trả lời của bạn. Apple đã cắt nó từ mười hai trường xuống còn năm, ba bắt buộc và hai tùy chọn. Đây là từng trường, các giá trị mỗi trường chấp nhận, và cửa sổ 12 giờ để bạn gửi nó.