iOS内购看我就够了(含代码)

内购是啥

App 内购买项目允许顾客通过访问 App Store 购买您 App 中的内容、功能或服务,并安全处理来自用户的付款。

详情传送门https://help.apple.com/itunes-connect/developer/#/devb57be10e7

下面来说内购集成流程

1.协议

登录苹果开发者中心,进入iTunes Connect,再进入“协议、税务和银行业务”页面,如图


图1.协议入口

点击进入可以看到,目前共有两个分组,三种合同。(此处有坑,比如我们当前账号不能申请合同!如下图)

Request Contracts 可以申请的合同;

Contracts In Effect 已经生效的合同。

三种合同分别是

Free Applications 免费应用(默认已经生效);

Paid Applications 付费应用,需要申请;

iAd App Network 广告应用,需要申请。


图2.未申请样式

内购对应的是Paid Applications 付费应用,需要申请,如图2.(如果Request按钮不显示,则说明当前账号权限有问题)

点击Request完善信息,提交就行.

2.内购集成

内购实现流程:

1.客户端向Appstore请求购买产品(假设产品信息已经取得),Appstore验证产品成功后,从用户的Apple账户余额中扣费。

2.Appstore向客户端返回一段receipt-data,里面记录了本次交易的证书和签名信息。

3.客户端向我们可以信任的服务器提供receipt-data

4.服务器对receipt-data进行一次base64编码

5.把编码后的receipt-data发往itunes.appstore进行验证

6.itunes.appstore返回验证结果给服务器

7.服务器对商品购买状态以及商品类型,向客户端发放相应的道具与推送数据更新通知

注,下图3步骤和上面流程不是一一对应

图3.内购流程

我项目里面的购买流程,加入了一点业务逻辑和后台验证流程,有什么问题欢迎大家指出.


图4.完整内购流程

3.去苹果开发者中心创建内购商品

如下图5,点击+号去创建内购商品,产品id最好是当前应用+数字,价格区间苹果提供了一张表,商品价格只能是表上的价格,苹果会抽取30%,商家能收到的钱是用户充值的70%.这就造成了部分平台区分安卓和苹果.两端账号不互通,也造就了代充行业,再次就不展开说了.

商品价格大于100$,提交审核的时候要说明这个金额是确认过的,不然可能会被拒


图5.添加内购商品

4.代码集成

建议单独建一个类来处理内购业务


导入头文件#import <StoreKit/StoreKit.h>

遵循协议<SKPaymentTransactionObserver,SKProductsRequestDelegate>

 [[SKPaymentQueue defaultQueue] addTransactionObserver:self];// 4.设置支付服务

-(void)starBuyToAppStore:(NSString *)goodsID{    if ([SKPaymentQueue canMakePayments]) {//5.判断app是否允许apple支付              [self getRequestAppleProduct:goodsID];// 6.请求苹果后台商品            } else {//        NSLog(@"not");    }}

#pragma mark ------ 请求苹果商品- (void)getRequestAppleProduct:(NSString *)goodsID{    self.goodsId = goodsID;//把前面传过来的商品id记录一下,下面要用    // 7.这里的com.czchat.CZChat01就对应着苹果后台的商品ID,他们是通过这个ID进行联系的。    NSArray *product = [[NSArray alloc] initWithObjects:goodsID,nil];    NSSet *nsset = [NSSet setWithArray:product];        //SKProductsRequest参考链接:https://developer.apple.com/documentation/storekit/skproductsrequest    //SKProductsRequest 一个对象,可以从App Store检索有关指定产品列表的本地化信息。    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];// 8.初始化请求    request.delegate = self;    [request start];// 9.开始请求}

// 10.接收到产品的返回信息,然后用返回的商品信息进行发起购买请求- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{    NSArray *product = response.products;        if([product count] == 0){//如果服务器没有产品        return;    }        SKProduct *requestProduct = nil;    for (SKProduct *pro in product) {//        NSLog(@"%@", [pro description]);//        NSLog(@"%@", [pro localizedTitle]);//        NSLog(@"%@", [pro localizedDescription]);//        NSLog(@"%@", [pro price]);//        NSLog(@"%@", [pro productIdentifier]);        // 11.如果后台消费条目的ID与我这里需要请求的一样(用于确保订单的正确性)        if([pro.productIdentifier isEqualToString:self.goodsId]){            requestProduct = pro;        }    }    // 12.发送购买请求,创建票据  这个时候就会有弹框了    SKPayment *payment = [SKPayment paymentWithProduct:requestProduct];    [[SKPaymentQueue defaultQueue] addPayment:payment];//将票据加入到交易队列    }

// 13.监听购买结果- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{    if (self.delegate && [self.delegate respondsToSelector:@selector(EMAppStorePay:responseAppStorePayStatusshow:error:)]) {        [self.delegate EMAppStorePay:self responseAppStorePayStatusshow:@{@"value":transaction} error:nil];    }    for(SKPaymentTransaction *tran in transaction){//        NSLog(@"%@",tran.payment.applicationUsername);        switch (tran.transactionState) {            case SKPaymentTransactionStatePurchased:{//                NSLog(@"交易完成");                // 购买后告诉交易队列,把这个成功的交易移除掉。                //走到这就说明这单交易走完了,无论成功失败,所以要给它移出。finishTransaction                [self completeTransaction:tran];//这儿出了问题抛异常,导致下面一句代码没执行                [[SKPaymentQueue defaultQueue] finishTransaction:tran];                            }                break;                            case SKPaymentTransactionStatePurchasing://                NSLog(@"商品添加进列表");                break;                            case SKPaymentTransactionStateRestored://                NSLog(@"已经购买过商品");                [[SKPaymentQueue defaultQueue] finishTransaction:tran];                break;                            case SKPaymentTransactionStateFailed://                NSLog(@"交易失败");                [[SKPaymentQueue defaultQueue] finishTransaction:tran];                break;                            case SKPaymentTransactionStateDeferred://                NSLog(@"交易还在队列里面,但最终状态还没有决定");                break;                            default:                break;        }            }    }

#pragma mark ------ 支付完成,得到交易凭证- (void)completeTransaction:(SKPaymentTransaction *)transaction{        //此时告诉后台交易成功,并把receipt传给后台验证    NSString *transactionReceiptString= nil;    //系统IOS7.0以上获取支付验证凭证的方式应该改变,切验证返回的数据结构也不一样了。    // 验证凭据,获取到苹果返回的交易凭据    // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址    NSURLRequest *appstoreRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];    NSError *error = nil;    // 从沙盒中获取到购买凭据        NSData * receiptData = [NSURLConnection sendSynchronousRequest:appstoreRequest returningResponse:nil error:&error];    // 20 BASE64 常用的编码方案,通常用于数据传输,以及加密算法的基础算法,传输过程中能够保证数据传输的稳定性 21 BASE64是可以编码和解码的 22    transactionReceiptString = [receiptData base64EncodedStringWithOptions:0];//[receiptData base64EncodedStringWithOptions:0];    //    NSLog(@"requestContentstr:%@",[receiptData base64EncodedStringWithOptions:0]);        //    NSDictionary *dic = @{@"orderCode":self.dataOrder.orderCode,    //                          @"receipt":transactionReceiptString,    //                          @"category":@"1"    //                          };    //    NSLog(@"diczhi:%@",dic);    //    //    self.tran = transaction;    //    [self.bizEBeanBuy requestAppStorePaySuccessCallBack:dic];//苹果支付成功,传receipt-data给后台验证             [[SKPaymentQueue defaultQueue] finishTransaction:transaction];    }


5.沙盒测试

如下图6,点添加创建沙盒测试账号,账号未未注册成AppleID的账号,测试前先到设置里退出当前AppleID,登录沙盒测试账号,沙盒测试账号只能用来测试沙盒支付,不具备正常AppleID的功能.


图6.创建沙盒测试账号

需要了解双重验证,交易凭证判重机制,漏单处理,提交审核坑,集成坑,交易流水对账的朋友下方留言我抽时间补充.

补充内容和代码请看我的另一篇文章:iOS内购全面实战

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 自己开发的视频直播项目,牵涉到充值金币,用到了苹果公司的内购,趴坑了两天,这里总结下实现苹果内购。 一. 创建测试...
    Leo丶Dicaprio阅读 3,365评论 8 7
  • - 消耗型项目 就像你玩游戏需要买金币,买钻石等,只要花钱就可以无限次的购买 - 非消耗型项目 就像你在App S...
    tiger2016阅读 650评论 0 1
  • 主要做一些转载 备注在自己的简书里面。 每篇文章都注明转载 本文章转载http://www.jianshu.com...
    aEva柳絮阅读 2,157评论 0 1
  • 内购的前提: 有个人开发者账号;开通了银行业务;在开发者后台添加了内购产品;创建了相应的Bundle id 和证书...
    无wu阅读 794评论 0 0
  • 姓名:刁伟聪 公司:宁波贞观电器有限公司 宁波盛和塾《六项精进》235期谦虚二组学员 【知~学习】 背诵六项精进,...
    真诚无敌阅读 112评论 0 0