IAP支付测试
一、支付流程
- APP向服务器发送请求,获得一份产品列表
- 服务器返回包含产品标识符的列表
- APP向App Store发送请求,得到产品的信息
- App Store返回产品信息
- APP把返回的产品信息显示给用户(App的store界面)
- 用户选择某个产品
- APP向App Store发送支付请求
- App Store处理支付请求并返回交易完成信息
- APP从信息中获得数据,并发送至服务器
- 服务器记录数据,并进行审查
- 服务器将数据发给App Store来验证该交易的有效性
- App Store对收到的数据进行解析,返回该数据和说明其是否有效的标识
- 服务器读取返回的数据,确定用户购买的内容
- 服务器将购买的内容传递给程序
二、IAP(In‑App Purchase) 支付:
StoreKit 相关字段的信息:
/// The unique product identifier.
public let id: String
/// The type of the product.
public let type: Product.ProductType
public let subscription: Product.SubscriptionInfo?
public subscript(key: Product.Key) -> BackingValue { get }
id 是指商品在苹果记载的ID
ProductType是商品的类型 四种订阅类型,这里每种类型就简单举个:
- consumable (消耗型商品),可以反复购买,购买后的商品会被一次性消费。
- nonConsumable (非消耗型商品),游戏解锁新关卡就是这个类型,只能买一次,买了之后永久有效。
- autoRenewable (自动续期订阅),每个周期会自动扣款的商品,例如 会员续费。
- nonRenewable (非自动续期订阅 ),不会自动扣款的,可多次订阅的商品。
public struct ProductType {
public static var consumable: Product.ProductType
public static var nonConsumable: Product.ProductType
public static var nonRenewable: Product.ProductType
public static var autoRenewable: Product.ProductType
}
- Subscription info 只有 .autoRenewable 类型的商品才会有这个属性 在Subscription info中有一个属性: isEligibleForIntroOffer,这个是现在用的比较多的首次购买优惠。 例如一些 APP 会有会员订阅服务,那些服务会有 1 个月,3 个月,12 个月等的自动续期,同时还会有一些第一次购买的优惠,这个第一次购买的优惠就是首购优惠,并且这个优惠跟 Apple ID 挂钩,跟 APP 内自己的账号体系无关。
/// Whether the user is eligible to have an introductory offer applied to their purchase.
public var isEligibleForIntroOffer: Bool { get async }
/// Whether the user is eligible to have an introductory offer applied to a purchase in this
/// subscription group.
/// - Parameter groupID: The group identifier to check eligibility for.
public static func isEligibleForIntroOffer(for groupID: String) async -> Bool
用 StoreKit 发起购买
- Request Request 方法就能获取到上一章说的 Product 类型。传入需要的 ProductId 就能返回对应的信息。
通过 Product.request 去请求你需要的 Product 类型数据,然后根据订阅类型存到不同的数组中。
Purchase
Payment
退款流程
苹果的Consumption API 实际上就是为我们提供了一个退款前置查询的能力,其整个交互过程如下:
1、用户退款
2、苹果收到退款请求后,会在 48 小时内进行审核,同时发送 CONSUMPTION_REQUEST 通知至我们
3、我们收到 CONSUMPTION_REQUEST 通知后,需要在 12 小时内,调用 Consumption API 进行请求,告知苹果用户信息
4、苹果根据我们反馈的信息,结合 AppleID 信息,对退款用户进行审核(需要注意的是,苹果不会完全采信我们信息,仅用做参考)
5、苹果同意退款
6、我们收到退款通知后,给予苹果正常回包,并进行索回等操作
三、测试准备:
1、准备沙盒账户 登录苹果开发者后台–App Store Connect–用户和访问–沙盒–测试员–添加,可以选择相应的地区,如果不涉及海外用户一般选择中国地区。
iOS15以及以上的系统,可以管理沙盒购买的订阅,这个对于测试订阅比较方便。
2、证书
dev证书和adhoc证书的包为测试包,只能用沙盒账号进行支付,线上包是不能沙盒支付的。
iOS证书主要分:
- dev dev的包主要用于前期测试,使用的是开发证书
- App Store App Store的包是上传至App Store时需要选择的
- Enterprise 证书为企业签,任何一台手机都可以安装了
- adhoc 个人签,打包时也需要加入udid才能安装
四、测试要点:
- 显示的货币与价格,符合预期,如果产品app在多个国家上线还应该查看各个国家的价格是否正确
- 支付流程能正常完成,商品也成功到账
- 支付完成后是否正常刷新界面
- 在购买交易中,通过付款方式扣款失败,用户不应收到商品。
- 可以多次购买的商品确保商品可以多次购买
由于涉及到续订、退订、体验期、首次折扣价格等操作,订阅的测试相对来说更复杂一些,QA侧需要额外关注以下几点:
- 需要验证所有的价格显示、支付流程、到账流程、涉及金额或权限的变化等通用case
根据游戏内订阅商品的实际配置,如是否有免费试用、是否有首次购买折扣等,参考官方用例,完成游戏自己的测试用例。
- 续订功能正常,一般沙盒账户可以设置续订周期,20分钟一次自动续订
- 退订后不再扣款,并且相应的会员权益在截止日期后特权不生效
- 如果有首次优惠,已经使用首次购买的用户和没有首次购买的用户看到的价格不同
- 首次购买完成后,价格应该显示正常价格
- 体验期内不扣款
- 体验期内退订
- 已经订阅的用户再次购买订阅
- 切换Apple ID进行购买
- 切换app账户购买,具体要看产品的逻辑,购买时Apple ID和app ID是否绑定
- 用户发起退款,这个需要在线上测试
- 黑产利用Apple 的退款机制,退款后大部分游戏内的点券并不会随着退款而消失,造成损失。
4、testflight支付
使用testflight的用户在支付的时候,是使用沙盒支付,即使是正常用户也是沙盒支付。所以需要规避这个问题。
五、其他方式保证支付功能
iOS应用内的第三方支付:
- 微信
- 支付宝
- PayPal
如果app内有第三方支付,提交审核的时候很可能被拒,最好关掉