iOS 内购遇到的坑

作者: 骑马纵天下 | 来源:发表于2017-07-24 14:46 被阅读1991次

    一.内购沙盒测试账号在支付成功后,再次购买相同 ID 的物品,会提示如下内容的弹窗。您以购买过此APP内购项目,此项目将免费恢复

    您以购买过此APP内购项目,此项目将免费恢复.PNG
    原因:

    当使用内购购买过商品后没有把这个交易事件关,所以当我们再次去购买商品后就会调用以前已经购买成功的交易事件去购买因为已经购买过,才会有这个提示

    解决方法:

    1.当我们使用[[SKPaymentQueue defaultQueue] addPayment:payment];这个方法进行支付请求后,因为我们已经把支付所需要的信息都添加到苹果的支付队列,苹果会自动完成后续的购买请求。
    在用户购买成功或者点击取消购买的后会回调- (void)paymentQueue:(SKPaymentQueue )queue updatedTransactions:(NSArray )transaction;方法返回响应的结果信息,在该方法内除了得到响应的支付信息编写自身的业务的代码外还要记得调用[[SKPaymentQueue defaultQueue] finishTransaction:transaction];方法通知苹果的支付队列该交易已经完成,否者就会调用已经购买成功的支付队列,就会出现您以购买过此APP内购项目,此项目将免费恢复这句提示。

    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
        NSLog(@"调用了几次这个方法?");
        SKPaymentTransaction *transaction = transactions.lastObject;
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchased: {
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];//记得关闭交易事件
    
                NSLog(@"购买完成,向自己的服务器验证 ---- %@", transaction.payment.applicationUsername);
                NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
                NSString *receipt = [data base64EncodedStringWithOptions:0];
    //            [self buySuccessWithReceipt:receipt transaction:transaction];
            }
                break;
            case SKPaymentTransactionStateFailed: {
                NSLog(@"交易失败");
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            }
                break;
            case SKPaymentTransactionStateRestored: {
                NSLog(@"已经购买过该商品");
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            }
                break;
            case SKPaymentTransactionStatePurchasing: {
                NSLog(@"商品添加进列表");
            }
                break;
            default: {
                NSLog(@"这是什么情况啊?");
            }
                break;
        }
    }
    
    2.在买次购买之前检测是否有未完成的交易如果有就关闭。
    NSArray* transactions = [SKPaymentQueue defaultQueue].transactions;
       if (transactions.count > 0) {
           //检测是否有未完成的交易
           SKPaymentTransaction* transaction = [transactions firstObject];
           if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
               [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
               return;
           }  
       }
    

    二.内购 元数据丢失

    一般情况下是需要填的选项没有填写完整,还有要填写完整不然审核内购项目可能会不通过。

    三.iOS 内购 您已经购买了此项目,您想免费再获取一次吗

    这个是内购选择类型不匹配原因导致。
    非消耗型就是消耗一次后在该appid下都能使用。
    消耗型比如一些直播平台的货币 使用完以后可以在充值。
    我有这个问题是 最开始我们的项目是购买完产品以后可以永久使用,后来修改成充值余额购买,但是我没有去修改类型才导致的这个错误,

    四.测试时记得把App Store上的账号注销,不然会出现购买失败,注销账号后,在进行内购时登录沙盒测试账号。

    五.In-App Purchase二次验证

    IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功。
    当应用向Apple服务器请求购买,成功之后,Apple会返回以下四个数据给应用

    1. 产品标识符: product Identifier[在itunes store应用内定义的产品ID,例如com.公司名.产品名.道具名(com.xxxx.317hu.66)]
    2. 交易状态: state
    3. Receipt:很长的一段字符串,大概49行,作为二次验证的重要依据
    4. 交易标识符: transaction Identifier 我们需要把Receipt发送給苹果的苹果的服务器验证,用户的购买信息是否真实
    交易状态 解释
    Purchased 购买成功
    Restored 恢复购买
    Failed 失败
    Deferred 等待确认,儿童模式需要询问家长同意

    苹果返回状态码 状态码

    状态 描述
    21000 App Store不能读取你提供的JSON对象
    21002 receipt-data域的数据有问题
    21003 receipt无法通过验证
    21004 提供的shared secret不匹配你账号中的shared secret
    21005 receipt服务器当前不可用
    21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送
    21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务
    21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务

    相关文章

      网友评论

      • b83bde1247ec:您好,请教一下,一个测试AppleID 购买非续期订阅的商品后 同样使用这个AppleID但是换一个游戏账号还是提醒已经购买是怎么回事呢?谢谢
        骑马纵天下:不是特别懂你的意思 你可以私信发给我
      • fba08aef555c:请问购买vip,选择消耗型还是非消耗型雅
        骑马纵天下:@我把光拿在手上 你完成交易后有没有关闭交易?
        48c9f8850c60:我想请教下。为什么有的购买成功后能拿到返回值,有的确显示恢复购买,没有近那个监听方法。是什么原因造成这样的?我这边有2个充值按钮来回出现这个情况。
        骑马纵天下:@ZXQ1234567 消耗性
      • weicyNO_1:大神想请问一下。我新添加了一个内购项目。如果项目中想获取这个项目用不用再次提交新版本。现在版本中模拟器跑真实环境能请求到数据。appstore中下载的请求不到产品。是什么原因?必须提交新版本吗?如果必须提交新版本中,新版本中没有添加内狗项目是不是不用添加
        weicyNO_1:@白发三千丈_ 有个问题想请教一下。我之前的版本没问题,这次更新版本结果一直是5.1.1被拒,如何解决
        weicyNO_1:谢谢
        骑马纵天下:如果你提交过以后 不需要提交第二次 就可以直接使用

      本文标题:iOS 内购遇到的坑

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