大多数浏览器和
Developer App 均支持流媒体播放。
-
实现 App Store Offers
了解如何使用 App Store Connect 通过 App Store Offers 来吸引顾客,以及如何同时运用最新的 StoreKit 功能和 API。探索如何为 Mac App 设置赢回优惠 (重新吸引过往订阅者的全新方式),并生成优惠代码。此外,了解如何在沙盒和 Xcode 中测试优惠,以确保优惠能够顺畅运作。
章节
- 0:00 - Introduction
- 1:32 - Updates to offers
- 4:37 - Introducing win-back offers
- 7:10 - Configure win-back offers
- 16:50 - Support win-back offers
- 28:44 - Streamlined purchasing
资源
- Forum: App Store Distribution & Marketing
- Generating a signature for promotional offers
- Merchandising win-back offers in your app
- Message
- offer
- PurchaseIntent
- Setting up StoreKit Testing in Xcode
- StoreKit views
- Submit feedback
- Supporting subscription offer codes in your app
- Supporting win-back offers in your app
- Testing win-back offers in the sandbox environment
- Testing win-back offers in Xcode
相关视频
WWDC24
WWDC23
-
下载
大家好 欢迎观看 “实现 App Store Offers” 我是 App Store Connect 的 工程师 Xiaolan 大家好 我是 StoreKit 团队的 工程师 Ricky 今天 我们很高兴与大家分享 App Store 优惠的所有重大更新 以及如何利用这些功能吸引顾客 首先 让我们快速回顾一下 App Store 优惠 对于以订阅为基础的业务来说 留住顾客是取得长期成功的关键 App Store 优惠是 获取、保留以及 重新吸引顾客的好方法 通过 App Store 优惠 可在特定时限内 为符合条件的顾客提供 免费订阅或折扣订阅
App Store 中有三种优惠: 推介促销优惠、 促销优惠和优惠代码
设置推介促销优惠可以让新订阅者 有机会免费试用订阅或 以折扣价体验订阅
促销优惠则更加灵活 你可以创建独特的折扣促销活动 并根据自己的业务需求 确定相应的资格条件 对于优惠代码 你可以使用 App Store 为你生成的 一次性唯一代码 也可以创建自己的自定代码 通过自己的营销渠道分发 我们对订阅优惠 StoreKit API 推出了许多增强功能 包括 Transaction 和 RenewalInfo 新增 offer 成员 以及 macOS 新增对优惠代码的支持 借助 StoreKit 中的一些关键 API 你可以轻而易举地 为 App 订阅优惠提供支持 而我们要分享的一些增强功能 可以让这些 API 功能更强大
首先 我们增强了 StoreKit 和 App Store Server API 中的 Transaction API 和 RenewalInfo API Transaction 结构 对于了解顾客在 App 中的 购买行为非常重要 RenewalInfo 结构 可指示订阅状态的未来情况
在 Transaction 中 新成员“offer”是一种新类型 包含所有与优惠相关的信息 如优惠的 ID、 类型和 paymentMode paymentMode 可指明 优惠属于免费试用、 随用随付还是提前支付
offer 成员是可选的 这意味着仅当购买订阅的顾客 兑换了优惠时 StoreKit 才会 将 offer 成员包含在交易中
从 iOS 17.2 开始 StoreKit 中提供了这个新的 API 从 iOS 18.0 开始 RenewalInfo API 中 也将提供 offer 成员 如果订阅的下一个续订期 应用了优惠 StoreKit 就会填充 offer 成员
如果是使用 App Store Server API JWSTransaction 和 JWSRenewalInfo API 中的三个字段 也提供相同的优惠数据
在这三个字段中 offerIdentifier 和 offerType 是目前已有的字段 而 offerDiscountType 是新增字段 也可用于历史交易
offerDiscountType 的值 类似于 StoreKit API 中的 paymentMode 它可指明当前优惠属于免费试用、 随用随付还是提前支付
有关 App Store Server API 的 更多信息 请查看“探索适用于 App 内购买 项目的 App Store Server API”
接下来 如果 App 使用 StoreKit 视图来陈列订阅项目 那么有一个新的视图修饰符 可在 SubscriptionStoreView 对应的 UI 中 显示促销优惠
这个视图修饰符名为 subscriptionPromotionalOffer
使用这个新的视图修饰符 可决定视图是否应该显示促销优惠
StoreKit 会提供这个产品的 促销优惠列表 因此你可以将逻辑重点 放在决定返回哪个优惠上
然后为选择的优惠 生成签名并返回优惠 StoreKit 会在 UI 中 显示详细信息 如果顾客选择订阅 StoreKit 还会为购买添加优惠
有关支持促销优惠 和生成签名的信息 请查看本讲座的 相关文档
最后 macOS 15.0 现在 与 iOS 和 visionOS 一样 可展示优惠代码兑换表
在 SwiftUI App 中 你可以使用与 iOS 相同的 API 展示优惠代码兑换表
刚才介绍了我们为现有订阅优惠 提供的新 StoreKit API 今年 我们推出一种新的优惠类型 帮你重新获得以前的订阅者 我们很高兴推出赢回优惠
让你更轻松地触达 以前的 App 订阅者 你可以使用 App Store 提供的 顾客资格条件 设置赢回优惠 还可以利用 App Store 自有渠道 推广你的赢回优惠 赢回优惠专注于 在订阅者的订阅过期 并停用自动续订时 重新吸引流失的订阅者
与 App 中处理和验证 顾客资格的机制不同 有了赢回优惠 就可以通过 App Store 根据特定规则和条件来细分顾客 你可以有效地构建 顾客相关度更高的新优惠
与现有优惠一样 你也可以通过自己的营销渠道 推广赢回优惠
赢回优惠会自动出现 在顾客的“订阅”页面上 你可以在 App Store 上 推广赢回优惠 这里有一个例子 App Store 以卡片形式展示 新的赢回优惠 赢回优惠卡包含优惠说明、 价格详情、 以及优惠适用的订阅信息
顾客可在你的产品页面上 发现赢回优惠 App Store 会在这个页面上 显示符合条件的优惠
当顾客轻点优惠卡时 就会出现一个详细页面 其中包含更详细的描述 和更大的图片 详情页面为顾客提供 有关优惠的更多信息
我们的编辑团队 在编辑面向顾客的个性化推荐时 可能会在“Today”、“游戏” 和“App”标签页上 将你的赢回优惠列入编辑精选
最后 顾客可以在“订阅”页面 找到符合条件的赢回优惠 今天 我将深入介绍赢回优惠 带大家了解 App Store Connect 配置过程 然后 Ricky 将通过示例向大家展示 如何在 App 中 支持和测试赢回优惠 最后 我们将讨论简化购买体验 以及如何在 App 中支持这种体验
首先 让我们来详细了解 赢回优惠 与现有优惠一样 在创建赢回优惠时 可以选择随用随付、 提前支付或免费试用 根据不同的类型和订阅情况 可以选择不同的优惠期限 你可以控制何时向顾客 提供赢回优惠 还可以选择指定优惠结束日期 通过优惠优先级配置 你可以指定 是否在普通优先级活动和优惠之前 显示这个优惠 这也是 App Store 上 用于个性化设定 赢回推荐的因素之一 此外 你还可以决定哪些 特定国家和地区可以获得这个优惠 使用 App Store Connect 定价工具 可帮助你 为所选的每个国家或地区设定价格
赢回优惠支持不同的顾客资格条件 包括付费订阅时长、 上次订阅距今的时间 以及两次优惠间的等待期
付费订阅时长是指 顾客为你的服务付费的时间长短 通过设置这种条件 你可以 根据顾客的订阅时长提供折扣
你可以指定以月为单位的最小值
只有最近连续订阅的付费服务月份 才会纳入计算范围
付费订阅时长包括 顾客在一个订阅组内 订阅任何项目的时间 同一订阅组中的升级和降级 不会影响资格计算
上次订阅距今的时间 表示最近一次有效订阅后 已过去的时间 需要以月为单位 来指定最小值和最大值 这样 你就可以 根据流失顾客的退订时长 采用不同的策略 来重新吸引他们
让我用一个例子来详细解释一下 我们的“Destination Video”App 有一个名为 Streaming Pass 的 订阅组 提供两种月度方案: Basic 和 Premium
这项赢回优惠可让符合条件的顾客 免费使用 Basic 订阅一个月 为了符合获得这项优惠的条件 顾客必须已连续支付订阅费用 至少三个月 顾客的订阅必须在 过去 2 至 24 个月内处于活跃状态 而且自顾客上次兑换这个优惠起 至少已过去 6 个月
让我们从顾客的角度来看看 一开始 顾客订阅了 Premium 方案
后来降级到 Basic 方案
最后 两个月后顾客取消了订阅 这时 这位顾客已经满足了 这项赢回优惠的付费订阅时长 资格要求
在顾客取消订阅后 我们就可以开始计算 上次订阅距今的时间
两个月后 顾客有资格获得赢回优惠 因为我们已将上次订阅距今的 最短时间设置为两个月
现在我们来谈谈两次优惠间的等待期 这是一项可选要求 可设置顾客再次兑换优惠前 必须等待的最短时间
赢回优惠期结束后 开始计算两次优惠间的等待期
后来 顾客续订了这个订阅项目
三个月后 顾客取消了订阅
取消后开始计算上次订阅 距今的时间
取消两个月后 顾客满足了上次订阅 距今的时间这项要求 但是 由于顾客之前 已经兑换过优惠 而优惠之间至少需要等待六个月 因此在优惠结束六个月后 这位顾客才有资格享受赢回优惠
刚才 我大致介绍了赢回优惠 以及顾客资格条件的运作机制 下面 我们在 App Store Connect 中 设置赢回优惠
要为现有订阅创建赢回优惠 首先要导航到订阅定价页面
这个页面上有一个新标签 名为“Win-Back Offers” 首次点按这个标签时 系统会显示类似这样的页面 点按“Create Offer”按钮 可开始配置新的赢回优惠 这时会出现一个模态视图 第一步是输入优惠的参考名称 以及优惠标识符 这两个字段在你的 订阅组中必须是唯一的 App 在与 StoreKit API 通信时 会使用优惠标识符 创建这些字段后就无法修改 按照统一的命名惯例为优惠命名 以便简化开发工作 下一步是选择 开始日期和结束日期、 优惠优先级以及确定顾客资格条件
要在 App Store 发布优惠 需要提供开始日期
你可以随时调整优惠优先级 最后 指定顾客资格 以便系统根据这些条件 判定顾客何时有资格获得优惠 你可以在优惠生效前 调整所有这些设置 但在优惠开始日期后 这些设置将被锁定
下一步 你可以选择 提供优惠的国家和地区 然后 选择优惠的类型是随用随付、 提前支付还是免费 接下来 选择持续时间
如果是付费优惠 还要从下拉菜单中选择 基于默认货币的价格 使用选择的价格 App Store Connect 会为你 提供多个最佳价格 与你为这个优惠选择的 每个国家和地区相匹配 你可以点按各自的 下拉菜单进行调整 创建优惠后 优惠价格设置无法更改
最后 你可以查看并确认 赢回优惠详情 如果你想更新设置 请点按返回按钮 重新查看之前的步骤
如果配置无误 请点按“确认” 完成新优惠的创建
现在你的赢回优惠已经创建好了 你可以通过自己的营销渠道 和 App Store 推广这个优惠
在这里 我们还提供一个优惠链接
以便你通过自己的 营销渠道发布优惠
如果你想在 App Store 上 推广你的赢回优惠 则需要为订阅配置一些设置详情
在优惠详情页面 有一个部分名为 “Promote on the App Store” 如果你的订阅没有图片 你就会看到这个部分 点按这里的链接 为你的订阅上传图片
然后 进入订阅详情页面 将图片提交给 App Review 团队
一旦订阅图片通过审核 而且你已经为优惠启用了 App Store 推广 赢回优惠生效后 就会在 App Store 自动进行推广
如果优惠尚未生效 你可以取消优惠 不在 App Store 上进行推广 但是 赢回优惠生效后 必须删除赢回优惠 才能让优惠不再显示在 App Store 上
在 App Store 上 已推广的赢回优惠 会以新优惠卡的形式 显示在详细视图中 我们会将已批准的订阅图片 和 App 图标组合在一起 创建一个新图片 就像这样
这就是如何在 App Store Connect 中 为订阅设置赢回优惠 App Store Connect API 3.6 提供了丰富的资源 让你可以按照自定流程 设置赢回优惠
新的 WinBackOffers API 包括 创建、读取、更新 和删除赢回优惠的端点 你可以使用这些 API 轻松 管理优惠流程 我们还为订阅和 inAppPurchase 添加了两个新的图片资源 同时 我们还弃用了现有的 PromotedPurchaseImages 资源 对于如何在 App Store Connect 中 设置赢回优惠 相信大家已有所了解 下面 Ricky 将讨论如何使用 StoreKit 2 为赢回优惠提供支持 感谢 Xiaolan 为我们讲解 如何在 App Store Connect 中 配置赢回优惠 下一步是使用 StoreKit 2 在 App 中添加代码 以支持这些新优惠 首先 让我们回顾一下如何区分 赢回优惠 和其他现有优惠类型 StoreKit 2 使用 OfferType 模型 来标识 SubscriptionOffer 类型 支持的类型有: 推介促销优惠、促销优惠 以及从 iOS 18.0 开始的赢回优惠 App 中优惠的定价和持续时间 可在产品模型下的订阅信息中找到 其中每个可用优惠类型都有成员: 适用的推介促销优惠、 促销优惠列表以及 从 iOS 18.0 开始 提供的赢回优惠列表 在 App 中构建对优惠的支持时 这些信息非常重要 可帮你判断 SubscriptionOffer 对象是哪种优惠 并获取为订阅配置的 特定优惠类型的信息 现在 我们看一下如何 为使用赢回优惠的订阅 提供订阅陈列和购买方面的支持
StoreKit Message API 是向顾客展示赢回优惠的 最快速、最简单的方法 StoreKit 视图提供了各种选项 可帮助你构建出色的陈列 UI 并显示订阅以及 任何优惠的详细信息 最后 如果你希望进一步掌控 订阅陈列和 UI 可以使用核心 StoreKit 2 API 你可以根据想要实现的自定程度 选择其中一个或多个选项
当 App 收到 winBackOffer 消息时 StoreKit 会向顾客 展示类似这样的表单 详细说明订阅和优惠价格 顾客可以使用下面的按钮 选择接受优惠并 重新订阅服务
为了支持这种体验 Message API 现提供一个新 Reason 名为 winBackOffer
当顾客有资格获得赢回优惠时 App 会自动接收这条消息
请确保你也在 App 中 侦听交易动态 这样你就可以收到购买通知并授予 访问解锁内容的权限
之后 你就可以进入 iOS 沙盒账户设置 在沙盒中测试赢回优惠 启用“Display Win-back Offers” 开关 以便在有资格获得新优惠时 在 App 中收到相应的消息
我们介绍了如何在 iOS 18.0 中 使用 StoreKit Message 在 App 中支持赢回优惠 以及如何在沙盒中进行测试
如果你希望提升陈列 UI 的 自定程度 我们在 WWDC23 上为大家展示了 如何使用 StoreKit 视图 这些精美的现成 API 可帮你 更好地显示和陈列 App 内购买项目 StoreKit 视图在顾客符合条件时 自动支持 在 SubscriptionStoreViews 中 显示所有订阅优惠的 定价详情 包括赢回优惠 因此无需额外工作 有时 一位顾客可能有 多个符合条件的优惠 你可能需要运行一些额外的逻辑 来确定应该在视图中显示哪项优惠 为此 我们在 StoreKit 视图中 新增了一个视图修饰符 名为 preferredSubscriptionOffer
将 preferredSubscriptionOffer 与 SubscriptionStoreView 搭配 这样 有多项可用优惠时 就可以控制应该使用哪项优惠 StoreKit 会负责获取优惠元数据 并完成购买设置
下面看看如何将这个新的视图修饰符 与 SubscriptionStoreView 相结合
为了陈列“Destination Video”App 中提供的订阅方案 我使用 Streaming Pass 方案的 订阅组 ID 设置了一个 SwiftUI 视图 SubscriptionStoreView 会自动显示可用优惠详情 例如这个月度订阅方案 在这里 你可以看到 StoreKit 会自动选择优惠的定价
添加 preferredSubscriptionOffer 修饰符 可检查任何其他可用的优惠 并确定要显示哪项优惠
preferredSubscriptionOffer API 只需一个参数 那就是 StoreKit 为组中 每项订阅调用的函数 在这个函数中 StoreKit会提供 产品对象、 订阅信息 以及顾客当前有资格获得的 所有优惠的列表
这就是你需要从 StoreKit 提取的 所有信息 在此基础之上 你可以运行自己的业务逻辑 确定要使用哪种优惠 选定优惠后 这里会返回 SubscriptionOffer 对象
请记住 如果返回的是 nil 而顾客有资格获得 订阅的推介促销优惠 App 就会在视图中 始终显示推介促销优惠 在本例中 我会查找提供 最长免费试用期的优惠 如果没有免费试用优惠 我会选择列表中的 第一项优惠 在 App 中 你可能希望 根据优惠的定价和持续时间 在这里添加更多逻辑 由于顾客有资格获得按月订阅的 三个月免费试用优惠 你可以在 SwiftUI 视图中 看到新的定价详情
这就是如何自定 SubscriptionStoreViews 向顾客显示不同的优惠 如果需要更好地控制 订阅的陈列体验 或者想要创建自定 UI 你可以使用核心 StoreKit API 自行管理优惠陈列
前面介绍了 在产品模型中 可以从何处查找优惠详情 但赢回优惠的资格问题 因顾客而异 Xiaolan 向大家展示了如何在 App Store Connect 中配置这种资格
为简化操作并帮助你 向顾客显示正确的优惠 StoreKit 推出了一个新 API 可向每位顾客提供个性化的优惠列表 显示符合条件的赢回优惠 这个 API 名为eligibleWinBackOfferIDs
你可以在订阅状态模型的 RenewalInfo 对象中 找到这个新的 API 还可快速访问 ID 列表 了解顾客能够立即兑换的 赢回优惠有哪些 使用这个列表可在订阅信息中 搜索相应的优惠 并在视图中显示定价详情
我将演示如何使用这些新 API 在“Destination Video”中添加 对赢回优惠的支持 根据我的 App 现有的逻辑 向顾客显示任何陈列内容之前 App 会先检查订阅状态 以及是否符合推介促销优惠 的资格条件 为了实现这一点 我使用这个函数 来确定顾客当前的订阅状态 以及顾客是否有资格获得任何优惠 这个函数需要两个参数: 需要检查状态的订阅 所对应的组 ID 以及产品 ID 列表
首先 获取订阅的当前状态
然后 使用之前创建的数据结构 进行解析 确定顾客是否有权使用服务 以及是否启用了自动续订功能
有了这些信息 我就可以确定是否需要 使用这个枚举来显示任何陈列 UI
如果顾客启用了自动续订功能 就会返回一个标志 表明不应显示任何陈列内容
如果顾客当前没有订阅 那么就可以显示陈列 UI 在这种情况下 我会首先载入 我想要陈列的 订阅产品 然后 我需要确定顾客是否 有资格获得推介促销优惠 如果有获得优惠的资格 则返回订阅产品和优惠 并在视图中显示相应的信息
如果顾客没有资格 获得推介促销优惠 我可以查看之前检索到的订阅状态 看看顾客是否有资格获得赢回优惠
由于赢回优惠只适用于 不再订阅这个产品的顾客 因此我需要查看 顾客过往订阅的状态 因为顾客也许还可以通过家人共享 访问服务
赢回优惠资格 可以在这个订阅状态的 续订信息中找到 有了这些信息 我就可以查找最佳赢回优惠 ID 通常是列表中的第一个对象 但如果有多个优惠 你可能需要查看其他可用优惠 如果至少有一个赢回优惠 我就可以返回这个优惠 以及相应的产品供顾客兑换 要获得优惠详情 我需要创建视图 我可以在订阅信息的 所有优惠列表中 搜索 SubscriptionOffer 对象
如果符合条件的 赢回优惠 ID 列表为空 则表示顾客不符合任何优惠的条件 因此我可以显示包含常规订阅定价的 陈列视图
这就是如何 在现有订阅状态工作流中 检查顾客是否有资格获得赢回优惠 一旦顾客选择兑换优惠 你需要做的最后一件事就是 将赢回优惠添加到购买中
这样做很简单 在 iOS 18.0 中 你可以使用一个新的 PurchaseOption API 名为 winBackOffer
使用这个 API 可将表示赢回优惠的 SubscriptionOffer 对象 添加到购买中 然后将购买选项传递给购买 API StoreKit 在 App 中显示 付款单之前 App Store 会检查 顾客是否符合优惠资格
这就是在 App 中支持 赢回优惠的全部内容! StoreKit Message 是向顾客 显示赢回优惠的 最快捷选择 利用 StoreKit 视图 你可能不需要添加任何代码 这取决于你的具体情况 而且你还可以创建精美的 订阅陈列 UI 要进一步了解 StoreKit 视图 中的其他新功能 请观看 WWDC24 讲座“StoreKit 和 App 内购买项目的新功能” 如果需要为你的 App 和订阅服务 创建自定工作流和 UI 可在 SubscriptionStatus 和 SubscriptionInfo 中使用 新的 StoreKit API 查找适合 顾客的优惠并在你自己的陈列视图中 显示相应的优惠
在 App 中添加代码 支持赢回优惠后 你需要在不同的场景以及 不同的订阅状态下 进行测试 你可以在沙盒中测试 实现赢回优惠的所有支持方法 我之前讨论过如何测试 赢回优惠 StoreKit Message
如果你决定使用 StoreKit 视图、 核心 StoreKit API 或两者的组合 这些也可以使用 Xcode 中的 StoreKit 测试功能进行测试 这也是在开发 App 时 测试优惠的最快方法
这是 Xcode 中的新功能 可帮助你 立即在 App 中测试赢回优惠
要在 Xcode 中配置赢回优惠 首先打开 StoreKit 配置 在其中设置本地 App 内购买项目 然后在“Auto-Renewable Subscriptions” 标题下找到你的订阅 向下滚动到“Win-back Offers” 部分 你会看到一个表格
点按加号 (+) 按钮配置新优惠 然后输入所需详情: 优惠名称、
优惠 ID、
所有其他优惠类型 都需要的支付模式、
持续时间
以及适用的价格
在 App Store Connect 中 你可以根据不同的规则、 状态以及顾客在兑换优惠前 需要满足的条件 配置赢回优惠的资格 为了快速有效地 测试顾客资格的结果 我们在 Xcode 中添加了一个开关 用于更改每项优惠的资格 因此无需担心订阅状态和 其他资格条件
使用这个顾客资格开关 来确定流失的订阅用户 是否应在 App 中接收赢回优惠 在调试时更改这个开关的状态 测试不同情况下 顾客的优惠资格 看看 App 的反应如何
点按“Save”后 我就为这个订阅 设置了一项新的赢回优惠 要配置更多优惠 请根据测试需求使用不同的设置 重复这些步骤
就是这样 我现在可以开始 在 App 中测试赢回优惠了 Xcode 中的 StoreKit 测试功能 是测试订阅优惠的好工具 你可以快速测试 不同设置和顾客状态下的 赢回优惠 感谢 Ricky! 最后一个话题是关于我们 为赢回优惠添加的简化购买体验 我已经介绍了如何 在 App Store 上推广赢回优惠 推广赢回优惠时 顾客可以使用简化购买功能 在 App Store 上 一次性兑换优惠 并订阅服务 你的 App 默认启用简化购买 你可以通过 App Store Connect 配置相关设置
如果你在 App 中 对赢回优惠使用简化购买 当顾客轻点“订阅”按钮兑换优惠时 App Store 将显示付款单 顾客可以在付款单中查看 订阅和优惠的详细信息 一旦顾客确认并完成购买 顾客打开 App 就可以立即访问订阅服务 你可能需要顾客 在 App 中进行某些操作 然后才能继续购买和兑换赢回优惠 在这种情况下 你可以使用 App Store Connect 中的设置 关闭赢回优惠的简化购买 进入订阅页面 你可以 在“Billing Grace Period”下 看到一个配置简化购买的新部分 点按编辑按钮 你可以选择 关闭简化购买
如果关闭简化购买 App Store 会将购买直接 发送到你的 App 而你可以 在 App 内创建自定体验 为了支持这种体验 你需要在 App 中进行一些更改
如果你决定关闭简化购买 但仍想在 App Store 上 推广赢回优惠 你需要在 App 中设置一些代码 以接收顾客在 App Store 上 发起的购买 为此 可以使用我们在 WWDC23 讨论过的 PurchaseIntent API 当顾客在 App 之外开始购买时 App Store 就会发送购买意图 例如推广的 App 内购买项目 或赢回优惠 当你收到新的购买意图时 你可以立即继续推进购买流程 并显示付款单 也可以存储 这个意图以供日后使用
PurchaseIntent 可用于 接收顾客 在 App Store 上开始 兑换的赢回优惠 为此 iOS 18.0 和 macOS 15.0 提供了名为 offer 的新成员 这是一个可选的 SubscriptionOffer 类型 只有当购买意图包含赢回优惠时 才会填充这个类型
收到带有赢回优惠的购买意图时 使用所提供的优惠信息 向顾客展示完整的优惠详情 和陈列内容 然后 像往常一样发起购买 并将所选优惠添加到 购买选项中
在 Xcode 16 中 使用 Xcode 中的 StoreKit 测试功能 测试购买意图侦听器和延迟逻辑 请查看 StoreKit 讲座 “StoreKit 和 App 内购买项目 的新功能” Rudy 将在讲座中详细介绍相关详情
关于赢回优惠的简化购买 以及需要关闭这个功能时 如何在 App 中处理这些购买 我们就讲到这里 这就是我们今天的全部内容! 我们讨论了 StoreKit 中的 新增和增强版订阅优惠 API 我们还向大家简要概述了赢回优惠 并演示了如何配置赢回优惠 以及在 App 中支持 这种新优惠类型的多种方法 最后 我们还展示了如何 在 App Store 上推广赢回优惠 以及顾客如何使用 简化购买方式兑换优惠
你现在就可以开始在 App 中 添加支持并测试赢回优惠 我们期待看到你创造的新体验 请使用“反馈助理” 与我们分享你的反馈 如果你想了解更多信息 请访问我们的开发者网站查阅文档 还有许多其他精彩讲座不容错过 别忘了观看 “StoreKit 和 App 内购买项目 的新功能” 和“App Store Connect 的新动向”! 希望这次讲座能给大家带来灵感 让你更顺畅地将优惠添加到 App 中 感谢你的参与
-
-
4:25 - Present offer code redemption sheet on macOS - SwiftUI API
// Present offer code redemption sheet on macOS - SwiftUI API import SwiftUI import StoreKit struct MyView: View { @State var showOfferCodeRedemption: Bool = false var body: some View { Button("Redeem Code") { showOfferCodeRedemption = true } .offerCodeRedemption(isPresented: $showOfferCodeRedemption) { result in // Handle result } } }
-
20:15 - Choose preferred offer in a SubscriptionStoreView
// Choose preferred offer in a SubscriptionStoreView import SwiftUI import StoreKit struct MyView: View { let groupID: String var body: some View { SubscriptionStoreView(groupID: groupID) .preferredSubscriptionOffer { product, subscription, eligibleOffers in let freeTrialOffer = eligibleOffers .filter { $0.paymentMode == .freeTrial } .max { lhs, rhs in lhs.period.value < rhs.period.value } return freeTrialOffer ?? eligibleOffers.first } } }
-
23:05 - Check subscription entitlement and offer eligibility
// Check subscription entitlement and offer eligibility import StoreKit func shouldShowMerchandising( for groupID: String, productIDs: [Product.ID] ) async throws -> MerchandisingVisibility { // Get subscription status let statuses = try await Product.SubscriptionInfo.status(for: groupID) // Check if the customer is already entitled to the subscription let entitlement = SubscriptionEntitlement(for: statuses) if entitlement.autoRenewalEnabled { return .hidden } // Check for offers to show in merchandising UI let products = try await Product.products(for: productIDs) let isEligibleForIntroOffer = await Product.SubscriptionInfo.isEligibleForIntroOffer(for: groupID) if isEligibleForIntroOffer { let subscriptions = products.map { ($0, $0.subscription?.introductoryOffer) } return .visible(subscriptions) } // Check for eligible win-back offers let purchasedStatus = statuses.first { $0.transaction.unsafePayloadValue.ownershipType == .purchased } let renewalInfo = try purchasedStatus?.renewalInfo.payloadValue let bestWinBackOfferID = renewalInfo?.eligibleWinBackOfferIDs.first // Return the product with the offer if there is one if let bestWinBackOfferID { let subscriptions: [(Product, Product.SubscriptionOffer?)] = products.map { let winBackOffer = $0.subscription?.winBackOffers.first { $0.id == bestWinBackOfferID } return ($0, winBackOffer) } return .visible(subscriptions) } // Only return the product if there is no offer return .visible(products.map { ($0, nil) }) } struct SubscriptionEntitlement { let isEntitled: Bool let autoRenewalEnabled: Bool init(for statuses: [Product.SubscriptionInfo.Status]) { let entitledStatuses = statuses.filter { $0.state == .subscribed || $0.state == .inBillingRetryPeriod || $0.state == .inGracePeriod } isEntitled = !entitledStatuses.isEmpty autoRenewalEnabled = entitledStatuses.contains { $0.renewalInfo.unsafePayloadValue.willAutoRenew } } } enum MerchandisingVisibility { case hidden case visible([(Product, Product.SubscriptionOffer?)]) }
-
25:26 - Add a win-back offer to a purchase
// Add a win-back offer to a purchase import StoreKit func purchase( _ product: Product, with offer: Product.SubscriptionOffer? ) async throws { // Prepare the purchase options var purchaseOptions: Set<Product.PurchaseOption> = [] // Add win-back offer to the purchase if let offer, offer.type == .winBack { purchaseOptions.insert(.winBackOffer(offer)) } // Make the purchase try await product.purchase(options: purchaseOptions) }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。