1、發(fā)送請(qǐng)求,注意請(qǐng)求ID
NSString *productID = @"這是創(chuàng)建內(nèi)購(gòu)項(xiàng)目填寫(xiě)的ID";
NSArray *product = [[NSArray alloc] initWithObjects: productID,nil];
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate = self;
2币叹、 在監(jiān)聽(tīng)購(gòu)買(mǎi)結(jié)果后,一定要調(diào)用[[SKPaymentQueue defaultQueue] finishTransaction:tran];來(lái)允許你從支付隊(duì)列中移除交易模狭。
//監(jiān)聽(tīng)購(gòu)買(mǎi)結(jié)果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
for(SKPaymentTransaction *tran in transaction){
switch (tran.transactionState) {
case SKPaymentTransactionStatePurchased:{
NSLog(@"交易完成");
// 發(fā)送到蘋(píng)果服務(wù)器驗(yàn)證憑證,進(jìn)行二次驗(yàn)證
[self verifyPurchaseWithProductionEnvironment];
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
}
break;
case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加進(jìn)列表");
break;
case SKPaymentTransactionStateRestored:{
NSLog(@"已經(jīng)購(gòu)買(mǎi)過(guò)商品");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
}
break;
case SKPaymentTransactionStateFailed:{
NSLog(@"交易失敗");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
[SVProgressHUD showErrorWithStatus:@"購(gòu)買(mǎi)失敗"];
}
break;
default:
break;
}
}
}
3颈抚、 沙盒環(huán)境測(cè)試appStore內(nèi)購(gòu)流程的時(shí)候,請(qǐng)使用沒(méi)越獄的設(shè)備嚼鹉。
請(qǐng)務(wù)必使用真機(jī)來(lái)測(cè)試贩汉,一切以真機(jī)為準(zhǔn)。
4锚赤、 項(xiàng)目的Bundle identifier需要與您申請(qǐng)AppID時(shí)填寫(xiě)的bundleID一致匹舞,不然會(huì)無(wú)法請(qǐng)求到商品信息。
5线脚、真機(jī)測(cè)試的時(shí)候赐稽,一定要退出原來(lái)的賬號(hào),才能用沙盒測(cè)試賬號(hào)
6浑侥、二次驗(yàn)證姊舵,請(qǐng)注意區(qū)分宏, 測(cè)試用沙盒驗(yàn)證锭吨,App Store審核的時(shí)候也使用的是沙盒購(gòu)買(mǎi)蠢莺,所以驗(yàn)證購(gòu)買(mǎi)憑證的時(shí)候需要判斷返回Status Code決定是否去沙盒進(jìn)行二次驗(yàn)證,為了線上用戶(hù)的使用零如,驗(yàn)證的順序肯定是先驗(yàn)證正式環(huán)境躏将,此時(shí)若返回值為21007,就需要去沙盒二次驗(yàn)證考蕾,因?yàn)榇速?gòu)買(mǎi)的是在沙盒進(jìn)行的祸憋。
//沙盒測(cè)試環(huán)境驗(yàn)證
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式環(huán)境驗(yàn)證
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
/**
* 驗(yàn)證購(gòu)買(mǎi),避免越獄軟件模擬蘋(píng)果請(qǐng)求達(dá)到非法購(gòu)買(mǎi)問(wèn)題
*
*/
-(void)verifyPurchaseWithProductionEnvironment{
//從沙盒中獲取交易憑證并且拼接成請(qǐng)求體數(shù)據(jù)
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//轉(zhuǎn)化為base64字符串
NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接請(qǐng)求數(shù)據(jù)
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
/*
注意:
自己測(cè)試的時(shí)候使用的是沙盒購(gòu)買(mǎi)(測(cè)試環(huán)境)
App Store審核的時(shí)候也使用的是沙盒購(gòu)買(mǎi)(測(cè)試環(huán)境)
上線以后就不是用的沙盒購(gòu)買(mǎi)了(正式環(huán)境)
所以此時(shí)應(yīng)該先驗(yàn)證正式環(huán)境肖卧,在驗(yàn)證測(cè)試環(huán)境
正式環(huán)境驗(yàn)證成功蚯窥,說(shuō)明是線上用戶(hù)在使用
正式環(huán)境驗(yàn)證不成功返回21007,說(shuō)明是自己測(cè)試或者審核人員在測(cè)試
*/
//第一步塞帐,驗(yàn)證正式環(huán)境
//創(chuàng)建請(qǐng)求到蘋(píng)果官方進(jìn)行購(gòu)買(mǎi)驗(yàn)證(正式環(huán)境)
NSURL *url=[NSURL URLWithString: AppStore];
NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];
requestM.HTTPBody=bodyData;
requestM.HTTPMethod=@"POST";
//創(chuàng)建連接并發(fā)送同步請(qǐng)求
NSError *error=nil;
NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];
if (error) {
NSLog(@"驗(yàn)證購(gòu)買(mǎi)過(guò)程中發(fā)生錯(cuò)誤拦赠,錯(cuò)誤信息:%@",error.localizedDescription);
return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dic);
if([dic[@"status"] intValue]==0){
//正式環(huán)境驗(yàn)證通過(guò)(說(shuō)明是上線以后的用戶(hù)購(gòu)買(mǎi))
NSLog(@"購(gòu)買(mǎi)成功!");
//在此處對(duì)購(gòu)買(mǎi)記錄進(jìn)行存儲(chǔ)葵姥,可以存儲(chǔ)到開(kāi)發(fā)商的服務(wù)器端
}else if([dic[@"status"] intValue]== 21007){
//This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.
//購(gòu)買(mǎi)憑證來(lái)自于測(cè)試環(huán)境荷鼠,但是卻發(fā)送到了正式環(huán)境,請(qǐng)改成測(cè)試環(huán)境(這種情況下可能是自己測(cè)試的榔幸,也可能是審核人員測(cè)試的)
//第二步允乐,驗(yàn)證測(cè)試環(huán)境
[self verifyPurchaseWithTestEnvironment];
}
}
//創(chuàng)建請(qǐng)求到蘋(píng)果官方進(jìn)行購(gòu)買(mǎi)驗(yàn)證(測(cè)試環(huán)境)
- (void)verifyPurchaseWithTestEnvironment {
NSURL *url=[NSURL URLWithString:SANDBOX];
NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];
requestM.HTTPBody=bodyData;
requestM.HTTPMethod=@"POST";
//創(chuàng)建連接并發(fā)送同步請(qǐng)求
NSError *error=nil;
NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];
if (error) {
NSLog(@"驗(yàn)證購(gòu)買(mǎi)過(guò)程中發(fā)生錯(cuò)誤矮嫉,錯(cuò)誤信息:%@",error.localizedDescription);
return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dic);
if([dic[@"status"] intValue]==0){
NSLog(@"購(gòu)買(mǎi)成功!");
//在此處對(duì)購(gòu)買(mǎi)記錄進(jìn)行存儲(chǔ)牍疏,可以存儲(chǔ)到開(kāi)發(fā)商的服務(wù)器端
}else{
NSLog(@"購(gòu)買(mǎi)失敗蠢笋,未通過(guò)驗(yàn)證!");
}
}