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

Đính kèm một appAccountToken vào mọi giao dịch mua trên App Store, nếu không bạn không thể bảo vệ khoản hoàn tiền

Apple gửi cho máy chủ của bạn một CONSUMPTION_REQUEST khi khách hàng yêu cầu hoàn tiền, nhưng giao dịch không bao giờ cho biết họ là ai. appAccountToken là UUID liên kết một giao dịch mua trở lại người dùng của bạn. Thiết lập nó và bạn có thể trả lời Apple bằng dữ liệu thực. Bỏ qua nó và bạn chỉ đang đoán.

Một chiếc chìa khóa đồng có đánh số nằm trên một cuốn sổ cái tối màu bên cạnh một điện thoại thông minh hiển thị biên lai mua hàng, minh họa cách một appAccountToken liên kết một giao dịch mua trên App Store với một tài khoản người dùng

Điểm chính

  • appAccountToken là một UUID mà bạn đính kèm vào một giao dịch mua trên App Store để giao dịch phát sinh trỏ ngược về đúng người dùng trong hệ thống của riêng bạn. Apple lưu nó trên giao dịch và trả lại ở mọi nơi giao dịch đó xuất hiện.
  • Quy tắc định dạng duy nhất mà Apple áp đặt là giá trị phải là một UUID hợp lệ. Truyền bất cứ thứ gì khác, một id, một email, hay một chuỗi ghép, và StoreKit lặng lẽ loại bỏ nó rồi trả về appAccountToken là nil.
  • Trong StoreKit 2 bạn thiết lập nó bằng một tùy chọn mua duy nhất, Product.PurchaseOption.appAccountToken(_:), dùng một UUID ổn định mà bạn đã tạo và lưu cho tài khoản đó.
  • Thiết lập một lần trên giao dịch mua ban đầu và Apple mang cùng token đó qua mọi lần gia hạn, thử lại thanh toán và nâng cấp trong chuỗi đăng ký.
  • Từ năm 2025, endpoint Set App Account Token cho phép máy chủ của bạn đính kèm token vào các giao dịch mua thực hiện bên ngoài ứng dụng của bạn, như đổi mã ưu đãi và mua được quảng bá, những giao dịch mà luồng trong ứng dụng không bao giờ chạm tới được.
  • appAccountToken là thứ khiến CONSUMPTION_REQUEST của Apple có thể trả lời được. Không có nó, bạn không thể ánh xạ khoản hoàn tiền tới khách hàng mà bạn phải mô tả mức sử dụng của họ trong cửa sổ 12 giờ.
  • Một khoản hoàn tiền bạn không thể nhận diện là một khoản hoàn tiền bạn không thể bảo vệ. Bạn trả lại tiền cho những giao dịch mua mà bạn có bằng chứng để giữ lại, cộng thêm phần tính toán, lệnh gọi API và chi trả mà bạn đã tiêu để cung cấp chúng.

Một khách hàng yêu cầu Apple hoàn tiền, Apple gửi cho máy chủ của bạn một CONSUMPTION_REQUEST, và bạn có mười hai giờ để trả lời bằng dữ liệu thực về cách người đó đã dùng sản phẩm. Rồi bạn mở thông báo ra và nhận ra bạn chẳng biết họ là ai. Giao dịch mang một originalTransactionId và một id sản phẩm, nhưng không có gì trỏ tới tài khoản trong cơ sở dữ liệu của riêng bạn. Khoảng trống đó chính là thứ appAccountToken lấp lại, và nếu bạn không thiết lập nó lúc mua, bạn không thể lấp lại sau đó cho giao dịch bán ấy.

appAccountToken là một UUID mà bạn đính kèm vào một giao dịch mua để giao dịch App Store phát sinh mang một con trỏ trở lại đúng người dùng trong hệ thống của bạn. Thiết lập nó, và mọi câu hỏi hoàn tiền mà Apple từng hỏi về khách hàng đó đều đến kèm danh tính của họ. Bỏ qua nó, và bạn đang đoán. Đây là trường này là gì, cách thiết lập nó, endpoint mới cứu vãn các giao dịch mua thực hiện bên ngoài ứng dụng của bạn, và mắt xích thiếu vắng thực sự tốn kém thế nào khi một khoản hoàn tiền ập đến.

appAccountToken thực sự là gì

appAccountToken là một UUID mờ đục mà bạn tạo ra và truyền cho StoreKit vào thời điểm mua. Apple lưu nó trên giao dịch và trả lại trong thông tin giao dịch cho lần mua đó, và nó ở nguyên đó. Theo lời Apple, đó là "UUID liên kết giao dịch với tài khoản người dùng trên dịch vụ của riêng bạn." Quy tắc định dạng duy nhất là nó phải là một UUID. Apple không đọc nó, không xác thực nó ánh xạ tới đâu, và không quan tâm nó có nghĩa gì ở phía bạn. Đó là một liên kết mà bạn kiểm soát.

Vì nó nằm trên giao dịch, nó quay lại ở mọi nơi giao dịch quay lại. Giao dịch đã ký trong một thông báo máy chủ, phản hồi Get Transaction Info của App Store Server API, và mọi lần gia hạn trong một chuỗi đăng ký, tất cả đều mang cùng token nếu bạn thiết lập nó trên giao dịch mua ban đầu. Một UUID, đính kèm một lần, theo dõi việc thanh toán của khách hàng suốt vòng đời mối quan hệ.

Nó phải là một UUID thật, nếu không nó lặng lẽ biến mất

Quy tắc duy nhất Apple áp đặt là định dạng. StoreKit 2 đòi hỏi một UUID RFC 4122. Nếu bạn truyền một chuỗi ghép, một id số nguyên, hay một địa chỉ email, StoreKit không báo lỗi. Nó loại bỏ giá trị và giao dịch quay lại với appAccountToken được đặt thành nil. Các nhà phát triển liên tục gặp phải điều này, và triệu chứng luôn giống nhau, một biến thể nào đó của "appAccountToken bị thiếu trong payload giao dịch" trên chính diễn đàn của Apple, gần như luôn vì giá trị được truyền không phải là một UUID hợp lệ. Hãy tạo một UUID thật ở phía máy chủ, lưu nó ứng với tài khoản, và đừng bao giờ đưa cho StoreKit bất cứ thứ gì khác.

Cách thiết lập nó lúc mua

Trong StoreKit 2 đây là một tùy chọn mua duy nhất. Tạo UUID trên máy chủ của bạn khi người dùng đăng ký hoặc lần đầu đến bước thanh toán, lưu nó trên bản ghi tài khoản của họ, và truyền chính giá trị đó vào lệnh gọi mua.

Chữ ký là Product.PurchaseOption.appAccountToken(_ token: UUID), và một giao dịch mua trông như try await product.purchase(options: [.appAccountToken(token)]). Khi giao dịch quay lại, được xác minh qua App Store Server API hoặc được gửi bởi một thông báo máy chủ, nó mang UUID đó, và máy chủ của bạn tra cứu khách hàng chỉ trong một truy vấn.

Dùng một token ổn định cho mỗi tài khoản

Đừng tạo một token mới cho mỗi giao dịch mua của cùng một người dùng. Apple trả lại token trên các lần gia hạn, thử lại thanh toán và nâng cấp trong cùng một chuỗi, vì vậy một UUID ổn định cho mỗi tài khoản cho bạn một sợi chỉ sạch sẽ từ lần mua đầu tiên qua mọi sự kiện tương lai. Một token thay đổi theo mỗi giao dịch mua làm đứt sợi chỉ đó và phá hỏng toàn bộ mục đích. Một tài khoản, một token, dùng lại mỗi lần tài khoản đó mua.

Endpoint cứu vãn các giao dịch mua ngoài ứng dụng

Cho đến năm 2025 vẫn có một lỗ hổng. Nếu một khách hàng đổi mã ưu đãi hoặc mua một giao dịch mua trong ứng dụng được quảng bá thẳng từ App Store, ứng dụng của bạn không bao giờ chạy luồng mua, nên không có chỗ nào để thiết lập appAccountToken. Những giao dịch đó đến ẩn danh và cứ thế ở nguyên vậy.

WWDC 2025 đã khép lại khoảng trống này bằng endpoint Set App Account Token. Máy chủ của bạn gọi PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken trên App Store Server API với UUID trong phần thân, và Apple thiết lập token trên giao dịch đó. Nó hoạt động cho mọi loại sản phẩm, bao trùm việc đổi mã ưu đãi và các giao dịch mua được quảng bá, và giá trị bạn gửi ghi đè bất kỳ token nào đã có trên giao dịch. Giờ đây bạn có thể liên kết một giao dịch mua sau thực tế, từ máy chủ của bạn, mà nó không bao giờ đi qua ứng dụng của bạn.

Một chồng biên lai bán hàng bằng giấy trên một chiếc bàn tối màu với dòng tên khách hàng để trống, một tờ được chiếu sáng bởi một luồng đèn ấm, minh họa một giao dịch mua trên App Store đến mà không có appAccountToken để nhận diện người mua
Kênh muaNơi bạn thiết lập appAccountTokenGhi chú
Mua trong ứng dụngTùy chọn mua StoreKit lúc muaProduct.PurchaseOption.appAccountToken(UUID)
Đổi mã ưu đãiEndpoint Set App Account Token, phía máy chủKhông có luồng trong ứng dụng để móc vào, nên thiết lập sau
Mua trong ứng dụng được quảng bá từ App StoreEndpoint Set App Account Token, phía máy chủViệc mua diễn ra bên ngoài ứng dụng của bạn
Gia hạn đăng kýKhông cần làm gìĐược chuyển tiếp tự động từ giao dịch mua ban đầu

Nơi mắt xích thiếu vắng khiến bạn mất tiền

Mục đích của token không phải là hồ sơ gọn gàng. Mà là câu hỏi hoàn tiền duy nhất của Apple dành cho nhà phát triển, CONSUMPTION_REQUEST, chỉ có thể trả lời được nếu bạn tìm được khách hàng mà nó nói đến.

Khi một người mua yêu cầu hoàn tiền cho một sản phẩm tiêu dùng hoặc một đăng ký không gia hạn, Apple gửi cho máy chủ của bạn một thông báo CONSUMPTION_REQUEST và cho bạn mười hai giờ để trả lời bằng Send Consumption Information. Câu trả lời của bạn là dữ liệu về đúng khách hàng đó: họ đã tiêu thụ bao nhiêu sản phẩm, thời gian gắn bó của tài khoản, tổng chi tiêu trọn đời, tình trạng giao hàng của họ. Bản thân appAccountToken là một trong các trường trong yêu cầu đó, và quan trọng hơn, đó là cách giao dịch của thông báo ánh xạ tới tài khoản mà bạn sắp mô tả mức sử dụng. Không token, không tra cứu, không câu trả lời chính xác.

Một câu trả lời trống thực sự tốn kém thế nào

Một khoản hoàn tiền không nhận diện được ép bạn vào một lựa chọn tồi. Bạn có thể trả lời yêu cầu tiêu thụ bằng chẳng gì cả, điều này được đọc là mức tiêu thụ thấp và đẩy Apple về phía chấp thuận hoàn tiền, kể cả cho những khách hàng đã dùng sản phẩm rất nhiều. Hoặc bạn có thể đoán. Dù cách nào bạn cũng đang hoàn tiền cho những giao dịch mua mà bạn có bằng chứng để bảo vệ, và bạn đã trả chi phí thực để phục vụ chúng.

Chi phí đó không phải là giá bán. Một sản phẩm tiêu dùng đã chạy một loạt lệnh gọi API mô hình, tạo hình ảnh, xuất một video, hay kích hoạt một khoản chi trả cho nhà sáng tạo đã tiêu tiền thật ngay khoảnh khắc nó được cung cấp. Khoản hoàn tiền trả lại tiền của khách hàng. Nó không trả lại hóa đơn của nhà cung cấp. Nhân một khách hàng không thể nhận diện với mỗi khoản hoàn tiền họ nộp, và với mỗi kẻ hoàn tiền hàng loạt trông cậy vào việc bạn không biết họ là ai, và token bạn đã bỏ qua trở thành dòng mã đắt đỏ nhất mà bạn chưa từng viết.

Ý tưởng tương tự tồn tại trên Android, dưới một cái tên khác

Google Play giải quyết đúng vấn đề đó bằng setObfuscatedAccountId, thứ đính kèm một mã định danh tài khoản vào một giao dịch mua để việc xem xét bồi hoàn của Google qua orders.reviewrefund có thể được trả lời dựa trên một người dùng thật. Cửa hàng khác, cơ chế khác, cùng một bài học: đính kèm danh tính lúc mua nếu không bạn không thể bảo vệ tranh chấp về sau. Trên App Store, công cụ đó là appAccountToken, và nó phải là một UUID.

Ba thói quen giữ token đúng chỗ

  • Tạo một UUID cho mỗi tài khoản và lưu nó. Một token ổn định cho mỗi khách hàng, tạo khi họ đăng ký hoặc lúc thanh toán lần đầu, lưu trên bản ghi của họ và dùng lại cho mọi giao dịch mua.
  • Xác thực trước khi bạn truyền nó. Xác nhận giá trị là một UUID thật trong mã mua của bạn, để một id sai định dạng không bao giờ có thể lặng lẽ trở thành một token nil trên giao dịch.
  • Bổ sung cho các giao dịch mua ngoài ứng dụng. Khi một thông báo máy chủ đến cho một lần đổi mã ưu đãi hoặc một giao dịch mua được quảng bá mà không có token, hãy gọi endpoint Set App Account Token để đính kèm token đúng.

Làm ba điều đó và mọi giao dịch Apple từng gửi cho bạn, kể cả các yêu cầu hoàn tiền, đều đến khi đã được gắn với khách hàng mà nó thuộc về.

Đây là nền tảng mà RefundHalt dựa vào. Chúng tôi đọc appAccountToken từ mọi giao dịch và thông báo máy chủ, gắn nó với mức sử dụng mà chúng tôi đã theo dõi cho tài khoản đó, và trả lời yêu cầu tiêu thụ của Apple trong cửa sổ mười hai giờ bằng những con số thực của khách hàng. Token là sợi chỉ. Thiết lập nó một lần và việc bảo vệ hoàn tiền của bạn có thứ gì đó để bám vào.

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

appAccountToken trong App Store là gì?
appAccountToken là một UUID mà bạn tạo ra và đính kèm vào một giao dịch mua thông qua StoreKit để giao dịch App Store phát sinh trỏ ngược về một tài khoản người dùng cụ thể trong hệ thống của riêng bạn. Apple lưu nó trên giao dịch và trả lại trong thông tin giao dịch, các thông báo máy chủ, và mọi lần gia hạn trong cùng một chuỗi, cho phép bạn kết nối bất kỳ sự kiện tương lai nào, kể cả một yêu cầu hoàn tiền, tới đúng khách hàng.
Vì sao appAccountToken của tôi là nil hoặc bị thiếu?
Gần như luôn vì giá trị bạn truyền không phải là một UUID hợp lệ. StoreKit 2 đòi hỏi một UUID RFC 4122 và lặng lẽ loại bỏ mọi thứ khác, nên một chuỗi ghép, một id số nguyên, hay một email trả về là appAccountToken nil trong khi giao dịch mua vẫn thành công. Nguyên nhân phổ biến khác là một giao dịch mua thực hiện bên ngoài ứng dụng của bạn, như đổi mã ưu đãi, nơi không có luồng trong ứng dụng nào chạy để thiết lập token.
Tôi có thể thiết lập appAccountToken sau khi mua, cho mã ưu đãi không?
Có, kể từ năm 2025. Endpoint Set App Account Token trên App Store Server API cho phép máy chủ của bạn đính kèm hoặc ghi đè token trên một giao dịch hiện có bằng cách gọi PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken với UUID trong phần thân. Nó hoạt động cho mọi loại sản phẩm và được xây dựng cho các giao dịch mua thực hiện bên ngoài ứng dụng của bạn, như đổi mã ưu đãi và các giao dịch mua trong ứng dụng được quảng bá.
appAccountToken có bắt buộc phải là một UUID không?
Có. Quy tắc định dạng duy nhất Apple áp đặt là giá trị phải là một UUID hợp lệ. Ngoài ra nó mờ đục, nên nó có thể ánh xạ tới bất kỳ khóa tài khoản nào bạn muốn ở phía bạn, nhưng nếu nó không phải là một UUID thì StoreKit sẽ không lưu nó và giao dịch quay lại với appAccountToken được đặt thành nil.
appAccountToken giúp ích cho việc hoàn tiền như thế nào?
Khi một khách hàng yêu cầu hoàn tiền, Apple gửi một CONSUMPTION_REQUEST và cho bạn mười hai giờ để phản hồi bằng dữ liệu về đúng người mua đó. appAccountToken là cách bạn khớp giao dịch của thông báo với tài khoản mà bạn cần báo cáo mức sử dụng, và nó là một trong các trường trong chính yêu cầu tiêu thụ. Không có nó bạn không thể trả lời bằng mức sử dụng thực, nên Apple nghiêng về phía chấp thuận những khoản hoàn tiền mà bạn có bằng chứng để phản đối.
appAccountToken có nên khác nhau cho mỗi giao dịch mua không?
Không. Dùng một UUID ổn định cho mỗi tài khoản và dùng lại nó cho mọi giao dịch mua mà người dùng đó thực hiện. Apple mang token qua các lần gia hạn và nâng cấp trong một chuỗi đăng ký, nên một token ổn định cho bạn một liên kết sạch sẽ theo thời gian. Một token thay đổi theo mỗi giao dịch mua làm đứt liên kết đó và khiến việc gắn các giao dịch trở lại cùng một khách hàng khó hơn.

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.