iOS苹果内购详细步骤

学而时习之,不亦悦乎,大家好,我是张杰。

iOS开发支付模块分为两个部分:

1、调取外部支付,例如支付宝、微信、银联等。

2、苹果内购。

什么是苹果内购呢?从技术层面来说就是走苹果自己的支付模式,例如现在的爱奇艺APP里面购买会员,QQ斗地主里面的充值QB等。有图便于理解:

11563767294_.pic.jpg

其中图标、价格、详情等都需要到https://developer.apple.com里面去设置。具体下面会讲到。

下面我们分两块来讲:

1、代码

2、设置

一、内购所需要写的代码是非常少的,主要难点在设置部分。

1、引入头文件
#import<StoreKit/StoreKit.h>
2、设置代理
@interface AppDelegate ()<WXApiDelegate,SKProductsRequestDelegate,SKPaymentTransactionObserver>
3、开启内购检测
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
4、设置内购点击事件
-(void)buy:(NSString *)buyID{
self.productId = buyID;
if ([SKPaymentQueue canMakePayments]) {
    [self requestProductData:self.productId];
}else{
    NSLog(@"不允许程序内付费");
    [MBProgressHUD showGameAQHUDAddto:self.window text:@"不允许程序内付费"];
}
}
5、请求商品,获取商品信息,以及代理
-(void)requestProductData:(NSString *)productId{
NSLog(@"--------请求对应的产品信息------------");
[MBProgressHUD showGameAQHUDAddto:self.window text:@"请求对应的产品信息"];
NSSet *nsset = [NSSet setWithObjects:productId, nil];
_request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
_request.delegate = self;
[_request start];
}

-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(@"-------收到产品反馈消息----------");
[MBProgressHUD showGameAQHUDAddto:self.window text:@"收到产品反馈消息"];
NSArray *product = response.products;
if ([product count] == 0) {
    NSLog(@"-----没有商品-------");
    [MBProgressHUD showGameAQHUDAddto:self.window text:@"没有商品"];
    return;
}

NSLog(@"productID:%@",response.invalidProductIdentifiers);
NSLog(@"产品付费数量:%lu",(unsigned long)product.count);
//     [MBProgressHUD showGameAQHUDAddto:self.window text:@"产品付费数量"];
//    [MBProgressHUD showGameAQHUDAddto:self.window text:[NSString stringWithFormat:@"productID:%@",response.invalidProductIdentifiers]];
SKProduct *prod = nil;
for (SKProduct *pro in product) {
    NSLog(@"%@",pro.description);
    NSLog(@"%@",pro.localizedTitle);
    NSLog(@"%@",pro.localizedDescription);
    NSLog(@"%@",pro.price);
    NSLog(@"%@",pro.productIdentifier);
    
    if ([pro.productIdentifier isEqualToString:self.productId]) {
        prod = pro;
    }
}
if (prod != nil) {
    SKPayment *payment = [SKPayment paymentWithProduct:prod];
    NSLog(@"-------发送购买请求-------");
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}
}

-(void)request:(SKRequest *)request didFailWithError:(NSError *)error{
NSLog(@"购买失败");
}

- (void)requestDidFinish:(SKRequest *)request{
NSLog(@"反馈信息结束");
}
6、沙盒测试环境验证以及正式环境
//沙盒测试环境验证
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式环境验证
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
/**
 *  验证购买,避免越狱软件模拟苹果请求达到非法购买问题
 *
 */
-(void)verifyPurchaseWithPaymentTransaction{
//从沙盒中获取交易凭证并且拼接成请求体数据
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//转化为base64字符串
NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接请求数据
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
//创建请求到苹果官方进行购买验证
NSURL *url=[NSURL URLWithString:AppStore];
NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];
requestM.HTTPBody=bodyData;
requestM.HTTPMethod=@"POST";
//创建连接并发送同步请求
NSError *error=nil;
NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];
if (error) {
    NSLog(@"验证购买过程中发生错误,错误信息:%@",error.localizedDescription);
    return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dic);
if([dic[@"status"] intValue]==0){
    NSLog(@"购买成功!");
    NSDictionary *dicReceipt= dic[@"receipt"];
    NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];
    NSString *productIdentifier= dicInApp[@"product_id"];//读取产品标识
    [MBProgressHUD showGameAQHUDAddto:self.window text:@"购买成功!"];
//        [MBProgressHUD showGameAQHUDAddto:self.window text:[NSString stringWithFormat:@"购买成功--%@",dicInApp[@"product_id"]]];
    //如果是消耗品则记录购买数量,非消耗品则记录是否购买过
//        NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
//        if ([productIdentifier isEqualToString:@"123"]) {
//            int purchasedCount=[defaults integerForKey:productIdentifier];//已购买数量
//            [[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];
//        }else{
//            [defaults setBool:YES forKey:productIdentifier];
//        }
//        //在此处对购买记录进行存储,可以存储到开发商的服务器端
    
    if ([productIdentifier isEqualToString:@"111111"]) {
        [self chongzhi:@"50"];
    }else if ([productIdentifier isEqualToString:@"22222"]) {
        [self chongzhi:@"108"];
    }else if ([productIdentifier isEqualToString:@"33333"]) {
        [self chongzhi:@"158"];
    }else if ([productIdentifier isEqualToString:@"44444"]) {
        [self chongzhi:@"208"];
    }
}else if([dic[@"status"] intValue]==21007){
    [self verifyPurchaseWithPaymentTransactionSANDBOX];
}else{
    NSLog(@"购买失败,未通过验证!");
}
}

-(void)verifyPurchaseWithPaymentTransactionSANDBOX{
//从沙盒中获取交易凭证并且拼接成请求体数据
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//转化为base64字符串
NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接请求数据
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
//创建请求到苹果官方进行购买验证
NSURL *url=[NSURL URLWithString:SANDBOX];
NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];
requestM.HTTPBody=bodyData;
requestM.HTTPMethod=@"POST";
//创建连接并发送同步请求
NSError *error=nil;
NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];
if (error) {
    NSLog(@"验证购买过程中发生错误,错误信息:%@",error.localizedDescription);
    return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dic);
if([dic[@"status"] intValue]==0){
    NSLog(@"购买成功!");
    NSDictionary *dicReceipt= dic[@"receipt"];
    NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];
    NSString *productIdentifier= dicInApp[@"product_id"];//读取产品标识
    [MBProgressHUD showGameAQHUDAddto:self.window text:@"购买成功!"];
    [MBProgressHUD showGameAQHUDAddto:self.window text:[NSString stringWithFormat:@"购买成功--%@",dicInApp[@"product_id"]]];
    //如果是消耗品则记录购买数量,非消耗品则记录是否购买过
    //        NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
    //        if ([productIdentifier isEqualToString:@"123"]) {
    //            int purchasedCount=[defaults integerForKey:productIdentifier];//已购买数量
    //            [[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];
    //        }else{
    //            [defaults setBool:YES forKey:productIdentifier];
    //        }
    //        //在此处对购买记录进行存储,可以存储到开发商的服务器端
    
    if ([productIdentifier isEqualToString:@"111111"]) {
        [self chongzhi:@"50"];
    }else if ([productIdentifier isEqualToString:@"22222"]) {
        [self chongzhi:@"108"];
    }else if ([productIdentifier isEqualToString:@"33333"]) {
        [self chongzhi:@"158"];
    }else if ([productIdentifier isEqualToString:@"44444"]) {
        [self chongzhi:@"208"];
    }
}else if([dic[@"status"] intValue]==21007){
    
}else{
    NSLog(@"购买失败,未通过验证!");
}
}

代码部分已经结束。仅仅看代码已经能懂60%了。剩余不懂得看完设置就差不多了。

设置部分

设置部分需要做的是:
1、税务等填写。
2、沙河账号申请。
3、商品和价格设置。
4、Appstore显示。

由于做的时候设置部分没有截图,下面提供两个补充文档:

https://www.jianshu.com/p/bded03fdbec9

https://www.jianshu.com/p/ebdeea271352

如果有错误或者还有其他问题,可以联系我:zhangjieiossky@163.com,谢谢

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

推荐阅读更多精彩内容

  • 一、设置协议等相关 1.点击协议、税务和银行业务。 2.点击 Request Contracts 下面的 Requ...
    樊二哈阅读 16,527评论 5 15
  • 每天进步一点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点~~从开始只能写几句话、模仿别人的观点,到现...
    一个帅气的名字呀阅读 18,040评论 4 31
  • 最近上架公司的一个关于儿童英语视频的App,因为内购问题,卡了很久,现在把我的这些经历整理出来,分享给大家。 苹果...
    XiaoWhite阅读 4,621评论 0 6
  • 肩膀在疼 脖子也在疼 上周去按摩店 按摩师傅说:头疼吗 还好,我答 好长时间没来了吧 嗯,最近疼的厉害才又来了 就...
    呆丫阅读 224评论 0 6
  • 知识广度 主要表现在对行业的了解,对领域的了解。从宏观的角度来看,作为一个开发人员,我每天的工作最多的是在计算机前...
    清水芦苇阅读 343评论 0 0