zoukankan      html  css  js  c++  java
  • iOS 自动订阅开发

    一、代码逻辑

    关于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;
            }
        }
    }            
    

      上述代码片段对 transaction.originalTransaction 进行了判断,如果有内容一定为订阅类型的。为什么在这加个判断处理,是因为续费 是发生在APP启动的时候,这时候你登录流程等可能还没有走完,因为有的游戏在跟服务器进行 校验的时候会传一些userid等信息,或是加密的信息,视情况而定,是否要区分处理。

          注意点:就是在沙箱环境测试时候,APP启动可能得到5次的 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions ;订单处理,算是要并发处理case SKPaymentTransactionStatePurchased: 这种case,这时候你得注意你得网络请求队列,不要最后一个订单请求覆盖了 前几个。(可以用信号量处理下,比较简单)

    二、服务器验证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";
    }
    

    "purchase-info"可以再次base64解码可得:

    {
    	"original-purchase-date-pst" = "2017-08-29 23:52:45 America/Los_Angeles";
    	"purchase-date-ms" = "1504144439749";
    	"unique-identifier" = "a063c2c321dd885642a5cddd9160e0ad8291d978";
    	"original-transaction-id" = "1000000328915948";
    	"expires-date" = "1504144739749";
    	"transaction-id" = "1000000329310742";
    	"original-purchase-date-ms" = "1504075965000";
    	"web-order-line-item-id" = "1000000036091900";
    	"bvrs" = "1";
    	"unique-vendor-identifier" = "B78549AC-58D4-4750-8E6F-F4CCE6138A5A";
    	"expires-date-formatted-pst" = "2017-08-30 18:58:59 America/Los_Angeles";
    	"item-id" = "1276511095";
    	"expires-date-formatted" = "2017-08-31 01:58:59 Etc/GMT";
    	"product-id" = "lcm.denachina.pickle.38.1month";
    	"purchase-date" = "2017-08-31 01:53:59 Etc/GMT";
    	"original-purchase-date" = "2017-08-30 06:52:45 Etc/GMT";
    	"bid" = "com.denachina.pickle";
    	"purchase-date-pst" = "2017-08-30 18:53:59 America/Los_Angeles";
    	"quantity" = "1";
    }
    

      你想要的东西,都可以获取到。客户端可以做这些事情,但是没有多大必要,还是服务器处理得好。(对于无服务器APP只能客户端处理了)

          附上一个在线base64解码的:http://base64.xpcha.com/

     

    三、自动续费测试

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

    先看下Apple原文档:

    When testing auto-renewable subscriptions in the test environment, keep in mind that the duration times are compressed. Additionally, test subscriptions only auto-renew a maximum of six times. Table 3-1 lists the compressed duration times.

    Actual duration

    Test duration

    1 week

    3 minutes

    1 month

    5 minutes

    2 months

    10 minutes

    3 months

    15 minutes

    6 months

    30 minutes

    1 year

    1 hour

    意思就是,沙箱环境 自动续费时间缩短了,一周 对应 三分钟,一月 对应 五分钟。。。

    购买完一个一周 类型订阅,就不要在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购买完的自动订阅,可以再次点击购买吗(有效期内)?

    答案:不可以,苹果自身会拦截,会出现这么个提示窗,如下图:

    但是,sandbox测试环境,在第三大点的对应表格对应时间内,apple会拦截的,过了这个时间苹果是不会拦截的。

    3.够买了自动订阅3个月的,可以换购 1年的  或是 1个月的吗?

    答案:可以,苹果文档有提到,视为升级订阅套餐  或是 降级订阅套餐。

    4.关于掉单的问题

    答案:一定要在服务器校验完票据后,客户端收到服务器的反馈结果后再:

    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    

    5.关于普通消费商品,如何防止黑卡、掉单、外币等?

    我有时间会再写一篇。

    五、了解更多

    https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/iTunesConnectInAppPurchase_Guide/Chapters/CreatingInAppPurchaseProducts.html#//apple_ref/doc/uid/TP40013727-CH3-SW10

    https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html

    https://stackoverflow.com/questions/8033673/ios-sandbox-environment-auto-renewal-subscription

    http://www.jianshu.com/p/28fc3cc8c49f

    http://www.cnblogs.com/zidong0822/p/4701839.html

    http://blog.csdn.net/xiaoyuanzhiying/article/details/46708043

    http://www.jianshu.com/p/e9e4dc3dc9ee

    https://www.raywenderlich.com/154737/app-purchases-auto-renewable-subscriptions-tutorial

    http://www.360doc.com/content/14/1118/16/12282510_426165722.shtml

    关于验证:

    https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html

    https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW20

    关于预防刷:

    http://blog.csdn.net/skylin19840101/article/details/71757055

  • 相关阅读:
    Oracle基础知识整理
    linux下yum安装redis以及使用
    mybatis 学习四 源码分析 mybatis如何执行的一条sql
    mybatis 学习三 mapper xml 配置信息
    mybatis 学习二 conf xml 配置信息
    mybatis 学习一 总体概述
    oracle sql 语句 示例
    jdbc 新认识
    eclipse tomcat 无法加载导入的web项目,There are no resources that can be added or removed from the server. .
    一些常用算法(持续更新)
  • 原文地址:https://www.cnblogs.com/qiyer/p/7442680.html
Copyright © 2011-2022 走看看