处理苹果平台的 CONSUMPTION_REQUEST 消息
最近完善了一下产品的购买流程,其中的一项工作是处理来自苹果 App Store 平台的 CONSUMPTION_REQUEST 消息,在这儿记录一下要点。
消息说明
App 如果使用了苹果的内购(IAP),每当发生用户购买、续费、退款等操作时,苹果服务器都会向开发者指定的地址发送一条消息,不同的消息有不同的 notificationType
值,其中 CONSUMPTION_REQUEST 消息的意思是用户为应用内购买发起了退款请求,App Store 请求开发者服务器提供用户的消费数据,用于协助 App Store 决定是否给用户退款。
开发者可以忽略 CONSUMPTION_REQUEST 消息,也可以根据需要,在 12 小时内回应 App Store。
回应消息
要回应 CONSUMPTION_REQUEST 消息,只需向指定的地址发一个 PUT 请求即可。具体细节可见官网文档。
这个 PUT 消息的要点主要有两个:
- 在 Header 中添加认证 token 信息;
- 在 Body 中发送一个 JSON 格式的对象,向 App Store 提交对应的信息。
数据内容
我们先看 Body 中的数据内容。
根据文档,数据字段以及含义大致如下:
{
"accountTenure": 0, // 用户年龄段,0 表示未知
"appAccountToken": "", // 用户 uuid,由于之前没有设置,此处留空
"consumptionStatus": 0, // 消费状态,0:未知,1:未消费,2:部分消费,3:全部消费
"customerConsented": True, // 用户是否同意提供消费数据
"deliveryStatus": 0, // 交付状态,0:已成功交付
"lifetimeDollarsPurchased": 0, // 用户在应用内购买的总金额,0 表示未知
"lifetimeDollarsRefunded": 0, // 用户在应用内退款的总金额,0 表示未知
"platform": 1, // 平台,0:未知,1:苹果平台,2:其他平台
"playTime": 0, // 用户在应用内的总时间,0 表示未知
"refundPreference": 1, // 商家对退款的意见,0:未知,1:支持,2:不支持,3:不确定
"sampleContentProvided": True, // 是否已经提供了示例内容
"userStatus": 1, // 用户账号状态,0:未知,1:活跃,2:暂停,3:关闭,4:受限
}
你可以根据需要,修改对应字段的值。
请求 Header
请求 Header 中有两个必填的自定义字段,分别是:
- Content-Type 值固定是
application/json
- Authorization 值为
Bearer $jwt_token
其中 jwt_token
必须要正确填写,否则请求会返回 401 错误。
jwt_token
的具体生成说明可见官方文档,大致格式类似下面这样:
Header:
{
"kid": "ZA12345678",
"alg": "ES256",
"typ": "JWT"
}
Payload:
{
"iss": "your_uuid",
"iat": 1723173620,
"exp": 1723183620,
"aud": "appstoreconnect-v1",
"bid": "your_bundle_id"
}
其中 kid
、iss
,以及生成 JWT 时所需的私钥等几项,需要去 App Store Connect 后台生成。
JWT 私钥
如果你之前还没有生成过对应的私钥,可以前往 App Store Connect 后台的“用户和访问” → “集成” → “App 内购买项目”页面生成,如下图所示:
生成之后,可以在这个页面下载 .p8 格式的私钥。注意这个私钥只能下载一次,下载之后请妥善保存,如果不慎遗失,只能删除再重新生成一个。
上面生成 JWT 所需的 kid
对应上图中的“密钥 ID”,iss
对应“Issuer ID”,私钥即上面下载的 .p8 文件中的内容。
然后就可以用类似下面的方法生成 JWT 了:
import jwt
jwt_token = jwt.encode(
payload,
private_key,
algorithm="ES256",
headers=headers,
)
最后,将得到的 jwt_token
以 Bearer $jwt_token
的形式包含在请求头的 Authorization
中,发起 PUT 请求即可。
如果请求返回 202 状态码,表示请求成功了。如果是其他值,可根据错误状态再仔细检查处理。
评论: