App Store Server Notifications V2 到不了你的服务器时,别再猜了,直接问 Apple 发生了什么:调用 App Store Server API 的 Request a Test Notification,再用返回的令牌调用 Get Test Notification Status。返回结果会列出每一次发送尝试和结果,比如 TLS_ISSUE、TIMED_OUT 或 UNSUCCESSFUL_HTTP_RESPONSE_CODE,原因基本就清楚了。常见原因都写在 Apple 自己的配置页里:App Store Connect 里没填 URL(或只填了沙盒 URL)、服务器不支持 TLS 1.2 及以上、端口不是 443 也不在 1024 及以上、防火墙挡了 Apple 的 17.0.0.0/8 网段,或者回应的不是 HTTP 200 到 206。
Apple 发什么,期望你回什么
App Store 用 HTTP POST 发送每条通知,正文是 JSON。V2 的正文是 responseBodyV2,其中的 signedPayload 由 App Store 以 JWS 格式签名。你的服务器用状态码回应:
- HTTP
200,或200到206之间的任何状态码,表示成功。 - HTTP
40x或50x表示请 App Store 重试。其他状态码 Apple 都算失败。 - 不需要返回正文。
第一次发送没收到成功回应时,Apple 会对 V2 通知重试五次,分别在上一次尝试之后 1、12、24、48、72 小时。只有正式环境会重试。 Apple 说沙盒环境只尝试发送一次。
V1 通知已弃用,Apple 要求改用 V2 端点。
按这个顺序检查配置
- App Store Connect 里填了 URL。 在 App 里选中应用,侧栏 General 下点 App 信息,找到 App Store Server Notifications。填写 Production Server URL,测试时再填 Sandbox Server URL,两个都选 Version 2。Apple 帮助页写的可操作角色是:Account Holder、Admin、App Manager 或 Marketing。
- 清楚哪个 URL 收什么。 Apple 帮助页说,没填沙盒 URL 时,沙盒和正式环境的通知都会发到正式 URL;只填了沙盒 URL 时,正式环境不会发送任何通知。两个环境可以用同一个 URL。
- TLS 1.2 及以上。 Apple 写明服务器"must support the Transport Layer Security (TLS) 1.2 protocol or later"(必须支持 TLS 1.2 或更高版本)。
TLS_ISSUE这个结果也包括证书无法验证的情况。 - 端口。 URL 里如果写了端口,必须是
443,或者大于等于1024。 - 防火墙。 如果服务器只接受白名单 IP,加上
17.0.0.0/8。Apple 说这个网段同时适用于沙盒和正式环境。 - 回应。 收到请求就先回
200。TIMED_OUT的说明是让你"check that your server isn't processing messages in line"(确认服务器没有在请求里同步处理消息),所以先把正文存下来,再另行处理。Apple 没有公开超时时间。 - 你测试的是哪个环境。 沙盒购买只发一次通知、不重试,发往沙盒 URL(没填沙盒 URL 则发往正式 URL)。
新保存的 URL 要多久开始收到通知,Apple 没说。
怎么检查:测试通知、发送状态、历史记录
调用 App Store Server API 需要用 In-App Purchase 密钥签名的 JSON Web Token。密钥在 App Store Connect 的 用户和访问 > 集成 > App 内购买项目 里生成;Apple 只允许下载一次私钥。测沙盒 URL 用沙盒主机,测正式 URL 用正式主机。
1. 请求一条 TEST 通知。
curl -X POST -H "Authorization: Bearer $JWT" \
https://api.storekit-sandbox.apple.com/inApps/v1/notifications/test
# {"testNotificationToken": "..."}
调用沙盒主机时,Apple 把 TEST 通知发到你的沙盒 URL;调用 api.storekit.apple.com 时,发到正式 URL。
2. 看 Apple 记录了什么。
curl -H "Authorization: Bearer $JWT" \
https://api.storekit-sandbox.apple.com/inApps/v1/notifications/test/$TOKEN
返回里有 sendAttempts 数组(最多六项:第一次尝试加最多五次重试),每项有 attemptDate 和 sendAttemptResult,另外还有 Apple 尝试发送的 signedPayload。一个令牌最长可查六个月。各结果的含义,按 Apple 的列表整理:
sendAttemptResult | Apple 的说明(节选) | 该查哪里 |
|---|---|---|
SUCCESS | Apple 收到了成功回应。 | 回应之后你自己的处理代码。 |
TLS_ISSUE | 无法建立 TLS 会话,或证书无法验证。 | 证书链、TLS 1.2+。 |
UNSUCCESSFUL_HTTP_RESPONSE_CODE | 没收到 HTTP 200 回应。 | 鉴权中间件、路由、状态码。 |
TIMED_OUT | 超时前没收到回应。 | 先回应,后处理。 |
NO_RESPONSE | 没收到有效的 HTTP 回应。 | 服务器或代理。 |
CIRCULAR_REDIRECT | 重定向循环。 | 重定向规则(http 转 https、结尾斜杠)。 |
PREMATURE_CLOSE | 发送过程中连接被关闭。 | 代理、负载均衡。 |
SOCKET_ISSUE | 网络错误。 | DNS、防火墙、端口。 |
INVALID_RESPONSE | 回应无效。 | 服务器写出的回应。 |
UNSUPPORTED_CHARSET | Apple 不支持该字符集。 | 回应头。 |
OTHER | 其他错误。 | 以上全部。 |
3. 找回错过的真实通知。 Get Notification History(POST /inApps/v1/notifications/history)返回 Apple 尝试发送过的 V2 通知及其发送记录。startDate 和 endDate 用 UNIX 毫秒;加上 "onlyFailures": true 只看没送达的,包括还在重试中的。正式环境可查 180 天,沙盒 30 天,每次返回最多 20 条。
curl -X POST -H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"startDate": 1761955200000, "endDate": 1762041600000, "onlyFailures": true}' \
https://api.storekit.apple.com/inApps/v1/notifications/history
Apple 提醒,历史记录反映的是通知发出那一刻的购买状态。要看当前状态,调用 Get All Subscription Statuses 或 Get Transaction History。
4. 看通知内容。 想知道一条通知里有什么,把 signedPayload(或整个正文)粘到 App Store JWS 解码工具 里。Apple 给的步骤:把 JWS 拆成 header、payload、signature,对 payload 做 Base64URL 解码,得到通知类型和 data,再用同样方法解码 signedTransactionInfo 和 signedRenewalInfo。在服务器上,按 header 里 alg 指定的算法验证每个签名。
常见问题
正式环境能收到,沙盒收不到,为什么?
先确认沙盒 URL 已填写并选了 Version 2,再对沙盒主机调用 Request a Test Notification。记住沙盒只尝试一次,失败一次就不会再发;沙盒的 Get Notification History 可以往回查 30 天。
测试通知能收到,真实通知收不到,怎么办?
对购买发生的那段时间调用 Get Notification History 并加上 onlyFailures。如果什么都没列出,说明那段时间 Apple 没尝试发送这类事件的通知,去对照 Apple 文档里该事件对应的通知类型。如果列出了发送记录,看 sendAttemptResult 就知道为什么失败。
服务器明明收到了,Apple 还在一直重试,为什么?
Apple 只把 200 到 206 算作成功。鉴权层返回的 401、一次重定向、或者回应太慢导致超时,都算失败;在正式环境,Apple 会在几天内最多重试五次。
我配置的是 Version 1,能收到测试通知吗?
能。不管 URL 设的是 V1 还是 V2,Apple 都按 V2 格式发送 TEST。V1 已弃用,在沙盒里测好 V2 之后就切换过去。
服务器宕机了一天,那些通知丢了吗?
正式环境下 Apple 会重试五次,分别在上一次尝试之后 1、12、24、48、72 小时,所以一天的宕机可能会被后面的重试补上。Get Notification History 也能返回最近 180 天的通知,可以把错过的取回来。
参考资料
均于 2026 年 11 月 1 日阅读。
- App Store Server Notifications,Apple Developer Documentation
- Enabling App Store Server Notifications,Apple Developer Documentation
- Receiving App Store Server Notifications,Apple Developer Documentation
- Responding to App Store Server Notifications,Apple Developer Documentation
- responseBodyV2,Apple Developer Documentation
- Request a Test Notification、Get Test Notification Status、CheckTestNotificationResponse、sendAttemptResult,App Store Server API
- Get Notification History、NotificationHistoryRequest、NotificationHistoryResponse,App Store Server API
- App Store Server API,Apple Developer Documentation
- Creating API keys to authorize API requests,Apple Developer Documentation
- Enter server URLs for App Store Server Notifications,App Store Connect 帮助
Apple 的接口和限制会变化,具体以上面这些页面的当前内容为准。