iOS内购(iap)

作者: Little_Dragon | 来源:发表于2015-10-06 15:13 被阅读8137次
    通过苹果应用程序商店有三种主要赚钱的方式:

    1.直接收费(我想天朝的大多数人是不会购买的)
    2.广告 iAd Framework
    3.内购:应用程序本身的增值产品,(比如什么欢乐豆之类的)
    一般式37开, 苹果3,开发商7

    内购的产品分类:

    1>非消耗品(Nonconsumable)一旦购买,终身拥有(终身会员)
    2>消费品(Consumable),买了就用,用了就没有了(欢乐豆)
    剩下三种不常用:(中国用不上 iBooks)
    3>免费订阅
    4>自动续费订阅
    5>非自动续费订阅

    内购流程, 苹果官方说明:


    Snip20151006_3.png Snip20151006_4.png

    添加StoreKit框架,进行内购流程的书写:

    #import "ViewController.h"
    #import <StoreKit/StoreKit.h>
    
    @interface ViewController () <SKProductsRequestDelegate, SKPaymentTransactionObserver>
    
    /** 所有的产品 */
    @property (nonatomic, strong) NSArray *products;
    
    @end
    
    @implementation ViewController
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        
        // 通过观察者监听交易状态
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 向苹果服务器请求可卖的商品
        [self requestProducts];
        
        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"恢复" style:UIBarButtonItemStyleDone target:self action:@selector(restore)];
    }
    
    /**
     *  请求可卖商品
     */
    - (void)requestProducts
    {
        // 1.请求所有的商品
        NSString *productFilePath = [[NSBundle mainBundle] pathForResource:@"iapdemo.plist" ofType:nil];
        NSArray *products = [NSArray arrayWithContentsOfFile:productFilePath];
        
        // 2.获取所有的productid
        NSArray *productIds = [products valueForKeyPath:@"productId"];
        
        // 3.获取productid的set(集合中)
        NSSet *set = [NSSet setWithArray:productIds];
        
        // 4.向苹果发送请求,请求可卖商品
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
        request.delegate = self;
        [request start];
    }
    
    /**
     *  当请求到可卖商品的结果会执行该方法
     *
     *  @param response response中存储了可卖商品的结果
     */
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
    {
        /*
        for (SKProduct *product in response.products) {
            NSLog(@"价格:%@", product.price);
            NSLog(@"标题:%@", product.localizedTitle);
            NSLog(@"秒速:%@", product.localizedDescription);
            NSLog(@"productid:%@", product.productIdentifier);
        }
         */
        // 1.存储所有的数据
        self.products = response.products;
        self.products = [self.products sortedArrayWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(SKProduct *obj1, SKProduct *obj2) {
            return [obj1.price compare:obj2.price];
        }];
        
        // 2.刷新表格
        [self.tableView reloadData];
    }
    
    #pragma mark - tableView的数据源和代理方法
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.products.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *ID = @"ProductCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
        }
        
        // 1.取出模型
        SKProduct *product = self.products[indexPath.row];
        
        // 2.给cell设置数据
        cell.textLabel.text = product.localizedTitle;
        cell.detailTextLabel.text = [NSString stringWithFormat:@"价格:%@", product.price];
        
        return cell;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 1.取出模型
        SKProduct *product = self.products[indexPath.row];
        
        // 2.购买商品
        [self buyProduct:product];
    }
    
    #pragma mark - 购买商品
    - (void)buyProduct:(SKProduct *)product
    {
        // 1.创建票据
        SKPayment *payment = [SKPayment paymentWithProduct:product];
        
        // 2.将票据加入到交易队列中
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
    
    #pragma mark - 实现观察者回调的方法
    /**
     *  当交易队列中的交易状态发生改变的时候会执行该方法
     *
     *  @param transactions 数组中存放了所有的交易
     */
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
    {
        /*
         SKPaymentTransactionStatePurchasing, 正在购买
         SKPaymentTransactionStatePurchased, 购买完成(销毁交易)
         SKPaymentTransactionStateFailed, 购买失败(销毁交易)
         SKPaymentTransactionStateRestored, 恢复购买(销毁交易)
         SKPaymentTransactionStateDeferred 最终状态未确定
         */
        for (SKPaymentTransaction *transaction in transactions) {
            switch (transaction.transactionState) {
                case SKPaymentTransactionStatePurchasing:
                    NSLog(@"用户正在购买");
                    break;
                    
                case SKPaymentTransactionStatePurchased:
                    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;
            }
        }
    }
    // 恢复购买
    - (void)restore
    {
        [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
    }
    
    广告: 苹果自己搞的内容

    1.添加iAd.framework
    2.添加ADBannerView视图,并设置代理方法
    3.广告条加载完成之前最好隐藏

    -
    (void)bannerViewDidLoadAd:(ADBannerView
    *)banner {
    
        self.bannerBottomConstraint.constant
    = 20.0;    
    
        [UIView
    animateWithDuration:0.5
    animations:^{
    
            [self.view
    layoutIfNeeded];
    
        }];   
    
        NSLog(@"加载广告成功");
    
    }
    
    -
    (void)bannerView:(ADBannerView
    *)banner didFailToReceiveAdWithError:(NSError
    *)error {
    
        NSLog(@"加载广告失败
    %@",
    error);
    
    }
    

    相关文章

      网友评论

      • e78ad8a1fbde:你好 请问 非消耗项目 是要加两个按钮在上面吗 一个购买 一个恢复购买 是这个意思吗
      • airron:写的不错。订阅型内购也是这个逻辑么?
      • Aacmr:请问后台验证返回“21004 你提供的共享密钥和账户的共享密钥不一致”,怎么破?我申请的是消耗性项目,应该没有共享密匙吧?不是自动续订的才有共享密匙吗?
        e78ad8a1fbde:楼主在吗 非消耗项目 需要加两个按钮吗 一个购买 一个恢复购买的按钮 是这个意思吗
        Aacmr:@我的老师罗振宇 这个好像是苹果的问题,昨天后台说他没改,又正常了。纳闷儿呢
        Evyn_:我也遇到同样的问题,如果解决了 请分享一下 谢谢啦
      • 独酌丿红颜:clang: warning: libstdc++ is deprecated; move to libc++
        Undefined symbols for architecture arm64:
        "_OBJC_CLASS_$_SKPayment", referenced from:
        objc-class-ref in IapPayObject.o
        "_OBJC_CLASS_$_SKProductsRequest", referenced from:
        objc-class-ref in IapPayObject.o
        "_OBJC_CLASS_$_SKPaymentQueue", referenced from:
        objc-class-ref in IapPayObject.o
        ld: symbol(s) not found for architecture arm64
        clang: error: linker command failed with exit code 1 (use -v to see invocation)


        请问下这是为什么
        Little_Dragon:@独酌丿红颜 显示 库冲突 . 要移除 libc++库, 真机调试 试一下
      • 9f92e0cbf407:你好楼主,我想请问一下 自动续费 里面的一个问题。用户购买了一个月的订购产品(自动续费),下个月到期了 appstore 是不用打开我的app自动扣费吗?
        刘小壮:而且扣费的时候,你和用户都不知道,只能请求苹果服务器做验证。
        刘小壮:只要用户没有取消自动订阅,而且用户银行卡有钱,苹果自己就扣了。
      • 我是nil:不错
      • 1364f57ee045:你好,请问有没有遇到这样的情况,判断是不是允许内购总是返回YES
      • 论丶道:楼主你好 我现在iOS用内购 然后同一账号在安卓机上充值之后再在iOS端登录 也会有相应的积分 这是不是就意味着绕过了苹果的内购??这样会不会被下架??望解答,谢谢~
      • 君临浮世:楼主您好,如果我是给自己app的账号(自己的账号体系)升级永久会员,而同一个appleID可以针对多个账号进行购买的话,我是需要选择消耗型的内购吗?因为非消耗型是需要恢复购买按钮,而我的购买了就会跟app账号绑定,不能恢复购买的哦。 望解答,谢谢~
        Little_Dragon:@君临浮世 永久性产品的话,选择的是 非消耗的, 一旦购买 你的帐号就会被绑定,
      • 无wu:验证购买 怎么切换测试和上架的URL
        Little_Dragon:@80cf3878d0f1 没有区分, 无论测试还是上架都需有在内购栏添加自己的商品,才可以进行内购的选择.

      本文标题:iOS内购(iap)

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