美文网首页
IOS库:IAP StoreKit2 服务器

IOS库:IAP StoreKit2 服务器

作者: 时光啊混蛋_97boy | 来源:发表于2022-06-02 17:00 被阅读0次

苹果服务器与开发者服务器之间的通讯,包括苹果通知、开发者主动请求苹果服务器、新的验证收据流程等。

  • 以前只支持 Apple server 单向发送状态变化的通知给我们自己的服务器,现在支持主动去请求 Apple server 获取历史交易记录
  • StoreKit 2 服务器端接口支持了新的格式(JWS 格式)。
  • 沙盒环境测试优化

构建开发者服务器可以实现以下几个功能:

  • 接收内购状态改变通知
  • 通过接口跟踪内购状态变化(获取所有的交易历史记录)
  • 随时验证用户的访问权限(是否已购买,是否已退款等信息)
  • 跟踪退款信息

一、验证票据

开发者可以用 receipt 收据或者使用StoreKit v2 新的 signed transactiond 来验证订单。

Receipt 收据验证方式:

  • 在用户设备App中验证收据
  • 在开发者服务端通过苹果/verifyReceipt接口验证收据

服务器端在通过/verifyReceipt接口验证票据时,新 API 的数据结构也发生了变化。例如统一了购买时间、过期时间、原始购买时间格式,新增了 appAcountToken 字段、内购类型字段、退款时间、退款原因、促销优惠类型等。

旧的 receipts收据内容如下图:

新的 JWS 格式的交易格式内容,如下图。对比 receipts 收据,可以知道有那些变化。旧的有 GMT(格林威治标准时间)、PST(太平洋标准时间)、Unix timestampUnix 时间戳),新的格式,只保留了 Unix 时间戳,并且字段做了更新。

内购的类型,也有返回了。

这个就是上面提到的关系的用户信息的 UUID。这里苹果用 appAccountToken 字段。

这个是用户退款时间和退款原因的字段。从之前的 cancellation_date 改成现在的 revocationData

最后是促销优惠的类型。


二、新增了一些 API

内购历史订单查询 API

获取交易历史记录:get_transaction_history,只需要用户任意一个交易里的originalTransactionId即可获取所有的历史记录。需要注意的是,这个返回的数据有一个字段 hasMoreture,表示历史订单有更新。


查找收据发票 API

这个就是前言提到的用户收到苹果的收据发票时,无法与开发者的订单匹配的问题!现有有新的 API 来解决了,这个新的接口,可以让用户提供的发票上的ORDER ID查到对应的transaction交易信息。整个流程,主是这样,用户客诉,提供订单 ID,查询到状态,为用户进行补单或者支持服务。开发者服务器记得保存对应的用户订单 ID 做好映射。


查找该客户过去的退款 API

除了苹果服务器的通知退款REFUND后,开发者现在可以主动通过inApps/v1/history接口,查询用户的所有交易订单,来确认订单的状态是不是退款(撤销)。

苹果提供了查询所有内购订单的接口,但是不可能让开发者查一次,然后再判断那些是退款订单吧!所以,苹果提供了另一个接口。这个接口也是一样,通过用户的任一个 originalTransactionId 可以查到这个用户的所有退款记录订单。用户退款有一个单独的 refundDate 字段,如果有内容时间就表示是退款。


三、通过通知跟踪状态

回调通知通过notificationTypesubType两个字段区分,自动续期订阅相关通知如下。

notificationType subType 说明
DID_CHANGE_RENEWAL_PREF DOWNGRADE 降级,降级下个周期生效
DID_CHANGE_RENEWAL_PREF UPGRADE 升级,升级马上生效
DID_CHANGE_RENEWAL_STATUS AUTO_RENEW_ENABLED 开启自动续期

...
理解不同类型通知中交易信息的含义。每个通知中都会携带交易信息,位于 data -> signedTransactionInfo字段,它总是当时(发送通知那一刻)生效的交易,比如初次购买时,携带的购买成功的交易信息。

总结来说,App Store server notifications V2 提供了多达20多种通知类型!当然,这里变动这么多,苹果不可能在原来的接口直接改啊!所以是有 v1 和 v2 接口,开发者可以设置。最后就是通知返回的内容,多了一个 subtype子类型,还有对应的 version 为 2 表示 App Store server notifications V2 版本。


四、购买流程变化

如果有服务端,权益发放在服务端,则流程如下:

客户端流程
  • 客户端通StoreKit SDK拉起支付
  • 用户输入密码或FaceID完成支付
  • StoreKit回调客户端并传入Transaction
  • 客户端校验该Transaction,校验通过后,将Transaction发送给服务端
服务端流程1
  • 接收来自客户端的Transaction并校验,校验通过后,为用户发放权益
服务端流程2
  • 接收来自Apple Server的回调通知,根据通知的内容,对用户发放权益
服务端流程3
  • 定期调用交易历史查询接口,为在回调通知漏掉的交易补发权益。

其中,服务端流程1和流程2是分开并行存在的,且流程1可选(回调通知较慢,加上流程1能够提升用户体验);流程2必须有,是唯一能够及时知悉所有交易发生的时机;流程3用于补单或者恢复购买。

注意事项:对于服务端流程3,由于交易历史查询接口需要输入originalTransactionId,所以如果用户的首次交易被遗漏,是没有办法查询的。所以它需要客户端协助:客户端获取当前Apple ID的任意一条交易上传服务端,服务端取其中的originalTransactionId查询交易历史,再取交易历史的最近一条交易作为发放权益的依据。


五、服务器迁移到 JWS 格式交易验证

对于 StoreKit 2,苹果已经废弃了用 receipt 收据验证逻辑,只需要提供交易的 originalTransactionId 即可获取到完整的交易信息。那么如何从 StoreKit 1 升级到 StoreKit 2 呢?

如果开发者需要兼容 StoreKit v1 版本,那么还可以使用receipt 收据通过苹果接口 /verifyReceipt 验证收据,收据中是包含 originalTransactionId 的,所以,开发者可以通过inApps/v1/history 接口,随时了解交易的状态。

  • 上传 receipt 到我们的服务器
  • 拿着 receipt 去苹果服务器验证,并获取 originalTransactionId 信息
  • 根据 originalTransactionId 去苹果服务器获取历史交易记录,找到特定 Transaction

六、注意事项

业务用户识别

Apple服务的回调通知中,并不会携带Apple ID信息,因此无法区分该通知属于哪个具体业务用户。Apple的提供的方式是appAccountToken字段,该字段在客户端发起支付时指定,在通知中携带,以便业务后端区分。关于它注意几个点。

  • appAccountToken由业务后端自己生成维护
  • 如果用户自行在控制台操作,可能出现回调通知不带appAccountToken的情况。此时可以从交易历史中查询(第一条交易一定会带appAccountToken,因为首次发起购买一定是从我们的APP客户端,就一定会设置)
JWS签名验证

StoreKit2的一个重要变化是,大部分信息都采用JWS进行组织。TransactionJWS、通知也是JWS。上面说的交易流程中,客户端交易成功上传Transaction时,后端需要验证其有效性;接收到通知时,也要验证其有效性。

客户端上传交易信息的验证

对于后端的处理,官方并没有规定一定要将客户端得到的Transaction传到服务端,加这一步只是我们为了实时性而做的。此时的签名就要我们自己来处理了。其实是有两种方式进行确认的

  • 在业务系统已有的安全传输条件下直接传输交易信息,比如业务系统已有登录鉴权,可以相信经过登录后传输的信息是可信的
  • 将整个原始的Transaction JWS传输给后端,后端自己验证,验证逻辑同下文“通知的签名验证”一致。
通知的签名验证

这一点是最多人搞不清楚的,我们观察任意一个通知的Header如下。没有kid字段,取而代之的是x5c,这代表提供验证公钥的是一个证书X.509证书链。我们需要先验证证书链的正确性,再用证书链提供的公钥验证整个JWS的正确性。

{
  "alg": "ES256",
  "x5c": [
    "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"
  ]
}

验证逻辑如下

  1. Apple官网下载根证书
  2. 取证书链的最后一个,和上述下载的根证书对比,如果不同则验证失败
  3. 验证证书链:第一个证书用第二个证书验证、第二个用第三个验证、以此类推,全都成功才算通过
  4. 从第一个证书取得公钥
  5. 用上一步得到的公钥验证整个JWS
服务器宕机

如果因为服务端宕机或代码bug等原因,未能正确处理Apple Server通知,Apple Server会进行重试。重试时间分别是:在上一次尝试的基础上间隔1, 12, 24, 48, 72小时。也就是说,6天13小时后,将放弃通知重试,这期间还没能正确处理通知,将发生掉单。

此外,如果等不及通知重试,也可以主动查询交易历史进行补单。注意:交易历史查询接口需要originalTransactionId作为路径参数,所以如果是丢了初次购买的交易信息,是无法补单的。

通知乱序

理论上通知存在乱序的可能:初次订阅,此时服务器未能正确处理交易信息,接着客户马上在设置界面升级,触发升级通知。会出现先收到升级通知,再收到初次订阅通知的情况。正确的处理方式是以升级通知的交易为准,忽略初次订阅通知。

为保证无论什么时候来通知,都能正确处理,可以在每次回调时都先查询交易历史,如果通知中的交易信息是最新的,则处理,否则忽略。

相关文章

  • IOS库:IAP StoreKit2 服务器

    苹果服务器与开发者服务器之间的通讯,包括苹果通知、开发者主动请求苹果服务器、新的验证收据流程等。 以前只支持 Ap...

  • ruby实现ios和google内购

    一、ios 和 google 内购 ios IAP二次验证 IAP(In App purchase):App和Ap...

  • iOS 内购 IAP

    1. iOS内购IAP(一) —— 基础配置篇(一)2. iOS内购IAP(二) —— 工程实践(一)3. iOS...

  • ios内购IAP相关内容

    ios内购IAP相关内容 iOS IAP应用内购详细步骤和问题总结指南 - 简书https://www.jians...

  • IAP开发指南

    IAP流程 介绍 这里介绍的IAP使用服务器模式: 调用服务器接口创建一个商品的订单 请求Apple的商品列表 选...

  • IAP支付,iOS微信、支付宝支付

    1. 支付宝支付 2. 微信支付 3. IAP支付 时序图 苹果应用内购买(IAP),服务器端开发处理流程 IAP...

  • 苹果常见规则整理

    苹果设备操作订阅/取消订阅 IAP 内部支付 Unity IAP插件使用 4 . IOS 打包不产生二进制文件

  • iOS开发 AIP支付总结

    iOS开发 IAP支付总结 一、IAP介绍 1.1、简介 这里先把官方文档给大家 App 内购买项目配置流程[ht...

  • 应用内支付 IAP支付流程 自动续期订阅 丢单处理 问题 流程详

    应用内支付 IAP支付流程 自动续期订阅 丢单处理 问题 流程详解 关于iOS的应用内支付(IAP), 我曾在项目...

  • iAP 的一些简介

    iAP 的小指南 in-App Purchase 内购的缩写为 iAP。是 iOS 自带的一种应用内数字产品的支...

网友评论

      本文标题:IOS库:IAP StoreKit2 服务器

      本文链接:https://www.haomeiwen.com/subject/aqgfmrtx.html