Retention Messaging API của Apple đưa lời nhắn của bạn lên màn hình hủy, nhưng yêu cầu hoàn tiền không bao giờ đi qua đó
Retention Messaging API của Apple cho phép bạn hiển thị một lời nhắn, gợi ý đổi gói hoặc ưu đãi khuyến mãi khi người đăng ký chạm Cancel. Bài này giải thích cách nó hoạt động, chi phí vận hành, và vì sao yêu cầu hoàn tiền đến Apple mà không hề chạm vào màn hình đó.

Điểm chính
- Retention Messaging API của Apple cho phép nhà phát triển chọn lời nhắn mà người đăng ký trên iPhone nhìn thấy sau khi chạm Cancel Subscription, với một trong bốn loại: văn bản, văn bản kèm hình ảnh, gợi ý đổi gói, hoặc ưu đãi khuyến mãi.
- Tài liệu của Apple vẫn mô tả Retention Messaging API là bản phát hành trước mà nhà phát triển phải xin tham gia. Phiên bản 1.0 ra mắt ngày 16 tháng 7 năm 2025, và phiên bản 1.5 tiếp nối vào ngày 27 tháng 4 năm 2026.
- Trong luồng thời gian thực, Apple gọi endpoint Get Retention Message của nhà phát triển khi một người đăng ký đang hoạt động xem trang chi tiết gói đăng ký có nút Cancel, và endpoint phải trả lời trong vòng 700 ms ở môi trường production, nếu không Apple sẽ dùng lời nhắn mặc định.
- Lời nhắn giữ chân chỉ ảnh hưởng đến các lần gia hạn sau. Yêu cầu hoàn tiền đến Apple qua reportaproblem.apple.com hoặc bảng hoàn tiền trong ứng dụng, và màn hình hủy nơi lời nhắn giữ chân xuất hiện không nằm trên con đường đó.
- Khi khách hàng yêu cầu hoàn tiền ngay trong ứng dụng qua API yêu cầu hoàn tiền của StoreKit, chính Apple tắt tự động gia hạn và gửi DID_CHANGE_RENEWAL_STATUS với subtype AUTO_RENEW_DISABLED, giống hệt type và subtype của một lần hủy từ trang cài đặt Subscriptions.
- Đầu vào duy nhất của nhà phát triển đối với một khoản hoàn tiền của Apple là CONSUMPTION_REQUEST, được trả lời trong vòng 12 giờ bằng Send Consumption Information, và chỉ khi khách hàng đồng ý chia sẻ dữ liệu đó.
- Google Play không có tính năng tương đương được ghi trong tài liệu cho lời nhắn trên màn hình hủy do nhà phát triển chọn. Nhà phát triển nhận thông báo SUBSCRIPTION_CANCELED sau đó, và trường userInitiatedCancellation cho biết lý do người đăng ký rời đi.
Người đăng ký chạm Cancel trên iPhone giờ đây có thể thấy một lời nhắn do bạn chọn, một gói rẻ hơn hoặc một khoản giảm giá, trước khi họ xác nhận. Đó là Retention Messaging API của Apple, và đây là lần đầu tiên nhà phát triển có tiếng nói trên chính màn hình hủy của Apple. Nó vẫn là bản phát hành trước mà bạn phải xin tham gia. Nó cũng có một ranh giới cứng, rất quan trọng nếu bạn quan tâm đến hoàn tiền: nó nói chuyện với những người sắp ngừng trả tiền, không phải với những người đòi lại tiền. Các yêu cầu đó đến Apple bằng một con đường khác.
Retention Messaging API của Apple làm gì
Retention Messaging API là một dịch vụ server-to-server. Bạn tải nội dung lời nhắn và hình ảnh lên Apple từ trước, Apple duyệt chúng, rồi bạn chọn lời nhắn đã được duyệt nào sẽ hiện cho người đăng ký khi họ sắp hủy một gói đăng ký tự động gia hạn. Tài liệu của Apple liệt kê bốn loại lời nhắn:
- Lời nhắn văn bản, có thể có các gạch đầu dòng.
- Lời nhắn văn bản kèm hình ảnh.
- Lời nhắn đổi gói, gợi ý một gói đăng ký khác trong cùng nhóm đăng ký.
- Lời nhắn ưu đãi khuyến mãi, đưa ra mức giá giảm ở cùng cấp hoặc cấp khác, dùng một ưu đãi khuyến mãi bạn thiết lập trong App Store Connect và ký trên server của bạn.
Lời nhắn xuất hiện sau khi khách hàng chạm Cancel Subscription trên trang chi tiết gói đăng ký. Sau đó Apple hiển thị trang Confirm Cancellation. Khách hàng vẫn có thể hủy, chạm Keep Subscription, hoặc nhận ưu đãi hay gói mà bạn gợi ý. Bạn không thể giấu lối ra, và Apple yêu cầu nhà phát triển không tải lên nội dung gây hiểu lầm hoặc không chính xác.
Lời nhắn mặc định và luồng thời gian thực
Có hai cách vận hành. Cách đơn giản là lời nhắn mặc định: văn bản, có hoặc không có hình ảnh hay gạch đầu dòng, gán cho từng sản phẩm và từng ngôn ngữ. Cách phong phú hơn là luồng thời gian thực, trong đó Apple gọi endpoint Get Retention Message trên server của bạn và bạn trả lời bằng một ID lời nhắn. Chỉ luồng thời gian thực mới hiển thị được lời nhắn đổi gói và ưu đãi khuyến mãi.
Trên thực tế, lời nhắn mặc định không phải là tùy chọn. Apple dùng chúng làm phương án dự phòng mỗi khi lệnh gọi thời gian thực thất bại, và hoàn toàn không hiển thị lời nhắn giữ chân nào cho một sản phẩm ở bất kỳ ngôn ngữ nào thiếu lời nhắn mặc định.
| Mục | Tài liệu của Apple nói gì |
|---|---|
| Trạng thái | Bản phát hành trước, nhà phát triển đăng ký quan tâm để tham gia |
| Sản phẩm | Gói đăng ký tự động gia hạn |
| Loại lời nhắn | Văn bản, văn bản kèm hình ảnh, đổi gói, ưu đãi khuyến mãi |
| Giới hạn phản hồi thời gian thực | 700 ms ở production |
| Quyền truy cập production | Phải qua bài kiểm tra hiệu năng sandbox trước, khoảng 700 ms |
| Văn bản tiêu đề và gạch đầu dòng | Mỗi loại 66 ký tự, tối đa năm gạch đầu dòng |
| Văn bản nội dung | 144 ký tự |
| Văn bản alt của hình ảnh | 150 ký tự |
| Số lời nhắn mỗi ứng dụng | 2.000 |
| Duyệt | Lời nhắn mới bắt đầu ở PENDING và chỉ hiển thị khi đã APPROVED |
| Thiết bị | iOS 15.1, iPadOS 15.1, visionOS 1, macOS 14 trở lên |
Apple cho server của bạn biết gì trong lệnh gọi thời gian thực
Yêu cầu là một JWS do App Store ký. Khi giải mã, nó chứa originalTransactionId, appAppleId, productId, userLocale, một requestIdentifier dạng UUID, environment và signedDate. Apple yêu cầu bạn kiểm tra appAppleId có khớp với ứng dụng của bạn hay không và không trả lời nếu không khớp. Phần hữu ích là originalTransactionId, vì nó cho phép bạn tra cứu người đăng ký này thực sự đã làm gì trong ứng dụng trước khi chọn điều cần nói.
Lời nhắn giữ chân xuất hiện ở đâu, và không xuất hiện ở đâu
Apple đặt lời nhắn trên một màn hình duy nhất, bước Confirm Cancellation sau khi khách hàng chạm Cancel Subscription, chẳng hạn từ Apple Account > Subscriptions hoặc từ trang của một gói đăng ký trên App Store. Màn hình đó quyết định lần gia hạn tiếp theo có diễn ra hay không. Nó không đụng đến số tiền đã thu.
Yêu cầu hoàn tiền là một hành động riêng. Trang hỗ trợ của Apple đưa khách hàng đến reportaproblem.apple.com, nơi họ chọn "Request a refund" (Yêu cầu hoàn tiền), chọn lý do và mục cần hoàn, rồi chờ 24 đến 48 giờ để có cập nhật. Trong ứng dụng của bạn, beginRefundRequest của StoreKit mở bảng hoàn tiền của Apple, và Apple cho biết App Store cần tối đa 48 giờ để chấp thuận hoặc từ chối. Không con đường nào đi qua màn hình Confirm Cancellation.
| Thời điểm | Nơi diễn ra | Điều bị đặt cược | Ai quyết định | Đầu vào của bạn |
|---|---|---|---|---|
| Hủy | Trang chi tiết gói đăng ký, rồi Confirm Cancellation | Các lần gia hạn sau | Khách hàng | Lời nhắn giữ chân do bạn chọn, trả lời trong 700 ms |
| Yêu cầu hoàn tiền | reportaproblem.apple.com hoặc bảng hoàn tiền trong ứng dụng của bạn | Số tiền đã trả | Apple | Dữ liệu CONSUMPTION_REQUEST trong 12 giờ, nếu khách hàng đồng ý |
Lời nhắn giữ chân có ngăn được yêu cầu hoàn tiền không?
Không. Yêu cầu hoàn tiền không bao giờ đến màn hình nơi lời nhắn nằm. Có một chi tiết trong tài liệu thông báo của Apple làm rõ điều này. Khi khách hàng yêu cầu hoàn tiền qua ứng dụng của bạn bằng API yêu cầu hoàn tiền, Apple tự tắt tự động gia hạn và gửi DID_CHANGE_RENEWAL_STATUS với subtype AUTO_RENEW_DISABLED. Một khách hàng hủy từ trang cài đặt Subscriptions cũng tạo ra đúng type và subtype đó. Server của bạn thấy một thông báo cho hai khách hàng rất khác nhau, và chỉ một trong hai người đã thấy lời nhắn giữ chân của bạn.
Nếu yêu cầu hoàn tiền tiếp tục, kênh bằng chứng là CONSUMPTION_REQUEST. Apple gửi nó cho yêu cầu hoàn tiền ở mọi loại sản phẩm, và bạn có 12 giờ để trả lời bằng Send Consumption Information. Bạn chỉ được trả lời nếu khách hàng đã đồng ý. Sau đó, quyết định của Apple đến dưới dạng thông báo REFUND, hoặc REFUND_DECLINED nếu Apple từ chối một khoản hoàn tiền mà khách hàng bắt đầu trong ứng dụng của bạn.
Google Play có API lời nhắn khi hủy không?
Không có trong tài liệu vòng đời gói đăng ký của Google. Người đăng ký Google Play hủy từ trung tâm gói đăng ký của Play, vẫn giữ quyền truy cập đến hết chu kỳ thanh toán hiện tại, và có thể chạm Resubscribe để hoàn tác trước thời điểm đó, điều Google gọi là khôi phục (restore). Bạn chỉ biết chuyện này sau đó qua thông báo SUBSCRIPTION_CANCELED, và trường userInitiatedCancellation trong resource gói đăng ký cho biết lý do người dùng rời đi. Tạm dừng (pause), mà Google cho biết được bật mặc định cho mọi gói đăng ký, là cách tích hợp sẵn chính của Google để giảm tỷ lệ rời bỏ tự nguyện.
Về phía hoàn tiền, Google Play có kênh bằng chứng riêng. PendingRefundReviewNotification đến khi một chargeback cần nhà phát triển xem xét, và bạn có 24 giờ để trả lời qua orders.reviewrefund. Với các đơn hàng đặt sau ngày 3 tháng 8 năm 2026, khi chargeback thành công, Google chuyển sang nhà phát triển khoản giá mua, trừ phí dịch vụ của Play, cộng với phí chargeback của ngân hàng.
Màn hình hủy khiến bạn tốn bao nhiêu tiền
Lời nhắn giữ chân trông có vẻ miễn phí. Thực ra không, và hóa đơn đến từ ba chỗ.
Chi phí tính toán cho mỗi lượt xem trang
Apple gọi endpoint của bạn khi một người đăng ký đang hoạt động xem trang chi tiết gói đăng ký có nút Cancel, không chỉ khi họ hủy. Mỗi lượt truy cập là một yêu cầu mà server của bạn phải xác thực, tra cứu và trả lời trong 700 ms, nếu không Apple sẽ dùng lời nhắn mặc định. Điều đó loại bỏ các hàm cold start đôi khi mất hai giây. Bạn trả tiền cho năng lực xử lý luôn sẵn sàng, cộng với các lần đọc cơ sở dữ liệu và lệnh gọi API bên thứ ba trả phí mà logic quyết định của bạn thực hiện cho mỗi yêu cầu.

Khoản giảm giá là doanh thu bạn chọn không thu
Một ưu đãi khuyến mãi giữ được người đăng ký là tiền thật được giữ lại. Một ưu đãi đến tay người vốn dĩ vẫn sẽ ở lại chỉ là giảm giá thuần túy. Đây là một ví dụ minh họa, không phải số liệu chuẩn. Gói tháng $9.99 được giảm nửa giá trong ba tháng sẽ mất $14.99 cho mỗi ưu đãi được chấp nhận. Nếu cứ ba người chấp nhận thì có một người vẫn sẽ ở lại với giá đầy đủ, một nghìn lượt chấp nhận tốn khoảng $5,000 tiền giảm giá trao cho những người chưa bao giờ cần nó. Phía bên kia của sổ sách là những người đăng ký thật sự đang định rời đi.
Khoản hoàn tiền mà một lối ra khó chịu kéo theo
Apple luôn giữ nút Cancel Subscription trên trang, nên bạn không thể giữ chân ai bằng cách gài bẫy, nhưng bạn vẫn có thể gây phiền. Một khách hàng cảm thấy bị ép còn một lựa chọn khác, đó là yêu cầu Apple trả lại khoản phí gần nhất. Khi hoàn tiền thực sự xảy ra, tiền quay về, còn chi phí tính toán, lưu trữ, lệnh gọi API và mọi khoản hoa hồng affiliate gắn với người đăng ký đó vẫn đã tiêu. Đó là những chi phí mà không lời nhắn giữ chân nào thu hồi được.
Cách dùng lời nhắn giữ chân mà không làm tăng tỷ lệ hoàn tiền
Hãy coi màn hình hủy là nơi để chính xác, không phải để khéo léo. Vài quy tắc sau giúp bạn đứng đúng phía của ranh giới hoàn tiền:
- Quyết định theo từng người đăng ký. Dùng originalTransactionId trong yêu cầu của Apple để tra cứu mức sử dụng gần đây. Đưa giảm giá hoặc gói rẻ hơn cho người có dùng sản phẩm. Gửi lời nhắn ngắn và trung thực cho người đã nhiều tuần không mở ứng dụng.
- Giữ câu trả lời nhanh. Tính trước quyết định mỗi khi dữ liệu sử dụng thay đổi, để bản thân yêu cầu chỉ là một lần tra cứu, nằm gọn trong 700 ms.
- Viết lời nhắn mặc định cho mọi sản phẩm và mọi ngôn ngữ. Nếu thiếu, một lệnh gọi thất bại đồng nghĩa với không có lời nhắn nào.
- Theo dõi sát AUTO_RENEW_DISABLED. Nếu một CONSUMPTION_REQUEST theo sau cho cùng originalTransactionId, bạn đang nhìn thấy một yêu cầu hoàn tiền, không phải một lần hủy, và đồng hồ 12 giờ đã bắt đầu chạy.
- Trả lời mọi CONSUMPTION_REQUEST mà bạn được phép trả lời. RefundHalt gửi cho Apple dữ liệu tiêu dùng chính xác trong khung 12 giờ và trả lời yêu cầu xem xét chargeback của Google Play trong vòng 24 giờ, vì đó là hai thời điểm duy nhất mà mỗi cửa hàng hỏi đến phía bạn.
Có đáng xin Apple quyền truy cập không?
Nếu bạn bán gói đăng ký tự động gia hạn và đã xử lý App Store Server Notifications V2, câu trả lời có lẽ là có. Màn hình hủy là nơi cuối cùng bạn có thể tiếp cận một người đăng ký trước khi họ đi, và một lần đổi gói tốn ít hơn so với mất hẳn họ. Chỉ cần dự trù ngân sách cho một endpoint trả lời ở mọi lượt xem trang gói đăng ký, và đặt hàng phòng thủ hoàn tiền của bạn ở nơi hoàn tiền thực sự diễn ra.
Câu hỏi thường gặp
- Retention Messaging API của Apple là gì?
- Đây là một API server-to-server cho phép nhà phát triển chọn lời nhắn mà người đăng ký nhìn thấy sau khi chạm Cancel Subscription trên một gói đăng ký tự động gia hạn. Apple hỗ trợ bốn loại: văn bản, văn bản kèm hình ảnh, gợi ý đổi gói và ưu đãi khuyến mãi. Tài liệu của Apple vẫn mô tả nó là bản phát hành trước mà nhà phát triển phải xin tham gia.
- Endpoint Get Retention Message của tôi cần phản hồi nhanh đến mức nào?
- Trong vòng 700 ms ở production. Nếu server của bạn chậm hơn hoặc gặp lỗi, Apple hiển thị lời nhắn mặc định được cấu hình cho sản phẩm và ngôn ngữ đó, và không hiển thị gì nếu không có lời nhắn mặc định. Bạn cũng phải vượt qua bài kiểm tra hiệu năng sandbox, khoảng 700 ms, trước khi Apple cho phép bạn đặt URL production.
- Lời nhắn giữ chân có xuất hiện khi khách hàng yêu cầu hoàn tiền không?
- Không. Apple hiển thị lời nhắn giữ chân trên màn hình Confirm Cancellation sau khi khách hàng chạm Cancel Subscription. Yêu cầu hoàn tiền đi qua reportaproblem.apple.com hoặc bảng hoàn tiền trong ứng dụng do beginRefundRequest mở ra, và đầu vào duy nhất của nhà phát triển ở đó là CONSUMPTION_REQUEST, được trả lời trong vòng 12 giờ nếu khách hàng đồng ý.
- Làm sao phân biệt yêu cầu hoàn tiền với một lần hủy trong App Store Server Notifications?
- Không thể chỉ dựa vào thông báo gia hạn. Một lần hủy từ trang cài đặt Subscriptions và một yêu cầu hoàn tiền thực hiện qua ứng dụng của bạn đều tạo ra DID_CHANGE_RENEWAL_STATUS với subtype AUTO_RENEW_DISABLED. Một CONSUMPTION_REQUEST cho cùng giao dịch, và sau đó là thông báo REFUND hoặc REFUND_DECLINED, cho thấy đang có một yêu cầu hoàn tiền.
- Google Play có cho phép nhà phát triển hiển thị lời nhắn khi người dùng hủy không?
- Tài liệu vòng đời gói đăng ký của Google không mô tả tính năng nào như vậy. Nhà phát triển nhận thông báo SUBSCRIPTION_CANCELED sau khi sự việc đã xảy ra và có thể đọc trường userInitiatedCancellation để biết lý do người dùng hủy. Tạm dừng (pause), được bật mặc định cho mọi gói đăng ký, là công cụ tích hợp sẵn chính của Google Play để chống tỷ lệ rời bỏ tự nguyện.
Nguồn và tài liệu đọc thêm
- Apple Developer Documentation: Retention Messaging API
- Apple Developer Documentation: Setting up your Get Retention Message endpoint
- Apple Developer Documentation: Upload Message
- Apple Developer Documentation: Retention Messaging API changelog
- Apple Developer Documentation: notificationType
- Apple Developer Documentation: Send Consumption Information
- Apple Support: Request a refund for apps or content that you bought from Apple
- Google Play Billing: Subscription lifecycle
- Google Play Billing: Real-time developer notifications reference
- Google 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
ROAS của ứng dụng vẫn tính cả những giao dịch Apple và Google đã hoàn tiền, vì vậy hãy đặt giá thầu theo ROAS ròng
Khoản hoàn tiền hiếm khi được gửi ngược về nền tảng quảng cáo, nên ROAS vẫn ghi nhận những giao dịch mà Apple và Google đã trả lại tiền. Bài viết chỉ ra nơi Firebase, Google Ads và AdAttributionKit bỏ sót hoàn tiền, cái giá phải trả, và cách xây dựng ROAS ròng cho ứng dụng.
Order ID App Store trên biên lai của khách hàng cho bạn biết họ đã mua gì và Apple đã hoàn tiền hay chưa
Endpoint Look Up Order ID của Apple biến order ID trên biên lai App Store của khách hàng thành các giao dịch đã ký, kèm ngày và lý do hoàn tiền. Đây là cách dùng nó cho email hoàn tiền, những gì nó không làm được, và order ID của Google Play khác ra sao.