转载注明出处:https://www.jianshu.com/p/8c958e75f98f
刚刚做了内购,记录一下
这里直接上代码,至于写代码之前的一些设置工作参考以下文章:
http://www.jianshu.com/p/690a7c68664e
http://www.jianshu.com/p/86ac7d3b593a
需要注意的是:
只要工程配置了对应的证书,就能请求商品信息,不需要任何其他处理沙盒测试填写的邮箱不能是已经绑定appleID的邮箱,也不能是AppleID的救援邮箱,其他的无所谓,其实,哪怕你填写的邮箱不存在也没有关系//// IAPManager.m// SpeakEnglish//// Created by DanIEl on 16/6/8.// copyright © 2016年 DanIEl. All rights reserved.//#import "IAPManager.h"#import <StoreKit/StoreKit.h>@interface IAPManager ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>// 所有商品@property (nonatomic,strong)NSArray *products;@property (nonatomic,strong)SKProductsRequest *request;@endstatic IAPManager *manager = nil;@implementation IAPManager+ (instancetype)shaReiaPManager { static dispatch_once_t oncetoken; dispatch_once(&oncetoken,^{ manager = [self new]; [[SKPaymentQueue defaultQueue] addTransactionObserver:manager]; }); return manager;}- (voID)dealloc { [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];}// 请求可卖的商品- (voID)requestProducts{ if (![SKPaymentQueue canMakePayments]) { // 您的手机没有打开程序内付费购买 return; } // 1.请求所有的商品ID Nsstring *productfilePath = [[NSBundle mainBundle] pathForResource:@"iapdemo.pList" ofType:nil]; NSArray *products = [NSArray arrayWithContentsOffile:productfilePath]; // 2.获取所有的productID NSArray *productIDs = [products valueForKeyPath:@"productID"]; // 3.获取productID的set(集合中) NSSet *set = [NSSet setWithArray:productIDs]; // 4.向苹果发送请求,请求可卖商品 _request = [[SKProductsRequest alloc] initWithProductIDentifIErs:set]; _request.delegate = self; [_request start];}/** * 当请求到可卖商品的结果会执行该方法 * * @param response response中存储了可卖商品的结果 */- (voID)productsRequest:(SKProductsRequest *)request dIDReceiveResponse:(SKProductsResponse *)response{ for (SKProduct *product in response.products) { // 用来保存价格 NSMutableDictionary *priceDic = @{}.mutablecopy; // 货币单位 NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; [numberFormatter setLocale:product.priceLocale]; // 带有货币单位的价格 Nsstring *formattedPrice = [numberFormatter stringFromNumber:product.price]; [priceDic setobject:formattedPrice forKey:product.productIDentifIEr]; NSLog(@"价格:%@",product.price); NSLog(@"标题:%@",product.localizedTitle); NSLog(@"秒速:%@",product.localizedDescription); NSLog(@"productID:%@",product.productIDentifIEr); } // 保存价格列表 [[NSUserDefaults standardUserDefaults] setobject:priceDic forKey:@"priceDic"]; [[NSUserDefaults standardUserDefaults] synchronize]; // 1.存储所有的数据 self.products = response.products; self.products = [self.products sortedArrayWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(SKProduct *obj1,SKProduct *obj2) { return [obj1.price compare:obj2.price]; }];}#pragma mark - 购买商品- (voID)buyProduct:(SKProduct *)product{ // 1.创建票据 SKPayment *payment = [SKPayment paymentWithProduct:product]; WELog(@"productIDentifIEr----%@",payment.productIDentifIEr); // 2.将票据加入到交易队列中 [[SKPaymentQueue defaultQueue] addPayment:payment];}#pragma mark - 实现观察者回调的方法/** * 当交易队列中的交易状态发生改变的时候会执行该方法 * * @param transactions 数组中存放了所有的交易 */- (voID)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{ /* SKPaymentTransactionStatePurchasing,正在购买 SKPaymentTransactionStatePurchased,购买完成(销毁交易) SKPaymentTransactionStateFailed,购买失败(销毁交易) SKPaymentTransactionStateRestored,恢复购买(销毁交易) SKPaymentTransactionStateDeferred 最终状态未确定 */ for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchasing: WELog(@"用户正在购买"); break; case SKPaymentTransactionStatePurchased: WELog(@"productIDentifIEr----->%@",transaction.payment.productIDentifIEr); [self buySuccessWithPaymentQueue:queue Transaction:transaction]; break; case SKPaymentTransactionStateFailed: NSLog(@"购买失败"); [queue finishTransaction:transaction]; break; case SKPaymentTransactionStateRestored: NSLog(@"恢复购买"); //Todo:向服务器请求补货,服务器补货完成后,客户端再完成交易单子 //[queue finishTransaction:transaction]; break; case SKPaymentTransactionStateDeferred: NSLog(@"最终状态未确定"); break; default: break; } }}- (voID)buySuccessWithPaymentQueue:(SKPaymentQueue *)queue Transaction:(SKPaymentTransaction *)transaction { AFhttpSessionManager *manager = [AFhttpSessionManager manager]; NSDictionary *params = @{@"user_ID":@"user_ID",// 获取商品 @"goods":[self goodsWithProductIDentifIEr:transaction.payment.productIDentifIEr]}; [manager POST:@"url" parameters:params success:^(NSURLSessionDataTask *task,ID responSEObject) { if ([responSEObject[@"code"] intValue] == 200) { // 防止丢单,必须在服务器确定后从交易队列删除交易 // 如果不从交易队列上删除交易,下次调用addTransactionObserver:,仍然会回调'updatedTransactions'方法,以此处理丢单 WELog(@"购买成功"); [queue finishTransaction:transaction]; } } failure:^(NSURLSessionDataTask *task,NSError *error) { }];}// 商品列表 也可以使用从苹果请求的数据,具体细节自己视情况处理// goods1 是商品的ID- (Nsstring *)goodsWithProductIDentifIEr:(Nsstring *)productIDentifIEr { NSDictionary *goodsDic = [[NSUserDefaults standardUserDefaults] objectForKey:@"priceDic"]; return goodsDic[productIDentifIEr];}// 恢复购买- (voID)restore{ [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];}- (voID)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error { // 恢复失败 WELog(@"恢复失败");}// 取消请求商品信息- (voID)dealloc { [_request cancel];}@end
补充:
对于丢单的交易,在执行初始化[[SKpaymentQueue defaultQueue] addTransactionObserver: self] 的时候,如果有未完成的交易,会直接回调updatedTransactions,并且进入case SKPaymentTransationStateRestored,此时把这些未完成的交易告知服务器进行补货,补货完成再通知客户端,客户端再执行completeTransaction关闭单子
总结:
内购有三个可能出现的问题
参考资料:
苹果内购二次验证 PHP代码
http://my.oschina.net/qianglong/blog/503861
in-app Purchase Programming GuIDe
https://developer.apple.com/library/prerelease/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html#//apple_ref/doc/uid/TP40008267
iPhone In App Purchase购买完成时验证transactionReceipt
http://www.cnblogs.com/eagley/archive/2011/06/15/2081577.html
总结
以上是内存溢出为你收集整理的iOS内购代码(苹果支付ApplePay)全部内容,希望文章能够帮你解决iOS内购代码(苹果支付ApplePay)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)