iOS 内购充值代码

//需要遵守的代理
<SKStoreProductViewControllerDelegate,UIGestureRecognizerDelegate,SKPaymentTransactionObserver,SKProductsRequestDelegate>


#import <StoreKit/StoreKit.h>

//沙盒测试环境验证
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式环境验证
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"

- (void)buyBtnAction {
    
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    
    NSArray* transactions = [SKPaymentQueue defaultQueue].transactions;
    
    for (SKPaymentTransaction *transaction in transactions) {
        
        NSLog(@"transactionState:%ld", transaction.transactionState);
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    }

    if([SKPaymentQueue canMakePayments]){
        
        NSLog(@"-------------请求对应的产品信息----------------");
        
        NSArray *product = [[NSArray alloc] initWithObjects:self.product_id,nil];
        NSSet *nsset = [NSSet setWithArray:product];
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
        request.delegate = self;
        [request start];
        
    }else{
        NSLog(@"不允许程序内付费");
    }
}

//收到产品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
    NSLog(@"--------------收到产品反馈消息---------------------");
    NSArray *product = response.products;
    if([product count] == 0){
        NSLog(@"--------------没有商品------------------");
        return;
    }
    
    NSLog(@"productID:%@", response.invalidProductIdentifiers);
    NSLog(@"产品付费数量:%lu",(unsigned long)[product count]);
    
    SKProduct *p = 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.product_id]){
            p = pro;
        }
    }
    
    SKPayment *payment = [SKPayment paymentWithProduct:p];
    
    NSLog(@"发送购买请求");
    
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    
    NSLog(@"------------------错误-----------------:%@", error);
}

- (void)requestDidFinish:(SKRequest *)request{
    
    NSLog(@"------------反馈信息结束-----------------");
}

/**
 *  验证购买,避免越狱软件模拟苹果请求达到非法购买问题
 *
 */
-(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(@"Appstore验证购买过程中发生错误,错误信息:%@",error.localizedDescription);
        return;
    }
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@",dic);
    if([dic[@"status"] intValue] == 0){
        
        NSLog(@"Appstore下购买成功!");
        [self rechargeSuccess];
    
        NSArray *items = @[MMItemMake(@"确定", MMItemTypeHighlight, nil)];
        [[[MMAlertView alloc] initWithTitle:@"充值成功!" detail:nil items:items] showWithBlock:nil];
        
        
    }else{
        
        NSLog(@"Appstore下购买失败,未通过验证!");
        
        //创建请求到苹果官方进行购买验证
        NSURL *url2 = [NSURL URLWithString:SANDBOX];
        NSMutableURLRequest *requestM2 = [NSMutableURLRequest requestWithURL:url2];
        requestM2.HTTPBody = bodyData;
        requestM2.HTTPMethod = @"POST";
        //创建连接并发送同步请求
        NSError *error2 = nil;
        NSData *responseData2 = [NSURLConnection sendSynchronousRequest:requestM2 returningResponse:nil error:&error2];
        
        if (error2) {
            
            NSLog(@"SandBox验证购买过程中发生错误,错误信息:%@",error2.localizedDescription);
            return;
        }
        NSDictionary *dic2 = [NSJSONSerialization JSONObjectWithData:responseData2 options:NSJSONReadingAllowFragments error:nil];
        NSLog(@"%@",dic2);
        if([dic2[@"status"] intValue] == 0){
            
            NSLog(@"SandBox下购买成功!");
            
            [self rechargeSuccess];
            NSArray *items = @[MMItemMake(@"确定", MMItemTypeHighlight, nil)];
            [[[MMAlertView alloc] initWithTitle:@"充值成功!" detail:nil items:items] showWithBlock:nil];
            
        }else{
            
            NSLog(@"SandBox下购买失败,未通过验证!");
            
        }
    }
}
//监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
    
    for(SKPaymentTransaction *tran in transaction){
        
        switch (tran.transactionState) {
            case SKPaymentTransactionStatePurchased:{
                NSLog(@"交易完成");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                [self verifyPurchaseWithPaymentTransaction];
                
            }
                break;
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"商品添加进列表");
                
                break;
            case SKPaymentTransactionStateRestored:{
                NSLog(@"已经购买过商品");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                
            }
                break;
            case SKPaymentTransactionStateFailed:{
                NSLog(@"交易失败");
                [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                
            }
                break;
            default:
                break;
        }
    }
}
//交易结束
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
    
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    NSLog(@"交易结束");
    
}

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

推荐阅读更多精彩内容

  • 最新更新:新增了选中项(默认选中第一个) 前言:项目中用到了内购,这里主要想记录一下内购代码封装和充值界面的封装,...
    Dxc_iOS阅读 932评论 2 3
  • 内购: --应用程序本身的增值产品,游戏装备,应用程序中增值功能同样可以内购 --三(苹果)七(开发商)开 --内...
    指头飞血阅读 5,835评论 0 2
  • 继上一篇iOS内购图文教程,下面是代码教程创建一个单例类.h文件 .m文件 在礼物页面,调起单例,添加内购代理方法...
    Aldon丶阅读 1,605评论 0 5
  • 夏日!天蓝,清澈的蓝,云白,纯净的白。 蓝如兰花,白如冰雪。 夏热,宁静,微微蝉鸣,吵闹,沙沙树摆 静如钟声,闹如鱼跃
    执笔书写自己的故事阅读 87评论 0 0
  • 故事的开始 是固执在放肆 作祟到结尾 他和她都不可一试 月亮与六便士 不一样的坚持 谁都不能越轨 无可迂回 不能轻...
    离书文阅读 691评论 0 0