zoukankan      html  css  js  c++  java
  • iOS应用程序内购/内付费

    很久之前就想出一篇IOS内付费的教程,但是一查网上的教程实在太多了,有的写得真的蛮不错的,就心想算了,于是就保存在草稿箱了。至于为什么写完它呢!真是说来话长,最近公司有个项目经理跑来问我有关苹果内付费相关的细节,跟他聊了半天,从项目对接苹果官方支付接口聊到了如何查看App收益,最后终于使他有了一些眉目,但是悲催的是还要我继续去跟他们项目的程序员讲解(真是疯了),所以我就决定给他们项目写一个内购的文档,所以我顺便把这篇博客完成吧!

    ========================================第一部份===================================

    首先进入苹果的ItunesConnection(https://itunesconnect.apple.com)点击左上角的加号新建一个App应用,点击后该网站会弹出一个信息编辑框,大家只要将上面的信息填充完毕点击save即可在苹果的app平台上拥有一个属于自己的App。

    在套装ID的上,需要提前为该App申请一个AppID以及BundleID,只要是申请成功了就会在选择列表中显示出来。如果有人有疑问如何申请,请看我之前那一篇推送的博客,里面有详细的步骤。附上链接点击打开链接

    这里顺便多说一句这个ItunesConnect是用来干嘛的,它是苹果公司给个人或企业提供管理自己App的一个平台。在这个平台上开发者可以新建,删除和管理自己的App应用,开发者可以根据需求对App应用进行上架与下架,编辑App信息,生成测试app所需的信息,例如账号,邀请码等,还有就是我们今天要讲的内付费功能。当然啦,他的功能可不止我讲的这些,我大致说一下这个平台的作用,如果你经常跟它打交道的话就会慢慢熟悉了。

    ============================================第二部分=====================================

    接下来,我就来为大家演示一下如何添加付费道具,首先打开iTunesConnect,显示如下页面

    选择红圈所圈起来的选项,然后将里面的相关信息补充完毕,如果缺少这一步,内购功能是不会成功的。

    假如你已经完成了上述相关银行账户的设置,就点击你的App,选择上面标题栏中的"App 内购买项目"

    随后点击左上角的 "create new"选项,如下图所示,进入到下一个界面

    这个界面是让你选择消费道具的种类,现在改版的网站是有简体中文翻译的,所以不像以前打开一看都不知道选哪一个,甚至都不知道每个代表的什么意思(比如我第一次遇到的时候,在领导面前真是囧)。它的种类分为如下几种:

    一般对项目来说大多数都是选择“消耗型项目”这个种类,比如游戏中购买金币,宝石balabala~之类的,选中之后就会到这个界面中来:

    在上图所示的编辑框中输入,商品名称,产品ID以及价格等级,在这边说明一下:

    1.商品名称根据你的消费道具的实际意义来说明,比如“100颗宝石”,“100金币”等。

    2.产品ID是比较重要的,由项目自定义,只要唯一即可,像我一般都是用App的bundleID加一个后缀来表示,这样既跟项目关联又具有唯一性。

    3.价格等级的话“查看价格表”中有对应的说明,可以对照着表中每个国家的货币价格与等级来选择。

    我们继续,在这个网页的接下来部分如图所示:

    选择添加语言选项,弹出一个编辑页面:

    点击save保存,则会在界面上显示成如下:

    最后一步就是点击“选取文件”提交一张苹果它指定像素(640*920)的商品图片,当他上传完毕后点击“save”按钮,我们这第二部分就大工告成了。提交的商品最后会在内购的页面上显示为如图:

    这个图是我在已经发布的app上面截取的,添加了3个商品,已经是通过的的状态了(显示绿色),当您刚提交的时候,因为通过苹果的审查需要一段时间所以会显示黄色的等待状态,所以不必担心是不是商品编辑错了。如图:

    =====================================第三部分======================================

    这部分,我主要给大家演示一下,如何申请测试账号,利用苹果的沙盒测试环境来模拟AppStore的购买流程。

    在ItunesConnect中选择“用户和职能”选项~

    随后在左上角的选项中选择沙盒测试者,点击左上角的加号图标增加一位测试者,如图:

    编辑好相应的内容,点击保存,就创建了一个测试账号,是不是很简单啊!当然这个账号如果你忘记了密码可以重新生成一个,无关紧要。

    顺带多句嘴,千万不要在正式的appstore上面用沙盒测试的账号来登录,不然后果很严重,千万要牢记在心,此账号只用于测试环境下~

    =====================================第四部分===========================================

    接下来就是代码部分啦~

    1.首先在项目工程中加入“storekit.framework”,加入头文件#import <StoreKit/StoreKit.h>

    2.在.h文件中加入“SKPaymentTransactionObserver,SKProductsRequestDelegate”监听机制

    下面贴上内购的核心代码,就几个函数,我在这边就不在做更多详细的解释了,各位看官可以运行跑一下就一目了然了。

    .h文件

    1. //  
    2. //  PaymentViewController.h  
    3. //  IAPPayTest  
    4. //  
    5. //  Created by silicon on 14-10-28.  
    6. //  Copyright (c) 2014年 silicon. All rights reserved.  
    7. //  
    8.   
    9. #import <UIKit/UIKit.h>  
    10.   
    11. #import <StoreKit/StoreKit.h>  
    12.   
    13. @interface PaymentViewController : UIViewController<SKPaymentTransactionObserver,SKProductsRequestDelegate>  
    14.   
    15. @property (strong, nonatomic) IBOutlet UITextField *productID;  
    16.   
    17. @property (strong, nonatomic) IBOutlet UIButton *purchase;  
    18.   
    19. - (IBAction)purchaseFunc:(id)sender;  
    20.   
    21. @end  


    .m文件

    1. //  
    2. //  PaymentViewController.m  
    3. //  IAPPayTest  
    4. //  
    5. //  Created by silicon on 14-10-28.  
    6. //  Copyright (c) 2014年 silicon. All rights reserved.  
    7. //  
    8.   
    9. #import "PaymentViewController.h"  
    10.   
    11. @interface PaymentViewController ()  
    12.   
    13. @end  
    14.   
    15. @implementation PaymentViewController  
    16.   
    17. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
    18. {  
    19.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
    20.     if (self) {  
    21.         // Custom initialization  
    22.     }  
    23.     return self;  
    24. }  
    25.   
    26. - (void)viewDidLoad  
    27. {  
    28.     [super viewDidLoad];  
    29.     // Do any additional setup after loading the view from its nib.  
    30.       
    31.     [[SKPaymentQueue defaultQueue] addTransactionObserver:self];  
    32.     self.productID.text = @"com.games.ztyxs.product_point.1";  
    33. }  
    34.   
    35. - (void)didReceiveMemoryWarning  
    36. {  
    37.     [super didReceiveMemoryWarning];  
    38.     // Dispose of any resources that can be recreated.  
    39. }  
    40.   
    41. - (IBAction)purchaseFunc:(id)sender {  
    42.     NSString *product = self.productID.text;  
    43.     if([SKPaymentQueue canMakePayments]){  
    44.         [self requestProductData:product];  
    45.     }else{  
    46.         NSLog(@"不允许程序内付费");  
    47.     }  
    48. }  
    49.   
    50. //请求商品  
    51. - (void)requestProductData:(NSString *)type{  
    52.     NSLog(@"-------------请求对应的产品信息----------------");  
    53.     NSArray *product = [[NSArray alloc] initWithObjects:type, nil nil];  
    54.   
    55.     NSSet *nsset = [NSSet setWithArray:product];  
    56.     SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];  
    57.     request.delegate = self;  
    58.     [request start];  
    59.       
    60. }  
    61.   
    62. //收到产品返回信息  
    63. - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{  
    64.   
    65.     NSLog(@"--------------收到产品反馈消息---------------------");  
    66.     NSArray *product = response.products;  
    67.     if([product count] == 0){  
    68.         NSLog(@"--------------没有商品------------------");  
    69.         return;  
    70.     }  
    71.       
    72.     NSLog(@"productID:%@", response.invalidProductIdentifiers);  
    73.     NSLog(@"产品付费数量:%d",[product count]);  
    74.       
    75.     SKProduct *p = nil;  
    76.     for (SKProduct *pro in product) {  
    77.         NSLog(@"%@", [pro description]);  
    78.         NSLog(@"%@", [pro localizedTitle]);  
    79.         NSLog(@"%@", [pro localizedDescription]);  
    80.         NSLog(@"%@", [pro price]);  
    81.         NSLog(@"%@", [pro productIdentifier]);  
    82.           
    83.         if([pro.productIdentifier isEqualToString:self.productID.text]){  
    84.             p = pro;  
    85.         }  
    86.     }  
    87.       
    88.     SKPayment *payment = [SKPayment paymentWithProduct:p];  
    89.       
    90.     NSLog(@"发送购买请求");  
    91.     [[SKPaymentQueue defaultQueue] addPayment:payment];  
    92. }  
    93.   
    94. //请求失败  
    95. - (void)request:(SKRequest *)request didFailWithError:(NSError *)error{  
    96.     NSLog(@"------------------错误-----------------:%@", error);  
    97. }  
    98.   
    99. - (void)requestDidFinish:(SKRequest *)request{  
    100.     NSLog(@"------------反馈信息结束-----------------");  
    101. }  
    102.   
    103.   
    104. //监听购买结果  
    105. - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{  
    106.     for(SKPaymentTransaction *tran in transaction){  
    107.           
    108.         switch (tran.transactionState) {  
    109.             case SKPaymentTransactionStatePurchased:  
    110.                 NSLog(@"交易完成");  
    111.                   
    112.                 break;  
    113.             case SKPaymentTransactionStatePurchasing:  
    114.                 NSLog(@"商品添加进列表");  
    115.                   
    116.                 break;  
    117.             case SKPaymentTransactionStateRestored:  
    118.                 NSLog(@"已经购买过商品");  
    119.               
    120.                 break;  
    121.             case SKPaymentTransactionStateFailed:  
    122.                 NSLog(@"交易失败");  
    123.                   
    124.                 break;  
    125.             default:  
    126.                 break;  
    127.         }  
    128.     }  
    129. }  
    130.   
    131. //交易结束  
    132. - (void)completeTransaction:(SKPaymentTransaction *)transaction{  
    133.     NSLog(@"交易结束");  
    134.       
    135.     [[SKPaymentQueue defaultQueue] finishTransaction:transaction];  
    136. }  
    137.   
    138.   
    139. - (void)dealloc{  
    140.     [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];  
    141.     [super dealloc];  
    142. }  
    143.   
    144. @end  


    代码就这么多,到这边我们的IOS内购教程就接近尾声了,在测试的时候还有几点因素要注意一下:

    1.沙盒环境测试appStore内购流程的时候,请使用没越狱的设备。

    2.请务必使用真机来测试,一切以真机为准。

    3.项目的Bundle identifier需要与您申请AppID时填写的bundleID一致,不然会无法请求到商品信息。

    讲了这么多,附上几张测试截屏给大家展示一下:

    请求商品时的打印日志

    交易成功后:

    手机截屏:

    要求输入AppStore帐密,使用测试生成的即可

    确定购买:

    交易完成:

     如何使用iTunes Connect这个平台:

    这个平台来查询App应用的收费情况。虽然比较简单,篇幅也比较小,但是我是一个追求完美的人(哈哈,装个叉),所以力争做到有头有尾。

    首先,打开iTunesConnect网站,映入大家眼帘的是如下图所示的7个功能:

    1.我的App主要用于管理自己的App应用,例如编辑资料,上架,下架等。

    2.销售和趋势主要是来查看App在各个平台的下载量,收入等方面数据,里面有曲线图等图文结合的方式给我们参考。

    3.付款和财务报告显示的是你的收入以及付款等相关信息。

    4.iAd主要是跟广告有关,开发者可以登录到Workbench,通过iAd对应用的广告进行控制。

    5.用户和职能用于生成相应账号,例如苹果沙河测试账号。

    6.协议,税务和银行业务则是你银行相关账户的信息设置。

    在这里我们主要是使用“销售和趋势”选项,点击打开它,我截取的是他的上半部分,下面是项目的一些数据,不好意思啊!不方便透露,所以没有截取,哈哈~

    通过方框1的选项,您可以过滤检索相关信息,直接查到你要的数据。

    方框2的选项是某一段时间区间内的数据,你可以拉取指定时间内的数据进行查看分析,默认最近是一个礼拜的数据。

    方框3是根据不同选项来显示不同的数据,如果你选择“Territory“则显示的是你App在各个地区的数据,Platform则是各个平台的数据如iphone, ipad~剩下的以此类推。

    方框4则是可以选择是曲线图还是柱状图。

    方框5你点击的话 可以将数据以xlsx或者cvs的文档格式保存在本地。

    说了这么些它的是不是功能很强大啊!不过光听我说这些还是不够的,关键是要自己亲自动手去点一下,好了今天就到这里啦!某人在催着休息了~

    如果讲得有什么不对的地方或者不清楚的地方,希望大家私信或者评论,我一定及时回复,谢谢~祝大家晚安。

    =======================我是分割线================================

    此为转载,原作为CSND:http://blog.csdn.net/shenjie12345678/article/details/40978977

  • 相关阅读:
    字符串 CSV解析 表格 逗号分隔值 通讯录 电话簿 MD
    Context Application 使用总结 MD
    RxJava RxPermissions 动态权限 简介 原理 案例 MD
    Luban 鲁班 图片压缩 MD
    FileProvider N 7.0 升级 安装APK 选择文件 拍照 临时权限 MD
    组件化 得到 DDComponent JIMU 模块 插件 MD
    gradlew 命令行 build 调试 构建错误 Manifest merger failed MD
    protobuf Protocol Buffers 简介 案例 MD
    ORM数据库框架 SQLite 常用数据库框架比较 MD
    [工具配置]requirejs 多页面,多入口js文件打包总结
  • 原文地址:https://www.cnblogs.com/tate-zwt/p/4527595.html
Copyright © 2011-2022 走看看