虽然通过苹果的StoreKit2框架客户端可以直接处理整个支付流程,不再需要验证票据了,但是绝大多数业务场景都需要再服务器端再次验证支付逻辑,这时我们就需要解析苹果服务器到服务器到支付通知了,这里只说明通知数据结构的解析,具体可以分为如下三步来实现:

iOS IAP应用内购买

第1步:苹果服务器POST过来的JSON数据:

{
	"signedPayload": "eyJhbGciOiJF这里是被加密的内容eyJhbGciOiJF"
}

第2步:按照苹果官方提供的方法提取出signedPayload的内容如下:

{
	"notificationType"	: "DID_RENEW",
	"subtype"			: "子类型",
	"notificationUUID"	: "f2d65c0c-4980-4211-9d02-d104959a468e",
	"data" {
		"appAppleId"	: 706*****38,
		"bundleId"		: "App的Bundle Id标志符",
		"bundleVersion"	: "20230506165910",
		"environment"	: "Sandbox",
		"signedTransactionInfo"	: "eyJhbGc加密的交易信息zV1Q",
		"signedRenewalInfo":"eyJhbGciO加密的续费信息giG29hdGA",
		"status"		: 1
		},
	"version"			: "2.0",
	"signedDate"		: 1717485836523
}

其中notificationType字段表示通知的具体类型,共有18种可能的情况 :
1、CONSUMPTION_REQUEST - 消费者发起了一个【退款/自动续期订阅】请求
2、DID_CHANGE_RENEWAL_PREF - 结合subtype字段【UPGRADE/DOWNGRADE】决定消费者修改了订阅计划,如果subtype字段为空表示该回至当前状态
3、DID_CHANGE_RENEWAL_STATUS - 结合subtype字段【AUTO_RENEW_ENABLED/AUTO_RENEW_DISABLED】一起决定订阅续期状态变化,如果用户发起了退款请求则App Store也会禁用自动续期
4、DID_FAIL_TO_RENEW - 结合subtype字段【GRACE_PERIOD/空】一起决定服务端是否可以停服务了,如还处在GRACE_PERIOD宽限期内不要停服务,否则可以收回服务了
5、DID_RENEW - 结合subtype字段【BILLING_RECOVERY/空】一起决定服务端是否可以提供服务了,subtype值为BILLING_RECOVERY表示上次过期的订阅自动续期成了,为空表示一个新的自动续期订阅成功了
6、EXPIRED - 结合subtype字段【VOLUNTARY/BILLING_RETRY/PRICE_INCREASE/PRODUCT_NOT_FOR_SALE/空】一起决定订阅过期原因,分别表示用户自主取消/上一个账单自动续期失败/用户不同意涨价/商品不再处于销售状态/其它原因
7、EXTERNAL_PURCHASE_TOKEN - 结合subtype字段【EXTERNAL_PURCHASE_TOKEN】仅启用了外部支付才有此值
8、GRACE_PERIOD_EXPIRED - 宽限期已结束还是无法扣款成功,服务端可以取消服务了
9、OFFER_REDEEMED - 结合subtype字段【INITIAL_BUY/RESUBSCRIBE/UPGRADE/DOWNGRADE/空】一起决定消费者使用了促销优惠或优惠码,分别表示第一次使用优惠码/非首次使用优惠码/用优惠码升级/用优惠码降级/用优惠码再次购买当前已买且有效的服务
10、PRICE_INCREASE - 结合subtype字段【PENDING/ACCEPTED】一起决定消费者是否同意服务涨价,分别表示待处理/接受涨价
11、REFUND - 表明App Store已经成功处理了一笔退款
12、REFUND_DECLINED - 表明App Store拒绝了开发发起的退款请求
13、REFUND_REVERSED - 表明App Store撤销了之前因消费者争议而产生的退款请求,需要继续提供服务
14、RENEWAL_EXTENDED - 表明App Store扩展了某个订阅的续订日期
15、RENEWAL_EXTENSION - 结合subtype字段【SUMMARY/FAILURE】一起决定App Store正尝试调用为所有活动订阅者延长订阅日期
16、REVOKE - 表明家庭共享服务关闭,不可再共享了
17、SUBSCRIBED - 结合subtype字段【INITIAL_BUY/RESUBSCRIBE】一起决定消费者订阅了一个产品,分别表示第一次订阅或通过家庭共享访问/非第一次
18、TEST - 表明App Store发送了一个测试通知,你请求了Test Notification API

第3步:同样按官方提示提取出signedTransactionInfo字段里的交易信息:

{
	"transactionId"			: "2000000618051216",
	"originalTransactionId"	: "2000000528520218",
	"webOrderLineItemId"	: "2000000063257619",
	"bundleId"				: "App的Bundle Id标志符",
	"productId"				: "PD11021501",
	"subscriptionGroupIdentifier"	: "10509057",
	"purchaseDate"			: 1717485886000,
	"originalPurchaseDate"	: 1708488949000,
	"expiresDate"			: 1717486186000,
	"quantity"				: 1,
	"type"					: "Auto-Renewable Subscription",
	"appAccountToken"		: "18fc0cf2-0379-5204-y70e-30ctdey20577", # 自定义UUID格式的数据
	"inAppOwnershipType"	: "PURCHASED",
	"signedDate"			: 1717485836502,
	"environment"			: "Sandbox",
	"transactionReason"		: "RENEWAL",
	"storefront"			: "CHN",
	"storefrontId"			: "143465",
	"price"					: 68000,
	"currency"				: "CNY"
}

至此便可以根据signedTransactionInfo里的交易信息进行相关服务的下发了。