苹果内购买笔记

苹果内购买包括4种类型:1.消耗性;  2.非消耗性;3.自动续订订阅;4.非续订订阅.

首先需要有一个itunesconnect上协议、税务和银行业务模块中有银行卡绑定同时遵守了各种苹果协议的开发帐号;(具体如何申请填写网上百度一堆)

然后代码前记得添加协议

<SKPaymentTransactionObserver,SKProductsRequestDelegate,SKRequestDelegate>

//购买点击
-(void)payBtnClick
{
    //购买
        if ([SKPaymentQueue canMakePayments]) {
            [self requestProductData:ProductId];

        } else {
            NSLog(@"用户禁止应用内付费购买.");

        }
}
//恢复点击
-(void)restoreClick
{
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

//请求商品
- (void)requestProductData:(NSString *)type{
    NSLog(@"----------请求对应的产品信息---------");
    NSArray *product = [[NSArray alloc] initWithObjects:type, nil];
    NSSet *nsset = [NSSet setWithArray:product];
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
    request.delegate = self;
    [request start];

}

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{

    NSLog(@"----------收到产品反馈消息-------------");
    NSArray *product = response.products;

    if(product.count == 0){
        NSLog(@"------没有商品,商品个数为%ld--------",product.count);
        return;
    }

    SKProduct *p = nil;
    for (SKProduct *pro in product) {

        if([pro.productIdentifier isEqualToString:ProductId]){
            p = pro;
        }
    }

    SKPayment *payment = [SKPayment paymentWithProduct:p];

    NSLog(@"发送购买请求");

    [[SKPaymentQueue defaultQueue] addPayment:payment];

}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易结果
{

    NSLog(@"paymentQueue");
    for (SKPaymentTransaction *transaction in transactions)
    {

        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStateRestored://已经购买过该商品,恢复商品
                [self restoreTransaction:transaction];
                NSLog(@"-----已经购买过该商品 恢复商品--------");
                //                [[XTool shareAppHandle]showWait:NO];
                break;
            case SKPaymentTransactionStatePurchased://交易完成
                [self completeTransaction:transaction];
                NSLog(@"-----交易完成 --------");
                break;
            case SKPaymentTransactionStateFailed://交易失败
                [self failedTransaction:transaction];
                NSLog(@"-----交易失败 --------");
                [[XTool shareAppHandle]showPaiXuWait:NO];
                break;
            case SKPaymentTransactionStatePurchasing:      //商品添加进列表
                NSLog(@"-----商品添加进列表 --------");
                break;
            case SKPaymentTransactionStateDeferred:
                break;
            default:
                break;
        }
    }

}

//完成恢复
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
    NSLog(@"paymentQueueRestoreCompletedTransactionsFinished");

    NSLog(@"%@",[queue description]);

    NSLog(@"-----完成恢复--------");

}

- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
    NSLog(@" 交易恢复处理");
    NSLog(@"-----恢复成功--------");

    NSData *iapData = transaction.transactionReceipt;

    // Your application should implement these two methods.
    NSString *product = transaction.payment.productIdentifier;
    if ([product length] > 0) {

        NSArray *tt = [product componentsSeparatedByString:@"."];
        NSString *bookid = [tt lastObject];
        if ([bookid length] > 0) {
            [self recordTransaction:bookid];
            [self provideContent:bookid];
        }
    }

    NSString *results = [[NSString alloc]initWithBytes:[iapData bytes] length:[iapData length] encoding:NSUTF8StringEncoding];

    {
        //    恢复交易信息发送给服务器代码
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

//记录交易
-(void)recordTransaction:(NSString *)product{
    NSLog(@"-----记录交易--------");
}

//处理下载内容
-(void)provideContent:(NSString *)product{
    NSLog(@"-----下载--------");
}

-(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{
    NSLog(@"-----PurchasedTransaction----");
    NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
    [self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

- (void) completeTransaction: (SKPaymentTransaction *)transaction

{
    NSLog(@"-----购买成功--------");

    NSData *iapData = transaction.transactionReceipt;

    // Your application should implement these two methods.
    NSString *product = transaction.payment.productIdentifier;
    if ([product length] > 0) {

        NSArray *tt = [product componentsSeparatedByString:@"."];
        NSString *bookid = [tt lastObject];
        if ([bookid length] > 0) {
            [self recordTransaction:bookid];
            [self provideContent:bookid];
        }
    }

    NSString *results = [[NSString alloc]initWithBytes:[iapData bytes] length:[iapData length] encoding:NSUTF8StringEncoding];
    NSLog(@"%@",results);

    {
            //购买信息发送给服务器
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}    

- (void) failedTransaction: (SKPaymentTransaction *)transaction{

    if (transaction.error.code != SKErrorPaymentCancelled)
    {
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{

    NSLog(@" 购买失败");
}

-(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{
    NSLog(@"-------paymentQueue----");
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    NSLog(@"%ld",(long)[(NSHTTPURLResponse *)response statusCode]);
    switch([(NSHTTPURLResponse *)response statusCode]) {
        case 200:
        case 206:
            break;
        case 304:
            break;
        case 400:
            break;
        case 404:
            break;
        case 416:
            break;
        case 403:
            break;
        case 401:
        case 500:
            break;
        default:
            break;
    }
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"test");
}

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

}

- (BOOL)verify:(SKPaymentTransaction *)transaction
{
    return YES;
}

购买所需基本代码如上;

1.消耗型

宏定义(或者从服务器都行,看需求)获取个购买产品的ID(itunesconnect上申请的产品ID),将上面代码中

ProductId替换成购买产品的ID

然后将返回信息发送给服务器进行处理

然后服务器端和苹果进行购买验证,确认购买成功后,返回给客户端购买产品成功

客户端显示相应购买内容。

2.非消耗型

同消耗型,唯一区别是重复购买,苹果会提示你不能重复购买。跟客户端及服务器没啥关系。

3.自动续订订阅

购买流程同消耗型,多了个恢复购买,同时在显示时一定要有提醒用户当前订阅为自动续订的文字说明,否则苹果审核可能被拒

恢复流程时,用户点击恢复购买后,执行

restoreClick方法

进行恢复流程正常的话会执行(不正常,就需要检查产品申请的内容;沙盒测试帐号问题;等等前面步骤是否有错)

restoreTransaction方法

在获取到用户购买信息后客户端传给服务器,服务器端和苹果进行数据验证,验证无误后返回给客户端相应用户应该恢复的产品内容,客户端进行展示。

4.非续订订阅

购买流程同消耗型;

恢复流程需要进入页面后点击恢复时执行

restoreClick方法

同时执行如下代码进行用户购买记录数据获取,不断获取直到获取到或者用户取消恢复为止。

    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];
    NSError *error = nil;
    NSData *iapData  = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
        NSString *transactionReceiptString = [iapData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];

如果获取到说明用户已经输入了AppleID,并进行了恢复操作;

此时将获取到的用户购买记录及当前恢复产品ID发送给服务器,服务器和苹果进行购买确认。如果已经购买此产品,则向客户端返回恢复成功信息。客户端展示相应需要恢复展示的内容。

时间: 2024-08-24 19:26:59

苹果内购买笔记的相关文章

苹果内购笔记

前提 苹果的开发者证书那边,已经为应用启用App内购,在Xcode更新配置文件 itunes store中的设置 itunes中创建App及其它设置 参考:iOS应用程序内购/内付费(一)  http://blog.csdn.net/shenjie12345678/article/details/40978977   1.一定要同意协议.银行.税务的协议,才能创建有价格的商品,且协议的状态一定要是已经生效 ,一般一两小时内就可以生效 参考:iOS App提交指南-协议.税务和银行业务 2.启用沙

苹果内购流程详解

苹果内购主要分为两部分 itunnes 相关配置 一.在itunnes 上配置相关信息资料 首先需要配置一些前提条件,详细步骤如下 1.进入itunnes选择协议,税务银行业务 2.完善资料信息,主要有3项(联系人,银行信息,税务信息) 4.完善联系人信息,一般填申请开发者账号人员的信息,可以修改 5.完善银行信息 需要银行支付号(就是开户银行的一个标识),银行卡持有人名字 6.完善税务信息 7.以下默认选择no 8.确认界面,下图可能不太对,当时我是上下2个界面,第四项要上下一致才行 二.上面

IAP-应用内购买

[-] In App Rage 管理 In App Purchases Retrieving Product List提取产品列表 Subclassing for Your App 添加帮助类代码 显示产品列表 给我钱看看 In App Purchases Accounts and the Sandbox 何去何从 前言:自我总结--- loadStore(监听交易,请求产品描述:完成交由委托->获取产品描述-.交给fetch自定义委托LB显示)-> 2,点击购买->激活交易监听进行购买

苹果内购和 Apple Pay

作者:CC老师_MissCC链接:http://www.jianshu.com/p/e3bc47e81785來源:简书 苹果内购 1.什么是内购? 如果你购买的商品,是在本app中使用和消耗的,就一定要用内购,否则会被拒绝上线,例如:游戏币,在线书籍,app中使用的道具等虚拟产品.如果购买的就是普通的商品,例如淘宝买东西等,就不需要用内购.内购的话,苹果公司需要抽取30%佣金. 当然,打赏功能被纳入内购项目中.所以例如微信打赏功能.直播项目打赏主播都必须采用内购. 可以简单理解成,带有内购功能的

关于苹果内购(IAP)的一些问题以及那些坑

最近在研究苹果内购功能,所以,在网上找了一些资料,进行学习.但是,内购功能在实现的过程中,有很多坑,笔者算是真的遇到了好多啊,下面也是自己对内购的一些心得与体会吧! 我这里说的可能不太详尽,所以,我先把再网上看到的一些帖子贴在这里,以便大家做内购的时候,方便查找相关信息. 这里是一篇写的比较全面的帖子,但是没有写中间问题处理: <iOS开发内购全套图文教程> 在网上搜了一些相关的帖子,简单归纳总结了一下,觉得论坛里有一个叫Teng的世界的大神,写了三篇博客,写的很详细: [IAP支付之一]In

IOS,苹果内购和添加广告

内购——应用内购买 通过苹果应用程序商店有三种主要赚钱的方式: 直接收费(与国内大部分用户的消费习惯相悖) 广告(降低用户体验 应用程序名称带Lite可以添加广告) O2O -> Online推广 & Offline交易,闭环 不要砍功能,增加内容,而不是增加功能 内购:应用程序本身的增值产品,游戏装备,应用程序中增值功能同样可以内购 第三方支付:跟应用程序无关的 内购分成:三(苹果)七(开发商)开 提示: 要做好游戏 & 应用,一定要研究心理,要研究哲学 人人都是产品经理 内购的五

苹果内购支付对接

public bool ValidateApplePay() { //客户端post过来的参数 string appleReceipt = Request.Form["appleReceipt"]; //苹果内购的验证收据 string orderId = PayHelper.GetOrderIDByPrefix("AP");  //订单编号 string amount = Request.Form["amount"];             

苹果内购服务器验证之receipt返回多组in_app思考

最近有部分用户反映,苹果内购充值失败,经过测试总结有几个关键点出现问题 1.app购买成功苹果没有返回票据,属于票据遗漏(取决于苹果服务器的响应状况),只能客户端进行监听刷新等处理 2.app连续购买的过程中,前几次苹果没有返回票据,几次之后,苹果返回了一个有效的票据,app提交给服务器进行验证的过程中in_app出现多组数据的情况,这种情况还是能充值成功了,只是不能全部到账 3.app连续购买,有一次正常返回票据,在提交给服务器的过程中出现意外,但实际服务端已经接受到票据,为用户成功充值,但a

iOS:苹果内购实践

iOS 苹果的内购 一.介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝等),当然开发者可以设置后门,在审核时避开审核人员.这个是有风险的,一旦发现,app会被立即下架,还是老老实实接入内购吧. 二.注意 内购接入还是比较简单的,苹果提供了专门的框架<StoreKit/StoreKit.h>,只要按照它提供的api进行开发就行.然而,接入的过程还是有需要注意的地方,分别是:漏单处理