屏幕快照 2017-01-23 15.19.12.png
馬上要過年了,而且還是本命年,為了慶祝下大雞年,放一張?zhí)O果官網(wǎng)的中國元素(不多說設(shè)計(jì)此圖的人NB).
1,了解蘋果內(nèi)購
當(dāng)我們?cè)贏ppStore里面下載下載軟件的時(shí)候,標(biāo)題下面會(huì)顯示提供App內(nèi)購買項(xiàng)目,通常我們下載的游戲也有購物的軟件,應(yīng)用里面采用了虛擬商品,例如:金幣,點(diǎn)券,奪寶幣,100顆寶石,,,,, 當(dāng)然像電商的軟件直接買實(shí)物就不是的, 蘋果公司就強(qiáng)制使用IAP內(nèi)購,原因很簡單,他要從中扣稅賺錢.蘋果2016賺了2000億主要來自這個(gè)地方.蘋果2016收入報(bào)表
65965B5B3055225F3E2FF2CFAA2C0776.png
2,熟悉內(nèi)購的流程;
- 程序向服務(wù)器發(fā)送請(qǐng)求右冻,獲得一份產(chǎn)品列表,以及訂單號(hào)(這里獲取商品的productID也可以放在本地)浑此。
- 服務(wù)器返回包含產(chǎn)品標(biāo)識(shí)符的列表秃嗜。
- 程序根據(jù)產(chǎn)品的productID向App Store發(fā)送請(qǐng)求惑申,得到產(chǎn)品的信息(包括價(jià)格,productID,,,,,)岩睁。
- App Store返回產(chǎn)品信息。
- 程序把返回的產(chǎn)品信息顯示給用戶(App的store界面)
- 用戶選擇某個(gè)產(chǎn)品
- 程序向App Store發(fā)送支付請(qǐng)求
- App Store處理支付請(qǐng)求并返回交易完成信息燥狰。
- 程序從信息中獲得數(shù)據(jù)棘脐,并發(fā)送至服務(wù)器(也可以在本地驗(yàn)證但是不安全)。
- 服務(wù)器記錄交易信息碾局。
- 服務(wù)器將數(shù)據(jù)發(fā)給App Store來驗(yàn)證該交易荆残。
- App Store對(duì)收到的數(shù)據(jù)進(jìn)行解析奴艾,返回該數(shù)據(jù)和說明其是否有效的標(biāo)識(shí)净当。
- 服務(wù)器讀取返回的數(shù)據(jù),確定用戶購買的內(nèi)容蕴潦。
- 服務(wù)器將購買的內(nèi)容傳遞給程序像啼。(如果你是在app內(nèi)驗(yàn)證當(dāng)然是沒有10-14的)
3,完成內(nèi)購前的準(zhǔn)備工作;
<1>. 去蘋果開發(fā)者中心填寫appid,創(chuàng)建齒輪文件;
<2>. 去iTunes上填寫合同、稅務(wù)以及銀行信息(下面給的參考文獻(xiàn)有具體步驟,不多說),關(guān)于填寫W-8BEN-E可以參考這篇文章
iOS-Appstore-iTunes Connect最新協(xié)議潭苞、稅務(wù)和銀行業(yè)務(wù)填寫(W-8BEN)
<3>. 去iTunes創(chuàng)建對(duì)應(yīng)appid的項(xiàng)目;
<4> 添加App內(nèi)購買項(xiàng)目;
<5> 添加沙箱測(cè)試賬號(hào);(在真機(jī)測(cè)試自己的程序時(shí)需要退出當(dāng)前手機(jī)在Appstore登錄的賬號(hào))
5,開始擼內(nèi)購的代碼;
1. 發(fā)蘋果服務(wù)器請(qǐng)求商品信息;
//productID就是你在創(chuàng)建購買項(xiàng)目時(shí)所填寫的產(chǎn)品ID
[self requestProductData: productID];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
-(void)requestProductData:(NSString *)type{
NSLog(@"-------------請(qǐng)求對(duì)應(yīng)的產(chǎn)品信息----------------");
NSArray *product = [[NSArray alloc] initWithObjects:type, nil];
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate = self;
[request start];
}
2. 接收商品信息并發(fā)送購買請(qǐng)求;
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSLog(@"--------------收到產(chǎn)品反饋消息---------------------");
NSArray *product = response.products;
if([product count] == 0){
NSLog(@"--------------沒有商品------------------");
return;
}
SKProduct *p = nil;
for (SKProduct *pro in product) {
NSLog(@"pro info");
NSLog(@"SKProduct 描述信息:%@", [pro description]);
NSLog(@"localizedTitle 產(chǎn)品標(biāo)題:%@", [pro localizedTitle]);
NSLog(@"localizedDescription 產(chǎn)品描述信息:%@", [pro localizedDescription]);
NSLog(@"price 價(jià)格:%@", [pro price]);
NSLog(@"productIdentifier Product id:%@", [pro productIdentifier]);
if([pro.productIdentifier isEqualToString: productID]){
p = pro;
}else{
NSLog(@"不相同");
}
}
SKPayment *payment = [SKPayment paymentWithProduct:p];
NSLog(@"發(fā)送購買請(qǐng)求");
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
3. 監(jiān)聽購買請(qǐng)求結(jié)果;
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
NSLog(@" 監(jiān)聽購買結(jié)果 -----paymentQueue--------");
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:{
NSLog(@"-----交易完成 --------");
//交易完成
[self commitSeversSucceeWithTransaction:transaction];
}
break;
case SKPaymentTransactionStateFailed:{
NSLog(@"-----交易失敗 --------");
//交易失敗
[self failedTransaction:transaction];
}
break;
case SKPaymentTransactionStateRestored:{
NSLog(@"-----已經(jīng)購買過該商品(重復(fù)支付) --------");
//已經(jīng)購買過該商品
[self restoreTransaction:transaction];
[self commitSeversSucceeWithTransaction:transaction];
}
case SKPaymentTransactionStatePurchasing: {
//商品添加進(jìn)列表
NSLog(@"-----商品添加進(jìn)列表 --------");
}
break;
default:
break;
}
}
}
5,得到receipt并向服務(wù)器驗(yàn)證;
NSString * productIdentifier = transaction.payment.productIdentifier;
NSLog(@"productIdentifier Product id:%@", productIdentifier);
NSString *transactionReceiptString= nil;
//系統(tǒng)IOS7.0以上獲取支付驗(yàn)證憑證的方式應(yīng)該改變忽冻,切驗(yàn)證返回的數(shù)據(jù)結(jié)構(gòu)也不一樣了。
// 驗(yàn)證憑據(jù)此疹,獲取到蘋果返回的交易憑據(jù)
// appStoreReceiptURL iOS7.0增加的僧诚,購買交易完成后遮婶,會(huì)將憑據(jù)存放在該地址
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData * receiptData = [NSData dataWithContentsOfURL:receiptUrl];
transactionReceiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSLog(@"transactionReceiptString == %@",transactionReceiptString);
[[NSUserDefaults standardUserDefaults]setObject:transactionReceiptString forKey:@"receipt"];
// 向自己的服務(wù)器驗(yàn)證購買憑證
[SDKRequestManager requestPayReceipt:transactionReceiptString Succee:^(NSDictionary *dic) {
NSLog(@"----yyy--%@",dic);
} withFail:^(NSError *error) {
}];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
6, 本地緩存receipt,,,,服務(wù)器驗(yàn)證成功刪除本地receipt,
代碼就不放到git上面了,內(nèi)購的代碼都差不多,自己問下度娘.
4,處理下工程中遇到的相關(guān)問題;
獲取不到商品信息(這是最痛苦的):
<1>. 合同、稅務(wù)以及銀行信息沒有填對(duì),如果你是公司賬號(hào),那么W-8BEN-E必須填,而且不要填錯(cuò)額!個(gè)人賬號(hào)的話就不需要填了.
<2>. 你的程序的AppID和iTunes上不一致;
<3>. 齒輪文件和AppID不匹配;蘋果驗(yàn)證后返回的結(jié)果;
{
"receipt":
{
"original_purchase_date_pst":"2015-06-22 20:56:34 America/Los_Angeles", //購買時(shí)間,太平洋標(biāo)準(zhǔn)時(shí)間
"purchase_date_ms":"1435031794826", //購買時(shí)間毫秒
"unique_identifier":"5bcc5503dbcc886d10d09bef079dc9ab08ac11bb",//唯一標(biāo)識(shí)符
"original_transaction_id":"xxxxxxxxx", //原始交易ID
"bvrs":"1.0",//iPhone程序的版本號(hào)
"transaction_id":"xxxxxxxxxx", //交易的標(biāo)識(shí)
"quantity":"1", //購買商品的數(shù)量
"unique_vendor_identifier":"AEEC55C0-FA41-426A-B9FC-324128342652", //開發(fā)商交易ID
"item_id":"1008526677",//App Store用來標(biāo)識(shí)程序的字符串
"product_id":"cosmosbox.strikehero.gems60",//商品的標(biāo)識(shí)
"purchase_date":"2015-06-23 03:56:34 Etc/GMT",//購買時(shí)間
"original_purchase_date":"2015-06-23 03:56:34 Etc/GMT", //原始購買時(shí)間
"purchase_date_pst":"2015-06-22 20:56:34 America/Los_Angeles",//太平洋標(biāo)準(zhǔn)時(shí)間
"bid":"com.cosmosbox.StrikeHero",//iPhone程序的bundle標(biāo)識(shí)
"original_purchase_date_ms":"1435031794826"http://毫秒
},
"status":0 //狀態(tài)碼,0為成功
}
這里的transaction_id和original_transaction_id是一樣的可以作為唯一標(biāo)示;;;
- "您已購買此App內(nèi)購買項(xiàng)目,此項(xiàng)目將免費(fèi)恢復(fù)"
在收到購買監(jiān)聽,處理相關(guān)邏輯的時(shí)候需要加上:[[SKPaymentQueue defaultQueue] finishTransaction:transaction];