苹果内购相关内容整理
第一步:iTunesConnect的《协议税务和银行业务》里填写好银行卡信息和公司地址等信息
第二步:如果是已上架APP直接在“我的APP”->“功能”页面创建APP内购项目,未上架或者未创建APP项目请先自行创建并配置APP证书
第三步:代码部分
//******判断是否允许内购******//
if ([SKPaymentQueue canMakePayments]) {
[MBProgressHUD showMessage:LELocalizedString(@"正在加载。。。", nil)];
NSLog(@"允许程序内付费购买");
[self RequestProductData];//去苹果服务器请求商品
}
else
{
NSLog(@"不允许程序内付费购买");
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:LELocalizedString(@"提示", nil)
message:LELocalizedString(@"您的手机没有打开程序内付费购买", nil)
delegate:nil cancelButtonTitle:LELocalizedString(@"关闭",nil) otherButtonTitles:nil];
[alerView show];
}
//******去苹果服务器请求商品******//
-(void)RequestProductData
{
NSLog(@"---------请求对应的产品信息------------");
NSArray *product = nil;
switch (buyType) {
case 0:
product=[[NSArray alloc] initWithObjects:ProductID_IAP0p6,nil];//ProductID_IAP0p6 产品ID常量
break;
case 1:
product=[[NSArray alloc] initWithObjects:ProductID_IAP1p18,nil];
break;
default:
break;
}
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
request.delegate=self;
[request start];
}
//******SKProductsRequest请求协议 收到的产品返回信息******//
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(@"-----------收到产品反馈信息--------------");
NSArray *myProduct = response.products;
// NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
// NSLog(@"产品付费数量: %d", (int)[myProduct count]);
if([myProduct count] == 0){
[MBProgressHUD hideHUD];
NSLog(@"--------------没有商品------------------");
return;
}
// populate UI
NSString *currentProId;
switch (buyType) {
case 0:
currentProId = ProductID_IAP0p6;
break;
case 1:
currentProId = ProductID_IAP1p18;
break;
default:
break;
}
SKProduct *p = nil;
for(SKProduct *product in myProduct){
// NSLog(@"product info");
// NSLog(@"SKProduct 描述信息%@", [product description]);
// NSLog(@"产品标题 %@" , product.localizedTitle);
// NSLog(@"产品描述信息: %@" , product.localizedDescription);
// NSLog(@"价格: %@" , product.price);
_productPrice = [product.price integerValue];
// NSLog(@"Product id: %@" , product.productIdentifier);
if([product.productIdentifier isEqualToString:currentProId]){
p = product;
}
}
SKPayment *payment = [SKPayment paymentWithProduct:p];
NSLog(@"---------发送购买请求------------");
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
//******请求失败******//
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
[MBProgressHUD hideHUD];
NSLog(@"-------弹出错误信息----------");
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:LELocalizedString(@"Alert",NULL) message:[error localizedDescription]
delegate:nil cancelButtonTitle:LELocalizedString(@"Close",nil) otherButtonTitles:nil];
[alerView show];
}
-(void) requestDidFinish:(SKRequest *)request
{
[MBProgressHUD hideHUD];
NSLog(@"----------反馈信息结束--------------");
}
//SKPaymentTransactionObserver 千万不要忘记绑定,代码如下:
//----监听购买结果
//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
//******监听购买结果******//
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
NSLog(@"-----paymentQueue--------");
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:{//交易完成
NSLog(@"-----交易完成 --------");
// 发送到苹果服务器验证凭证
[self verifyPurchaseWithPaymentTransaction:AppPurchase];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
} break;
case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加进列表");
break;
case SKPaymentTransactionStateRestored:{
NSLog(@"已经购买过商品");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
break;
case SKPaymentTransactionStateFailed:{
NSLog(@"交易失败");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
[MBProgressHUD showError:LELocalizedString(@"购买失败",nil)];
[self hideLoadingView];
}
break;
default:
break;
}
}
}
//******验证购买,避免越狱软件模拟苹果请求达到非法购买问题******//
-(void)verifyPurchaseWithPaymentTransaction:(NSString *)verifyUrlStr
{
[MBProgressHUD showMessage:LELocalizedString(@"正在验证订单。。。", nil)];
//从沙盒中获取交易凭证并且拼接成请求体数据
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:verifyUrlStr];
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) {
NSString *errStr = [NSString stringWithFormat:LELocalizedString(@"验证购买过程中发生错误,错误信息:%@",nil),error.localizedDescription];
// NSLog(@"验证购买过程中发生错误,错误信息:%@",error.localizedDescription);
[MBProgressHUD hideHUD];
[MBProgressHUD showError:errStr];
return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dic);
if([dic[@"status"] intValue]==0)
{
[MBProgressHUD hideHUD];
NSLog(@"购买成功!");
// [self buySuccess:dic];调取自己服务器函数
}
else if ([dic[@"status"] intValue]==21007)
{
// SANDBOX
NSLog(@"应验证沙盒环境!");
[self verifyPurchaseWithPaymentTransaction:SANDBOX];
}
else{
NSLog(@"购买失败,未通过验证!");
[MBProgressHUD hideHUD];
[MBProgressHUD showError:LELocalizedString(@"购买失败",nil)];
}
}
PS:
1、//沙盒测试环境验证购买
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//真实环境验证购买
#define APPSTORE @"https://buy.itunes.apple.com/verifyReceipt"
苹果审核时使用的仍是沙盒测试,所以需要确保在真实环境中沙盒测试依然可行,我的方案是dic[@"status"] intValue]==21007时多一步向沙盒请求验证购买,后台交易记录时记录购买环境
2、除非App Store版本,其它包均只能使用沙盒测试
3、内购项目的提交审核必须和包含内购代码的APP版本一起审核