Tất cả bài viết
PlaybookĐọc trong 7 phút

Ba thông báo hoàn tiền App Store đến sau khi Apple quyết định, và REFUND_REVERSED trả lại doanh số cho bạn

Apple gửi bốn tin nhắn hoàn tiền qua App Store Server Notifications V2, và hầu hết ứng dụng chỉ xử lý hai. REFUND yêu cầu bạn thu hồi, REFUND_DECLINED nghĩa là giữ doanh số, và REFUND_REVERSED trả lại doanh số và yêu cầu bạn khôi phục những gì đã lấy đi. Đây là những gì mỗi loại đòi hỏi.

Một điện thoại thông minh hiển thị biên nhận thanh toán bên cạnh một phong bì được trả lại và một đồng xu, minh họa các thông báo hoàn tiền App Store mà Apple gửi sau khi quyết định một khoản hoàn tiền

Điểm chính

  • Apple gửi bốn tin nhắn liên quan đến hoàn tiền qua App Store Server Notifications V2. CONSUMPTION_REQUEST yêu cầu bằng chứng của bạn, còn REFUND, REFUND_DECLINED và REFUND_REVERSED báo cáo kết quả sau khi Apple đã quyết định.
  • Thông báo REFUND nghĩa là App Store đã hoàn tiền cho giao dịch. Nó mang theo revocationDate và revocationReason, và đó là tín hiệu để bạn thu hồi quyền lợi gắn với một giao dịch đó, không phải mọi lần mua sản phẩm đó.
  • revocationReason có hai giá trị. 1 nghĩa là khoản hoàn tiền được cấp do vấn đề với sản phẩm của bạn, và 0 nghĩa là được cấp vì lý do khác. Giá trị vấn đề là một tín hiệu chất lượng đáng ghi lại và theo dõi xu hướng.
  • REFUND_DECLINED nghĩa là Apple từ chối yêu cầu hoàn tiền của khách hàng. Bạn giữ doanh số và không thay đổi gì, điều này chỉ an toàn nếu bạn chưa thu hồi quyền truy cập trước khi quyết định trở thành cuối cùng.
  • REFUND_REVERSED nghĩa là Apple đảo ngược một khoản hoàn tiền đã cấp trước đó, thường sau khi khách hàng khiếu nại. Các trường thu hồi biến mất khỏi giao dịch, và chỉ dẫn của chính Apple là nếu bạn đã thu hồi nội dung, bạn cần khôi phục lại.
  • Phản hồi cả bốn thông báo bằng HTTP 200. Nếu máy chủ của bạn ngừng hoạt động và bỏ lỡ một thông báo, endpoint Get Refund History cho phép bạn tra cứu các giao dịch được hoàn tiền theo id giao dịch và đối soát.
  • Một khoản hoàn tiền cho kỳ đăng ký đã qua không phải lúc nào cũng nghĩa là quyền truy cập phải chấm dứt. Nếu một kỳ trả phí mới hơn vẫn đang hoạt động, thu hồi trên giao dịch cũ sẽ cắt đứt một khách hàng đang thanh toán đúng hạn.

Apple quyết định khoản hoàn tiền của bạn, rồi tiếp tục nói. Một khi kết quả được ấn định, App Store gửi máy chủ của bạn một trong ba thông báo hoàn tiền App Store, và mỗi loại yêu cầu một hành động khác nhau. REFUND nói tiền đã đi và bạn nên rút quyền truy cập. REFUND_DECLINED nói khách hàng đã thua yêu cầu và bạn giữ doanh số. REFUND_REVERSED nói Apple đã hủy một khoản hoàn tiền mà họ đã cấp, nên doanh số lại là của bạn và bạn cần trả lại bất cứ thứ gì đã lấy đi. Hầu hết ứng dụng đấu nối cái đầu tiên và âm thầm bỏ qua hai cái còn lại. Đó là cách một khách hàng đang trả tiền rốt cuộc bị khóa khỏi thứ họ đã trả tiền.

Ba loại này tách biệt với CONSUMPTION_REQUEST, tin nhắn hoàn tiền duy nhất yêu cầu bạn trả lời. Các thông báo sau quyết định không muốn tranh luận. Chúng muốn một HTTP 200 và thay đổi đúng đắn đối với quyền truy cập của khách hàng. Đây là ý nghĩa của từng loại, các trường chính xác mang theo sự thật, và nơi tiền rò rỉ khi bạn xử lý sai.

Bốn thông báo hoàn tiền, và loại nào muốn được trả lời

App Store Server Notifications V2 là một luồng duy nhất. Bạn trỏ nó vào một URL và Apple gửi mọi loại thông báo đến đó, nên bạn đã nhận cả bốn tin nhắn hoàn tiền dù bạn có xử lý chúng hay không. Bốn trong số các loại chạm đến hoàn tiền, và chỉ một loại là câu hỏi.

Thông báoApple đang nói gì với bạnHành động của bạnCó mong đợi trả lời
CONSUMPTION_REQUESTKhách hàng yêu cầu hoàn tiền và Apple muốn dữ liệu của bạnGửi Send Consumption Information trong vòng 12 giờCó, dữ liệu thật
REFUNDApp Store đã hoàn tiền cho giao dịchThu hồi quyền lợi cho giao dịch đóKhông, HTTP 200
REFUND_DECLINEDApp Store đã từ chối khoản hoàn tiềnGiữ quyền truy cập, không thay đổi gìKhông, HTTP 200
REFUND_REVERSEDApple đã đảo ngược một khoản hoàn tiền đã cấpKhôi phục nội dung bạn đã thu hồiKhông, HTTP 200

Một thông báo REFUND thực sự nói gì với bạn

REFUND kích hoạt khi App Store đã hoàn tiền thành công một giao dịch cho khách hàng. Nó áp dụng cho mọi loại giao dịch mua: hàng tiêu hao, hàng không tiêu hao, đăng ký tự động gia hạn, và đăng ký không gia hạn. Giao dịch đã ký bên trong thông báo giờ mang theo hai trường mà nó không có trước khi hoàn tiền, và hai trường đó là toàn bộ câu chuyện.

revocationDate và revocationReason mang theo sự thật

revocationDate là thời gian UNIX, tính bằng mili giây, mà App Store hoàn tiền giao dịch hoặc thu hồi nó. revocationReason cho bạn biết danh mục của khoản hoàn tiền, và nó nhận đúng hai giá trị.

revocationReasonÝ nghĩa theo AppleNên đọc ra điều gì
1Khoản hoàn tiền được cấp do vấn đề với sản phẩmMột tín hiệu về chất lượng hoặc bàn giao. Ghi lại, theo dõi xu hướng, và tìm một khuôn mẫu ở một sản phẩm hoặc một bản dựng
0Khoản hoàn tiền được cấp vì lý do khácMột khoản hoàn tiền thông thường. Thu hồi quyền lợi và tiếp tục

Sự hiện diện của revocationDate trên một giao dịch tự nó là dấu hiệu. Nếu sau này bạn truy xuất một giao dịch và nó có revocationDate, giao dịch mua đó đã được hoàn tiền, dù có thông báo hay không. Đọc lý do bên cạnh nó để một làn sóng hoàn tiền giá trị 1 trên một bản phát hành duy nhất không lọt qua bạn như nhiễu.

Thu hồi theo giao dịch, không theo sản phẩm

Cái bẫy ở đây là thu hồi quá nhiều. Một REFUND nêu tên một giao dịch. Nó không bảo bạn vô hiệu hóa mọi giao dịch mua mà khách hàng từng thực hiện với id sản phẩm đó. Chỉ dẫn của chính Apple là kiểm tra khách hàng còn giữ quyền truy cập nào trước khi bạn cắt bất cứ thứ gì, vì các quyền lợi chồng lấn nhau. Trường hợp kinh điển là một đăng ký: một khoản hoàn tiền rơi vào lần gia hạn tháng trước trong khi lần gia hạn tháng này đang hoạt động và đã thanh toán đầy đủ. Thu hồi theo sản phẩm và bạn vừa cắt đứt một khách hàng hiện tại đang trả tiền vì một khoản hoàn tiền cho kỳ đã kết thúc.

REFUND_DECLINED nghĩa là bạn đã thắng, nên đừng hủy bỏ điều đó

REFUND_DECLINED đến khi App Store từ chối yêu cầu hoàn tiền của khách hàng. Khách hàng đã hỏi, Apple nói không, và bạn giữ doanh số. Nhìn bề ngoài không có gì để làm, và đó chính là điểm mấu chốt. Sai lầm mà thông báo này phơi bày là một sai lầm khác: thu hồi quyền truy cập quá sớm.

Nếu mã của bạn phản ứng với CONSUMPTION_REQUEST bằng cách rút quyền truy cập của khách hàng trước khi Apple phán quyết, một REFUND_DECLINED là khoảnh khắc quyết định đó nổ tung. Apple giữ tiền của bạn, và bạn đã khóa một khách hàng có khoản hoàn tiền bị từ chối. Khách hàng đó giờ trả tiền cho một sản phẩm họ không thể dùng, mở một phiếu hỗ trợ, và nhớ điều đó. Cách khắc phục là một quy tắc, không phải một tính năng: thu hồi khi REFUND, không bao giờ khi có yêu cầu. REFUND_DECLINED chỉ đơn giản là Apple xác nhận rằng thu hồi sớm sẽ là một quyết định sai.

REFUND_REVERSED là thông báo trả lại tiền cho bạn

REFUND_REVERSED là loại gần như không ai xử lý, và nó là loại trả lại tiền cho bạn. Apple gửi nó khi đảo ngược một khoản hoàn tiền đã cấp trước đó, thường sau khi khách hàng khiếu nại khoản hoàn tiền đó. Các trường thu hồi mà một REFUND đã thêm vào giao dịch bị gỡ bỏ lần nữa, nên giao dịch mua lại được đọc là đã thanh toán. Apple nêu công việc của nhà phát triển trong một dò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 liên quan, nó cần khôi phục lại. Nó áp dụng cho bất kỳ loại giao dịch mua nào, từ hàng tiêu hao đến đăng ký tự động gia hạn.

Vấn đề nhiều tuần sau

Câu hỏi thực sự mà các nhà phát triển nêu ra, trên chính diễn đàn của Apple, là thời điểm. Một REFUND_REVERSED có thể đến nhiều tuần sau REFUND ban đầu, rất lâu sau khi một kỳ đăng ký đã hết hạn. Vậy bạn có khôi phục quyền truy cập khi đó không? Khôi phục những gì giao dịch thực sự cấp, giới hạn trong phạm vi giao dịch đó bao trùm. Đối với hàng tiêu hao hoặc hàng không tiêu hao, bật lại việc mở khóa. Đối với một kỳ đăng ký đã trôi qua, bạn không phát thêm thời gian mới, bạn đang sửa lại hồ sơ để lịch sử của khách hàng chính xác và bất kỳ quyền lợi nào vẫn còn hiệu lực được kích hoạt lại. Khôi phục giao dịch cụ thể, và logic chồng lấn của bạn quyết định cái gì đang hoạt động hiện tại.

Một đồng xu được đặt lại bên cạnh một điện thoại thông minh, minh họa một khoản hoàn tiền App Store bị đảo ngược trả lại doanh số cho nhà phát triển

Tiền nằm ở đâu khi làm đúng điều này

Mỗi thông báo trong số này ánh xạ tới một con số thực, và chi phí của việc xử lý sai không chỉ là giá bán.

REFUND: ngừng trả tiền để phục vụ một khách hàng đã được hoàn tiền

Giá bán đã mất ngay khoảnh khắc REFUND đến. Thứ bạn vẫn còn kiểm soát được là chi phí tiếp tục cung cấp. Mỗi giờ một quyền lợi đã hoàn tiền vẫn còn hoạt động, bạn tiếp tục chi tiêu cho những thứ khách hàng không còn trả tiền: tính toán, lệnh gọi API mô hình, lưu trữ, và bất kỳ khoản chi trả cho nhà sáng tạo hay đối tác nào gắn với việc sử dụng của họ. Thu hồi kịp thời khi REFUND sẽ dừng đồng hồ đó lại. Bỏ qua thông báo nghĩa là bạn tài trợ một sản phẩm cho một người mà cửa hàng đã bù đắp xong.

REFUND_DECLINED: đừng biến một chiến thắng thành một khoản hoàn tiền thiện chí

Khi bạn thu hồi sớm và khoản hoàn tiền sau đó bị từ chối, bạn giữ doanh số trên giấy tờ và mất nó trên thực tế. Khách hàng đã trả tiền không thể dùng sản phẩm, nên bạn thừa hưởng một cuộc trò chuyện hỗ trợ và, thường là, một khoản hoàn tiền tùy ý để làm cho đúng. Đó là trả tiền hai lần cho một doanh số chưa bao giờ gặp nguy hiểm. Xử lý REFUND_DECLINED đúng cách không tốn gì cả, đó chính là lý do để nguyên quyền truy cập cho đến khi REFUND là quy tắc rẻ nhất bạn có thể áp dụng.

REFUND_REVERSED: cặp tồi tệ nhất là tiền của họ và quyền truy cập của họ đều mất

Bỏ qua REFUND_REVERSED và bạn đạt tới kết cục tồi tệ nhất trên bàn cờ. Bạn đã được trả tiền, và khách hàng không có gì. Họ đã liên hệ ngân hàng một lần để đảo ngược khoản hoàn tiền, và một người bị khóa khỏi một sản phẩm mà giờ họ đang bị tính phí là một người có khả năng liên hệ ngân hàng lần thứ hai. Khiếu nại tiếp theo đó có thể trở thành một khoản bồi hoàn thẻ, vốn là quyết định cuối cùng ở phía ngân hàng và tốn kém hơn giá bán rất nhiều. Khôi phục quyền truy cập ngay khoảnh khắc REFUND_REVERSED đến là khoản bảo hiểm rẻ nhất trong toàn bộ luồng hoàn tiền.

Cần đấu nối những gì

Việc xử lý nhỏ gọn một khi mô hình đã đúng. Gắn khóa quyền lợi trên id giao dịch để mọi thông báo trỏ vào một giao dịch mua. Với CONSUMPTION_REQUEST, gửi dữ liệu của bạn trong vòng 12 giờ. Với REFUND, thu hồi giao dịch đó. Với REFUND_DECLINED, không làm gì cả. Với REFUND_REVERSED, khôi phục. Trả về HTTP 200 nhanh chóng cho tất cả và thực hiện thay đổi quyền truy cập vào thời gian của riêng bạn.

Đối với khoảng trống mà các thông báo để lại, hãy dùng endpoint Get Refund History. Nếu máy chủ của bạn ngừng hoạt động trong một sự cố và bỏ lỡ một REFUND, hãy gọi tra cứu hoàn tiền của App Store Server API cho một id giao dịch, tại /inApps/v2/refund/lookup/{transactionId}, và đọc lại các giao dịch đã ký với revocationDate và revocationReason của chúng. Nó đối soát từng giao dịch một và phân trang qua các giao dịch mua đã hoàn tiền của khách hàng, nên một webhook bị bỏ lỡ không trở thành một quyền lợi bị đặt sai vĩnh viễn.

Đây là phần RefundHalt chạy thay cho bạn. Nó lắng nghe cả bốn loại, thu hồi khi REFUND, giữ nguyên quyền truy cập khi REFUND_DECLINED, và tự động khôi phục khi REFUND_REVERSED, mỗi loại được gắn khóa vào đúng giao dịch. Một khoản hoàn tiền bị đảo ngược không nằm chờ trong hàng đợi trong khi một khách hàng đang trả tiền vẫn bị khóa, và một khoản bị từ chối không bao giờ kích hoạt một lần thu hồi mà bạn phải rút lại.

Câu hỏi thường gặp

Sự khác biệt giữa REFUND và REFUND_REVERSED là gì?
REFUND nghĩa là App Store đã hoàn tiền một giao dịch và bạn nên thu hồi quyền lợi đó, trong khi REFUND_REVERSED nghĩa là Apple đã hủy một khoản hoàn tiền đã cấp và bạn nên khôi phục nội dung bạn đã thu hồi. Hai loại này là một cặp: một giao dịch mua có thể trải qua REFUND rồi, nếu khiếu nại của khách hàng bị lật ngược, REFUND_REVERSED. Gắn khóa các thay đổi quyền truy cập của bạn trên id giao dịch để mỗi thông báo tác động đúng giao dịch mua.
Tôi có cần gửi lại thứ gì cho một thông báo REFUND không?
Không. Bạn phản hồi REFUND, REFUND_DECLINED và REFUND_REVERSED bằng một HTTP 200 và không có phần thân. Chỉ CONSUMPTION_REQUEST yêu cầu bạn gửi dữ liệu, và nó làm vậy qua endpoint Send Consumption Information trong vòng 12 giờ. Ba loại còn lại là Apple báo cáo một quyết định, không phải đặt một câu hỏi.
Tôi nên làm gì khi nhận được một thông báo REFUND_DECLINED?
Không có gì thay đổi, vì khoản hoàn tiền của khách hàng đã bị từ chối và bạn giữ doanh số. Cách duy nhất khiến REFUND_DECLINED gây ra việc phải làm là nếu bạn đã thu hồi quyền truy cập sớm, trước khi Apple phán quyết. Hãy thu hồi khi REFUND thay vì khi có CONSUMPTION_REQUEST, và một REFUND_DECLINED trở thành xác nhận rằng quyền truy cập đã được để nguyên đúng đắn.
Tôi có nên khôi phục quyền truy cập khi REFUND_REVERSED đến nhiều tuần sau khoản hoàn tiền không?
Có, hãy khôi phục quyền lợi mà giao dịch cụ thể đó cấp. Apple nêu rõ rằng nếu ứng dụng của bạn đã thu hồi nội dung do khoản hoàn tiền liên quan, nó cần khôi phục lại. Đối với hàng tiêu hao hoặc hàng không tiêu hao, hãy bật lại việc mở khóa. Đối với một kỳ đăng ký đã hết hạn, bạn đang sửa lại hồ sơ, không phải cấp thời gian mới, nên logic chồng lấn của bạn vẫn quyết định cái gì đang hoạt động hiện tại.
Làm thế nào để bắt được một thông báo hoàn tiền mà máy chủ của tôi đã bỏ lỡ?
Hãy dùng endpoint Get Refund History của App Store Server API, nó tra cứu các giao dịch được hoàn tiền của một khách hàng theo id giao dịch tại /inApps/v2/refund/lookup/{transactionId}. Nó trả về các giao dịch đã ký với revocationDate và revocationReason, nên sau một sự cố bạn có thể đối soát quyền truy cập mà không phải chờ một thông báo đã kích hoạt rồi. Nó xử lý một id giao dịch mỗi lệnh gọi và phân trang qua các giao dịch mua đã hoàn tiền của khách hàng.

Nguồn và tài liệu đọc thêm

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 tiếp theo đã đang trên đường đến.

Thiết lập RefundHalt trong khoảng thời gian bạn cần để đọc thêm một email hỗ trợ về khoản hoàn tiền mà mình chưa kịp phản biện.