本次分享由 App Store 服务器团队工程师 Riyaz 主讲,聚焦 In-App Purchase(应用内购买)相关的 App Store 服务器 API 最新更新,旨在帮助开发者简化应用服务器职责、提升效率。以下是内容的详细梳理。
一、应用服务器的核心职责
Riyaz 首先明确了应用服务器在 In-App Purchase 流程中的三大关键职责,这也是本次分享的核心围绕方向:
- 管理应用内购买(Manage In-App Purchases)
将交易数据与用户账户关联,确保应用能无缝交付内容或服务(如虚拟商品、订阅权益等)。 - 签名请求(Sign Requests)
生成签名以授权服务器向 App Store 发起的请求,保障请求的合法性与安全性。 - 参与退款决策流程(Participate in the Refund Decision Process)
通过共享购买相关的消费数据,帮助 App Store 做出合理的退款判断,提升用户满意度。
二、管理应用内购买:交易标识符与核心更新
管理应用内购买的核心是建立用户账户与 App Store 交易的关联 ,而交易标识符是实现这一关联的关键工具。App Store 提供三类核心数据结构传递交易信息:AppTransaction
、JWSTransaction
、JWSRenewalInfo
,本次重点围绕其中的标识符与新增功能展开。
1. 核心交易标识符解析
标识符
来源
作用与特点
包含位置
transactionId
App Store 生成
唯一标识单次交易(如首次购买、订阅续订、恢复购买),每次交易的 ID 不同。
JWSTransaction
、JWSRenewalInfo
originalTransactionId
App Store 生成
标识 "原始购买" 的 ID,在自动续订订阅的生命周期中保持不变(如续订、升级 / 降级订阅),便于管理订阅状态。
JWSTransaction
、JWSRenewalInfo
appAccountToken
开发者生成
由开发者在服务器生成的 UUID,关联用户在自身系统的账户;需通过 StoreKit 或新接口设置,用于绑定用户账户与交易。
JWSTransaction
、JWSRenewalInfo
(需开发者设置)
appTransactionId
App Store 生成
新增!为每个 Apple 账户 + 应用分配的全局唯一 ID,跨重新下载、退款、回购、商店区域变更保持不变;支持家庭共享(每个家庭成员 ID 唯一)。
AppTransaction
、JWSTransaction
、JWSRenewalInfo
关键更新:appTransactionId 的价值
appTransactionId
是本次的核心新增标识符,解决了此前多场景下 "用户账户与交易关联难" 的问题,主要价值包括:
- 统一关联入口 :用户下载应用时,可将自身系统的用户账户与
AppTransaction
中的appTransactionId
绑定;后续该用户的所有 In-App Purchase 交易(如多个不同订阅)都会包含相同的appTransactionId
,无需重复关联。 - 支持多场景判断 :例如,判断两个不同订阅(如 "月度体育通讯" 和 "年度赛事直播")是否属于同一用户,可通过比对
appTransactionId
实现。 - 扩展 API 能力 :可作为
Get Transaction History
、Get All Subscription Statuses
等热门 API 的交易标识符;同时新增Get App Transaction Info
接口,支持服务器直接获取AppTransaction
信息(无需依赖设备),可查询应用版本、平台、环境等下载信息(不含设备验证细节)。
2. 新增接口:Set App Account Token
此前,appAccountToken
仅能通过 StoreKit 在 "应用内购买" 场景下设置,无法覆盖 "应用外购买"(如在 App Store 兑换优惠码、推广购买)。本次新增的 Set App Account Token 接口 解决了这一问题:
- 功能 :为已有交易(包括历史一次性购买、自动续订订阅的最新交易)设置或更新
appAccountToken
;设置后,自动续订订阅的后续续订(含升级 / 降级)会继承该 Token。 - 使用场景 :
- 用户通过应用外渠道购买后,补充绑定
appAccountToken
; - 修复自身系统中 "用户账户与
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 下载)、keyId
、issuerId
、bundleId
、productId
、offerId
(可选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
:退款已批准,需根据通知中的新增字段处理:refundPercentage
:退款比例(如 75 代表 75% 退款),用于计算需回收的内容(如虚拟货币需扣除对应比例);revocationType
:退款类型,包括REFUND_FULL
(全额退款,需立即回收所有内容)、REFUND_PRORATED
(按比例退款,回收对应比例内容)、FAMILY_REVOKE
(家庭共享回收,立即回收内容)。
处理规则示例
- 消耗型商品(如虚拟货币):若
refundPercentage
为 75%,则扣除用户账户中该商品对应 75% 的余额; - 自动续订订阅:按比例退款的处理逻辑与全额退款一致,需先查询当前订阅状态,再执行回收操作。
五、总结与后续行动
1. 核心内容回顾
- 交易标识符 :新增
appTransactionId
作为统一关联工具,解决多场景下用户账户与交易的绑定问题;新增Set App Account Token
接口覆盖应用外购买场景。 - 签名请求:统一所有场景为 JWS 格式,简化签名逻辑;新增 Introductory Offer 自定义资格控制。
- 退款决策 :
Send Consumption Information V2
接口支持全商品类型、按比例退款,参数更少、功能更强。
2. 后续行动建议
- 参与开源库贡献:访问 App Store Server Library 的 GitHub 页面,贡献代码或反馈问题,支持开发者社区;
- 提交反馈:通过 Feedback Assistant 向 App Store 服务器团队提交功能需求或建议;
- 学习延伸内容 :
- 了解 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"。