Tất cả bài viết
Deep diveĐọc trong 8 phút

Không xác nhận một giao dịch mua trên Google Play trong ba ngày và Google sẽ hoàn tiền, đây là cái giá bạn phải trả

Google Play tự động hoàn tiền và thu hồi bất kỳ giao dịch mua nào mà máy chủ của bạn không xác nhận trong ba ngày. Đó là một lỗi tích hợp, không phải quyết định của khách hàng, và hoàn toàn có thể ngăn chặn. Đây là quy tắc chính xác, lý do nó kích hoạt, và chi phí thực sự của mỗi lần bán hàng bị mất.

Một chiếc đồng hồ cát sắp cạn bên cạnh một chiếc điện thoại thông minh, minh họa khoảng thời gian ba ngày để xác nhận một giao dịch mua trên Google Play trước khi nó bị hoàn tiền tự động

Điểm chính

  • Google Play tự động hoàn tiền cho người mua và thu hồi giao dịch mua nếu ứng dụng của bạn không xác nhận nó trong ba ngày. Đó là một lỗi tích hợp, không phải quyết định của khách hàng, và hoàn toàn có thể ngăn chặn ở phía máy chủ.
  • Đồng hồ ba ngày bắt đầu khi trạng thái giao dịch mua chuyển thành PURCHASED, không phải khi bắt đầu thanh toán. Một giao dịch mua đang ở trạng thái PENDING chưa khởi động đồng hồ và chưa được phép xác nhận.
  • Hai lệnh gọi đáp ứng yêu cầu này. Tiêu thụ một mặt hàng consumable qua purchases.products.consume và xác nhận một mặt hàng non-consumable hoặc một gói đăng ký qua purchases.products.acknowledge hoặc purchases.subscriptions.acknowledge đều được tính là xác nhận.
  • Chỉ giao dịch mua gói đăng ký ban đầu mới cần xác nhận. Gia hạn thì không, và Google tự động đánh dấu chúng ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED.
  • Các gói trả trước ngắn hơn một tuần phải được xác nhận trong nửa thời lượng của gói, một hạn chót chặt chẽ hơn ba ngày tiêu chuẩn.
  • Việc hoàn tiền lấy lại giá bán, nhưng chi phí tính toán, các lệnh gọi API mô hình, lưu trữ, và các khoản chi trả cho nhà sáng tạo mà bạn đã bỏ ra để cung cấp sản phẩm thì không được trả lại. Số tiền bạn mất lớn hơn dòng chi phí trên hóa đơn.
  • Apple không có thứ tương đương. Một giao dịch StoreKit chưa hoàn tất sẽ được gửi lại cho đến khi bạn hoàn tất nó, nhưng Apple không bao giờ tự động hoàn tiền. Kiểu lỗi này chỉ có ở Google Play.

Một khách hàng mua sản phẩm của bạn, khoản thanh toán được duyệt, và ba ngày sau Google Play lặng lẽ hoàn tiền và thu hồi những gì bạn đã cung cấp. Không ai yêu cầu khoản hoàn tiền đó. Khách hàng không yêu cầu, và không có nhân viên hỗ trợ nào cấp nó. Nó kích hoạt vì máy chủ của bạn không bao giờ báo cho Google rằng giao dịch mua đã được xử lý. Nếu bạn không xác nhận một giao dịch mua trên Google Play trong ba ngày, Google hoàn tiền cho người mua và thu hồi giao dịch mua, mỗi lần đều vậy. Đây là một trong số ít khoản hoàn tiền trên cả hai cửa hàng mà hoàn toàn thuộc về việc tích hợp của bạn để ngăn chặn, và là một trong những cách âm thầm nhất để rò rỉ doanh thu.

Đây không phải vấn đề gian lận hay tranh chấp chính sách. Đó là một callback bị bỏ lỡ. Việc sửa thì nhỏ và chi phí bỏ qua nó là tiền thật, nên đáng để biết quy tắc một cách chính xác, tại sao các giao dịch mua lọt qua mà không được xác nhận, và mỗi lần bán hàng bị mất thực sự kéo theo những gì.

Quy tắc ba ngày thực sự nói gì

Tài liệu Play Billing của Google nói thẳng về điều này. Sau khi ứng dụng của bạn cấp quyền sử dụng và báo cho người dùng rằng giao dịch mua thành công, nó phải thông báo cho Google rằng giao dịch mua đã được xử lý. Theo lời của Google, việc này "phải được thực hiện trong ba ngày để giao dịch mua không bị tự động hoàn tiền và quyền sử dụng bị thu hồi." Trang sản phẩm mua một lần lặp lại điều đó mà không làm dịu đi: "Nếu bạn không xác nhận một giao dịch mua trong ba ngày, người dùng tự động nhận được khoản hoàn tiền, và Google Play thu hồi giao dịch mua." Gói đăng ký mang quy tắc y hệt cho giao dịch mua ban đầu.

Xác nhận là một tín hiệu, không phải một thủ tục hình thức. Nó báo cho Google rằng quyền sử dụng đã đến với người dùng. Google coi sự vắng mặt của tín hiệu đó là một lần giao hàng chưa bao giờ xảy ra, và nó đảo ngược giao dịch thay mặt khách hàng. Từ phía người mua, nó trông giống như một khoản hoàn tiền miễn phí mà họ chưa bao giờ yêu cầu. Từ phía bạn, nó trông giống như một lần bán hàng bốc hơi.

Đồng hồ bắt đầu tại PURCHASED, không phải tại thanh toán

Khoảng thời gian ba ngày không bắt đầu khi người dùng nhấn mua. Nó bắt đầu khi trạng thái giao dịch mua chuyển sang PURCHASED. Một giao dịch mua có thể ở trạng thái PENDING trước, điều xảy ra với thanh toán tiền mặt, chuyển khoản ngân hàng chậm, hoặc phụ huynh phê duyệt yêu cầu của con. Google nói rõ ràng: "Khoảng thời gian xác nhận ba ngày chỉ bắt đầu khi trạng thái giao dịch mua chuyển từ PENDING sang PURCHASED."

Điều đó có hai hệ quả. Chỉ cấp quyền sử dụng khi trạng thái là PURCHASED, đừng bao giờ cấp khi PENDING, nếu không bạn trao sản phẩm cho một khoản thanh toán có thể không bao giờ hoàn tất. Và cũng đừng xác nhận một giao dịch mua PENDING. Bạn gọi enablePendingPurchases() khi bạn dựng BillingClient, chờ sự chuyển đổi, và chỉ khi đó mới bắt đầu đồng hồ xác nhận trong đầu bạn.

Xác nhận hay tiêu thụ, và bạn nợ cái nào

Có hai cách để đáp ứng yêu cầu này, và bạn dùng cách nào tùy thuộc vào sản phẩm. Cả hai đều vượt qua hạn chót ba ngày. Sự khác biệt là chúng còn làm gì nữa.

Đối với một mặt hàng consumable, bạn tiêu thụ nó. Trên một backend an toàn thì đó là purchases.products.consume, hoặc consumeAsync() ở phía máy khách trong Play Billing Library. Việc tiêu thụ vừa xác nhận giao dịch mua vừa làm cho sản phẩm có thể mua lại, đó chính xác là điều bạn muốn cho xu, tín dụng, hoặc một lần tạo dùng một lần. Đối với một mặt hàng non-consumable hoặc một gói đăng ký, bạn xác nhận nó: purchases.products.acknowledge hoặc purchases.subscriptions.acknowledge trên backend, hoặc acknowledgePurchase() ở phía máy khách. Việc xác nhận vượt qua hạn chót mà không giải phóng sản phẩm để mua lại.

Loại giao dịch muaLệnh gọi đáp ứng hạn chótCòn làm gì nữaHạn chót
Consumablepurchases.products.consume hoặc consumeAsync()Cũng làm cho sản phẩm có thể mua lại3 ngày kể từ PURCHASED
Non-consumablepurchases.products.acknowledge hoặc acknowledgePurchase()Đánh dấu quyền sử dụng đã cấp, không mua lại3 ngày kể từ PURCHASED
Gói đăng ký, giao dịch mua ban đầupurchases.subscriptions.acknowledge hoặc acknowledgePurchase()Xác nhận gói đăng ký mới3 ngày kể từ PURCHASED
Gia hạn gói đăng kýKhông cần gì cảĐược Google tự động đánh dấu đã xác nhậnKhông áp dụng
Gói trả trước dưới một tuầnXác nhận như trênXác nhận quyền sử dụngNửa thời lượng của gói

Gia hạn đã được xử lý, giao dịch mua ban đầu thì chưa

Bạn chỉ có nghĩa vụ xác nhận đối với lần mua đầu tiên của một gói đăng ký. Google nói thẳng rằng "bạn không cần xác nhận các lần gia hạn gói đăng ký," và nó tự đóng dấu ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED cho các lần gia hạn. Một giao dịch mua mới đến với trạng thái ACKNOWLEDGEMENT_STATE_PENDING và vẫn là trách nhiệm của bạn cho đến khi bạn giải quyết xong. Trước khi bạn xác nhận, hãy kiểm tra acknowledgementState trên backend hoặc isAcknowledged() ở phía máy khách để bạn không xác nhận hai lần.

Gói trả trước có ngòi nổ ngắn hơn

Các gói đăng ký trả trước thu hẹp khoảng thời gian. Quy tắc của Google: các gói trả trước kéo dài một tuần hoặc lâu hơn phải được xác nhận trong ba ngày, nhưng "các gói trả trước có thời lượng ngắn hơn một tuần phải được xác nhận trong nửa thời lượng của gói." Một gói trả trước ba ngày cho bạn một ngày rưỡi, không phải ba ngày. Nếu bạn bán các khoản nạp trả trước ngắn hạn, đường dẫn xác nhận của bạn phải nhanh và do máy chủ điều khiển, không phụ thuộc vào việc người dùng mở lại ứng dụng.

Tại sao các giao dịch mua lại không được xác nhận ngay từ đầu

Không ai chủ tâm bỏ qua việc xác nhận. Nó bị bỏ lỡ vì đoạn mã xác nhận nằm sai chỗ. Kiểu chống mẫu phổ biến là một máy khách chỉ xác nhận khi luồng mua hàng quay lại tiền cảnh. Điều đó hiệu quả với một người dùng hoàn tất mua hàng và tiếp tục dùng ứng dụng. Nó thất bại với tất cả những người khác.

Các lập trình viên gặp phải điều này liên tục. Các chủ đề trong chính cộng đồng lập trình viên của Google đều đọc theo cùng một cách mỗi lần, một biến thể nào đó của "một người dùng tự động được hoàn tiền sau khi mua từ ứng dụng của tôi sau ba ngày" và "tại sao các khoản thanh toán tự động bị hoàn tiền sau ba ngày." Câu trả lời hầu như luôn giống nhau: lệnh gọi xác nhận không bao giờ được kích hoạt vì ứng dụng chưa bao giờ ở trạng thái để kích hoạt nó.

Bản dùng thử miễn phí và người dùng không bao giờ quay lại

Phiên bản tệ nhất là bản dùng thử miễn phí hoặc một giao dịch mua ngay trước khi người dùng đóng ứng dụng vĩnh viễn. Nếu việc xác nhận của bạn phụ thuộc vào lần mở ứng dụng tiếp theo, và không có lần mở ứng dụng tiếp theo nào, giao dịch mua sẽ hết hạn. Vào ngày thứ ba Google hoàn tiền và thu hồi nó. Đối với một bản dùng thử lẽ ra sẽ chuyển thành gói đăng ký trả phí, bạn mất khoản thanh toán đầu tiên mà bạn chưa kịp thu, cộng với một quyền sử dụng của khách hàng đã âm thầm biến mất. Không sự kiện nào trong số đó hiện ra dưới dạng một phiếu hỗ trợ. Nó hiện ra dưới dạng một giao dịch mua bị hủy mà bạn phải tự đi tìm.

Một khoản hoàn tiền không được xác nhận thực sự tốn kém đến đâu

Dòng hoàn tiền đánh giá thấp tổn thất. Khi Google đảo ngược giao dịch bán, bạn trả lại giá, và đó là con số nhìn thấy được. Đó không phải toàn bộ hóa đơn.

Hãy nghĩ về một mặt hàng consumable kích hoạt công việc thực sự ngay khi nó được mua. Một loạt lần tạo hình ảnh, một loạt lệnh gọi tới API của nhà cung cấp mô hình, một lần xuất video, một khoản chi trả cho nhà sáng tạo. Bạn đã trả cho phần tính toán đó, các lệnh gọi API đó, phần lưu trữ đó, và các khoản chi trả đó tại thời điểm sử dụng. Khoản hoàn tiền trả lại giá bán cho khách hàng. Nó không trả lại hóa đơn của nhà cung cấp cho bạn. Bạn đã cung cấp một chi phí thực và không nhận lại được gì cho nó.

Đối với gói đăng ký và bản dùng thử, tổn thất là khoản thanh toán đầu tiên bạn không bao giờ thu và mối quan hệ khách hàng kết thúc trước khi nó bắt đầu. Và bắt đầu từ ngày 3 tháng 8 năm 2026, Google Play chuyển giá mua chargeback và phí ngân hàng sang cho nhà phát triển đối với các đơn hàng đặt sau ngày đó, điều này khiến bất kỳ rò rỉ doanh thu có thể tránh được nào cũng đáng để khắc phục ngay bây giờ thay vì để sau. Một khoản hoàn tiền không được xác nhận không phải là một chargeback, nhưng đó là cùng một bài học: tiền bạn đã tiêu không phải là tiền bạn tự động giữ được.

Một hóa đơn gấp lại và những đồng xu bị kéo lùi trên một chiếc bàn tối màu, minh họa số tiền đã tiêu khi một giao dịch mua Google Play không được xác nhận bị hoàn tiền và thu hồi

Cách xác nhận một giao dịch mua Google Play ở phía máy chủ

Mẫu đáng tin cậy loại bỏ ứng dụng khỏi đường dẫn quan trọng. Hãy làm điều đó trên backend của bạn, do các thông báo điều khiển, không phải do người dùng mở lại màn hình.

  • Lắng nghe Real-time developer notifications. Một sự kiện mua ONE_TIME_PRODUCT hoặc SUBSCRIPTION_PURCHASED báo cho máy chủ của bạn rằng một giao dịch mua tồn tại ngay khoảnh khắc Google biết, bất kể ứng dụng có mở hay không.
  • Xác minh mã token giao dịch mua đối chiếu với Play Developer API và xác nhận trạng thái là PURCHASED, không phải PENDING.
  • Cấp quyền sử dụng trong hồ sơ của riêng bạn, gắn với người dùng.
  • Xác nhận hoặc tiêu thụ ngay lập tức. Tiêu thụ các mặt hàng consumable, xác nhận các mặt hàng non-consumable và các gói đăng ký ban đầu. Kiểm tra acknowledgementState trước để bạn không bao giờ xác nhận hai lần.
  • Bù đắp ở phía máy khách nữa. Gọi queryPurchasesAsync() trong onResume() để bất kỳ giao dịch mua nào hoàn tất khi ứng dụng đóng vẫn được xử lý. Đây là lưới an toàn, không phải đường dẫn chính.

Điểm mấu chốt là việc xác nhận được kích hoạt từ một sự kiện Google gửi cho bạn, không phải từ một hành động của người dùng mà bạn không thể trông cậy. Một người dùng mua rồi không bao giờ quay lại vẫn được bao phủ hoàn toàn vì máy chủ của bạn đã hành động ngay khoảnh khắc giao dịch mua hạ cánh.

Một lưới đối chiếu cho những cái lọt qua

Ngay cả một pipeline sạch cũng được lợi từ một lần kiểm tra. Voided Purchases API liệt kê các giao dịch mua đã bị hoàn tiền, thu hồi, hoặc chargeback, và nó nêu tên trường hợp mà lý do là giao dịch mua "chưa bao giờ được nhà phát triển xác nhận, và do đó có thể không tồn tại trong hồ sơ của nhà phát triển." Hãy poll nó và bạn có thể thu hồi quyền sử dụng bạn đã cấp cho bất cứ thứ gì Google đã đảo ngược. Lưu ý giới hạn: API chỉ trả về các giao dịch mua bị hủy từ 30 ngày qua, nên việc đối chiếu phải chạy theo lịch, không phải một lần mỗi quý.

Apple không có thứ tương đương, và điều đó quan trọng

Đây cụ thể là vấn đề của Google Play. StoreKit của Apple cũng có một bước hoàn tất, hoàn tất một giao dịch, nhưng nó làm điều ngược lại khi thất bại. Nếu bạn không bao giờ hoàn tất một giao dịch StoreKit, Apple giữ nó trong hàng đợi và gửi lại mỗi lần ứng dụng của bạn khởi chạy hoặc observer gắn vào, nên bạn có thêm một cơ hội để cấp quyền sử dụng. Apple không hoàn tiền một giao dịch chưa hoàn tất. Không có khoản hoàn tiền tự động ba ngày trên App Store.

Vậy nên mô hình tư duy phải giữ tính đặc thù theo nền tảng. Trên Google Play, một giao dịch mua chưa được xử lý là một khoản hoàn tiền đang chờ xảy ra và một hạn chót bạn đang chạy đua. Trên App Store, một giao dịch mua chưa được xử lý là một lần gửi lại đang chờ xảy ra và hoàn toàn không có đồng hồ nào. Áp giả định của Apple sang Android là cách các đội ngũ kết thúc với một bức tường các khoản hoàn tiền không được xác nhận mà họ không giải thích được.

Đây là lý do RefundHalt xác nhận các giao dịch mua Google Play tự động ngay khoảnh khắc thông báo cửa hàng đến, và đối chiếu với Voided Purchases API để một quyền sử dụng được cấp cho một giao dịch mua mà Google sau đó đã đảo ngược không tiếp tục còn hiệu lực. Quy tắc ba ngày thôi là một cuộc đua bạn có thể thua và trở thành một bước đã hoàn thành từ trước.

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

Tại sao giao dịch mua Google Play của tôi bị tự động hoàn tiền sau ba ngày?
Vì ứng dụng của bạn không xác nhận nó kịp thời. Google Play tự động hoàn tiền cho người mua và thu hồi bất kỳ giao dịch mua nào không được xác nhận trong ba ngày kể từ khi đạt trạng thái PURCHASED. Đó không phải yêu cầu của khách hàng hay hình phạt của Google, đó là một lệnh gọi xác nhận bị thiếu, và việc xác nhận ở phía máy chủ từ thông báo cửa hàng loại bỏ nó.
Sự khác biệt giữa xác nhận và tiêu thụ một giao dịch mua là gì?
Cả hai đều đáp ứng yêu cầu ba ngày. Bạn tiêu thụ một mặt hàng consumable, qua purchases.products.consume hoặc consumeAsync(), điều này cũng làm cho sản phẩm có thể mua lại. Bạn xác nhận một mặt hàng non-consumable hoặc một gói đăng ký, qua purchases.products.acknowledge, purchases.subscriptions.acknowledge, hoặc acknowledgePurchase(), điều này xác nhận quyền sử dụng mà không giải phóng sản phẩm để mua lại.
Tôi có cần xác nhận các lần gia hạn gói đăng ký Google Play không?
Không. Chỉ giao dịch mua gói đăng ký ban đầu mới cần xác nhận. Google không yêu cầu xác nhận các lần gia hạn và tự động đánh dấu chúng ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED. Một giao dịch mua mới đến với trạng thái ACKNOWLEDGEMENT_STATE_PENDING và vẫn là trách nhiệm của bạn cho đến khi bạn giải quyết xong.
Tôi có thể xác nhận một giao dịch mua khi nó vẫn đang PENDING không?
Không. Bạn chỉ nên xác nhận khi trạng thái giao dịch mua là PURCHASED. Một giao dịch mua PENDING, chẳng hạn như thanh toán tiền mặt hoặc một yêu cầu phê duyệt của phụ huynh, chưa khởi động đồng hồ ba ngày. Chỉ cấp quyền sử dụng và xác nhận sau khi trạng thái chuyển từ PENDING sang PURCHASED.
Apple có hoàn tiền các giao dịch mua mà tôi không hoàn tất không?
Không. StoreKit của Apple gửi lại một giao dịch chưa hoàn tất mỗi lần ứng dụng của bạn khởi chạy cho đến khi bạn hoàn tất nó, nhưng không bao giờ tự động hoàn tiền. Khoản hoàn tiền tự động ba ngày cho các giao dịch mua chưa được xác nhận là duy nhất ở Google Play, nên hai nền tảng cần cách xử lý khác nhau.
Làm thế nào để khắc phục nếu một giao dịch mua đã bị hoàn tiền vì không được xác nhận?
Bạn không thể đảo ngược khoản hoàn tiền, nhưng bạn có thể đối chiếu. Hãy poll Voided Purchases API, nơi liệt kê các giao dịch mua đã bị hoàn tiền và thu hồi từ 30 ngày qua và gắn cờ những cái bị hủy vì chưa bao giờ được xác nhận, rồi thu hồi quyền sử dụng bạn đã cấp. Về sau, hãy xác nhận từ thông báo cửa hàng để cái tiếp theo không lọt qua.

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.