0%

苹果IAP支付流程

我们通常说的“苹果支付IAP”其实是指 In-App Purchase (IAP),即“应用内购买”。而 Apple Pay 是苹果的支付工具,可以在 App、网页或实体店里用来付款,两者是不同的体系。我们这里主要讨论 IAP。

客户端只负责“请求购买”和“展示商品”,而“校验票据”和“发放商品”的权威必须是你的服务器。

1. 流程

  • 用户操作: 用户在 App 中点击“购买”按钮。

  • 客户端获取商品信息: App 通过 StoreKit 向苹果服务器请求商品信息(价格、名称等),并展示给用户。

  • 客户端发起支付: 用户确认购买后,App 通过 StoreKit 创建一个支付请求。

  • Apple 处理支付: iOS 系统接管,弹出 Apple ID 登录和支付确认界面(包括 Touch ID/Face ID)。

  • Apple 返回交易结果:

    • 成功: 苹果服务器记录交易,更新设备上的 App Receipt,并通过 StoreKit 回调通知你的 App 交易成功。

    • 失败/取消: 通过 StoreKit 回调通知你的 App 交易失败或被用户取消。

  • 客户端处理成功交易:

    • App 收到成功回调,从设备中获取加密的 Receipt Data。

    • App 将这份 receipt-data 和一些关联信息(如用户ID、交易ID)发送到你自己的服务器。

  • 服务器验证收据:

    • 你的服务器收到 receipt-data 后,向苹果的 verifyReceipt 服务器接口发起验证请求。

    • 苹果服务器返回解码后的 JSON 格式的收据信息,其中包含所有购买记录。

  • 服务器更新用户权益:

    • 你的服务器解析苹果返回的 JSON 数据,找到对应的购买记录。

    • 验证该交易是否已处理过(防止重复发货)。

    • 如果验证通过且是新交易,服务器更新数据库,为该用户解锁相应的功能或发放物品(例如:标记为Pro用户,增加金币数量,记录订阅到期时间)。

  • 服务器返回结果给客户端: 服务器告知客户端“发货”成功。

  • 客户端结束交易: 客户端收到服务器的成功确认后,调用 StoreKit 的 finishTransaction 方法。这一步至关重要,它告诉苹果:“这笔交易我们已经处理完毕,请不要再重复通知我了。”

  • 客户端更新 UI: 客户端刷新界面,让用户立即看到购买的商品或功能已生效。

2. 介绍

2.1 支付 id 的区别

在苹果支付系统中,transaction_id 和 original_transaction_id 的主要区别如下:

transaction_id(交易ID)

  • 每次交易都会生成一个唯一的 transaction_id
  • 代表当前这笔具体的交易
  • 对于首次购买和后续续订,都会生成新的 transaction_id

original_transaction_id(原始交易ID)

  • 表示首次订阅时的交易ID
  • 对于订阅类型的商品,续订时会保持相同的 original_transaction_id
  • 用于追踪整个订阅周期的所有相关交易

同组级别

  • 同组升级:保持original_transaction_id 不变,便于追踪
  • 跨组升级:生成新的original_transaction_id,视为新订阅

2.2 订阅的升级与降级

类型为: DID_CHANGE_RENEWAL_PREF,配合 subtype

  • 如果 subtype 为 UPGRADE ,则用户升级了订阅。升级立即生效,开启新的计费周期,用户会收到上一周期未使用部分的按比例退款。

  • 如果 subtype 为 DOWNGRADE ,则用户降级了订阅。降级将在下一个续订日期生效,不会影响当前有效的计划。

2.3 订单续期

续期失败怎么办

与账单相关的问题会导致订阅自动进入账单重试状态,在此期间 App Store 会尝试恢复该订阅。

  • App Store 服务器通知会发送 DID_FAIL_TO_RENEW 通知类型。
  • 当订阅续订失败时,Apple 会在 60 天内尝试恢复。如果你在此期间选择暂停用户访问服务或内容,一旦问题解决,你需要重新恢复访问权限。
  • 如果订阅在 60 天内续订,付费服务天数将从续订日期起继续计算。
  • 你可以选择将账单宽限期应用于所有续订(包括现有付费续订和从免费优惠转为付费续订的情况),或仅应用于现有付费续订。你还可以将宽限期时长设为 3 天、16 天或 28 天。

续期少税

自动续期订阅的净收入结构与 App Store 上的其他商业模式不同。在订阅者的第一年服务期间,你在每个计费周期可获得订阅价格的 70%,并扣除相应税费。

当订阅者累计付费满一年后,你的净收入将提升至订阅价格的 85%,并扣除相应税费。

2.4 服务器验证API

  • 订阅状态API: “/inApps/v2/subscriptions/{originalTransactionId}” 视频里用这个的多
  • 历史记录API: “/inApps/v1/history/{originalTransactionId}”
  • 查询id信息API: “/inApps/v1/transactions/{transactionId}”,经测试某些情况下查不到,但是 subscriptions 可以追踪到。

3. 问题

商品升级是按比例抵扣还是退款?

退款。用户购买了一个比当前订阅更高级别的订阅。他们会立即升级,并获得原订阅按比例退款的金额。

1
一种通知类型,与其 subtype 一起表示客户对其订阅计划进行了更改。如果 subtype 为 UPGRADE ,则用户升级了订阅。升级立即生效,开启新的计费周期,用户会收到上一周期未使用部分的按比例退款。如果 subtype 为 DOWNGRADE ,则用户降级了订阅。降级将在下一个续订日期生效,不会影响当前有效的计划。

订单续期失败

  • DID_FAIL_TO_RENEW

    • 一种通知类型,与其 subtype 一起表示由于账单问题导致订阅续订失败。订阅进入账单重试期。如果 subtypeGRACE_PERIOD ,请在宽限期内继续提供服务。如果 subtype 为空,则订阅不在宽限期内,你可以停止提供订阅服务。
  • GRACE_PERIOD_EXPIRED

    • 表示账单宽限期已结束且订阅未续订的通知类型,因此你可以关闭对服务或内容的访问。告知客户其账单信息可能存在问题。
    • App Store 会继续重试扣费 60 天,或直到客户解决账单问题或取消订阅,以先到者为准。

苹果宽限期到了还是扣款失败,服务器会收到哪些类型通知?

EXPIRED,附带 subtype

如果 subtypeVOLUNTARY ,则订阅因用户关闭自动续订而过期。

如果 subtypeBILLING_RETRY ,则订阅因账单重试期结束且未成功完成账单交易而过期。

如果 subtypePRICE_INCREASE ,则订阅因用户未同意需要用户确认的价格上调而过期。

如果 subtypePRODUCT_NOT_FOR_SALE ,则订阅因订阅尝试续订时产品不可购买而过期。

客户端首次购买成功后获得一个transaction_id,如果换设备,恢复购买的transaction_id会变吗?

文档里说是会变的。

1
2
3
4
每当订阅自动续期或用户在新设备上恢复订阅时,App Store 都会为该交易生成一个新的交易标识符。


当用户首次购买订阅时,交易标识符始终与原始交易标识符( originalTransactionId )相同。对于恢复或续期,交易标识符与原始交易标识符不同。如果用户多次恢复或续订同一订阅,每次恢复或续期都会有一个唯一的交易标识符。

4. 参考资料

可以加首页作者微信,咨询相关问题!