IAP

苹果内购(IAP)从入门到精通(8)- StoreKit2 Server to Server

苹果内购(IAP)从入门到精通(8)- StoreKit2 Server to Server

Posted by WTJ on July 8, 2022

acc1cbcb437c417dae8c56e926292dcd~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

图,苹果服务器、用户设备、开发者服务器,三者之间的交互越来越多,随着苹果的迭代和开放,三者如今已经成循环~

9b0e67752060437e8d9d9513139cafea~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

构建开发者的服务器:

  • 接收苹果内购的状态改变通知
  • 通过接口跟踪内购状态改变
  • 随时验证访问权限(就是用户的购买是不是有效的,比如用户退款了)
  • 管理订单状态
  • 跟踪退款 接下来,将会从以上几个方面展开说:

1.1 Validate status with receipts

Receipt 收据验证方式:

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

410e9ceeed1940c78635f37ffb9debf8~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

旧的 receipts 收据内容如上图。

468683656d6b41669d326b906f2914ab~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

新的 JWS 格式的交易格式内容,如上图。对比 receipts 收据,可以知道有那些变化:

5541d86377ff495fb4091dd545e716bd~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

内购的类型,也有返回了

5056435e958b46fcaab891402bab0b4a~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

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

fe8075281e284e1b84bbd33cc3936331~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

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

0ab055faf0dd43a8936d6ce6f5c8c04b~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

最后是促销优惠的类型。

1f394c9ea3d34c3796118fa63b2616dd~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

验证签名信息,这里就不多说了,上文已经说过了。

1.2 Check status with APIs

使用 APIs 检查状态

c30d292bbfff488a994cace47559aade~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

新提供了2个接口:

  • 订阅品项状态查询 API
  • 内购历史订单查询 API

1.2.1 获取用户所有订阅的状态

b648bf0361704b3895b470e2e4a0c9dd~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

先来看看订阅品项状态查询 API。需要参数只有一个:originalTransactionId,这个大家很熟悉了,就不展开了。详细文档:Get All Subscription Statuses

0983a7876cda43f5856151eb935afa92~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

接口请求和返回的数据格式示意如上。

586b808a87a04b819a2b033cb350667f~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

lastTransactions 是最后的订阅状态,1是有效,2是过期,3是账号扣费重试,4是账号宽限期(这个是开发者设置,比如到期扣费失败时,可以给用户延期多长时间。),5是已经撤销。

15154efceee343af943a6d365fde5c0d~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

对 signedTransactionId 进行 JWS 解码后的内容,就是单个更新订阅类型的数据内容。

1.2.2 获取交易的历史订单

64f71e4eb03e4c50a11835d1dc4c7389~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

获取用户的交易历史记录,包括他们在你的 App 中的所有应用内购买。 也是只需要参数一个:originalTransactionId,注意,只需要是用户的任意一个交易的 originalTransactionId 就可以啦。这个大家一看就明白了,就不展开了。详细文档:Get Transaction History

63f9204239eb463f82a98be56b840c38~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

需要注意的是,这个返回的数据有一个字段 hasMore 为 ture,表示有更新的历史订单有更新,默认是 20 条。目前开发者不能控制这个条数。

1.2.3 App Store Server API 验证

cf8e153faf4d454d9a0e39f1172790ed~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

App Store Server 接口标准:

  • JWT 认证
  • JWS 交易内容格式
  • Json 请求和响应
  • 基于 originalTransactionId 标识参数

9b09de643c0b4ba1826943283568f761~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

所有的 App Store Server API 接口都必须使用 JWT 认证,关于验证规则和流程,请查看文档:[Generating Tokens for API Requests]

(https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fappstoreserverapi%2Fgenerating_tokens_for_api_requests)

在苹果后台生成私钥的示例,详见文档:Creating API Keys to Use With the App Store Server API

786d09df5b1249039f2c006966cb3f3d~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

验证可查看文档:Generating Tokens for API Requests

e972648c5648492c93fc6a73ef8eed63~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

所以,如果需要使用 App Store Server API 查询订阅品项状态或用户的历史订单,关键要点:

  • 独立的状态和历史功能
  • 只需要提供 originalTransactionId
  • 获取已验证签名的交易并存储必要字段(比如 originalTransactionId)
  • 无需存储已验证签名的完整交易数据(也就是验证过的 JWS 内容,只需要保存 originalTransactionId 字段就可以了,一个字段走天下!给我们点个赞吧~)

1.3 Track status with notifications

通过通知跟踪状态!

b763a55e47344492a7a661593727581d~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

苹果服务器的通知更新,苹果说很好,开发者可以接受通知、更新的状态也及时?不需要开发者主动请求询问!行吧,你说的都对~

0d962ed7cd0a4b65a8f7a9d41ae2893d~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

当订阅状态发生变化时,Apple server 会主动通知我们的服务器,告知发生了哪些变化。功能跟之前的版本一样,但是删除了一些状态,也新增了一些状态。

ad917750bd294a019b8cf3a849524ccd~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

主要变动是,通知的类型,有一部分是删除了,也新增了一些通知类型。

总结来说,App Store server notifications V2 提供了多达20多种通知类型!子类型提供了更精细的通知类型!

5990dd90b80b4829a5ab25d7bf13e852~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

最后就是通知返回的内容,多了一个 subtype 子类型,还有对应的 version 为 2 表示 App Store server notifications V2 版本。

为了方便测试沙盒环境的退款通知,App Store 可以为沙盒环境单独设置一个 server URL 配置。

32d615a68f974f48b0ff01cc0087b2e5_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0

1.4 购买流程变化

新的购买流程处理

1.4.1 对于首次订阅的购买,流程上的变化是,开发者 App 与开发者服务器完成订阅流程后,苹果服务器也会发送通知 SUBSCRIBED + INITAL_BUY,然后开发者服务器可以随时通过接口 inApps/v1/subscriptions 随时查询用户订阅项目的状态,不用等苹果服务器的通知也可以啦!避免了开发者处于被动的情况,更好的实时获取。

95c0f7bb02184ccb84906d3d67d642ae~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

1.4.2 订阅更新,也是开发者服务器随时通过接口 inApps/v1/subscriptions 随时查询用户订阅项目的状态。是不是爽歪歪啦~ 点个赞吧~

5aa2a1951a7243ac9335325b0a7070a9~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

1.4.3 订阅类型的账单宽限期和计费重试,也是同样的道理,苹果服务器会发通知 DID_FAIL_TO_RENEW 、DID_RECOVER 给开发者服务器,开发者服务器随时通过接口 inApps/v1/subscriptions 随时查询用户订阅项目的状态,然后对 App 里用户实时操作和限制等。

10d5bb3735494c6bac84b248515ffac4~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

1.4.4 首次消耗型购买,还是一样。不同的时,开发者可以用 receipt 收据或者使用 StoreKit v2 新的 signed transactiond 来验证订单啊。

6fe53e573ee74427ba8077447c1a5a03~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

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

6f4c362550cd488fb1bbe0028d9b4b3c~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

1.4.6 如果是订阅类型的退款,开发者服务器就通过接口 inApps/v1/subscriptions 随时查询用户订阅项目的最新状态。

66d94b0286c44ca781fd0c5849868821~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

1.5 服务器迁移升级到 JWS 格式

迁移到 JWS 格式交易验证

对于 StoreKit v2 新的接口,苹果已经弃用了 receip 收据验证,所以,对于开发者来说,应该怎么迁移到新的 JWS 格式验证呢?所以,苹果给出了方案:

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

1f79912305724f0693eb3acde74cf8ea~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

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

  • 如果是订阅类型的商品,可以继续去获取订阅状态

17b11d6d8ca5446c8493e7d2aa4140f2~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

订阅类型,就通过 inApps/v1/subscriptions 接口查询。

1.6 Manage family sharing

目前苹果对 非消耗型 和 自动订阅 类型品项是支持 家庭共享(family sharing),另外,苹果会返回一个字段 inAppOwnershipType 表示当前用户是否为购买品项的主用户。 ad2fb18714fa46f8b8456d9b5c559ec7~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

1f00c22ab3ca48f58dc98ce8524c0147~tplv-k3u1fbpfcp-zoom-in-crop-mark-3024-0-0-0 image

家庭共享更新了新的通知,增加了4个类型的通知。

参考:

https://developer.apple.com/documentation/appstoreserverapi?language=_9 https://juejin.cn/post/6974733392260644895#heading-12 https://juejin.cn/post/7096063372159877150 【WWDC21 10174】 IAP 后台通信优化与实践 - 小专栏.pdf