Lý do hủy gói đăng ký thường đến tay bạn trước yêu cầu hoàn tiền, và Google Play cung cấp nhiều hơn Apple rất nhiều
Google Play ghi lại lý do hủy gói đăng ký từ khảo sát hủy, còn Apple chỉ gửi một mã hết hạn. Đây là những gì mỗi cửa hàng cho bạn biết, tín hiệu nào báo trước một yêu cầu hoàn tiền hoặc chargeback, và mỗi tín hiệu khiến bạn tốn bao nhiêu.

Điểm chính
- Google Play hỏi người đăng ký vì sao họ rời đi khi họ hủy, và câu trả lời đến với nhà phát triển qua canceledStateContext.userInitiatedCancellation.cancelSurveyResult trong purchases.subscriptionsv2.
- Khảo sát hủy của Google Play có năm câu trả lời mà nhà phát triển đọc được: dùng không đủ nhiều, sự cố kỹ thuật, liên quan đến chi phí, tìm được ứng dụng tốt hơn, và lý do khác. Văn bản tự do trong reasonUserInput chỉ có khi người dùng chọn lý do khác.
- Thông báo SUBSCRIPTION_CANCELED từ Google Play chỉ mang purchase token. Lý do hủy phải được lấy bằng purchases.subscriptionsv2.get, và Google xóa mọi trường liên quan đến việc hủy nếu người dùng khôi phục gói đăng ký.
- App Store Server API của Apple không có khảo sát hủy. Trường expirationIntent trả về một trong năm mã: khách hàng đã hủy, lỗi thanh toán, không đồng ý tăng giá hoặc chuyển đổi ưu đãi, sản phẩm không còn bán, hoặc lý do khác.
- Thông báo DID_CHANGE_RENEWAL_STATUS của Apple với subtype AUTO_RENEW_DISABLED có thể có nghĩa là App Store đã tắt tự động gia hạn sau khi khách hàng yêu cầu hoàn tiền, chứ không chỉ là khách hàng tự tắt.
- Lý do hủy không bao giờ cho nhà phát triển quyền quyết định về hoàn tiền. Chỉ có hai luồng yêu cầu bằng chứng: CONSUMPTION_REQUEST của Apple, phải trả lời trong 12 giờ, và quy trình xem xét chargeback của Google Play qua orders.reviewrefund, phải trả lời trong 24 giờ.
- Người đăng ký Google Play hủy vì sự cố kỹ thuật là người có khả năng đòi lại tiền cao nhất. Với đơn hàng đặt sau August 3, 2026, một vụ chargeback họ thắng khiến nhà phát triển mất giá mua trừ phí dịch vụ của Play, cộng thêm phí ngân hàng.
Phần lớn người đăng ký cuối cùng được hoàn tiền đều hủy gói trước. Việc hủy đó đi kèm một lý do, và hai cửa hàng cung cấp cho bạn lượng thông tin rất khác nhau. Google Play chạy một khảo sát ngắn và chuyển câu trả lời đến máy chủ của bạn, kể cả văn bản tự do. Apple gửi một mã số cho biết gói đăng ký kết thúc như thế nào, chứ không phải vì sao khách hàng muốn rời đi. Đọc đúng cả hai, bạn sẽ thấy yêu cầu hoàn tiền đang đến khi vẫn còn kịp làm gì đó.
Google Play cho bạn biết gì về lý do hủy gói đăng ký
Khi người dùng hủy trong trung tâm gói đăng ký của Play, Google hỏi họ lý do. Câu trả lời nằm trong subscription resource mà bạn nhận được từ purchases.subscriptionsv2.get, bên dưới canceledStateContext. Object này chỉ tồn tại khi gói đăng ký ở trạng thái đã hủy hoặc đã hết hạn, và cho biết ai đã kết thúc gói: người dùng, hệ thống của Google, bạn, hoặc một thay thế như đổi gói.
Khi người dùng là người hủy, object userInitiatedCancellation có hai trường. cancelTime cho biết họ hủy lúc nào. cancelSurveyResult chứa câu trả lời khảo sát.
| Lý do khảo sát | Mô tả của Google | Điều nó thường báo hiệu |
|---|---|---|
| CANCEL_SURVEY_REASON_NOT_ENOUGH_USAGE | Không dùng gói đăng ký đủ nhiều | Mức dùng thấp, nên chi phí bỏ ra cho tài khoản ít |
| CANCEL_SURVEY_REASON_TECHNICAL_ISSUES | Sự cố kỹ thuật khi dùng ứng dụng | Tín hiệu hoàn tiền và chargeback mạnh nhất |
| CANCEL_SURVEY_REASON_COST_RELATED | Vấn đề liên quan đến chi phí | Nhạy cảm về giá, đôi khi là lần gia hạn họ không ngờ tới |
| CANCEL_SURVEY_REASON_FOUND_BETTER_APP | Người dùng tìm được ứng dụng tốt hơn | Đối thủ thắng, hiếm khi có tranh chấp |
| CANCEL_SURVEY_REASON_OTHERS | Lý do khác | Đọc reasonUserInput, lời của chính người dùng |
| CANCEL_SURVEY_REASON_UNSPECIFIED | Lý do khảo sát hủy không xác định | Không có câu trả lời để xử lý |
Cột bên phải là cách chúng tôi diễn giải, không phải của Google. Hai cột đầu lấy trực tiếp từ tài liệu tham khảo API.
Thông báo không mang theo lý do
Một gói đăng ký bị hủy sẽ kích hoạt thông báo nhà phát triển theo thời gian thực SUBSCRIPTION_CANCELED, type 3. Google nói rõ các thông báo này chỉ cho biết trạng thái giao dịch đã thay đổi. Payload chỉ có purchase token và không có gì hữu ích khác, nên handler của bạn phải gọi purchases.subscriptionsv2.get để đọc câu trả lời khảo sát.
Góc nhìn trong Play Console
Bạn không cần viết code để xem số liệu tổng. Báo cáo gói đăng ký trong Play Console có thẻ Cancellations chia churn thành tự nguyện, không tự nguyện và khác, cùng thẻ Cancellation survey responses cho những người dùng chọn trả lời. Câu trả lời văn bản tự do từ người dùng chọn lý do khác có thể tải về dưới dạng CSV từ thẻ Other responses. Việc tải này cần quyền View financial data, cũng là quyền bạn cấp cho công cụ đọc đơn hàng của mình.
Apple cho bạn biết gì, và bỏ qua điều gì
Apple không chạy khảo sát hủy nào gửi kết quả về cho nhà phát triển. Trường gần nhất là expirationIntent trong thông tin gia hạn đã ký, và nó mô tả gói đăng ký kết thúc như thế nào, chứ không phải khách hàng nghĩ gì.
| expirationIntent | Ý nghĩa theo Apple | Subtype EXPIRED tương ứng |
|---|---|---|
| 1 | Khách hàng đã hủy gói đăng ký | VOLUNTARY |
| 2 | Lỗi thanh toán, ví dụ thông tin thanh toán không hợp lệ | BILLING_RETRY |
| 3 | Không đồng ý với việc tăng giá hoặc chuyển đổi ưu đãi cần sự đồng ý | PRICE_INCREASE |
| 4 | Sản phẩm không còn bán vào lúc gia hạn | PRODUCT_NOT_FOR_SALE |
| 5 | Một lý do khác | Không có subtype |
Mã 1 là mã duy nhất mô tả một lựa chọn của khách hàng, và nó cũng không nói gì về động cơ. Một khách hàng rời đi vì ứng dụng liên tục bị crash và một khách hàng chỉ đơn giản đã xong dự án trông giống hệt nhau.
Tín hiệu ẩn trong AUTO_RENEW_DISABLED
Có một thông báo của Apple đáng xem kỹ hơn. DID_CHANGE_RENEWAL_STATUS với subtype AUTO_RENEW_DISABLED thường có nghĩa là khách hàng đã tắt tự động gia hạn. Tài liệu của Apple bổ sung một trường hợp thứ hai: App Store cũng tắt tự động gia hạn sau khi khách hàng yêu cầu hoàn tiền.
Vậy trên iOS, một sự kiện tắt gia hạn có thể là dấu vết đầu tiên của một yêu cầu hoàn tiền. Nếu giao dịch là consumable hoặc gói đăng ký tự động gia hạn, CONSUMPTION_REQUEST có thể theo sau, và từ lúc đó bạn có 12 giờ để gửi dữ liệu tiêu thụ. Một sự kiện tắt gia hạn đến mà không có hành động nào hiển thị trong ứng dụng đáng được coi là lời cảnh báo sớm để chuẩn bị sẵn dữ liệu sử dụng của tài khoản đó.
Apple và Google đặt cạnh nhau
| Google Play | Apple App Store | |
|---|---|---|
| Hỏi người dùng lý do | Có, bằng khảo sát hủy | Không có khảo sát nào nhà phát triển thấy được |
| Lý do nằm ở đâu | canceledStateContext trong purchases.subscriptionsv2 | expirationIntent trong thông tin gia hạn |
| Văn bản tự do | reasonUserInput, chỉ với lý do khác | Không có |
| Ai đã hủy | Người dùng, hệ thống, nhà phát triển hoặc thay thế | Suy ra từ mã và subtype |
| Thông báo | SUBSCRIPTION_CANCELED, rồi gọi get | DID_CHANGE_RENEWAL_STATUS, EXPIRED |
| Mất đi nếu người dùng đăng ký lại | Có, bị xóa khi khôi phục | Thông tin gia hạn phản ánh trạng thái hiện tại |
| Bảng điều khiển | Thẻ Cancellation survey responses | Không có cho lý do |

Khi nào việc hủy biến thành hoàn tiền
Hủy gói sẽ dừng lần thu tiền tiếp theo. Nó không trả lại lần thu gần nhất. Tiền có được trả lại hay không phụ thuộc vào luồng hoàn tiền mà khách hàng tìm đến tiếp theo, và phần lớn các luồng đó diễn ra mà không cần bạn.
- Trên Google Play, người mua có thể tự nhận hoàn tiền trong vòng 48 giờ sau khi mua, và Google là bên quyết định.
- Hoàn tiền qua bộ phận hỗ trợ của Google hoặc Apple do cửa hàng quyết định.
- CONSUMPTION_REQUEST của Apple yêu cầu dữ liệu tiêu thụ của bạn, trong khung thời gian 12 giờ.
- Quy trình xem xét chargeback của Google Play yêu cầu bằng chứng qua orders.reviewrefund, trong khung thời gian 24 giờ. Quyết định của ngân hàng về chargeback là cuối cùng.
Lý do hủy không thay đổi bất kỳ quy tắc nào trong số đó. Điều nó thay đổi là bạn biết sớm đến mức nào khách hàng nào đang không hài lòng, và bằng chứng của bạn đã sẵn sàng chưa khi một trong hai luồng yêu cầu bằng chứng xuất hiện.
Mỗi lý do khiến bạn tốn bao nhiêu
Câu trả lời khảo sát cũng là chỉ dấu sơ bộ về chi phí bạn đã bỏ ra để phục vụ một tài khoản, tức là số tiền bạn phải tự gánh sau khi hoàn tiền.
Sự cố kỹ thuật
Đây là lý do tốn kém nhất. Khách hàng đã dùng sản phẩm đủ nhiều để gặp sự cố, nên bạn đã trả tiền cho compute phía sau các phiên của họ, các lệnh gọi model API từ yêu cầu của họ, dung lượng lưu trữ cho những gì họ tạo ra, và mọi khoản chi trả cho nhà sáng tạo có nội dung họ đã dùng. Nếu sau đó họ được hoàn tiền, khoản tiền quay về họ còn các chi phí đó vẫn ở lại với bạn. Nếu họ tìm đến ngân hàng trên Google Play, một đơn hàng đặt sau August 3, 2026 khiến bạn mất giá mua trừ phí dịch vụ của Play, cộng thêm phí ngân hàng.
Liên quan đến chi phí
Một lời phàn nàn về giá khiến bạn tốn ít hơn vẻ ngoài của nó, trừ khi đằng sau là một lần gia hạn bất ngờ. Đó là câu chuyện chargeback kinh điển, vì vậy hãy kiểm tra xem việc hủy có diễn ra ngay sau một lần thu tiền gia hạn không, và lời nhắc gia hạn của bạn đã được gửi chưa.
Dùng không đủ nhiều
Mức dùng thấp nghĩa là chi phí phục vụ thấp, nên hoàn tiền ở đây chủ yếu trả lại số tiền bạn không tốn nhiều để kiếm được. Đây cũng là lý do mà dữ liệu tiêu thụ trung thực, nếu Apple yêu cầu, cho thấy chính xác khách hàng đã dùng gì và chưa dùng gì.
Tìm được ứng dụng tốt hơn
Những khách hàng này hiếm khi tranh chấp điều gì. Họ đã chuyển sang đối thủ. Lý do này hữu ích cho quyết định sản phẩm, nhưng gần như không bao giờ giúp ích cho việc bảo vệ trước hoàn tiền.
Quy trình đọc lý do hủy
- Với mỗi SUBSCRIPTION_CANCELED từ Google Play, hãy gọi purchases.subscriptionsv2.get và lưu canceledStateContext cùng purchase token và cancelTime.
- Lưu nguyên văn reasonUserInput khi lý do là khác. Đây là văn bản tự do duy nhất mà cả hai cửa hàng cung cấp cho bạn.
- Với mỗi DID_CHANGE_RENEWAL_STATUS từ Apple có AUTO_RENEW_DISABLED, hãy ghi log sự kiện và lấy dữ liệu sử dụng của tài khoản đó, phòng khi CONSUMPTION_REQUEST theo sau.
- Với mỗi thông báo EXPIRED từ Apple, hãy ghi lại subtype và expirationIntent để churn tự nguyện và lỗi thanh toán không bị lẫn vào nhau.
- Với các lượt hủy trên Google Play nêu lý do sự cố kỹ thuật, hãy kiểm tra log lỗi của tài khoản đó và liên hệ khách hàng trước khi họ tìm đến ngân hàng.
- Lưu log sử dụng theo từng tài khoản, để CONSUMPTION_REQUEST được trả lời trong vòng 12 giờ và quy trình xem xét chargeback trong vòng 24 giờ.
Câu hỏi thường gặp
- Làm sao để biết vì sao một người đăng ký Google Play đã hủy?
- Gọi purchases.subscriptionsv2.get và đọc canceledStateContext.userInitiatedCancellation.cancelSurveyResult. Trường reason chứa câu trả lời khảo sát, còn reasonUserInput chứa văn bản tự do khi người dùng chọn lý do khác. Play Console cũng hiển thị số liệu tổng trong thẻ Cancellation survey responses.
- Apple có cho nhà phát triển biết vì sao khách hàng hủy gói đăng ký không?
- Không. Apple không có khảo sát hủy nào mà nhà phát triển thấy được. Trường expirationIntent cho biết gói đăng ký kết thúc như thế nào, với các mã cho khách hàng đã hủy, lỗi thanh toán, không đồng ý tăng giá, sản phẩm không còn bán, hoặc lý do khác, nhưng không cho biết động cơ của khách hàng.
- Thông báo SUBSCRIPTION_CANCELED có chứa lý do hủy không?
- Không. Thông báo nhà phát triển theo thời gian thực của Google Play chỉ cho biết trạng thái giao dịch đã thay đổi. Hãy lấy gói đăng ký bằng purchases.subscriptionsv2.get để đọc lý do, và lưu lại ngay, vì Google xóa các trường liên quan đến việc hủy nếu người dùng khôi phục gói đăng ký.
- Thông báo AUTO_RENEW_DISABLED của Apple có thể là dấu hiệu của yêu cầu hoàn tiền không?
- Có. Tài liệu của Apple cho biết subtype AUTO_RENEW_DISABLED bao gồm cả trường hợp khách hàng tắt tự động gia hạn và trường hợp App Store tắt nó sau khi khách hàng yêu cầu hoàn tiền.
- Tôi có thể thu hồi quyền truy cập khi người đăng ký hủy không?
- Trên Google Play thì không, khi họ vẫn còn quyền sử dụng. Google cho biết người đăng ký đã hủy vẫn giữ quyền truy cập đến hết chu kỳ thanh toán, và gỡ quyền truy cập sớm là vi phạm chính sách gói đăng ký của Google Play. Hãy dùng expiryTime để quyết định khi nào quyền truy cập kết thúc.
Nguồn và tài liệu đọc thêm
- Google Play Developer API: purchases.subscriptionsv2
- Google Play Billing: Subscription lifecycle
- Google Play Billing: Real-time developer notifications reference
- Play Console Help: Review in-app subscription performance
- Apple Developer: expirationIntent
- Apple Developer: notificationType
- Apple Developer: Send Consumption Information
- Play Console Help: Updates to refund protection and chargeback cost responsibility
RefundHalt
Chế độ tự động xử lý hoàn tiền cho App Store và Google Play
Đọc tiếp
Yêu cầu hoàn tiền quá mức có thể khiến bạn mất nhiều hơn chính khoản hoàn tiền, vì cả hai kho ứng dụng đều coi đó là tín hiệu chất lượng
Hướng dẫn 5.6.4 của Apple nêu rõ yêu cầu hoàn tiền quá mức là dấu hiệu ứng dụng không đạt chuẩn chất lượng, còn Thỏa thuận phân phối của Google cho phép gỡ ứng dụng của nhà phát triển mới dựa trên tỷ lệ hoàn tiền. Đây là những gì mỗi kho quy định, cái giá khi bị gỡ và cách tránh rủi ro.
Hãy xác minh thông báo máy chủ App Store trước khi xử lý hoàn tiền, vì bất kỳ ai cũng có thể gửi yêu cầu đến URL webhook của bạn
Một thông báo hoàn tiền chỉ là một yêu cầu HTTPS cho đến khi bạn kiểm tra chữ ký của nó. Bài viết này hướng dẫn cách xác minh thông báo máy chủ App Store và tin nhắn RTDN của Google Play, mỗi cửa hàng ký những gì, và một khoản hoàn tiền giả mạo hoặc bị từ chối nhầm khiến bạn tốn bao nhiêu.