IAP 自动订阅开发

2020/08/20 IAP

一、代码逻辑

关于 iOS 订阅、自动订阅 本身功能开发很简单。跟正常的购买没什么大的差异。唯一需要特殊处理(自动订阅)的是,
在 APP 启动时候要增加侦听:
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

因为自动订阅,除了第一次购买行为是用户主动触发的。后续续费都是 Apple 自动完成的,一般在要过期的前 24 小时开始,苹果会尝试扣费,扣费成功的话 会在 APP 下次启动的时候主动推送给 APP。所以,APP 启动的时候一定要添加上面的那句话。

另外就是处理续费了:

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    for (SKPaymentTransaction *transaction in transactions)
    {
        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchasing: // 0
                break;
            case SKPaymentTransactionStatePurchased: // 1
                 //订阅特殊处理
                 if(transaction.originalTransaction){
                      //如果是自动续费的订单originalTransaction会有内容
                 }else{
                      //普通购买,以及 第一次购买 自动订阅
                 }
                break;
            case SKPaymentTransactionStateFailed: // 2
                [self failTracker:transaction];
                break;
            case SKPaymentTransactionStateRestored: // 3
                [self restoreTransaction:transaction];

                break;
            default:

                break;
        }
    }
}

二、服务器验证 receipt

服务器在校验 receipt 时候也就有一个坑:

1、那就是创建自动订阅的时候需要新建一个共享秘钥,就是一串字母。

2、服务器在向苹果服务器校验 receipt 时候,不仅需要传 receipt,还需要传秘钥。

{
    receipt-data : (actual receipt bytes here)
    password : (shared secret bytes here)
}

3、介绍下 receipt 结构
  receipt 通过 base64 解码可得:

{
    "signature" = "dfreree...."; //也是base64
    "purchase-info" = "ewoJIm9x....."; //也是base64,这个里面存放详细时间,流水号等
    "environment" = "Sandbox";
    "pod" = "100";
    "signing-status" = "0";
}

三、自动续费测试

重点都不是上面的,重点是测试,如何测试?尤其自动续费怎么测?

意思就是,沙箱环境 自动续费时间缩短了,一周 对应 三分钟,一月 对应 五分钟。。。
购买完一个一周 类型订阅,就不要在 APP 不退出的情况等待了,必须 3 分钟 或是 10 分钟后重新登录,Apple 才会主动告知你结果,也就是第一点提到的。

测试中会遇到几个问题:

1.沙箱环境自动续费是一定会自动续费的吗?
答案:不一定的,有时候会,有时候不会。所以要多测测,多建几个测试账号。

2.是否需要实现 restoreCompletedTransactions ?
答案:视需求吧。有少量文章说 2014 年起苹果审核严格了,必须要有一个按钮实现 restoreCompletedTransactions。另外,我听百度一位同学说,爱奇艺 2015 年因为这个被拒过。但是,目前来看很多使用了订阅的应用或是游戏,并没有这个功能。
我是感觉,看需求了。订阅 是跟着 userid 唯一呢? 还是跟着 apple id 呢?在国内,一般都是前者。

四、讨论

1.自动订阅归属的问题:
a. 苹果设计自动订阅的初衷是 ,订阅一个服务, 这个服务需要跟着 Apple ID 走。说白了,就是你 A 设备 用了 Apple 账号 100001 购买了,你换了 B 设备 用 Apple 账号 100001 登录 app store,你同样能享受到服务。国外的一些音乐类型、杂志报刊等用的比较多,游戏类的少,苹果自己的 Apple music 也有自动订阅(首创)。

b. 目前国内的一些应用或是游戏,希望的是自动订阅 关联的是 APP 的 user id ,而不是 Apple ID。说白了,就是你购买了一个自动订阅服务,我不管你哪个 apple id 支付的, 但是只能我一个 APP 的 唯一用户可以享受服务。这时候就需要 APP 自身做处理了,就是记住首次购买的 transaction-id,并且绑定某个用户。以后自动续费的话,都会有 original-transaction-id,这个 id 是第一次购买的 transaction-id,根据这个服务器可以联系初始购买的服务。有点描述偏了,当 transaction-id 绑定了用户,再次收到其它用户 transaction-id 请求时候,视情况处理了。(你也可以根据 unique-vendor-identifier 处理)

2.同一个 Apple ID 购买完的自动订阅,可以再次点击购买吗(有效期内)?
答案:不可以,苹果自身会拦截

3.购买了自动订阅 3 个月的,可以换购 1 年的 或是 1 个月的吗?
答案:可以,苹果文档有提到,视为升级订阅套餐 或是 降级订阅套餐。

4.关于掉单的问题
答案:一定要在服务器校验完票据后,客户端收到服务器的反馈结果后再:
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

5.关于普通消费商品,如何防止黑卡、掉单、外币等?
我有时间会再写一篇。

6.沙箱测试时候,偶发的启动时候收到多个(有可能 40 个以上)票据?
这种情况一般发生在沙箱环境,一个账号多次测试订阅会偶发遇到,这里要注意这些票据的校验,要不批处理,要不通过信号量控制一下请求数。(PS:处理不好容易造成内存问题,小心!)

Search

    Table of Contents