跳到正文

← 全部工具

给 iOS 和 Mac 开发者的免费工具

App Store JWS 解码与验证

粘贴 App Store 服务器通知里的 signedPayload、signedTransactionInfo 或 signedRenewalInfo、StoreKit 2 的 jwsRepresentation 或 signedAppTransactionInfo。本页会告诉你它是否真由 Apple 签名(x5c 证书链到 Apple Root CA - G3、Apple 标记扩展、签名日期时的证书有效期、ES256 签名),并把负载变成易读的表格:日期显示为 UTC 和你的本地时间,价格换算成实际金额,每个通知类型、子类型和状态值都有解释。通知里嵌套的交易也会一起解码。全部在浏览器中运行。

通知正文(signedPayload)、signedTransactionInfo、signedRenewalInfo、StoreKit 2 的 jwsRepresentation 或 signedAppTransactionInfo 都可以,整段 JSON 正文也行。 不上传任何内容:解码和校验都在本页完成。

在上方粘贴签名数据,即可解码并校验。

字段名和取值已于 2026-10-30 对照 Apple 文档和 App Store Server Library 核对。

工作原理

  • •JWS 由三段 base64url 组成:头部、负载和签名。头部写明算法(App Store 用 ES256),并在 x5c 中携带证书链:签名用的叶证书、Apple 中间证书和 Apple 根证书。
  • •证书链检查遵循 Apple 开源的 App Store Server Library(jws_verification.ts):x5c 必须有三张证书;中间证书须由 Apple Root CA - G3 签名,叶证书须由中间证书签名;中间证书须为证书颁发机构;叶证书须带扩展 1.2.840.113635.100.6.11.1,中间证书须带 1.2.840.113635.100.6.2.1。
  • •Apple Root CA - G3 内置在本页(SHA-256 63:34:3A:BF:…:3E:91:79,取自 apple.com,并与 macOS 自带的副本核对过)。和 Apple 的库一样,本页从不信任 x5c 里传来的根证书。
  • •证书有效期按负载里的 signedDate 检查,允许一分钟误差,与该库离线模式的规则相同,所以证书过期后旧通知依然能验证。
  • •ES256 签名(原始 R 和 S,共 64 字节)用 Web Crypto 以叶证书公钥校验,证书本身的签名(ECDSA,SHA-256 或 SHA-384)也用同样方式校验。
  • •日期是自 1970 年起的毫秒数,显示为 UTC 和你所在时区的时间。价格以毫单位表示(1990 即 currency 字段所示货币的 1.99)。枚举值依据 Apple 文档和服务器库中的列表。

它不做什么

  • •不发出任何网络请求:不做 OCSP 吊销检查,也不调用 Apple 的 App Store Server API。签名后才被 Apple 吊销的证书在这里仍会通过。Apple 的库在开启在线检查时会做 OCSP 检查。
  • •不检查 bundleId、appAppleId 或 environment 是否与你的 App 相符,这需要你的服务器来做,Apple 的库也会做。
  • •无法得知交易之后是否被退款或是否仍然有效:签名数据只是某一时刻的快照。最新状态请向 App Store Server API 查询。
  • •不解码旧版收据(verifyReceipt 用的 base64 PKCS #7),也不生成签名。

常见问题

signedPayload 是什么?
App Store 向你的服务器发送通知(App Store Server Notifications V2)时,POST 正文是只有一个字段 signedPayload 的 JSON。它是 Apple 签名的 JWS,负载包含 notificationType、subtype、notificationUUID、signedDate 和 data 对象。data 里的 signedTransactionInfo 和 signedRenewalInfo 也是各自独立、同样签名的 JWS。本页会一次解码这三者。
我的服务器应该怎样验证 App Store 签名数据?
使用 Apple 的 App Store Server Library(GitHub 上有 Swift、Java、Python 和 Node 版本)。把 Apple 根证书、你的 bundle ID、App 的 Apple ID 和环境交给它的 SignedDataVerifier,再调用 verifyAndDecodeNotification、verifyAndDecodeTransaction 或 verifyAndDecodeRenewalInfo。它会检查证书链、有效期、签名以及数据是否属于你的 App,还能在线检查吊销。本页适合调试时查看负载,不能代替服务器上的校验。
为什么 Xcode 的 StoreKit 测试数据通不过证书链?
Xcode 中的 StoreKit 测试用你 Mac 上生成的证书("StoreKit Testing in Xcode")签名交易,负载里的 environment 是 Xcode。没有 Apple 证书链可查,所以本页标为 Xcode 测试数据,而不是失败。要在 App 里验证它,可在 Xcode 中导出证书(Editor > Save Public Certificate)并在测试环境中信任它。沙盒和生产数据由 Apple 签名,可以通过验证。
各种通知类型是什么意思?
notificationType 说明发生了什么,subtype 进一步细分。常见的有:SUBSCRIBED(INITIAL_BUY 或 RESUBSCRIBE)、DID_RENEW、DID_FAIL_TO_RENEW(GRACE_PERIOD 时保留访问权)、EXPIRED(VOLUNTARY、BILLING_RETRY、PRICE_INCREASE、PRODUCT_NOT_FOR_SALE)、DID_CHANGE_RENEWAL_STATUS(续期被打开或关闭)、DID_CHANGE_RENEWAL_PREF(UPGRADE 或 DOWNGRADE)、REFUND、REVOKE 和 CONSUMPTION_REQUEST。粘贴哪种,本页就解释哪种。
Sandbox 和 Production 有什么区别?
Production 数据来自真实的 App Store 购买。Sandbox 数据来自 TestFlight 和沙盒 Apple 账户,不产生真实付款,订阅按缩短的周期续期。两者都由 Apple 用同一条证书链签名,因此在这里都能验证。请检查 environment 字段并在服务器上区分处理;Apple 会分别发到你在 App Store Connect 设置的生产和沙盒通知地址。
App 发给服务器的交易可以直接信任吗?
验证之后才可以。StoreKit 2 的 jwsRepresentation 由 Apple 签名,服务器可以离线校验签名和证书链,再检查 bundleId、environment,订阅还要看 expiresDate 和 revocationDate。JWS 只能证明 Apple 在 signedDate 时签过什么,不能证明此刻购买仍然有效:要获取当前状态,请调用 App Store Server API(Get Transaction Info 或 Get All Subscription Statuses)并接收通知。

相关内容