最近项目的第三方支付导致项目被拒,记录一下关于内购
1 #import2 3 //沙盒测试环境验证 4 #define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt" 5 //正式环境验证 6 #define AppStore @"https://buy.itunes.apple.com/verifyReceipt" 7 8 #define ProductID_GPSTC01 @"xmws_tc1" //xmws_tc1是在itunes上注册的物品,这个要保持一致 9 #define ProductID_GPSTC02 @"xmws_tc2" 10 #define ProductID_GPSTC03 @"xmws_tc3" 11 12 @interface ViewController () 13 14 - (void)viewDidLoad { 15 [super viewDidLoad]; 16 [self createViews]; 17 // 01监听购买结果 18 [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 19 } 20 21 - (void)dealloc 22 { 23 [[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; 24 } 25 26 - (void)createViews 27 { 28 NSArray * buttonNames = @[@"GPS套餐01", @"GPS套餐02", @"GPS套餐03"]; 29 __weak typeof(self) weakSelf = self; 30 [buttonNames enumerateObjectsUsingBlock:^(NSString * buttonName, NSUInteger idx, BOOL * stop) { 31 UIButton * button = [UIButton buttonWithType:UIButtonTypeSystem]; 32 [weakSelf.view addSubview:button]; 33 button.frame = CGRectMake(100, 100 + idx * 60, 150, 50); 34 button.titleLabel.font = [UIFont systemFontOfSize:18]; 35 [button setTitle:buttonName forState:UIControlStateNormal]; 36 37 // 设置tag值 38 button.tag = 1000 + idx; 39 [button addTarget:self action:@selector(buyProduct:) forControlEvents:UIControlEventTouchUpInside]; 40 }]; 41 } 42 43 44 - (void)buyProduct:(UIButton *) sender 45 { 46 self.buyType = sender.tag - 1000; 47 if ([SKPaymentQueue canMakePayments]) { 48 // 02判断是否允许程序内付费购买 49 [self requestProductData]; 50 NSLog(@"允许程序内付费购买"); 51 } 52 else 53 { 54 NSLog(@"不允许程序内付费购买"); 55 UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示" 56 message:@"您的手机没有打开程序内付费购买" 57 delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil]; 58 [alerView show]; 59 60 } 61 } 62 63 64 // 03查询。下面的ProductId应该是事先在itunesConnect中添加好的,已存在的付费项目。否则查询会失败。 65 - (void)requestProductData { 66 NSLog(@"---------请求对应的产品信息------------"); 67 NSArray *product = nil; 68 switch (self.buyType) { 69 case 0: 70 product = [NSArray arrayWithObject:ProductID_GPSTC01]; 71 break; 72 case 1: 73 product = [NSArray arrayWithObject:ProductID_GPSTC02]; 74 break; 75 case 2: 76 product = [NSArray arrayWithObject:ProductID_GPSTC03]; 77 break; 78 } 79 NSSet *nsset = [NSSet setWithArray:product]; 80 SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers: nsset]; 81 request.delegate = self; 82 [request start]; 83 } 84 85 #pragma mark - SKProductsRequestDelegate 86 // 05收到的产品信息回调 87 - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{ 88 89 NSArray *myProduct = response.products; 90 NSLog(@"----收到产品反馈信息%@-----",myProduct); 91 if (myProduct.count == 0) { 92 NSLog(@"无法获取产品信息,购买失败。"); 93 return; 94 } 95 NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers); 96 NSLog(@"产品付费数量: %d", (int)[myProduct count]); 97 // populate UI 98 for(SKProduct *product in myProduct){ 99 NSLog(@"product info");100 NSLog(@"SKProduct 描述信息%@", [product description]);101 NSLog(@"产品标题 %@" , product.localizedTitle);102 NSLog(@"产品描述信息: %@" , product.localizedDescription);103 NSLog(@"价格: %@" , product.price);104 NSLog(@"Product id: %@" , product.productIdentifier);105 }106 SKPayment * payment = [SKPayment paymentWithProduct:myProduct[0]];107 NSLog(@"---------发送购买请求------------");108 [[SKPaymentQueue defaultQueue] addPayment:payment];109 110 }111 112 //弹出错误信息113 - (void)request:(SKRequest *)request didFailWithError:(NSError *)error{114 NSLog(@"-------弹出错误信息----------");115 UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription]116 delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];117 [alerView show];118 119 }120 121 -(void) requestDidFinish:(SKRequest *)request122 {123 NSLog(@"----------反馈信息结束--------------");124 125 }126 127 #pragma mark - SKPaymentTransactionObserver128 // 处理交易结果129 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {130 for (SKPaymentTransaction *transaction in transactions)131 {132 switch (transaction.transactionState)133 {134 case SKPaymentTransactionStatePurchased://交易完成135 NSLog(@"transactionIdentifier = %@", transaction.transactionIdentifier);136 [self completeTransaction:transaction];137 break;138 case SKPaymentTransactionStateFailed://交易失败139 [self failedTransaction:transaction];140 break;141 case SKPaymentTransactionStateRestored://已经购买过该商品142 [self restoreTransaction:transaction];143 break;144 case SKPaymentTransactionStatePurchasing: //商品添加进列表145 NSLog(@"商品添加进列表");146 break;147 default:148 break;149 }150 }151 152 }153 154 // 交易完成155 - (void)completeTransaction:(SKPaymentTransaction *)transaction {156 NSString * productIdentifier = transaction.payment.productIdentifier;157 // NSString * receipt = [transaction.transactionReceipt base64EncodedString];158 if ([productIdentifier length] > 0) {159 // 向自己的服务器验证购买凭证160 [self verifyPurchaseWithPaymentTransaction];161 }162 163 // Remove the transaction from the payment queue.164 [[SKPaymentQueue defaultQueue] finishTransaction: transaction];165 166 }167 168 // 交易失败169 - (void)failedTransaction:(SKPaymentTransaction *)transaction {170 if(transaction.error.code != SKErrorPaymentCancelled) {171 NSLog(@"购买失败");172 } else {173 NSLog(@"用户取消交易");174 }175 [[SKPaymentQueue defaultQueue] finishTransaction: transaction];176 }177 178 /**179 * 验证购买,避免越狱软件模拟苹果请求达到非法购买问题180 *181 */182 -(void)verifyPurchaseWithPaymentTransaction{183 //从沙盒中获取交易凭证并且拼接成请求体数据184 NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];185 NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];186 187 NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//转化为base64字符串188 189 NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接请求数据190 NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];191 192 193 //创建请求到苹果官方进行购买验证194 NSURL *url=[NSURL URLWithString:SANDBOX];195 NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];196 requestM.HTTPBody=bodyData;197 requestM.HTTPMethod=@"POST";198 //创建连接并发送同步请求199 NSError *error=nil;200 NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];201 if (error) {202 NSLog(@"验证购买过程中发生错误,错误信息:%@",error.localizedDescription);203 return;204 }205 NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];206 NSLog(@"苹果返回的购买凭证 == %@",dic); //苹果返回的购买凭证207 if([dic[@"status"] intValue]==0){208 NSLog(@"购买成功!");209 NSDictionary *dicReceipt= dic[@"receipt"];210 NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];211 NSString *productIdentifier= dicInApp[@"product_id"];//读取产品标识212 //如果是消耗品则记录购买数量,非消耗品则记录是否购买过213 NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];214 // if ([productIdentifier isEqualToString:ProductID_IAP_XYJ]) {215 // int purchasedCount = [defaults integerForKey:productIdentifier];//已购买数量216 // [[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];217 // }else{ 218 [defaults setBool:YES forKey:productIdentifier];219 // }220 //在此处对购买记录进行存储,可以存储到开发商的服务器端221 }else{222 NSLog(@"购买失败,未通过验证!");223 }224 }225 226 // 已购商品227 - (void)restoreTransaction:(SKPaymentTransaction *)transaction {228 // 对于已购商品,处理恢复购买的逻辑229 [[SKPaymentQueue defaultQueue] finishTransaction: transaction];230 }
补充:01-测试时一定要在真机上测试,并且要先去设置中退出当前的appleID账号
02-沙盒的测试账号是没有金额限制的,可以无数次测试,刚开始的时候还担心会扣我的钱,实测不会的,请放心测试。
03-提交审核的时候不需要提供沙盒技术测试账号的,苹果有自己的测试账号。