最近项目的第三方支付导致项目被拒,记录一下关于内购

 #import <StoreKit/StoreKit.h>

 //沙盒测试环境验证
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式环境验证
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt" #define ProductID_GPSTC01 @"xmws_tc1" //xmws_tc1是在itunes上注册的物品,这个要保持一致
#define ProductID_GPSTC02 @"xmws_tc2"
#define ProductID_GPSTC03 @"xmws_tc3" @interface ViewController ()<SKPaymentTransactionObserver> - (void)viewDidLoad {
[super viewDidLoad];
[self createViews];
// 01监听购买结果
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
} - (void)dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
} - (void)createViews
{
NSArray * buttonNames = @[@"GPS套餐01", @"GPS套餐02", @"GPS套餐03"];
__weak typeof(self) weakSelf = self;
[buttonNames enumerateObjectsUsingBlock:^(NSString * buttonName, NSUInteger idx, BOOL * stop) {
UIButton * button = [UIButton buttonWithType:UIButtonTypeSystem];
[weakSelf.view addSubview:button];
button.frame = CGRectMake(, + idx * , , );
button.titleLabel.font = [UIFont systemFontOfSize:];
[button setTitle:buttonName forState:UIControlStateNormal]; // 设置tag值
button.tag = + idx;
[button addTarget:self action:@selector(buyProduct:) forControlEvents:UIControlEventTouchUpInside];
}];
} - (void)buyProduct:(UIButton *) sender
{
self.buyType = sender.tag - ;
if ([SKPaymentQueue canMakePayments]) {
// 02判断是否允许程序内付费购买
[self requestProductData];
NSLog(@"允许程序内付费购买");
}
else
{
NSLog(@"不允许程序内付费购买");
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示"
message:@"您的手机没有打开程序内付费购买"
delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
[alerView show]; }
} // 03查询。下面的ProductId应该是事先在itunesConnect中添加好的,已存在的付费项目。否则查询会失败。
- (void)requestProductData {
NSLog(@"---------请求对应的产品信息------------");
NSArray *product = nil;
switch (self.buyType) {
case :
product = [NSArray arrayWithObject:ProductID_GPSTC01];
break;
case :
product = [NSArray arrayWithObject:ProductID_GPSTC02];
break;
case :
product = [NSArray arrayWithObject:ProductID_GPSTC03];
break;
}
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
request.delegate = self;
[request start];
} #pragma mark - SKProductsRequestDelegate
// 05收到的产品信息回调
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{ NSArray *myProduct = response.products;
NSLog(@"----收到产品反馈信息%@-----",myProduct);
if (myProduct.count == ) {
NSLog(@"无法获取产品信息,购买失败。");
return;
}
NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
NSLog(@"产品付费数量: %d", (int)[myProduct count]);
// populate UI
for(SKProduct *product in myProduct){
NSLog(@"product info");
NSLog(@"SKProduct 描述信息%@", [product description]);
NSLog(@"产品标题 %@" , product.localizedTitle);
NSLog(@"产品描述信息: %@" , product.localizedDescription);
NSLog(@"价格: %@" , product.price);
NSLog(@"Product id: %@" , product.productIdentifier);
}
SKPayment * payment = [SKPayment paymentWithProduct:myProduct[]];
NSLog(@"---------发送购买请求------------");
[[SKPaymentQueue defaultQueue] addPayment:payment]; } //弹出错误信息
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
NSLog(@"-------弹出错误信息----------");
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription]
delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];
[alerView show]; } -(void) requestDidFinish:(SKRequest *)request
{
NSLog(@"----------反馈信息结束--------------"); } #pragma mark - SKPaymentTransactionObserver
// 处理交易结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased://交易完成
NSLog(@"transactionIdentifier = %@", transaction.transactionIdentifier);
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed://交易失败
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored://已经购买过该商品
[self restoreTransaction:transaction];
break;
case SKPaymentTransactionStatePurchasing: //商品添加进列表
NSLog(@"商品添加进列表");
break;
default:
break;
}
} } // 交易完成
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
NSString * productIdentifier = transaction.payment.productIdentifier;
// NSString * receipt = [transaction.transactionReceipt base64EncodedString];
if ([productIdentifier length] > ) {
// 向自己的服务器验证购买凭证
[self verifyPurchaseWithPaymentTransaction];
} // Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction]; } // 交易失败
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if(transaction.error.code != SKErrorPaymentCancelled) {
NSLog(@"购买失败");
} else {
NSLog(@"用户取消交易");
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
} /**
* 验证购买,避免越狱软件模拟苹果请求达到非法购买问题
*
*/
-(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:SANDBOX];
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(@"验证购买过程中发生错误,错误信息:%@",error.localizedDescription);
return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"苹果返回的购买凭证 == %@",dic); //苹果返回的购买凭证
if([dic[@"status"] intValue]==){
NSLog(@"购买成功!");
NSDictionary *dicReceipt= dic[@"receipt"];
NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];
NSString *productIdentifier= dicInApp[@"product_id"];//读取产品标识
//如果是消耗品则记录购买数量,非消耗品则记录是否购买过
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
// if ([productIdentifier isEqualToString:ProductID_IAP_XYJ]) {
// int purchasedCount = [defaults integerForKey:productIdentifier];//已购买数量
// [[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];
// }else{
[defaults setBool:YES forKey:productIdentifier];
// }
//在此处对购买记录进行存储,可以存储到开发商的服务器端
}else{
NSLog(@"购买失败,未通过验证!");
}
} // 已购商品
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
// 对于已购商品,处理恢复购买的逻辑
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

补充:01-测试时一定要在真机上测试,并且要先去设置中退出当前的appleID账号

02-沙盒的测试账号是没有金额限制的,可以无数次测试,刚开始的时候还担心会扣我的钱,实测不会的,请放心测试。

03-提交审核的时候不需要提供沙盒技术测试账号的,苹果有自己的测试账号。

05-11 15:48