platojobs / Iap-In-App-Purchases

Iap-In-App Purchases IOS应用内支付IAP

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Iap-In-App-Purchases

Iap-In-App Purchases IOS应用内支付IAP


流程

一般有以下几种内购流程

  1. 直接使用Apple的服务器进行购买和验证
  2. 就是自己假设服务器进行验证 网上有几张图,不过是英文版的,看着流程也很复杂,其实很简单,我简单说一下

第一种流程就是用户在买你app里面的道具A的时候,点击了购买按钮 这时候你的app会发送一个请求给苹果服务器,告诉它,我要买A 由于苹果服务器那边你已经配置好了有哪些东西(后面会叫你怎么在那边配置你要卖的商品ABCD),苹果找出商品A,然后itunes store会向你确认是否真的要买A(只要用过苹果支付的基本都知道) 用户确定了以后,苹果服务器会给你返回一个购买凭证,app再把东西下发给用户,ok了 但是,一般的app都有自己的服务器,道具之类的物品也都是存在服务器的,所以,往往我们会采取第二种方式—把这个购买凭证发给我们自己的服务器,然后我们服务器通过给苹果服务器发送这个凭证来校验是不是真的,是真的,就下发道具,不是,则不下发!



- (void)viewDidLoad {
    [super viewDidLoad];
    
    //设置购买的观察者,处理购买的
    [[SKPaymentQueue defaultQueue]addTransactionObserver:self];
    // Do any additional setup after loading the view, typically from a nib.
}
//用户点击了一个IAP项目,我们事先需要查询用户是否允许应用内购买,如果不允许则不用进行以下步骤了
- (IBAction)pochaseAC:(UIButton *)sender {
    if ([SKPaymentQueue canMakePayments]) {
        //
    }else{
        NSLog(@"失败,用户禁止应用内付费购买");
    }
    
}
/*先通过该IAP的ProductID 向APP store查询,获得SKPayment实例,通过SKPaymentQueue 的addPayment方法发起一个购买的操作*/
- (void)getProductInfo{
    NSSet *set=[NSSet setWithArray:@[@"ProductId"]];
    SKProductsRequest* request = [[SKProductsRequest alloc]initWithProductIdentifiers:set];
    request.delegate=self;
    [request start];
}
/*以上查询的回调函数*/
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    NSArray * myProduct = response.products;
    if (myProduct.count==0) {
        NSLog(@"无法获取产品信息,购买失败");
        return;
    }
    SKPayment *payment = [SKPayment paymentWithProduct:myProduct[0]];
    [[SKPaymentQueue defaultQueue]addPayment:payment];
    
    
}

#pragma mark处理观察者的回调
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    for (SKPaymentTransaction * transaction in transactions) {
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchased:
                NSLog(@"transactionIdentifier= %@",transaction.transactionIdentifier);
                //交易完成
                [self transactionsSuccess:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                [self transactionsFailed:transaction];
                break;
            case SKPaymentTransactionStateRestored:
                [self transactionsRestored:transaction];
                break;
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"商品添加进列表");
                break;
            case SKPaymentTransactionStateDeferred:
                NSLog(@"事务在队列中,但它的最终状态是等待外部操作");
                break;
                
            default:
                break;
        }
    }
    
    
}
#pragma mark==交易完成的操作
-(void)transactionsSuccess:(SKPaymentTransaction*)transaction{
    
    //your app should implement these two methods
    
    NSString * productIdentifer = transaction.payment.productIdentifier;
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];
    NSURLSession *session = [NSURLSession sharedSession];
    // 创建任务
    NSURLSessionDataTask *task = [session dataTaskWithRequest:urlRequest  completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
        NSString * receipt = [data base64EncodedStringWithOptions:0];
        if (productIdentifer.length>0) {
            //向自己的服务器验证购买凭证  receipt 给服务器验证
            /*这里是可选的。也可以不验证。如果购买成功,如果购买成功,我们需要将凭证发送到服务器上进行验证。
            老点到网络异常情况,iOS 端的发送凭证操作应该可以持久化,如果程序退出、崩溃或
            网络异常,可以恢复重试。*/
        }
        // remove the paymentQueue
        [self removePaymentQueue:transaction];
    }];
    // 启动任务(必须的)
    [task resume];
    
}
#pragma mark cancel or fail
-(void)transactionsFailed:(SKPaymentTransaction*)transaction{
    
    if (transaction.error.code!=SKErrorPaymentCancelled) {
        NSLog(@"购买失败");
    }else{
        NSLog(@"购买取消");
    }
    [self removePaymentQueue:transaction];
}
#pragma mark Restored
-(void)transactionsRestored:(SKPaymentTransaction*)transaction{
    
    //对于已经购买过的商品,处理恢复购买的逻辑
    // insert your code here
    [self removePaymentQueue:transaction];
    
}
#pragma mark==remove the paymentQueue
-(void)removePaymentQueue:(SKPaymentTransaction*)transaction{
     [[SKPaymentQueue defaultQueue ]finishTransaction:transaction];
}
//移除观察者
-(void)dealloc{
    [[SKPaymentQueue defaultQueue]removeTransactionObserver:self];
}

/*
服务端的开发:
 
 服务端后台的工作比较简单,分为4步:
 1.接收iOS端发过来的购买凭证。
 2.判断凭证是否已经存在,是否验证过,然后存储该凭证。
 3.将该凭证发送到苹果的服务器验证,并将验证结果返回给客户端。
 4.如果需要,修改用户相应的会员权限。
 考虑到网络异常情况,服务器的验证应该是一一个可恢复的队列,如果失败了,应该进行重
 试。
 与苹果的验证接口文档在http://developer.com/library/ios/#documentation/NeworkinInternet/Conceptual/StoreKitGuide/Verifyingstoreceipts/VerifingStoreReceipts.html#//apple_ref/doc/uid/TP40008267-CH104-SW3。简单来说就是将该购买凭证用Base64编码,然后POST给苹果的验证服务器,苹果将验证结果以jSON形式返回。
 苹果App Store线上的购买凭证验证地址是https://buy.itunes.apple.com/verifyRceipt
 ,测试的验证地址是https://sandbox.itunes.apple.com/verifyRceipt
 
 */

About

Iap-In-App Purchases IOS应用内支付IAP


Languages

Language:Objective-C 100.0%