美文网首页iOS运薄IAP 苹果支付
iOS自动续订订阅开发----验证收据和状态回调JSON解析

iOS自动续订订阅开发----验证收据和状态回调JSON解析

作者: Trigger_o | 来源:发表于2019-03-25 15:20 被阅读511次

    一.基本信息

    1.1订阅后,每次成功续期,打开App后会走- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions回调方法,因此启动就要监听[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    并且之后在打开时调用,一直开着App是不行的,不过我没有对此做什么处理,后面会说到

    1.2sandbox的续期时间是缩短了很多的


    续期时间

    并且会在5次续订(一共6条收据)后自动取消

    二.验证收据(调用apple server的接口)

    1.接口调用
    自动订阅的收据验证接口和其他IAP一样
    沙盒状态下使用:https://sandbox.itunes.apple.com/verifyReceipt来验证
    生产环境下使用:https://buy.itunes.apple.com/verifyReceipt

    但是传参不同
    {
    “receipt-data” : “(actual receipt bytes here)”
    “password” : “(shared secret bytes here)”
    }
    receipt-data对应的即下面的receiveString(凭证)

    NSURL * receiveUrl = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData * receiveData = [NSData dataWithContentsOfURL:receiveUrl];
    NSString * receiveString = [receiveData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    

    password对应的是在App Store connect上创建的秘钥


    秘钥

    关于秘钥:

    1.秘钥有公共和商品专用两种,如果创建使用公共秘钥,其他类型商品的对账也要传password,比如消耗型,原本App内有消耗型商品,对账只传了凭证,当我创建公共秘钥后,对账立即返回错误,加上password就可以了,不过我没有测试单个商品专用秘钥.
    2.同样的,由于接口一样,使用公共秘钥后,password也必须传,现在不管是那种商品,传参都一样,因此对账的json会返回全部的票据,包括消耗型,订阅型等全部四种.没有更详细的测试,不管我猜测使用专用秘钥结果会不同.

    2.JSON解析
    2.1首先在第一次订阅或者回复订阅(也就是停止连续订阅后又买了)后,在- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions 回调中,
    可以从SKPaymentTransaction中拿到 tran.originalTransaction.transactionIdentifier,这个标识符是绑定该appleID的,可以和App server的用户系统绑定起来,之后会继续用到.

    但是这么做一旦用户使用一个appleId给多个账户充值,就会出现一对多的情况,因此这么解决
    首先如果订阅不取消,是不能再购买订阅的,iOS会提示已经购买了该订阅
    然后,如果取消了一个userid下的订阅,使用另一个userid购买订阅,后台在拿到original_transaction_id的时候,去数据
    库查询有没有绑定了这个original_transaction_id的userid,有的话,删除绑定,这样就可以维持original_transaction_id和userid一对一的绑定,之后恢复订阅也会给这个新的userid恢复.

    另外每次交易都有一个transactionIdentifier

    for (SKPaymentTransaction * tran in transactions) {
        NSString *tranId = tran.transactionIdentifier;
    }
    

    这是每笔交易的票据号,需要传给后台

    2.2JSON结构


    JSON结构

    state :0 表示正常
    JSON里有两个收据列表,一个是receipt -> in_app,一个是latest_receipt_info,
    前面说到的receiveString(凭证)是可以一直使用的,但是一直使用同一个receiveString,拿到的JSON里receipt -> in_app不会变化,latest_receipt_info会随着续期的期数而变化,并且会越来越多,并且如果使用公共秘钥,这里面会包含所有的票据

    单个收据

    前面说到的传给App server的transactionIdentifier,需要作为唯一的票据号去验证,
    首先对于非连续订阅的其他类型:
    都是单笔交易,每次拿到的都是新的凭证,因此in_app里都是有对应票据的,而且我发现非连续订阅的票据有时候不会在latest_receipt_info中出现, 因此这些类型是遍历in_app里的票据
    如果找到transactionIdentifier相同的,那么本次交易就是有效的

    然后对于连续订阅型:
    1.第一次对账
    遍历latest_receipt_info里的票据,如果transactionIdentifier相同,那么本次交易就是有效的,找到对应的票据后,其中最关键的是expires_date_ms这个时间戳,这个和expires_date字符串不相符, expires_date是GMT时间,少8个小时,而expires_date_ms转换后是正常的,因此不用把这个时间戳再加8小时.

    2.之后的对账
    由于苹果会在到期前充值,充值失败也会有回调通知,所以当数据库中的时间到期后,再去用之前存的凭据调用对账接口,
    然后遍历latest_receipt_info根据product_id,也就是商品id,把连续订阅的票据筛选出来
    现在筛选出来的这些就是所有的此商品的订阅票据了,而且顺序是按照时间排序的,新的在后面,如果不放心,可以自己根据里面的expires_date_ms(或者其他时间戳)再排序,然后创建订单,更新过期时间等等操作
    官方文档有每个字段的含义说明

    三.状态回调(apple 调用App server的接口)

    这个接口(post请求)事先在App Store connect配置,在App信息一项里,并且测试时可以先填测试的url,之后再修改,应该是立即起效
    配置这个url后,apple会在以下状态时调用


    server to server的回调

    第一个是首次订阅成功
    第二个是取消了订阅
    第三个是恢复了订阅
    第四个也是恢复了订阅,在sandbox测试时,6次收据之后,重新订阅,就会是这个状态
    第五个也是取消了订阅,在sandbox测试时,6次收据之后,就会变成这个状态
    第六个是各种状态改变下都会调用,比如说首次购买会收到两次回调,一个是INITIAL_BUY一个是DID_CHANGE_RENEWAL_STATUS

    取消时apple调用回调传的参数

    上面是一个6次后自动取消的JSON,notification_type属于第六种.
    其中auto_renew_status是false,表示续订取消,并且返回了上一次的凭证,可以获取到期时间,
    并且返回了最关键的original_transaction_id,通过这个可以确定是哪个用户做了取消操作
    这个回调很重要
    官方文档有更详细的说明

    总结一下
    我使用了这种方法去标记订阅的有效期
    首次订阅后App中得到receiveString和,App server存储receiveString和transactionId,绑定用户账户,
    之后App server去调用验证收据接口,根据,获得original_transaction_id绑定用户,并且拿到过期时间,存储下来
    快要过期时,App server再去调用收据接口,拿到最新的过期时间,然后更新
    如果收到了Apple关于订阅取消的通知(DID_CHANGE_RENEWAL_STATUS并且auto_renew_status是false),一样是根据original_transaction_id更新到期时间
    如果收到了apple关于恢复订阅的通知,也一样是根据original_transaction_id更新到期时间

    四.关于审核

    1.订阅和其他内购一样必须可以不登录购买
    2.自动续订订阅只能在App Store connect创建商品,然后再App中购买.
    3.有的App中含有走内购的虚拟币,因此想用虚拟币购买非自动续订订阅,这一点审核默认是不允许的,不过与审核沟通,有可能说服审核.
    4.充值界面需要显示出自动续期订阅的说明,以及相关服务的协议(如会员)的连接,还有自动续期订阅的协议的连接


    自动续期订阅的说明

    相关文章

      网友评论

        本文标题:iOS自动续订订阅开发----验证收据和状态回调JSON解析

        本文链接:https://www.haomeiwen.com/subject/ougvvqtx.html