What's new in App Store server APIs
App Store & Distribution 进阶 20m

App Store 服务端 API 新特性

What's new in App Store server APIs

2023年6月5日

在 Apple 官方观看视频

一句话判断

如果你负责服务端的内购逻辑,这场 Session 带来了两个关键更新——新的 Get Transaction Info 端点让你不再需要翻遍整个交易历史,而 App Store Server Notifications V2 的订阅状态信息让判断订阅是否有效变得确定。

这场 Session 讲了什么

Session 围绕 App Store Server API 和 App Store Server Notifications V2 的更新展开,分为三个部分:交易查询的灵活性提升、通知中订阅状态的明确化、以及旧 API 的迁移时间表。

Get Transaction Info 端点。这是今年新增的单交易查询接口。之前如果你知道一个 transactionId 想查它的详情,唯一的办法是调用 Get Transaction History 然后翻页查找——如果用户有大量历史记录,这要发多次请求。新端点只需要一个 transactionId 作为路径参数,直接返回签名的交易信息。而且它支持所有产品类型,包括已消费的消耗型项目(这在 Transaction History 中是不出现的)。

更灵活的 transactionId 支持。之前多个端点(如 Get All Subscription Statuses、Send Consumption Information 等)要求使用 originalTransactionId。现在这些端点都接受任意 transactionId,服务端会自动解析到对应的 originalTransactionId。省去了先查一次再调一次的麻烦。

通知中的订阅状态字段。这是一个看似小改动但实际影响深远的更新。以前收到一个通知(比如退款 REFUND),你无法仅从通知数据确定订阅当前是 Active 还是 Revoked。现在,每个与订阅相关的通知都会附带 statusexpirationIntent 等字段,让你直接知道订阅当前状态,不再需要额外查询。

值得深挖的点

通知不再”不完整”:之前收到 REFUND 通知时,如果同一订阅有更新的续期交易,订阅可能仍然是 Active。开发者需要自己调用 API 查最新状态才能确认。这个不确定性在服务端逻辑中制造了大量边界判断。新版本直接在通知中包含最终状态,大幅简化了处理逻辑。

消耗型项目的查询:Get Transaction History 不返回已消费的消耗型项目。如果你的服务端需要验证某笔消耗型购买(比如防作弊校验),之前没有可靠的查询方式。新端点填补了这个空白。

旧 API 迁移:苹果明确表示 originalTransactionId 参数仍然有效,现有代码无需修改。但新项目建议直接使用更灵活的 transactionId 方式。

代码片段

使用新的 Get Transaction Info 端点查询单笔交易:

// 发送 GET 请求到 App Store 服务端
// GET https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId}

// 响应包含签名的交易信息
// {
//   "signedTransactionInfo": "eyJhbGciOiJFUz..."  // JWS 签名格式
// }

// 解码 JWS 后可获取完整的交易信息:
// - productId: 产品标识
// - purchaseDate: 购买时间
// - originalTransactionId: 原始交易 ID
// - type: 交易类型

通知中新增的订阅状态信息:

// App Store Server Notification V2 现在包含明确的订阅状态
// {
//   "notificationType": "REFUND",
//   "subtype": "...",
//   "data": {
//     "status": 2,  // 0=active, 1=expired, 2=revoked, 3=gracePeriod...
//     "expirationIntent": 1,
//     "signedTransactionInfo": "eyJ...",
//     "signedRenewalInfo": "eyJ..."
//   }
// }
// 不再需要额外调 API 来确定订阅是否仍然有效

最佳实践

  • 新项目直接使用 Get Transaction Info 替代翻页查询交易历史
  • 利用通知中的 status 字段直接更新订阅状态,减少对 Server API 的轮询
  • 旧代码无需立刻迁移,originalTransactionId 参数会继续支持
  • 消耗型项目的服务端验证现在有了可靠的查询方式,建议尽快接入
  • 关注 App Store Server API 的 Swift/Java/Node.js 官方 SDK 更新

还有什么值得关注

  • 旧版 App Store Server Notifications V1 的下线时间表
  • JWS 签名验证的最佳实践和官方库支持
  • 通知重试机制和幂等处理建议
  • 服务端 API 的速率限制和错误处理策略
WWDC 2023