Apple có thể đảo ngược một khoản hoàn tiền đã cấp, và một khoản hoàn tiền bị đảo ngược mà máy chủ của bạn bỏ qua sẽ khóa quyền truy cập của một khách hàng đã trả tiền
Khi App Store đảo ngược một khoản hoàn tiền đã cấp, nó kỳ vọng máy chủ của bạn khôi phục quyền truy cập mà bạn đã thu hồi. Đây là cách các thông báo hoàn tiền, từ chối hoàn tiền và hoàn tiền bị đảo ngược hoạt động trên App Store và Google Play, cùng cái giá của mỗi thông báo khi bạn bỏ qua nó.

Điểm chính
- App Store gửi thông báo REFUND_REVERSED khi nó đảo ngược một khoản hoàn tiền đã cấp trước đó vì khách hàng khiếu nại, và chỉ dẫn của Apple rất rõ ràng: nếu ứng dụng của bạn đã thu hồi nội dung hoặc dịch vụ, nó cần khôi phục lại chúng.
- Thông báo REFUND nghĩa là App Store đã hoàn tiền giao dịch, nên máy chủ của bạn nên thu hồi quyền lợi. Thông báo REFUND_DECLINED nghĩa là Apple đã từ chối yêu cầu, và khách hàng giữ cả quyền truy cập lẫn khoản phí.
- Nếu bạn thu hồi khi có hoàn tiền nhưng không bao giờ xử lý việc đảo ngược, một khách hàng có khoản phí được khôi phục sẽ vẫn bị khóa. Đó là một phiếu hỗ trợ, một đánh giá một sao, và trên Google Play là sự bực bội có thể biến thành một khoản chargeback giờ đây khiến bạn tốn tiền.
- Trường revocationReason của Apple cho bạn biết vì sao khoản hoàn tiền xảy ra: value 1 nghĩa là Apple hoàn tiền do một vấn đề thực tế hoặc được cảm nhận bên trong ứng dụng của bạn, value 0 nghĩa là một lý do khác chẳng hạn như mua nhầm.
- Google Play không có thông báo đảo ngược. Nó gửi một VoidedPurchaseNotification khi một giao dịch mua bị hủy và một PendingRefundReviewNotification riêng cho các khoản chargeback, còn phần còn lại bạn đối soát bằng mô hình kéo của Voided Purchases API.
- Google Play cho bạn 24 hours để trả lời một PendingRefundReviewNotification bằng cách gọi orders.reviewrefund, và chỉ ghi nhận lần gọi đầu tiên của bạn. Từ ngày 3 tháng 8 năm 2026, một khoản chargeback bị thua khiến nhà phát triển mất giá bán trừ phí dịch vụ của Google cộng phí của ngân hàng.
- Xử lý các thông báo hoàn tiền của App Store một cách idempotent. Việc gửi trùng lặp là bình thường, nên hãy gắn mỗi lần thu hồi và khôi phục với id giao dịch và làm cho một thông báo lặp lại không có tác động gì.
Một khoản hoàn tiền không phải lúc nào cũng là phán quyết cuối cùng. App Store có thể đảo ngược một khoản hoàn tiền đã cấp, sau khi khách hàng khiếu nại, và khi khoản hoàn tiền bị đảo ngược đó đến máy chủ của bạn, nó mang theo một chỉ dẫn: hãy trả lại quyền truy cập. Hầu hết các nhóm chỉ đấu nối thông báo REFUND đơn giản, cắt quyền của khách hàng, rồi dừng ở đó. Họ không bao giờ xây dựng nửa còn lại. Vì vậy khi việc đảo ngược đến, không có gì chạy, và một khách hàng đang trả tiền lần nữa vẫn bị khóa khỏi thứ họ đã mua. Đây là cách toàn bộ tập hợp thông báo hoàn tiền hoạt động trên App Store và Google Play, cùng cái giá của mỗi thông báo khi bạn bỏ qua nó.
App Store gửi ba thông báo hoàn tiền, không phải một
Hầu hết việc xử lý hoàn tiền được xây dựng cho một sự kiện duy nhất: tiền đã được trả lại, cắt quyền khách hàng. Luồng App Store Server Notifications V2 thực ra mang theo ba kết quả hoàn tiền riêng biệt, và chúng yêu cầu ba thứ khác nhau. Hai trong số đó thay đổi những gì khách hàng có thể truy cập. Một trong số đó hoàn tác thứ đầu tiên. Đây là toàn bộ tập hợp, bằng chính lời của Apple.
| Thông báo | Nó có nghĩa là gì | Máy chủ của bạn làm gì |
|---|---|---|
| CONSUMPTION_REQUEST | Khách hàng yêu cầu hoàn tiền và Apple muốn dữ liệu tiêu thụ | Gửi payload tiêu thụ trong vòng 12 hours |
| REFUND | App Store đã hoàn tiền giao dịch | Thu hồi quyền lợi cho giao dịch đó |
| REFUND_DECLINED | App Store đã từ chối yêu cầu hoàn tiền | Không làm gì; khách hàng giữ quyền truy cập và khoản phí |
| REFUND_REVERSED | App Store đã đảo ngược một khoản hoàn tiền đã cấp | Khôi phục nội dung hoặc dịch vụ bạn đã thu hồi |
REFUND, thông báo mà mọi nhóm đều xử lý
Khi App Store xử lý một khoản hoàn tiền, nó gửi một thông báo REFUND đến URL bạn cấu hình, và định nghĩa của Apple rất rõ ràng: nó 'cho biết App Store đã hoàn tiền thành công một giao dịch cho một In-App Purchase tiêu hao, một In-App Purchase không tiêu hao, một gói đăng ký tự động gia hạn, hoặc một gói đăng ký không gia hạn.' Bạn lưu giao dịch được hoàn tiền, thu hồi bất cứ thứ gì nó đã mua, và Apple yêu cầu bạn cho khách hàng biết điều gì đã thay đổi bằng thông điệp theo ngữ cảnh trong ứng dụng. Đây là thông báo mà mọi người đấu nối đầu tiên, và thường là thông báo duy nhất.
REFUND_DECLINED, thông báo không cần gì từ bạn
REFUND_DECLINED có nghĩa đúng như tên gọi: 'App Store đã từ chối một yêu cầu hoàn tiền.' Khách hàng đã hỏi, Apple nói không, và giao dịch vẫn có hiệu lực. Không có gì về quyền truy cập của khách hàng thay đổi, nên logic quyền lợi của bạn không làm gì ở đây. Giá trị của thông báo này là việc ghi sổ. Nó khép lại một yêu cầu hoàn tiền mà bạn có thể đã trả lời bằng một CONSUMPTION_REQUEST, và xác nhận khách hàng vẫn có những gì họ đã trả tiền. Hãy coi nó là một bản ghi, không phải một hành động.
REFUND_REVERSED, thông báo khiến các nhóm bất ngờ
Đây là thông báo mà hầu hết các pipeline hoàn tiền không bao giờ xử lý. Định nghĩa của Apple rõ ràng không mập mờ: REFUND_REVERSED 'cho biết App Store đã đảo ngược một khoản hoàn tiền được cấp trước đó do một khiếu nại mà khách hàng nêu ra. Nếu ứng dụng của bạn đã thu hồi nội dung hoặc dịch vụ do khoản hoàn tiền liên quan, nó cần khôi phục lại chúng.' Hãy đọc điều đó hai lần. Apple đã cấp cho khách hàng một khoản hoàn tiền, bạn đã thu hồi quyền truy cập, rồi Apple quyết định khoản hoàn tiền không nên có hiệu lực và rút nó lại. Khoản phí lại hoạt động. Khách hàng đã trả tiền, và nếu máy chủ của bạn chỉ biết cách thu hồi, họ vẫn bị khóa. Một khoản hoàn tiền bị đảo ngược là sự kiện hoàn tiền duy nhất thêm quyền truy cập trở lại, và đó là sự kiện gần như không ai xây dựng để xử lý.
Một khoản hoàn tiền bị đảo ngược thực sự khiến bạn tốn bao nhiêu
Một lần đảo ngược bị bỏ lỡ không phải là sai số làm tròn. Hãy lần theo dòng tiền theo cả hai hướng, vì làm sai nửa nào cũng có cái giá.
Bỏ lỡ việc đảo ngược và bạn giữ một khách hàng đang trả tiền bị khóa. Apple đã khôi phục khoản phí, nên khách hàng lại mất tiền, và ứng dụng của bạn đang từ chối cho họ thứ họ đã mua. Chi phí trước mắt là thời gian hỗ trợ và một khoản hoàn tiền thiện chí mà giờ bạn có thể phải tự cấp, lần này không có hoa hồng cửa hàng nào trả lại để giảm nhẹ. Chi phí chậm hơn là đánh giá và tỷ lệ rời bỏ, và trên Google Play chính sự bực bội vì bị khóa đó là thứ biến thành một khoản chargeback.
Bỏ lỡ khoản hoàn tiền ban đầu và bạn tiếp tục phục vụ một khách hàng không trả gì cả. Sai lầm phản chiếu là không bao giờ thu hồi. Một khách hàng đã được hoàn tiền mà vẫn tạo hình ảnh, gọi các API của bạn, và làm đầy bộ lưu trữ của bạn sẽ tích lũy chi phí thực đối với một giao dịch bán hàng đã bị đảo ngược. Tính toán, các lệnh gọi bên thứ ba, và lưu trữ là tiền bạn đã chi, và không khoản nào quay lại cùng với khoản hoàn tiền.
- Chi phí hỗ trợ: một con người trả lời một phiếu về quyền truy cập mà chính mã của bạn đã gỡ bỏ và không bao giờ khôi phục.
- Hoàn tiền thiện chí: cấp lại tiền cho một khách hàng bạn khóa nhầm, không có hoa hồng cửa hàng nào được trả lại cho một cử chỉ thủ công.
- Chi tiêu lãng phí: tính toán, các lệnh gọi API, và lưu trữ bị tiêu thụ bởi một tài khoản đã được hoàn tiền mà bạn không bao giờ cắt quyền.
- Rủi ro chargeback: trên Google Play, một khách hàng cảm thấy bị tính phí hai lần có thể khiếu nại, và một khiếu nại bị thua giờ đây rơi vào bạn.
Khoản hoàn tiền bị đảo ngược và khoản hoàn tiền đơn giản là cùng một luồng webhook chỉ theo hai hướng ngược nhau. Xử lý cái này và bỏ qua cái kia thì bạn trả giá ở cả hai đầu.

Vì sao Apple đảo ngược một khoản hoàn tiền, và cách đọc revocationReason
Một lần đảo ngược không phải ngẫu nhiên. Apple gắn nó với 'một khiếu nại mà khách hàng nêu ra', tức là khách hàng phản đối quyết định hoàn tiền sau khi việc đã rồi. Khi khoản hoàn tiền được cấp lần đầu, giao dịch mang theo một revocationDate và một revocationReason, và lý do đó đáng để đọc trước khi bất cứ thứ gì phía sau hành động dựa trên nó.
- revocationReason 1: App Store hoàn tiền 'do một vấn đề thực tế hoặc được cảm nhận bên trong ứng dụng của bạn.' Đó là một tín hiệu về sản phẩm của bạn, không chỉ về khách hàng này.
- revocationReason 0: App Store hoàn tiền 'vì các lý do khác, ví dụ như mua nhầm.' Không có tín hiệu chất lượng ứng dụng nào kèm theo.
Khi một REFUND_REVERSED đến cho giao dịch đó, việc thu hồi đang được hoàn tác. Logic khôi phục của bạn nên tra cứu id giao dịch gốc, xác nhận rằng bạn đã thu hồi nó, và đặt quyền lợi trở lại đúng như trước.
Google Play không gửi một lần đảo ngược, nên thay vào đó bạn đối soát
Mô hình của Google Play thì khác, và sự khác biệt này quan trọng nếu bạn chạy cả hai cửa hàng qua một trình xử lý webhook. Không có thứ tương đương của Google cho REFUND_REVERSED. Thông báo dành cho nhà phát triển theo thời gian thực của Google chia các sự kiện hoàn tiền thành hai thông điệp, và việc đảo ngược được xử lý bằng đối soát, không phải bằng push.
Thông báo giao dịch mua bị hủy
Khi một giao dịch mua trên Google Play bị hủy, máy chủ của bạn nhận được một VoidedPurchaseNotification. Nó nêu purchaseToken và orderId, một productType là subscription hoặc one-time, và một refundType là một lần hủy toàn bộ hoặc một khoản hoàn tiền một phần dựa trên số lượng đối với các giao dịch mua nhiều số lượng. Google nói dữ liệu đó đủ để tìm đúng giao dịch mua và điều chỉnh quyền lợi. Với bất cứ điều gì hơn thế, nó chỉ bạn đến Voided Purchases API, một mô hình kéo liệt kê các đơn hàng bị hủy trong một khoảng thời gian bạn truy vấn.
Việc xem xét chargeback, và bộ đếm 24 giờ của nó
Các khoản chargeback đến qua một thông điệp khác, PendingRefundReviewNotification. Khi một khách hàng khiếu nại một khoản phí với ngân hàng của họ, Google Play gửi thông báo này và bắt đầu một bộ đếm. Bạn có 24 hours để gọi orders.reviewrefund với một tùy chọn hoàn tiền và bất kỳ bằng chứng sử dụng nào, để Google có thể phản bác một khoản chargeback bất hợp pháp thay mặt bạn. Google ghi nhận lần gọi đầu tiên của bạn và bỏ qua phần còn lại. Đây là tương đương của Google với CONSUMPTION_REQUEST của Apple, cửa sổ duy nhất mà phía của bạn trong một tranh chấp được tính đến.
Vì không có push đảo ngược, một khoản chargeback mà Google phản bác và thắng không đến dưới dạng một sự kiện khôi phục gọn gàng. Bạn đối soát nó với Voided Purchases API và hồ sơ của riêng bạn. Bài học giống như trên App Store: một đơn hàng bị hủy không phải lúc nào cũng vĩnh viễn, và trạng thái quyền lợi của bạn phải có khả năng lùi lại, không chỉ tiến lên.
| Sự kiện hoàn tiền | App Store | Google Play |
|---|---|---|
| Hoàn tiền được cấp | Thông báo REFUND | VoidedPurchaseNotification |
| Hoàn tiền bị từ chối | Thông báo REFUND_DECLINED | Không có thông điệp riêng |
| Hoàn tiền bị đảo ngược | Thông báo REFUND_REVERSED | Không có push; đối soát qua Voided Purchases API |
| Cửa sổ bằng chứng tranh chấp | CONSUMPTION_REQUEST, 12 hours | PendingRefundReviewNotification, 24 hours |
| Ai có thể cấp khoản hoàn tiền | Chỉ Apple | Google, hoặc bạn từ tab Orders |
Cách xử lý mọi thông báo hoàn tiền mà không khóa quyền của ai
Bạn không cần các pipeline riêng cho từng cửa hàng. Bạn cần một trình xử lý có thể di chuyển một quyền lợi theo cả hai hướng và coi mọi thông điệp là có thể bị trùng lặp.
- Xây dựng khôi phục, không chỉ thu hồi. Với mỗi đường dẫn gỡ bỏ quyền truy cập khi có REFUND, hãy viết đường nghịch đảo khôi phục nó khi có REFUND_REVERSED, gắn với cùng một id giao dịch.
- Làm cho nó idempotent. Cả hai cửa hàng đều có thể gửi cùng một thông báo hơn một lần, nên hãy gắn mỗi lần thu hồi và khôi phục với id giao dịch hoặc đơn hàng và làm cho một lần lặp lại không có tác động gì.
- Đọc lý do trước khi hành động. Dùng revocationReason để phân biệt một khoản hoàn tiền vì chất lượng ứng dụng với một khoản mua nhầm, và chuyển những khoản vì chất lượng ứng dụng đến người phụ trách chất lượng sản phẩm.
- Trả lời các cửa sổ bằng chứng đúng hạn. Gửi dữ liệu tiêu thụ của Apple trong vòng 12 hours kể từ một CONSUMPTION_REQUEST, và gọi orders.reviewrefund trong vòng 24 hours kể từ một PendingRefundReviewNotification.
- Lưu mọi sự kiện. Giữ lại REFUND_DECLINED và các thông báo thô, để một lần đảo ngược đến sau này có thể được khớp với khoản hoàn tiền mà nó hoàn tác.
Không điều nào trong số này thay đổi việc một khoản hoàn tiền có xảy ra hay không. Nó thay đổi việc liệu khách hàng ở phía bên kia của một khoản hoàn tiền bị đảo ngược có bao giờ nhận ra máy chủ của bạn đã xử lý sai hay không.
Câu hỏi thường gặp
- Thông báo REFUND_REVERSED trên App Store là gì?
- Đó là App Store cho máy chủ của bạn biết rằng nó đã đảo ngược một khoản hoàn tiền được cấp trước đó, vì khách hàng khiếu nại. Chỉ dẫn của Apple rất rõ ràng: nếu ứng dụng của bạn đã thu hồi nội dung hoặc dịch vụ do khoản hoàn tiền đó, nó cần khôi phục lại chúng. Khoản phí lại hoạt động, nên khách hàng nên được lấy lại quyền truy cập.
- Tôi nên làm gì khi nhận được thông báo REFUND_DECLINED?
- Không làm gì với quyền truy cập của khách hàng. REFUND_DECLINED nghĩa là App Store đã từ chối yêu cầu hoàn tiền, nên giao dịch vẫn có hiệu lực và khách hàng giữ những gì họ đã trả tiền. Hãy coi nó là một bản ghi khép lại yêu cầu hoàn tiền, thường là yêu cầu bạn đã trả lời bằng một CONSUMPTION_REQUEST.
- Google Play có gửi thông báo khi một khoản hoàn tiền hoặc chargeback bị đảo ngược không?
- Không. Google Play không có thứ tương đương với REFUND_REVERSED của Apple. Nó gửi một VoidedPurchaseNotification khi một giao dịch mua bị hủy và một PendingRefundReviewNotification cho các khoản chargeback, nhưng một khoản chargeback bị phản bác mà Google thắng không được push lại cho bạn. Bạn đối soát nó bằng Voided Purchases API và hồ sơ của riêng bạn.
- Tôi có bao nhiêu thời gian để phản hồi một khoản chargeback của Google Play?
- 24 hours. Khi Google Play gửi một PendingRefundReviewNotification, bạn có 24 hours để gọi orders.reviewrefund với một tùy chọn hoàn tiền và bằng chứng sử dụng. Google chỉ ghi nhận lần gọi đầu tiên của bạn. Từ ngày 3 tháng 8 năm 2026, một khoản chargeback bị thua khiến nhà phát triển mất giá bán trừ phí dịch vụ của Google cộng phí của ngân hàng.
- revocationReason cho tôi biết gì trên một giao dịch App Store đã được hoàn tiền?
- Nó cho bạn biết vì sao Apple hoàn tiền. Value 1 nghĩa là Apple hoàn tiền do một vấn đề thực tế hoặc được cảm nhận bên trong ứng dụng của bạn, đó là một tín hiệu về sản phẩm. Value 0 nghĩa là một lý do khác, chẳng hạn như mua nhầm. Đọc nó cho phép bạn tách các khoản hoàn tiền chỉ ra một lỗi khỏi những khoản thông thường.
Nguồn và tài liệu đọc thêm
- Apple Developer: App Store Server Notifications V2 notificationType
- Apple Developer: Handling refund notifications
- Apple Developer: revocationReason (App Store Server API)
- Android Developers: Real-time developer notifications reference
- Google Play Developer API: Method orders.reviewrefund
- Play Console Help: Updates to refund protection and chargeback cost responsibility
- Google Play Developer: Voided Purchases API
RefundHalt
Chế độ tự động xử lý hoàn tiền cho App Store và Google Play
Đọc tiếp
Ai trả tiền cho khoản hoàn tiền trên ứng dụng của bạn chủ yếu là bạn, nhưng không phải cho khoản hoa hồng bạn nghĩ mình đang mất
Khi một khách hàng được hoàn tiền, cả Apple lẫn Google đều trả lại phần hoa hồng của họ, nên phần chiết khấu của cửa hàng không phải là thứ bạn mất. Đây là ai trả tiền cho khoản hoàn tiền trên ứng dụng của bạn, thứ gì thực sự rời khỏi khoản chi trả của bạn, và vì sao một chargeback tốn kém hơn một khoản hoàn tiền thông thường.
Hủy một gói đăng ký và nhận hoàn tiền là hai việc khác nhau, và chỉ một trong hai trả lại tiền cho khách hàng của bạn
Hủy một gói đăng ký thì cửa hàng chỉ dừng lần tính phí kế tiếp, khách hàng giữ quyền truy cập đến hết kỳ, và không có đồng tiền nào dịch chuyển. Hoàn tiền đảo ngược một khoản thanh toán đã hoàn tất và kéo theo cả quyền truy cập. Đây là chỗ hai việc tách ra, mỗi việc tốn của bạn những gì, và vì sao chỉ hoàn tiền mới từng chạm tới máy chủ của bạn.