WWDC Quick Look 💓 By SwiftGGTeam
What's new in App Store server APIs

What's new in App Store server APIs

观看原视频

Highlight

Apple 在 WWDC23 为 App Store Server API 新增了 Get Transaction Info 端点、为 Notifications V2 新增了 subscription status 字段和 onlyFailures 筛选器,同时正式废弃了 verifyReceipt 和 Notifications V1,推动开发者迁移到更现代的 JWS 签名数据体系。

核心内容

用 transactionId 直接查询单笔交易

以前,服务器上验证一笔交易需要调用 Get Transaction History,然后在多页结果中翻找匹配的记录。如果用户的交易历史很长,这个过程既慢又繁琐。更麻烦的是,已完成的消耗型交易不会出现在 Get Transaction History 的响应中,这让验证消耗型交易变得不可能。

03:12)Apple 推出了新的 Get Transaction Info 端点。你只需要提供一个 transactionId,就能直接获取该笔交易的签名信息。所有类型的交易 ID 都支持,包括已完成的消耗型交易。

调用方式很简单:

GET https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId}

响应中包含 signedTransactionInfo 字段,解码后即可查看该笔交易的完整信息。

06:32)另一个便利更新是:原先需要 originalTransactionId 作为路径参数的核心端点(如 Get Transaction History、Get All Subscription Statuses),现在支持使用任意 transactionId。你不再需要先用 Get Transaction Info 去转换 ID,直接就能调用。

订阅状态一目了然

07:42)追踪订阅状态是订阅制应用的核心需求。Notifications V2 会在订阅状态变化时发送事件,但有些通知的类型并不能直接告诉你当前状态。

比如收到 REFUND 通知时,你无法直接判断订阅是否被撤销。如果用户在同一 originalTransactionId 下有更新的续期交易,订阅状态可能仍然是 Active。仅凭通知数据无法做出正确判断。

10:22)Apple 在 Notifications V2 的数据对象中新增了一个 status 字段。这是一个整数,直接表示订阅的五种核心状态之一。每个自动续期订阅相关的通知都会包含这个字段,服务器不再需要额外调用 API 来确认状态。

只获取失败的通知

11:36)当服务器出现故障时,App Store 可能无法成功发送通知。Get Notification History 端点允许你请求过去六个月内的 V2 通知,用于恢复遗漏的通知。

但问题是:即使服务器正常运行,偶尔也可能因为瞬时网络问题错过个别通知。这种情况下,你没有一个明确的时间窗口去查询,只能翻阅大量已经收到的通知来寻找遗漏。

12:30)Apple 为 Get Notification History 新增了一个 onlyFailures 请求字段。启用后,响应中只包含那些未能成功送达你服务器的通知,包括正在重试过程中的通知。

请求示例:

{
  "onlyFailures": true
}

响应中的每个通知条目包含 sendAttempts 数组,记录了每次发送尝试的结果。如果后续重试成功,该通知将不再出现在 onlyFailures 的查询结果中。

verifyReceipt 正式废弃

14:44)Apple 宣布 verifyReceipt 端点和 App Store Server Notifications V1 正式废弃。这两个 API 不会再接收新功能更新。

迁移到 App Store Server API 需要三个步骤:

  1. 生成 JWT 以代表你的应用身份
  2. 为每个用户保存一个 transactionId
  3. 使用 transactionId 调用核心端点

迁移到 Notifications V2 更简单:

  1. 让服务器准备好解析 V2 格式(使用与 Server API 相同的 JWS 交易格式)
  2. 在 App Store Connect 中将通知偏好从 V1 切换到 V2
  3. 先在沙盒环境测试 V2 通知

19:35)Apple 还发布了 App Store Server Library 开源库,支持 Swift、Java、Node.js 和 Python,帮助开发者更轻松地调用 API、验证签名数据,以及从收据中提取 transactionId 来简化迁移。

详细内容

Get Transaction Info 端点详解

05:47)新的 Get Transaction Info 端点解决了服务器端验证单笔交易的痛点。

请求格式:

GET /inApps/v1/transactions/{transactionId}
Authorization: Bearer {JWT}

响应格式:

{
  "signedTransactionInfo": "eyJhbGciOiJFUzI1Ni..."
}

关键点:

  • signedTransactionInfo 是 JWS 格式的签名交易数据
  • 解码后可获得完整的交易信息,包括 productId、purchaseDate、type 等
  • 支持所有交易类型:消耗型、非消耗型、自动续期订阅、非续期订阅
  • 支持已完成和未完成的交易

Notifications V2 的 status 字段

10:30)status 字段是一个整数,对应五种订阅状态:

状态含义
1Active订阅活跃中
2Expired订阅已过期
3Billing Retry账单重试中
4Billing Grace Period账单宽限期内
5Revoked订阅已撤销

这个字段出现在所有自动续期订阅相关的通知中。收到 REFUND 通知时,直接检查 status 就能知道是否需要禁用内容访问。

onlyFailures 的使用场景

13:08onlyFailures 字段解决了两种场景:

  1. 已知服务器故障:服务器宕机后恢复,查询故障期间遗漏的通知
  2. 未知网络问题:日常运行中偶尔漏掉个别通知,快速定位遗漏项
{
  "startDate": 1686000000000,
  "endDate": 1686086400000,
  "onlyFailures": true
}

响应中的 notificationHistory 数组只包含失败的通知。每个条目包含:

  • signedPayload:原始通知的签名内容
  • sendAttempts:发送尝试记录,最多 6 条(1 次初始发送 + 5 次重试)

迁移路径

17:16)从 verifyReceipt 迁移:

旧流程:

设备 → 收据 → 你的服务器 → verifyReceipt → Apple → 解码后的收据 → 你的服务器

新流程:

设备 → transactionId → 你的服务器 → App Store Server API → 签名交易数据

你不再需要存储 base64 编码的收据,只需要保存一个 transactionId。

核心启发

  1. 构建实时订阅状态看板

    • 做什么:在服务器上维护一个实时订阅状态仪表板,支持客服团队查看用户订阅状态
    • 为什么值得做:Notifications V2 的 status 字段让状态同步变得直接可靠,不再需要复杂的推断逻辑
    • 怎么开始:设置 Notifications V2 接收端点,解析每个通知中的 status 字段,更新数据库中的用户订阅状态
  2. 实现智能通知恢复机制

    • 做什么:在服务器健康检查流程中集成 onlyFailures 查询,自动恢复遗漏的通知
    • 为什么值得做:网络问题不可避免,onlyFailures 让恢复遗漏通知从”翻遍历史”变成”精准定位”
    • 怎么开始:在服务器启动或定时任务中调用 Get Notification History 并传入 onlyFailures: true,处理返回的遗漏通知
  3. 简化服务器端交易验证

    • 做什么:用 Get Transaction Info 替代 Get Transaction History 进行单笔交易验证
    • 为什么值得做:代码更简洁、响应更快、支持消耗型交易验证
    • 怎么开始:将现有验证逻辑从”查询历史+搜索匹配”改为直接调用 Get Transaction Info,传入 transactionId
  4. 规划 verifyReceipt 迁移

    • 做什么:制定从 verifyReceipt 到 App Store Server API 的迁移计划
    • 为什么值得做:verifyReceipt 已废弃,新功能只会在 JWS 签名数据体系中发布
    • 怎么开始:使用 App Store Server Library 开源库,从收据中提取 transactionId,逐步替换 verifyReceipt 调用

关联 Session

评论

GitHub Issues · utterances