App Store 服务器 API 深度解析(In-App Purchase 相关)

本次分享由 App Store 服务器团队工程师 Riyaz 主讲,聚焦 In-App Purchase(应用内购买)相关的 App Store 服务器 API 最新更新,旨在帮助开发者简化应用服务器职责、提升效率。以下是内容的详细梳理。

一、应用服务器的核心职责

Riyaz 首先明确了应用服务器在 In-App Purchase 流程中的三大关键职责,这也是本次分享的核心围绕方向:

  1. 管理应用内购买(Manage In-App Purchases)
    将交易数据与用户账户关联,确保应用能无缝交付内容或服务(如虚拟商品、订阅权益等)。
  2. 签名请求(Sign Requests)
    生成签名以授权服务器向 App Store 发起的请求,保障请求的合法性与安全性。
  3. 参与退款决策流程(Participate in the Refund Decision Process)
    通过共享购买相关的消费数据,帮助 App Store 做出合理的退款判断,提升用户满意度。

二、管理应用内购买:交易标识符与核心更新

管理应用内购买的核心是建立用户账户与 App Store 交易的关联 ,而交易标识符是实现这一关联的关键工具。App Store 提供三类核心数据结构传递交易信息:AppTransactionJWSTransactionJWSRenewalInfo,本次重点围绕其中的标识符与新增功能展开。

1. 核心交易标识符解析

标识符

来源

作用与特点

包含位置

transactionId

App Store 生成

唯一标识单次交易(如首次购买、订阅续订、恢复购买),每次交易的 ID 不同。

JWSTransactionJWSRenewalInfo

originalTransactionId

App Store 生成

标识 "原始购买" 的 ID,在自动续订订阅的生命周期中保持不变(如续订、升级 / 降级订阅),便于管理订阅状态。

JWSTransactionJWSRenewalInfo

appAccountToken

开发者生成

由开发者在服务器生成的 UUID,关联用户在自身系统的账户;需通过 StoreKit 或新接口设置,用于绑定用户账户与交易。

JWSTransactionJWSRenewalInfo(需开发者设置)

appTransactionId

App Store 生成

新增!为每个 Apple 账户 + 应用分配的全局唯一 ID,跨重新下载、退款、回购、商店区域变更保持不变;支持家庭共享(每个家庭成员 ID 唯一)。

AppTransactionJWSTransactionJWSRenewalInfo

关键更新:appTransactionId 的价值

appTransactionId 是本次的核心新增标识符,解决了此前多场景下 "用户账户与交易关联难" 的问题,主要价值包括:

  • 统一关联入口 :用户下载应用时,可将自身系统的用户账户与 AppTransaction 中的 appTransactionId 绑定;后续该用户的所有 In-App Purchase 交易(如多个不同订阅)都会包含相同的 appTransactionId,无需重复关联。
  • 支持多场景判断 :例如,判断两个不同订阅(如 "月度体育通讯" 和 "年度赛事直播")是否属于同一用户,可通过比对 appTransactionId 实现。
  • 扩展 API 能力 :可作为 Get Transaction HistoryGet All Subscription Statuses 等热门 API 的交易标识符;同时新增 Get App Transaction Info 接口,支持服务器直接获取 AppTransaction 信息(无需依赖设备),可查询应用版本、平台、环境等下载信息(不含设备验证细节)。

2. 新增接口:Set App Account Token

此前,appAccountToken 仅能通过 StoreKit 在 "应用内购买" 场景下设置,无法覆盖 "应用外购买"(如在 App Store 兑换优惠码、推广购买)。本次新增的 Set App Account Token 接口 解决了这一问题:

  • 功能 :为已有交易(包括历史一次性购买、自动续订订阅的最新交易)设置或更新 appAccountToken;设置后,自动续订订阅的后续续订(含升级 / 降级)会继承该 Token。
  • 使用场景
    1. 用户通过应用外渠道购买后,补充绑定 appAccountToken
    2. 修复自身系统中 "用户账户与 appAccountToken 关联不一致" 的问题(如用户账户所有权变更)。
  • 调用方式 :在请求路径中传入 originalTransactionId(标识目标交易),在请求体中传入目标 appAccountToken(UUID 格式),新 Token 会覆盖旧 Token。

三、签名请求:统一 JWS 格式

此前,开发者需根据不同场景(如生成推广优惠签名、 introductory offer 签名)使用不同的签名格式,复杂度较高。本次更新统一所有场景的签名格式为 JWS(JSON Web Signature),简化开发流程。

1. 核心改进

  • 统一格式:所有需签名的 StoreKit 调用(如推广优惠、introductory offer)均使用 JWS 格式,无需维护多套签名逻辑。
  • 新增 Introductory Offer 签名:支持为每个用户、每笔交易设置自定义的 introductory offer 资格,开发者可更灵活地控制用户可兑换的优惠次数。
  • 简化签名参数 :以 "推广优惠签名" 为例,使用 App Store Server Library 生成签名时,仅需传入 private key(从 App Store Connect 下载)、keyIdissuerIdbundleIdproductIdofferId(可选 transactionId,用于限定优惠仅对特定用户生效),参数数量大幅减少。

2. 签名流程示例(Java 语言)

java 复制代码
// 1. 初始化签名生成器(传入从 App Store Connect 获取的关键信息)
PromotionalOfferV2SignatureCreator creator = new PromotionalOfferV2SignatureCreator(
    privateKey,  // 私钥
    keyId,       // Key ID
    issuerId,    // Issuer ID
    bundleId     // 应用 Bundle ID
);

// 2. 设置可选参数(限定优惠仅对特定用户生效,可不传)
String transactionId = "用户的交易ID(如 appTransactionId)";

// 3. 生成 JWS 签名
String jwsSignature = creator.createSignature(
    productId,   // 商品 ID
    offerId,     // 优惠 ID(在 App Store Connect 配置)
    transactionId// 可选:用户交易 ID
);

四、参与退款决策:Send Consumption Information V2 接口

开发者可通过共享 "用户消费数据" 帮助 App Store 制定退款策略,本次新增的 Send Consumption Information V2 接口 是对旧版(V1)的重大升级,更易用、功能更全面。

1. 接口升级亮点

对比维度

旧版(V1)

新版(V2)

支持商品类型

仅消耗型商品、自动续订订阅

所有类型(含非消耗型、非续订订阅)

输入参数数量

12 个

5 个(3 个必填,2 个可选)

退款偏好

仅支持 "全额退款" 或 "不退款"

新增 "按比例退款(GRANT_PRORATED)"

状态

已废弃(仍接受请求)

推荐使用

2. 接口调用说明

当用户发起退款时,App Store 会向开发者服务器发送 CONSUMPTION_REQUEST 通知,开发者需通过该接口响应消费数据:

  • 请求路径 :传入 CONSUMPTION_REQUEST 通知中的 transactionId

  • 请求体参数(5 个):

    参数名

    类型

    说明

    customerConsented

    布尔值(必填)

    若用户同意共享消费数据,设为 true;否则不响应通知(设为 false 会被拒绝)。

    sampleContentProvided

    布尔值(必填)

    购买前是否向用户提供了样品内容(如免费试用)。

    deliveryStatus

    枚举(必填)

    DELIVERED(已成功交付内容)或 UNDELIVERED(未交付,需指定原因)。

    refundPreference

    枚举(可选)

    FULL_REFUND(全额退款)、NO_REFUND(不退款)、GRANT_PRORATED(按比例退款);不填则不表达偏好。

    consumptionPercentage

    数值(可选)

    商品消耗比例(单位:毫百分比,如 25000 代表 25%);选择 "按比例退款" 时,消耗型、非消耗型、非续订订阅必填(自动续订订阅由 App Store 计算)。

3. 退款结果处理

App Store 会根据开发者提供的消费数据决定退款策略,并通过以下通知告知开发者:

  • REFUND_DECLINED:退款被拒绝,无需操作。
  • REFUND :退款已批准,需根据通知中的新增字段处理:
    1. refundPercentage:退款比例(如 75 代表 75% 退款),用于计算需回收的内容(如虚拟货币需扣除对应比例);
    2. revocationType:退款类型,包括 REFUND_FULL(全额退款,需立即回收所有内容)、REFUND_PRORATED(按比例退款,回收对应比例内容)、FAMILY_REVOKE(家庭共享回收,立即回收内容)。

处理规则示例

  • 消耗型商品(如虚拟货币):若 refundPercentage 为 75%,则扣除用户账户中该商品对应 75% 的余额;
  • 自动续订订阅:按比例退款的处理逻辑与全额退款一致,需先查询当前订阅状态,再执行回收操作。

五、总结与后续行动

1. 核心内容回顾

  • 交易标识符 :新增 appTransactionId 作为统一关联工具,解决多场景下用户账户与交易的绑定问题;新增 Set App Account Token 接口覆盖应用外购买场景。
  • 签名请求:统一所有场景为 JWS 格式,简化签名逻辑;新增 Introductory Offer 自定义资格控制。
  • 退款决策Send Consumption Information V2 接口支持全商品类型、按比例退款,参数更少、功能更强。

2. 后续行动建议

  1. 参与开源库贡献:访问 App Store Server Library 的 GitHub 页面,贡献代码或反馈问题,支持开发者社区;
  2. 提交反馈:通过 Feedback Assistant 向 App Store 服务器团队提交功能需求或建议;
  3. 学习延伸内容
    • 了解 StoreKit 最新更新:观看 WWDC25 session "What's new in StoreKit and In-App Purchase";
    • 深入 App Store 服务器 API:观看 WWDC24 session "Explore App Store server APIs for In-App Purchase"。
相关推荐
大熊猫侯佩25 天前
WWDC 25 玻璃态星际联盟:SwiftUI 视图协同“防御协议”
swiftui·swift·wwdc
大熊猫侯佩1 个月前
WWDC 25 极地冰原撸码危机:InlineArray 与 Span 的绝地反击
swift·apple·wwdc
大熊猫侯佩1 个月前
代码精讲:WWDC 25 @Animatable 宏 —— SwiftUI 动画的新突破
swiftui·swift·wwdc
东吴贾诩1 个月前
[WWDC 2025] 用新设计构建一个SwiftUI应用程序
swiftui·wwdc
大熊猫侯佩2 个月前
探秘 WWDC 25 全新 #Playground 宏:提升 Swift 开发效率的超级神器
xcode·swift·wwdc
大熊猫侯佩2 个月前
SwiftUI 7 新 WebView:金蛇出洞,网页江湖换新天
swiftui·webview·wwdc
大熊猫侯佩2 个月前
Swift 6.2:江湖再掀惊涛浪,新功出世震四方
swift·apple·wwdc
大熊猫侯佩2 个月前
WWDC 25 风云再起:SwiftUI 7 Charts 心法从 2D 到 3D 的华丽蜕变
swiftui·swift·wwdc
大熊猫侯佩2 个月前
Swift 6.2 并发江湖:两大神功破局旧制,代码运行经脉革新(下)
swiftui·swift·wwdc