美文网首页
ios 内购

ios 内购

作者: wesk痕 | 来源:发表于2016-09-23 13:03 被阅读0次

    从开发iOS到现在,内购app也做过两个了,现在好好记录下这个流程。

    首先需要在所属的app下创建物品,这个流程网上很多也不难。这边就详细说明了,可参考下面网址。
    http://blog.csdn.net/shenjie12345678/article/details/40978977/

    我们定义好一个或多个product 后 每个product id对应着一个product。 我们拿到一个或多个product id,数据处理后对appstore 发起购物请求,等待appstore处理后的响应(之间很多操作,都是appStore和用户之间,客户端无法干预), 客户端对购物成功的回执单进行校验。


    内购流程示意图.png

    这个流程基本就是这样,如上图所示。

    理清整个流程后,我们对内购就非常清晰了,要注意的就是细节了,对各种异常情况的处理。各种case 见下列枚举,基本和app的sdk保持一致

    typedef enum : NSUInteger {
        EPaymentTransactionStateNoPaymentPermission, //没有Payment权限
        EPaymentTransactionStateAddPaymentFailed, //addPayment失败
        EPaymentTransactionStatePurchasing,//正在购买
        EPaymentTransactionStatePurchased,//购买完成(销毁交易)
        EPaymentTransactionStateFailed, //购买失败(销毁交易)
        EPaymentTransactionStateCancel,//用户取消
        EPaymentTransactionStateRestored,//恢复购买(销毁交易)
        EPaymentTransactionStateDeferred, //最终状态未确定
    } EPaymentTransactionState;
    

    内购有个重要的协议 SKPaymentTransactionObserver
    需要特殊特殊处理,不多说废话 直接附上代码

    #pragma mark - SKPaymentTransactionObserver
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
    {
        for (SKPaymentTransaction *transaction in transactions)
        {
            EPaymentTransactionState state;
            switch (transaction.transactionState){
                case SKPaymentTransactionStatePurchasing:
                {
                    // 连接appStore
                    state = EPaymentTransactionStatePurchasing;
                }
                    break;
                case SKPaymentTransactionStatePurchased:
                {
                    state = EPaymentTransactionStatePurchased;
                    //交易完成
                    if (isServiceVerify) {
                        [self completeTransaction:transaction];
                    }
                    else
                    {
                        //本地作校验
                        [self verifyPurchase:transaction];
                    }
                }
                    break;
                    
                case SKPaymentTransactionStateFailed:
                {
                    //交易失败
                    if (transaction.error.code != SKErrorPaymentCancelled)
                    {
                        state = EPaymentTransactionStateFailed;
                    }else
                    {
                        state = EPaymentTransactionStateCancel;
                    }
    
                    [self finshTransaction:transaction];
                }
                    break;
                    
                case SKPaymentTransactionStateRestored:
                {
                    state = EPaymentTransactionStateRestored;
                    //已经购买过该商品
            
                    [self finshTransaction:transaction];
                }
                    break;
                case SKPaymentTransactionStateDeferred:
                {
                    state = EPaymentTransactionStateDeferred;
                }
                    break;
                default:
                    break;
            }
            if (self.delegate && [self.delegate respondsToSelector:@selector(updatedTransactions:)]) {
                [self.delegate updatedTransactions:state];
            }
    
        }
    }
    

    补充一点 :一旦启动了开始购买流程,必须要调用

        //结束交易
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    

    来结束购买流程,否者在下一次调用到 方法

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    

    还是会触发继续购买流程,这个特性可以解决购买过程中出现的各种异常场景,比如购买完成app crash(没网络了),在下一次启动app时调用上面的方法可以回复购买。
    具体类 放在gitHub下
    https://github.com/weskhen/InAppPurchasing

    贴上一段苹果本地校验成功的json返回 估计服务器也是相同的

    Printing description of jsonResponse:
    {
        environment = Sandbox; //购买环境 
        receipt =     {
            "adam_id" = 0;
            "app_item_id" = 0;
            "application_version" = 30;
            "bundle_id" = "com.wesk.PaoBa";
            "download_id" = 0;
            "in_app" =         (
                            {
                    "is_trial_period" = false;
                    "original_purchase_date" = "2016-09-27 04:52:58 Etc/GMT";
                    "original_purchase_date_ms" = 1474951978000;
                    "original_purchase_date_pst" = "2016-09-26 21:52:58 America/Los_Angeles";
                    "original_transaction_id" = 1000000238538249;
                    "product_id" = “com.PaoBa.Product.001";
                    "purchase_date" = "2016-09-27 04:52:58 Etc/GMT";
                    "purchase_date_ms" = 1474951978000;
                    "purchase_date_pst" = "2016-09-26 21:52:58 America/Los_Angeles";
                    quantity = 1;
                    "transaction_id" = 1000000238538249;
                }
            );
            "original_application_version" = "1.0";
            "original_purchase_date" = "2013-08-01 07:00:00 Etc/GMT";
            "original_purchase_date_ms" = 1375340400000;
            "original_purchase_date_pst" = "2013-08-01 00:00:00 America/Los_Angeles";
            "receipt_creation_date" = "2016-09-27 07:42:18 Etc/GMT";
            "receipt_creation_date_ms" = 1474962138000;
            "receipt_creation_date_pst" = "2016-09-27 00:42:18 America/Los_Angeles";
            "receipt_type" = ProductionSandbox;
            "request_date" = "2016-09-27 07:43:44 Etc/GMT";
            "request_date_ms" = 1474962224281;
            "request_date_pst" = "2016-09-27 00:43:44 America/Los_Angeles";
            "version_external_identifier" = 0;
        };
        status = 0;
    }
    

    苹果反馈的状态码;

    21000 App Store无法读取你提供的JSON数据
    21002 收据数据不符合格式 (踩过坑,越狱机会出现)
    21003 收据无法被验证
    21004 你提供的共享密钥和账户的共享密钥不一致
    21005 收据服务器当前不可用
    21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
    21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证
    21008 收据信息是产品环境中使用,但却被发送到测试环境中验证

    相关文章

      网友评论

          本文标题:ios 内购

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