如何用StoreKit 2实现服务端收据验证?含单笔交易验证疑问
StoreKit 2 消耗型内购服务端验证方案解答
一、jwsRepresentation方式的正确性
这种方式完全正确,且是StoreKit 2官方推荐的单笔交易验证方案,相比传统的整包收据(receiptData)更精准、高效:
- 每个成功交易返回的
jwsRepresentation是针对当前单笔交易的JSON Web Signature(JWS),包含交易ID、商品ID、购买时间、环境标识、交易状态等核心信息。 - 后端可直接解析JWS的签名与payload,无需处理包含所有历史交易的整包收据,避免冗余数据解析和重复交易误判。
二、单笔交易的验证方案
StoreKit 2 JWS方式(推荐)
获取到result.jwsRepresentation后,按以下流程实现精准验证:
- iOS端:将JWS字符串与用户唯一标识(如用户ID)一起发送到后端接口。
- 后端处理:
- 验证JWS签名:用苹果公钥验证凭证合法性,确保是官方签发且未被篡改。
- 解析payload校验关键信息:
- 检查
productId是否匹配目标消耗型商品ID; - 确认
transactionStatus为0(交易成功状态); - 校验环境标识(沙箱/生产)与服务器运行环境一致;
- 检查
transactionId是否已在数据库中存在(防止重复提交请求导致重复发币)。
- 检查
- 发放权益:所有校验通过后,为用户发放200金币,同时记录
transactionId为已处理状态。
传统receiptData方式(不推荐)
传统receiptData是应用的整包收据,包含所有历史交易,验证单笔交易需额外处理:
- iOS端将base64编码后的receiptData发送给后端;
- 后端把receiptData提交到苹果验证服务器(生产/沙箱地址如你提供的);
- 解析苹果返回的结果,遍历
receipt或latest_receipt_info数组,找到对应交易的transaction_id; - 校验该交易的商品ID、状态等信息,同时确认未处理过此
transaction_id,再发放权益。
这种方式的问题是:消耗型交易不会从收据中移除,后端需额外过滤已处理交易;且收据可能因用户重装APP等原因不存在,可靠性不如JWS方式。
三、核心注意事项
- 无论用哪种方式,后端都必须记录已处理的
transactionId,这是防止重复发币的关键。 - 沙箱测试时,后端需切换到苹果沙箱验证地址,避免验证失败。
内容的提问来源于stack exchange,提问作者Pratik
相关产品推荐
相关产品推荐

