大多数浏览器和
Developer App 均支持流媒体播放。
-
探索 App 内购买的集成和迁移
了解如何迁移到最新的 App Store Server API 并整合 App Store 服务器通知。我们将帮助您着手使用这些工具,提供在服务器中管理 App 内购买项目的最佳实践。学习如何为 JSON 网络令牌签名,验证签名的交易,并从 verifyReceipt 中迁移。
资源
- App Store Server API
- Apple PKI
- Creating API keys to authorize API requests
- Generating JSON Web Tokens for API requests
- Responding to App Store Server Notifications
相关视频
WWDC23
WWDC22
Tech Talks
WWDC21
-
下载
♪ ♪
Gabriel Ting: 大家好 欢迎大家收看我们的课程 探索 App 内购买项目集成和迁移 本次课程分为两部分 一部分专门介绍 迁移到 App Store Server API 另一部分专门介绍 迁移到 App Store Server Notifications Version 2 我叫 Gabriel 我会向大家介绍 如何迁移到 App Store Server API 我叫 Alex 我将带大家了解 迁移到 App Store Server Notifications Version 2 的过程 我们先来简单介绍一下 App Store Server API 和 App Store Server Notifications 我们去年引入了 App Store Server API 将其作为一种强大 安全和高效的 从服务器获取数据和执行操作的方法 我们的目标是为大家提供 所需的数据 这些数据是以 JSON Web Signature 或 JWS 格式签名的 这样你就可以验证你收到的数据 是未经篡改的 为你准备的 以及由 App Store 签名的 例如我们的 App Store Server API 的一个接口: Get Transaction History 接口 与新的筛选和排序功能相结合 可以让你只用一个 originalTransactionId 就能获取任何指定的交易集 在 App Store Notifications Version 2 的窗格中 随着表示订阅状态数量的增加 Notifications Version 2 将实时更新 订阅的所有可能状态 我们的目标是主动提供你需要了解的 有关订阅者情况的所有信息 而无需向我们索取信息 在本课程中 Alex 将详细介绍这一点 如果你对轻松高效地 使用这些功能感兴趣 本课程的内容就非常适合你 我们将带你了解 如何使用 App Store Server API 和 App Store Server Notifications Version 2 以及一些迁移技巧和最佳实践 关于这些课程的其他信息 请参阅下面列出的其他课程
我们先来讨论迁移到 App Store Server API 的问题吧 首先 我们将讨论如何使用 App Store Server API 其次 我们将深入研究 签署 JSON Web Tokens 的一些细节 第三 我们将演示如何验证 你从 App Store 收到的 签名交易是否是真实的 最后 我们将讨论如何 从 verifyReceipt 迁移到 App Store Server API 我们开始吧 首先 我们要讨论的是如何 在不同的 StoreKit 版本中 使用 App Store Server API 首先是原始 StoreKit 然后是 StoreKit 2 然后讨论如何同时支持 两个顾客端使用支持 StoreKit 2 的 iOS 版本 即 iOS 15 或更高版本 以及那些不支持 StoreKit 2 的顾客端 首先 让我们看看 App Store Server API 的 请求是什么样子的 我们可以看到 这里列出的五个 API 都使用 originalTransactionID 作为路径参数 让你可以使用从收据 签名交易 签名续订和通知接收到的 originalTransactionId 中 轻松调用这些 API 接下来是 Look Up Order ID 端点 此端点转而使用顾客提供的 orderId 来支持查询 这是为了更好地帮助顾客 直接提出问题 因为顾客在每笔交易的顾客收据中 都会收到 orderId 但没有提供 originalTransactionId 这样可以确保 你可以直接使用顾客手头的数据 来响应顾客的查询 这里列出的最后一个端点与通知相关 Alex 将在本次课程中讨论这个部分
接下来 让我们看看在原始 StoreKit 中 可以从哪里获得 originalTransactionId 使用统一 App 收据调用 verifyReceipt 时 originalTransactionId 会返回到 该用户购买的 每笔交易收据的 in_app 字段 以及 latest_receipt_info 和 pending_renewal_info 中 现在我们知道了如何从 Original StoreKit 交易中 获取 originalTransactionId 那么让我们看看 顾客 App Store Server 和 你的服务器之间的整个流程
首先 在你的服务器上获取 App 收据 接下来 拿到 App 收据 并从服务器上调用 verifyReceipt
这样就能返回解码后的收据 从解码的收据中 以我之前展示的完全相同的方式 收集所有的 originalTransactionId 接下来 你可以使用收集到的 任何 originalTransactionId 调用 Get Transaction History 端点 这将把该用户的交易历史记录 作为签名交易返回 这些交易包括非消耗品 退款消耗品 不续订订阅和自动续订订阅 然后 如果你要获取特定订阅的 最新签名交易和签名续订信息 请使用 相应的 originalTransactionId 调用 Get All Subscription Statuses 接口 这将返回与给定的 originalTransactionId 对应的 订阅的所有签名交易和续订信息 接下来 让我们看看在 StoreKit 2 交易用例中 originalTransactionId 的位置 这是顾客端上的代码 用于从交易中 获取 originalTransactionId 在支持 StoreKit 2 的设备上 即 iOS 15 或更高版本 你可以在经过验证 已解码的交易中 获取 OriginalID 属性 以获取 OriginalTransactionID 现在 看看服务器端 这是一个签名 JWS 交易的例子 它是你从 App Store Server API 和 App Store Server Notifications 中 收到的签名交易 和签名续订的数据类型 这里 我们看到 originalTransactionId 是一个顶级字段
接下来 让我们看看 顾客 App Store Server 和 StoreKit 2 交易服务器之间的 整个流程 首先 在设备上获取签名交易 使用 StoreKit 2 你可以在设备上验证此交易 使用设备上的状态侦听器 交易侦听器 或最后一笔交易 将让你随时了解最新的交易情况 取消和退款 然后将这些信息 发送到你的服务器进行记录 例如 这些更新包括 订阅续订 订阅报价赎回 过期等
将交易发送到你的服务器 结合 App Store Server Notifications Alex 将在接下来的部分详细介绍 你无需调用 App Store Server API 就可以了解订阅的最新状态 如果确实需要对订阅执行操作 例如延长订阅的续订日期 你可以使用签名交易中的 originalTransactionId 调用相应的端点并获取所需的数据 现在我们已经了解了如何在 原始 StoreKit 和 StoreKit 2 中 使用 App Store Server API 接下来让我们一起讨论下 如何同时支持 StoreKit 和 StoreKit 2 你可以在完全不采用 StoreKit 2 的情况下 使用 App Store Server API 如前所述 你可以从原始 StoreKit 的收据中 获得 OriginalTransactionID 你还可以从 JWS 交易中获取 StoreKit 2 的 originalTransactionID
你也可以独立于任何其他 API 使用 App Store Server API 它不依赖于使用其他 API 的特定版本 就 App Store Server Notifications 而言 它可以与 Version 1 或 Version 2 通知一起使用 我们建议使用 Version 2 因为它会在 订阅发生变化时 使用安全的 JWS 等格式通知你 Alex 将在本课程的这个部分 对此进行详细介绍 但是 你可以单独使用 App Store Server API 使用 Version 1 通知或完全没有通知 接下来 让我们讨论一下 在完成了我之前介绍的 迁移步骤之后如何处理新的购买 为了在使用原始 StoreKit 的设备上 支持新的购买 你可以在收到新收据时 将其发送到你的服务器上 并执行与我之前展示的 完全相同的步骤 同时收集新数据 使用新收据调用 verifyReceipt 并使用 latest_receipt 中的 新 originalTransactionId 获得解码的收据 将这些 originalTransactionId 与收据的 in_app 部分中的其他 originalTransactionId 相关联 以将你的交易信息分在一个组 然后 你可以获取新的 originalTransactionId 并根据需要调用 App Store Server API 例如 如果需要调用 Get All Subscription Statuses 端点 以获取相应订阅的最新状态 现在 我们已经介绍了 如何将 App Store Server API 与原始 StoreKit 和 StoreKit 2 一起使用 那么让我们深入了解签署 JSON Web Tokens 的一些细节 这是调用 App Store Server API 的要求 为了验证你的开发人员帐户 是 App Store Server API 的调用方 我们用JSON Web Tokens 也就是 JWTs 来验证请求 此令牌必须作为 服务器调用中的授权头 包含在每个请求中 JWT 由 header 有效载荷和签名组成 接下来 我们将讨论如何构造 特定于 APP 的 JWT
在这里 我们可以看到 JSON Web Token 是如何组成的 以及 header 和有效载荷的结构 令牌本身可以分为三个部分 由句点分隔 Base 64 编码的 header Base 64 编码的有效载荷 然后是签名 由 Base 64 编码的 header 和有效载荷组成 签名使用签名密钥 header 由这些字段组成 其中包含 有关如何对数据进行签名的元数据 这里的一个重要字段是密钥 ID 它是你在 App Store Connect 中的 私钥 ID 这需要与你用来签署 JWT 的 密钥相匹配
有效载荷包含有关 特定 App 的附加信息 有关如何获取 API 密钥的 其他信息和指导 请参阅文章 “Creating API Keys to Use With the App Store Server API ” 关于每个字段的详细信息 请参阅文章“Generating Tokens for API Requests”
一旦获得了包含所有适当信息的 header 和有效载荷 接下来将使用与 keyId 对应的证书 对 JWT 进行签名 这是你可以使用的核心伪代码 无论使用何种语言 首先 确保你拥有与我们刚才查看的 header 中提供的密钥 ID 相对应的私钥 然后 用你的私钥 header 和有效载荷 调用你的 JWT 库公开的签名函数 由于 header 包含签名算法 JWT 库根据提供的算法对其进行签名
最后 下面是在验证对 Get All Subscription Statuses 端点的 cURL 调用时该令牌的用法示例 用你生成的令牌值 和所需的 OriginalTransactionID 值 分别替换 $ 和 $ 接下来 让我们谈谈如何验证 你收到的签名交易 是为你所用 并且是由 App Store 签名的 签名交易本质上 是 JavaScript 对象表示法或 JSON 这些对象是经过加密签名的 如果在 App Store 和服务器之间被篡改 你可以检测出来 签名交易是以 JSON Web Signature 或 JWS 格式签署的 App Store 发送给你的签名交易 将以 JWS 格式送达 通过验证你收到的 JWS 你可以验证数据 是否来自 App Store 且内容是否未被篡改 现在 让我们看看如何验证签名交易 首先是 Base 64 解码 header 然后 可以通过算法声明 确定使用哪种签名算法 这将作为验证 JWS 的一部分 X5c 证书中的证书链 是由 Apple 颁发的 证书的验证表明数据 已正确签名且未被篡改 有关如何验证 JWS 的更多信息 请参阅 App Store 开发人员文档 本质上 x5c 链是一个证书链 证书链的成功验证表明 数据是可信的 并且数据是由 Apple 签名的 顺序对证书链很重要 首先是根证书 此根证书之后可能会有其他证书 其中每个证书都由前一个证书签名 我将链中的最后一个证书 称为叶子证书
第一个证书称为根证书 是自签名的 此证书应与你从 Apple 证书颁发机构 获得的根证书相匹配 如果证书不匹配 则该链不应被信任 叶子证书是证书链中的 最后一个证书 是用于签署 JWS 的证书 下面是 App Store 发送的 JWS header 的一个示例 首先是用于签署 JWS 的算法 接下来是 x5c 证书链 证书按顺序列出 现在 让我们从高层次的角度来看 生成 x5c 证书链 是什么样子的 我们从 Apple 证书颁发机构的 根证书开始 然后使用根证书 对中间签名证书进行签名 接着使用中间签名证书 对叶子证书进行签名
现在我们已经介绍了 生成 x5c 证书链的过程 接下来让我们看看验证链的过程 从叶子证书开始 我们确保它是由 中间签名证书签名的 然后 我们确保中间签名证书 由根证书签名 此外 根证书应与 Apple 证书颁发机构 提供的证书相匹配 如果所有这些步骤都成功 则整个链被验证为合法 我们来讨论一下验证证书链的方法 下面是使用 OpenSSL 验证 x5c 证书链的命令 大体上讲 verify 命令 将其分解为几个部分 允许你传入证书进行验证 trusted 标志 允许你提供可信任的证书 换句话说 该证书将用于验证以下证书 在这种情况下 我们传入的是 你从 Apple 证书颁发机构 获得的根证书 因此是可信任的 我们将用它来验证 WWDR 证书 这是证书链中的下一个证书
untrusted 标志允许你使用信任的证书 提供要验证的一个或多个证书 这里 我们首先从 Apple 证书颁发机构 传入 WWDR 证书 该证书由根证书签名 这应该与 x5c 链中的 第二个证书相匹配 最后 这里的叶子证书 是最后一个证书 由前一个证书签名 如果验证成功 则返回成功代码 然后 你可以继续使用解码后的信息 如果验证失败 请根据返回的错误代码确定问题 如果无法验证 此数据可能被篡改 不应使用 有关使用 OpenSSL 验证 x5c 证书链的完整说明 请参考 App Store 开发者文档 这里有一些关于如何验证 签名交易的伪代码 首先 获取你想要验证的 JWS 然后 获取 JWS 库验证所需的证书 使用适当的证书 调用 JWS 库的 verify function 签署 JWS 的证书是叶子证书 尽管有些库需要传递整个链
如果调用成功 则可以继续执行任务 如果这是调用 App Store Server API 的结果 则可以继续存储已验证的数据 至于通知的情况 Alex 将在他的视频部分 进行更多的讨论 如果 JWS 无法验证 请不要使用 JWS 这可能意味着它已被篡改 或者不是由 App Store 发送的 Alex 将深入探讨如何在使用通知时 更好地确保安全性 有关验证和处理 JWS 的完整说明 请参考 App Store 开发者文档 现在 让我们回顾一下 从 verifyReceipt 迁移到 App Store Server API 的 一些用例 首先 让我们看看你想要检查 任何给定订阅者的最新状态 这使你可以随时了解 单个订阅的任何更改情况 以前 要获取订阅者的最新状态 必须调用 verifyReceipt 并根据到期意图 宽限期 到期日期等字段确定订阅的状态 现在 使用 App Store Server API 可以调用 Get All Subscription Statuses 端点 来获取订阅的最新状态 其中的状态字段包含当前状态 以及最新的签名交易和续订信息 让我们来看看如何执行这一流程 首先 对于你拥有的 任何解码后的收据 你可以按照我之前展示的方式 从中获取 originalTransactionId 然后 可以调用 originalTransactionId 的 Get All Subscription Statuses 端点 该端点将返回 该交易的最新签名交易和续订信息 接下来 我们来看获取最新交易的案例 获取最新的交易信息会通知你 用户购买了哪些内容 续订了哪些内容 用户的订阅是否有任何更改等 以前 要获取用户的最新交易信息 必须调用 verifyReceipt 并使用 in_app 数组 并检查 Latest_Receipt_INFO 其中包含用户的所有交易 使用 App Store Server API 获取最新的交易 Get Transaction History 端点 允许你获取用户的 完整购买历史记录 此外 分页与 WWDC22 演讲 “What's new with in-app purchase”中 介绍的新的筛选和排序功能相结合 确保你可以高效地准确获取 所需的数据
让我们来看看可能需要的流程 对于属于该用户的任何 OriginalTransactionID 你可以调用 Get Transaction History 端点 该端点将该用户的交易历史记录 作为签名交易返回 并根据你的规范进行 筛选 排序和分页
最后 我们看看采用 appAccountToken 的情况 appAccountToken 字段允许你 提供一个 UUID 将 StoreKit 2 交易与用户关联起来 然后 在签名交易 签名续订 和该交易的通知上 将出现 appAccountToken 以前 原始 StoreKit 不支持 appAccountToken 因为这是 StoreKit2 的新功能 现在 我们在原始 StoreKit 的 applicationUsername 字段中 增加了对提供 UUID 的支持 以支持与 Original StoreKit 客户的兼容 在这种情况下 UUID 将支持 appAccountToken 的所有功能 然后 appAccountToken 以 verifyReceipt 的形式 返回给 Original StoreKit 用户 并在调用 App Store Server API 和 App Store Server API 的通知中 显示给原始 StoreKit 和 StoreKit 2 用户 本课程的 App Store Server API 部分 到此为止 接下来 Alex 将介绍迁移到 App Store Notifications Version 2 的内容 Alex: 谢谢 Gabriel 我是 Alex 很高兴今天能在这里 讨论 App Store Notifications Version 2 首先 我们将讨论如何使用 Version 2 通知 接下来是 Version 2 通知的不同之处 以及如何构建在其他可用模型的基础上 第三 我们将讨论 在错过通知的情况下进行修复 以及一些有助于 完成这项任务的新资源 最后是 通知如何提供 对顾客行为的洞察 并为了解订阅生命周期 创造更多机会 让我们简单介绍一下什么是通知 以及谁可以使用它们 App Store Server Notifications 是 我们在 App 用户执行某些操作时 向你发送的消息 这些通知大致分为两类 订阅更新和退款更新 虽然我们一直在努力覆盖其他场景 我们提供这些通知 以帮助填补你在 App 中 可能无法执行的用户操作的空白 例如 我们最常见的一个用例 是订阅的续订 当此交易可用时 用户可能不在 App 中 订阅更新时 App Store 服务器通知 通过主动将最新的交易信息 直接发送至你的服务器 来帮助解决这个问题 Version 2 通知与 StoreKit 2 模型 以及 Gabriel 刚刚讲的 App Store Server API 有很多相似之处 然而 虽然它们可以很好地协同工作 但它们都是 可以在不同时间使用的独立工具 最重要的是 你可以 继续支持 StoreKit 2 不可用的客户端 iOS 15 之前的客户端 同时使用 Version 2 服务器通知 我们已经努力使 Version 2 通知成为了 我们最深入 灵活的工具之一 用于在整个订阅生命周期中提供 有关用户的信息 我们将在稍后的演示中 更深入地讨论该问题 但通知提供的信息也可以抓取 应用程序之外执行的操作 我希望我已经引起了你对通知 尤其是 Version 2 通知的概念的兴趣 在我们深入讨论之前 虽然这个演示文稿 能引导你了解接收通知的入门 及最佳解决方案 但它并不能说明全部情况 请参阅近期的一些视频 了解有关通知以及它们 如何满足各种用例的更多信息 我们来看看如何设置 Version 2 通知 我们将逐步了解如何设置通知 直到接收你的第一个通知 首先 转到 App Store Connect 中的 应用页面 向下滚动 你会看到一个 App Store Server Notifications 的部分 大家会看到生产和沙盒的选项 每个环境都可以包含一个单独的 URL 和一个单独的通知版本 下面是用于 产品设置选项页面的示例 沙盒设置是完全相同的 特别是 如果你是 Version 1 通知的用户 我们建议你首先在沙盒环境下 尝试 Version 2 通知 这是在不影响产品设置的情况下 熟悉通知的好途径 选择 Set Up Sandbox 按钮 提供服务器的 URL 然后选择 Version 2 Notifications
在触发通知之前 请确认你的服务器端点 有一个有效的 HTTPS 证书 还要确认你已允许 Apple 的 公共 IP 访问你的服务器 在设置通知时 一些最常见的故障 与防火墙和证书有关 作为初始故障排除步骤 这些也非常适合检查 你是否突然停止接收通知 现在你已准备好接收第一个通知了 在沙盒中 可以通过多种操作来触发通知 例如购买应用内订阅 然而 为了便于在测试时使用 我们建议使用新的 Request a Test notification 端点 来触发通知 这是 App Store Server API 的一部分 该端点有助于自动化通知测试过程 触发 Request a Test Notification 端点后 你应该很快就会收到通知 如果你在接收通知方面遇到问题 请参考新的 Get Test Notification Status 端点 该端点可以提供有关 通知未能传递原因的简要状态 例如 SSL_ISSUE 这样的状态 可能就是提示再次检查你的 HTTPS 证书 我们建议在执行配置更改时 触发测试通知 这是确认你在更改后 仍能收到通知的 好方法 现在 让我们继续了解 你刚刚收到的通知
就像我们之前从 Gabriel 那里 看到的交易一样 通知也是 JWS 格式的 让我们来看看如何解码 及验证通知有效载荷 首先 收到通知时 你希望提取 JSON 正文的 signedPayload 字段 接下来 你将执行与前面 Gabriel 介绍的完全相同的步骤 来验证签名交易 你将按照相同的步骤 来验证签名数据 无论它是来自通知的 签名通知有效载荷 还是来自 App Store Server API 的签名交易 接下来 重要的是要验证通知 是针对哪个 App 的 如果你有多个应用程序 共享同一个端点 那么这是确定目标 App 的好方法 同样重要的是 要确认 通知针对的 App 是你的 App 而且通知针对的不是其他开发者 最后 一项更实用的检查是确保 通知的环境与你的预期环境相匹配 无论是生产环境还是沙盒环境 由于 App Store Connect 允许 每个环境使用单独的 URL 因此可以强制执行此要求 或者 如果 URL 是共享的 要保证你是基于环境单独存储 和处理通知 此时 JWS 已完全验证 并可以存储以供进一步处理 除了一些基本检查外 我们建议你的服务器异步处理通知 如果通知的处理时间过长 我们的服务器将记录超时 并假设通知未成功传递 然后我们将重新发送通知 因此 将耗时的处理移到此功能之外 有助于确保 App Store 服务器 将你的通知 记录为成功发送 并且重试时 无需服务器再重新处理通知 现在 我们回顾一下 验证后的通知正文 第一个字段是 通知类型和可选子类型 结合在一起之后 它们将告诉你通知适用的场景 这些字段还有助于显示 自上次通知以来发生了哪些更改 并提供有关 发生这些更改原因的信息 notificationUUID 是 每个通知的唯一标识符 如果服务器重试通知 则重试通知包含 相同的 notificationUUID 这有助于检测服务器处理通知 但没有及时响应成功的 HTTP 响应代码的情况 我们建议基于此字段添加 由于重试导致的 重复通知检测 signedDate 字段告诉你 通知是何时创建的 这对于检测重试通知特别有用 接下来是 appAppleId 和 bundleId 这些对于检测目标应用程序很重要 正如我们前面所讨论的 检查这些字段并确认它们 与预期值匹配是很重要的 以防止重放攻击 此外 确保通知的环境 与预期的环境相匹配 沙盒通知不会被记录为 生产数据 反之亦然
最后 实际的 signedTransactionInfo 和可选的 signedRenewalInfo 这将是签署时的 标的购买的最新状态 此时 解析完通知后 你只剩下最新的交易和更新信息 以及状态更改的最新原因 既然我们已经介绍了 特定通知的设置和接收 我们通过与 Version 1 通知的比较 来测试 Version 2 通知模型 通知如何组合在一起 来跟踪订阅生命周期 以及Version 2 通知背后的设计决策 Version 2 在发送有关购买状态的信息时 采用了不同的原理 与每次通知都发送所有 最近的历史记录不同 版本 2 的通知只专注于 发送最新的信息 即最新的交易信息 订阅的情况 还有待续订信息
通过通知 我们可以提供 关于订阅生命周期的每一步的信息 因此 通知只包含关于 最新的购买或订阅的信息 这些通知一起创建了 订阅状态的完整时间线 如果你需要查看整个交易历史记录 但无权访问通知历史记录 则可以使用 Get transaction history 端点 它能让你在分页和可筛选的上下文中 查询用户的整个交易历史记录 第二 Version 1 通知不需要 客户端使用 StoreKit 2 没错 Version 2 也是如此 事实上 无论客户端使用什么框架 你都可以从今天开始 享受 Version 2 通知的优点 最后 Version 2 通知通过添加其他的类型 以及添加新的子类型字段 来提高所提供的详细程度 并扩展所涵盖的案例 通过这种方式 我们能够覆盖更多的场景 并在订阅生命周期的每个步骤中 提供通知 我们添加的一些值得注意的场景 包括到期 与自动续订状态更改相关的 更详细的信息 以及与退款流程相关的更多场景 现在 为了说明所涵盖场景的复杂性 并提供一个更具体的示例 让我们从头到尾看看通知是如何 通知订阅所采取的 每个步骤的 让我们想象一个订阅前的用户 订阅后 用户进入续订订阅状态 并发送带有子类型 INITIAL_BUY 的订阅通知 或者如果使用了报价 则发送 带有子类型 INITIAL_BUY 的 OFFER_REDEEMED 通知中包含第一个签名交易 以及签名续订信息 时间流逝 订阅更新 保持更新状态 每次续订时 我们发送一个包含 下一个签名交易信息的 DID_RENEW 通知 每当用户取消自动续订时 他们就会进入即将到期的订阅状态 那么将收到一个子类型为 AUTO_RENEW_DISABLED 的 DID_CHANGE_RENEWAL_STATUS
如果他们不启用自动续订 那么到期后 他们就会进入过期状态 你将收到带有子类型 VOLUNTARY 的 EXPIRED 现在 你可能会疑惑 其他所有的通知类型在哪里呢
下面是通过通知看到的 订阅生命周期 有很多在进行 这张图还不能说明全部 例如 这里不包括退款 撤销生命周期 这个图表说明了 Version 2 通知 所涵盖的大量场景 它们可用于通知你 订阅生命周期的每个步骤
我要说的另一点是我们努力包含 所有可能的过渡状态 这有助于通过 成为跟踪订阅的单一来源 来提高通知的效用 并提高你看到 订阅者使用历程的信心 然而 即使所有数据都在这里 你也不需要使用所有可用的类型 例如 即使只是处理 与续订偏好更改相关的通知 也可以提供价值 特别是 如果各位刚刚开始 那么请从对自己的情况 最有用的通知类型开始 现在 我们讨论一下 设置好服务器后会发生什么 一切都很顺利 但是 唉 服务器罢工了 不管是几天 几分钟 还是你认为你可能只错过了一分钟 让我们通过一些步骤来帮助 解决此问题 我们来想象一下你的服务器 它已成功设置 并且正在接收通知 在某些情况下 服务器出现问题 无法接收通知 我们仍试图向你的服务器发送消息 但现在这些请求开始失败了 有几种方法可以处理这种情况 首先就是等待 如果我们没有从你的服务器 收到成功的状态代码 或根本无法连接到它 我们将根据记录的重试策略 来重试通知 对于 Version 2 通知 我们在每次尝试后重试 首先延迟 1 小时 然后延迟 12 小时 延迟 24 小时 48 小时 最后延迟 72 小时 对于 1小时内的中断来说 等待非常有效 因为通知将在首次故障 1 小时后重试
在某个时刻 服务器恢复了 你开始再次接收通知 首先 你会收到一个 与错过的通知无关的新通知 通知会延迟重试 所以一旦你的服务器上线 并不会立即收到所有错过的通知
一段时间后 你开始收到错过的通知 并穿插着新的通知
这就产生了一个问题 那就是如何检测通知 是原始通知还是重试通知 让我们检查一个通知
在这个通知里 我们只显示了几个字段
通知包含一个 signedDate 字段 通过比较签名日期 与收到通知的时间 这个字段可用于检测重试 如果你看到签名日期 明显早于你收到通知的日期 这表明你可能遇到了中断
想象在这种情况下 标记为 6 和 3 的通知 是针对同一个订阅的 这可以通过比较 originalTransactionIds 来确定 在这种情况下 仅仅因为通知 3 是在通知 6 之后收到的 并不意味着它包含 比通知 6 更新的信息 其他时候 你的服务器 可能已收到通知 但它未能响应成功的 HTTP 200 状态代码 这可能会导致通知 重新发送到你的服务器 如前所述 请确保检查 notificationUUID 字段 以重复这些请求 即使你成功记录了通知 也可能会看到大量的重试通知 在这种情况下 确保每次 收到通知时都使用 HTTP 200 响应来回应 此外 确保及时地这样做 并且在成功响应之前 没有进行大量处理 以防止我们记录超时 并重新发送通知 有时 尤其是较长的中断 下一次重试可能在数小时或数天之后 或者对于较长时间的停机 可能已无法重试 从错过的通知中恢复的下一个选项 是 Get Notification History 端点
我们刚刚介绍了新的 Get Notification History 端点 它提供了我们发送给你的服务器的 六个月的通知历史记录 请参阅视频 “What's new with in-app purchases” 了解这个端点 以及我们介绍的其他很棒的功能 在这里 我们将重点介绍 使用此端点时的最佳实践 以及它可以提供帮助的场景 故障解决后 请注意故障的开始和结束时间戳 Get Notification History 端点 允许在特定的时间范围内进行查询 通过指定中断的开始和结束时间 你可以只处理可能错过的通知 而不需要翻阅整个历史记录 这将有助于提高恢复速度 并减少重新处理已记录通知的工作 接下来 Get Notification History 端点 允许你根据通知的类型进行筛选 如果你经历了长时间的中断 并预计会收到大量通知 请考虑按类型过滤 并从可能产生直接影响的类型开始 如 DID_RENEW 和 EXPIRED 这些将帮助你首先 对最相关的案例采取行动 在传递通知类型时有一个提示 如果忽略 notificationSubtype 字段 将只返回同样没有子类型的通知 因此 对于 DID_RENEW notificationType 所显示的示例 它不会返回子类型为 BILLING_RECOVERY 的 DID_RENEW 通知
最后 Get Notification History 端点 允许使用 originalTransactionId 过滤到特定用户 回顾订阅生命周期 我们努力确保通知 覆盖用户使用的每一步 因此 如果你发现自己的程序 以意想不到的方式跳跃 例如从更新订阅直接跳到过期 这可能表明你错过了该用户的通知 在顾客支持环境中 如果用户帐户 处于与你的预期不同的状态 这也很有用 在这些情况下 你可以发送一个 查询该用户的通知历史记录
让我们回顾一下 Get Notification History 端点的响应 为简单起见 响应中仅显示某些值
响应中恢复的值 在 notificationHistory 数组中
数组中的每个条目都表示一个通知
签名有效载荷字段 包含发送给你的确切通知
其次 我们有第一个 sendattemptresult 字段 该字段包含基于服务器记录的 初始通知尝试结果的几个值之一 在成功的情况下 这个值将是 SUCCESS 然而 正如我们刚才所讨论的 有时服务器无法收到通知 这些消息旨在作为一般指南帮助你 指出问题的方向 以简化解决过程 例如 我们在这里看到 SSL_ISSUE 这表明服务器上的 SSL 证书 或进程有问题 除了看到通知未到达外 此字段还提高了 诊断服务器问题的可见性 我们还在 Get Test Notification Status 端点中 提供了相同的字段 这些可用于在引导流程 或故障排除期间提供帮助 或在追溯确定中断的 根本原因期间提供帮助 通知或许不能涵盖 用户历史记录的所有情况 你可能刚刚采用了通知 并有历史记录未覆盖的现有用户 你还可能希望在 Get Notification history 端点中 检查比通知保留周期更长的 历史记录 这就是 Get Transaction History 端点的作用所在 正如我们之前在 Gabriel 的 演讲中看到的那样 此端点通过在你开始使用通知之前 为你的顾客 提供涵盖案例的历史记录 来解决这些问题 现在 我们来看看通知如何提供 超越购买历史记录的洞察和机会 Version 2 通知中新增的内容之一 是子类型字段 它向 notificationType 字段 添加了额外的环境 该字段用于在某些场景中 提供更详细的信息 比如 EXPIRED 或 DID_CHANGE_RENEWAL_STATUS 例如 使用 EXPIRED 你所采取的操作通常是相同的 将订阅标记为⾮活跃状态 并撤销对产品的访问权限 但是 了解用户过期的原因通常很有用 是由于账单问题 自愿选择 还是接受不了的涨价 另一个通知 DID_CHANGE_RENEWAL_STATUS 是在使用通知时获得额外信息 和机会的一个很好的例子 从表面上看 它的优先级似乎不高 不需要立即采取行动 撤销产品访问权的重要通知 是 EXPIRED 通知 别被骗了 这里有很多机会 第一 此通知是尝试 在订阅到期之前 赢回顾客的绝佳机会 特别是由于停用自动续订 可能发生在应用程序之外 这可能是在到期日期前 续订状态更改中 被通知的唯一触发器 此通知还提供对顾客行为的洞察 此通知可用于确定订阅者 在续订期间何时取消 是续订的前一天吗 新订阅者是否会在注册你的服务后 立即停用自动续订呢 此类信息对于了解取消的原因 以及改进你的产品非常重要 最后 在没有通知的情况下 某些场景可能永远不会 反映在用户的历史记录中 例如 用户可以在 订阅期到期之前停用 但随后重新激活自动续订 因为这一切都发生在订阅期内 所以不会对订阅的长期状态 产生影响 这些决策对于了解你的顾客 可能很重要 通知提供了检测 和记录这些类型场景的信息 总体而言 通知通过 在顾客使用的每一步提供信息 来增强和创造了解顾客行为的机会 覆盖比以往任何时候都多的场景 总之 今天我们已经介绍了 App Store Server API 和 App Store Server Notifications 这些功能可用于改进 管理和跟踪购买的功能 它们使用了更新的消息类型 覆盖了比以往任何时候都多的案例 这些系统可用于所有的客户 并与 Original StoreKit 和 StoreKit 2 交叉兼容 可以提高你 监控订阅生命周期的能力 最后 这些工具在沙盒和生产中 都是可用的 并且是任何系统的重要补充 谢谢你加入我们 祝你的 WWDC 之旅一切顺利
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。