美文网首页
iOS内购-如何防止掉单

iOS内购-如何防止掉单

作者: Dosun | 来源:发表于2017-04-14 14:39 被阅读674次

    好久没有写博客,不是因为工作太忙,只是太懒罢了。昨日,经理开除同部门兄弟(中午还和那个哥们一起吃饭,下午,人说被 HR找去谈话,就走了,哎,生活本不应该苟且,就应该是有诗和远方,若没有诗和远方,那也应该有和曹文轩笔下的草房子、油麻地的田野吖),瞬间有了危机感,害怕那一天也我会失业。我上有八十岁老母,至于下吗?嘻嘻,今年,刚满足18岁,所以还没有小呢。。。。。
    呵呵,不啰嗦了,今天要讲述一下,工作中如何处理内购成功后,如何防止掉单。对内购比较熟悉,可以直接看最后面章节如何防止掉单,大神可以略过。如下用一个思维导图展示内购的大体思路,本文也是按照思路讲述。

    Snip20170414_4.png

    一、什么是APP内购

    • APP内购简称IAP(In-App Purchase)
    • 翻译:在APP中购买,也就是在APP中让用户购买东西
    • 用户在APP中购买东西的方式:
      1> 通过第三方支付购买,比如支付宝/微信支付.
      2> APP内购
    • 集成时如何选择是要那个第三方支付还是内购?
      1> 如果用户购买的物品和应用程序本身有关系,必须采用内购(如果say NO,苹果不允许上架)
      2> 只有购买的物品与应用程序无关,才可以使用第三方支付.(比如淘宝衣服/京东电子产品/百度外卖)
    • 内购的盈利需要和苹果3:7分(苹果3,公司7)
    • 内购的常见类别:
      1> 消耗品:用完就没.(比如欢乐豆/阅读豆)
      2> 非消耗品:购买一次,永远存在.(比如游戏装备等)

    二、如何集成APP内购

    • 1.对应程序的BundleID和开发者中心配置的APPID必须是明确的
      1> 明确的APPID才能做内购(不再详细介绍)

    • 2.在iTunes Connect中创建应用程序,并且添加内购项目(让购买的物品)
      1> 填写好应用程序的基本信息
      2> 创建内购项目
      3> 添加内购项目
      4> 添加测试账号(用于测试内购)

    • 3.在程序中集成内购
      1> 内购代码

    三、添加内购项目

    因为这样的文件的技术文章,网上一大把,就不多余介绍。具体请参考iTunes Connect(一) —— iOS应用上架到AppStore

    四、添加内购项目

    由于没有配置过财务相关的信息,请参考iOS开发 内购流程 手把手教你还不学?

    五、代码的实现

    1 、向苹果服务器请求

    /*
     向苹果服务器发送内购请求,并得到内购有价格,将价格返回到游
     */
    -(void)requestProductWithIDs:(NSArray*)productIDs{
        
        //向苹果请求,得到可以卖的产品
        NSSet *productId = [NSSet setWithArray:productIDs];
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:productId];
        request.delegate = self;
        
        [request start];
        
    }
    

    2、苹果通过代理返回,将产品保存起来,并把产品的价格和id通过sendMsgToGame:发回给游戏,让Unity3D 来展示物品信息。

    //SKProductsRequestDelegate 代理方法
    // Sent immediately before -requestDidFinish:
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
        
        if (!response ) {
            NSLog(@"sorry,服务器没有响应");
            return;
        }
        //拿到苹果服务器返回的物品,并排列其顺序
        NSArray<SKProduct*> *products = [response.products sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult(SKProduct* obj1, SKProduct* obj2) {
            return [obj1.price compare:obj2.price];
        }];
        
        //设置字典,存放每个product 的id 和价格
        NSMutableDictionary *productDict = [NSMutableDictionary dictionary];
        
        //product 和ID的字典
        NSMutableDictionary *productDictID = [NSMutableDictionary dictionary];
    
        
        for (SKProduct *product  in products) {
            NSString *key = product.productIdentifier;
            NSString *value = [NSString stringWithFormat:@"%@",product.price];
            if ( key && value){
                //将物品的价格和id保存在字典中
                [productDict setObject:value forKey:key];
                [productDictID setObject:product forKey:key];
            }
            _productDict = [NSDictionary dictionary];
            
            //记录物品
            _productDict =productDictID.copy;
        }
        
        NSDictionary *mDict = [[NSDictionary alloc] initWithObjectsAndKeys:@"999",@"type",productDict,@"products", nil];
        //将物品的信息,发送给游戏,让Unity3D 来展示物品信息。
        [GDMsgService sendMsgToGame:mDict];
    }
    

    3、设置交易事件的监听者

    -(instancetype)init{
        if (self = [super init]) {
        //设置交易队列的监听者
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        }
        return self;
    }
    

    4、移除交易事件的监听者

    -(void)dealloc{
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    }
    

    5、在苹果商店购买商品,创建票据,将票据加入在交易队列中

    #pragma mark - 购买商品
    - (void)buyProduct:(SKProduct *)product
    {
        // 1.创建票据
        SKPayment *payment = [SKPayment paymentWithProduct:product];
        
        // 2.将票据加入到交易队列
        [[SKPaymentQueue defaultQueue] addPayment:payment];
        
        // 3.添加观察者,监听用户是否付钱成功
        // [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
    

    6、实现观察者协议中的方法,来监听交易的变化

    #pragma mark - 实现观察者协议中的方法,来监听交易的变化
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
    {
     
        for (SKPaymentTransaction *transaction in transactions) {
            switch (transaction.transactionState) {
                case SKPaymentTransactionStatePurchasing:
                {
                    NSLog(@"正在购买商品");
                  
                }
                    break;
                    
                case SKPaymentTransactionStatePurchased:
                {
                    if (transaction.payment.productIdentifier) {
    initWithObjectsAndKeys:@"7","type",transaction.payment.productIdentifier,@"productID",@"0",@"result", nil];         
                        NSDictionary *mDict = @{@"type": @"7",@"productID":transaction.payment.productIdentifier,@"result":@"0"};
                        [GDMsgService sendMsgToGame:mDict];
                    }
                    NSLog(@"购买成功.给用户对应商品");
                    [queue finishTransaction:transaction];
                }
                    break;
                    
                case SKPaymentTransactionStateFailed:
                    NSLog(@"购买失败");
                    [queue finishTransaction:transaction];
                    break;
                    
                case SKPaymentTransactionStateRestored:
                    NSLog(@"恢复购买");
                    [queue finishTransaction:transaction];
                    break;
                    
                case SKPaymentTransactionStateDeferred:
                    NSLog(@"未决定状态");
                    break;
                default:
                    break;
            }
        }
    }
    

    六、如何防止掉单

    相信上面代码大家都应该很熟悉,但是第六步的“实现观察者协议中的方法,来监听交易的变化”,是有问题的。如果用户付钱了,但是游戏没有得到收据,那么该怎么办?其实现有两种方式用来处理,具体的代码实现就没有写(后续会更新),只是两种可行的思路。

    第一种是无服务器(因为是单机游戏,老大说不需要服务器)

    将收据存放在本地中,然后再将数据发送给游戏,如果游戏收到数据,将返回内容给SDK,这样就可以删除本地的收据。
    A、游戏将用户点击的产品 id 和 点击时的时间(点击时间作为 key 存放在本地) 返回给 SDK(客户端)。
    B、用户购买成功,将以时间作为key, 产品id 和价格组合成数组 作为value,保存在本地中
    C、SDK(客户端)将时间、产品id 和价格发送给游戏。
    D、游戏接收成功时,会返回 点击购买的时间和reslut,SDK(客户端)将删除本地购买信息。
    E、假如本地有购买信息,将按照上面C和D的步骤操作。

    Snip20170414_3.png
    第二种有服务器

    大致思路都是一样的,先将成功买的信息存储在本地数据库中,然后再发送给服务器,成功发送给数据库后,再删除本地数据库中的成功购买的信息。


    Snip20170414_7.png

    若有不足之处,请指正,感恩!
    May maker help us all!!

    相关文章

      网友评论

          本文标题:iOS内购-如何防止掉单

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