公司項(xiàng)目中有虛擬產(chǎn)品,所以要使用蘋果內(nèi)購(gòu).自此記錄一下蘋果內(nèi)購(gòu)的流程.前提是已有開發(fā)者賬號(hào)
協(xié)議,稅務(wù)和銀行業(yè)務(wù)
- 協(xié)議,稅務(wù)和銀行業(yè)務(wù)
協(xié)議,稅務(wù)和銀行業(yè)務(wù)
申請(qǐng)合同
- 這里提示地址太長(zhǎng),按照要求重新填寫一下就可以
添加聯(lián)系人
- 同意協(xié)議并提交
- 設(shè)置相關(guān)信息
- 聯(lián)系人信息
添加相關(guān)聯(lián)系人信息之后,注意在role(角色)中,為聯(lián)系人選擇身份(高級(jí)管理人員 ,金融,技術(shù),法律,營(yíng)銷),點(diǎn)擊Done保存
聯(lián)系人
- 銀行信息
- 添加銀行信息
添加銀行
2.選擇國(guó)家
選擇國(guó)家
3.填寫CNAPS
CNAPS 銀行網(wǎng)點(diǎn)聯(lián)行號(hào).我們可以直接到銀行客服電話查詢 CNAPS, 快速便捷.還可以通過(guò)下圖的Look up CNAPS Code 查詢. 不過(guò)有的查詢不到
CNAPS
Look up CNAPS Code
4.確認(rèn)銀行信息
銀行信息
5.填寫公司銀行賬號(hào)信息
公司銀行信息
- 稅務(wù)信息
稅務(wù)信息有三個(gè)選項(xiàng):美國(guó)稅務(wù)就珠、澳大利亞稅務(wù)撇吞、加拿大稅務(wù)牍白。我們?cè)谶@里選擇美國(guó)稅務(wù)就可以
稅務(wù)信息
這里有兩個(gè)問(wèn)題:如下圖.我選擇的都是NO
填寫稅務(wù)相關(guān)信息
9b.Foreign TIN 是填寫公司稅務(wù)識(shí)別碼.公司營(yíng)業(yè)執(zhí)照上同意社會(huì)信用代碼去掉前兩位和最后一位就是公司稅務(wù)識(shí)別碼(15位)
點(diǎn)擊提交之后會(huì)讓你確認(rèn)信息,確認(rèn)無(wú)誤后再次點(diǎn)擊提交(提交后無(wú)法修改)
創(chuàng)建測(cè)試APP
新建APP在這里就不詳細(xì)描述了
添加內(nèi)購(gòu)
- 選擇功能步咪,我們添加一個(gè)app內(nèi)購(gòu)項(xiàng)目
添加內(nèi)購(gòu)
- 根據(jù)項(xiàng)目需求,選擇內(nèi)購(gòu)項(xiàng)目
消耗性項(xiàng)目
- 填寫內(nèi)購(gòu)項(xiàng)目的相關(guān)信息
- 商品名稱根據(jù)你的消費(fèi)道具的實(shí)際意義來(lái)說(shuō)明
- 產(chǎn)品ID是比較重要的,只要唯一即可铲球,在實(shí)際應(yīng)用中离唐,一定要認(rèn)真填寫嗤疯。
- 選擇價(jià)格
- 本地化版本
將在 App Store 上可見的 App 內(nèi)購(gòu)買項(xiàng)目名稱肯夏〉讣可以參考App Store中其他應(yīng)用的內(nèi)購(gòu)項(xiàng)目描述
描述不得少于10個(gè)字符.沒(méi)有重新截圖
本地化
- 審核信息
1.只會(huì)在審核中使用屏幕快照烁试,不會(huì)將其顯示在 App Store 上。屏幕快照必須具有適合您 App 平臺(tái)的有效尺寸拢肆。
2.能夠有助于我們進(jìn)行審核的關(guān)于您的 App 內(nèi)購(gòu)買項(xiàng)目的其他信息减响,如測(cè)試帳戶(包括用戶名、密碼等)善榛。審核備注不得超過(guò) 4000 個(gè)字符辩蛋。
審核信息
- 內(nèi)購(gòu)項(xiàng)目則添加完成
申請(qǐng)沙盒測(cè)試賬號(hào)(用來(lái)測(cè)試購(gòu)買項(xiàng)目)
我們不必用真實(shí)的人民幣測(cè)試購(gòu)買內(nèi)購(gòu)項(xiàng)目
- 首先我們回到iTunes Connect中,在這里我們選擇用戶和職能。
- 添加沙箱技術(shù)測(cè)試員
測(cè)試人員
- 添加測(cè)試員詳細(xì)信息
所有信息都可以隨意填寫移盆,不用管是否真實(shí)悼院。但是App Store地區(qū)必須對(duì)應(yīng)
注意: 郵件地址不能填寫與 Apple ID 關(guān)聯(lián)的, 密碼保護(hù)問(wèn)題必須在 6 到 35 個(gè)字符之間。密碼必須包含至少一個(gè)大寫字母咒循。
信息
所有準(zhǔn)備工作都已完成.打開項(xiàng)目開始擼代碼
在項(xiàng)目中實(shí)現(xiàn)購(gòu)買
首先在項(xiàng)目工程中加入
storekit.framework
据途,加入頭文件#import <StoreKit/StoreKit.h>
遵守代理SKPaymentTransactionObserver
,SKProductsRequestDelegate
//添加一個(gè)交易隊(duì)列觀察者
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
//self.productIds是在開發(fā)者平臺(tái)填寫的產(chǎn)品id
self.productId = @"701";
if ([SKPaymentQueue canMakePayments]) {
[self requestProductData:self.productId];
}else{
DLog(@"不允許程序內(nèi)付費(fèi)");
}
- 去蘋果服務(wù)器請(qǐng)求產(chǎn)品信息
// 去蘋果服務(wù)器請(qǐng)求產(chǎn)品信息
- (void)requestProductData:(NSString *)productId {
[SVProgressHUD show];
NSArray *productArr = [[NSArray alloc]initWithObjects:productId, nil];
NSSet *productSet = [NSSet setWithArray:productArr];
SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:productSet];
request.delegate = self;
[request start];
}
- SKProductsRequestDelegate
// 收到產(chǎn)品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *productArr = response.products;
if ([productArr count] == 0) {
[SVProgressHUD dismiss];
DLog(@"沒(méi)有該商品");
return;
}
DLog(@"productId = %@",response.invalidProductIdentifiers);
DLog(@"產(chǎn)品付費(fèi)數(shù)量 = %zd",productArr.count);
SKProduct *p = nil;
for (SKProduct *pro in productArr) {
DLog(@"description:%@",[pro description]);
DLog(@"localizedTitle:%@",[pro localizedTitle]);
DLog(@"localizedDescription:%@",[pro localizedDescription]);
DLog(@"price:%@",[pro price]);
DLog(@"productIdentifier:%@",[pro productIdentifier]);
if ([pro.productIdentifier isEqualToString:self.productId]) {
p = pro;
}
}
SKPayment *payment = [SKPayment paymentWithProduct:p];
//發(fā)送內(nèi)購(gòu)請(qǐng)求
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- SKRequestDelegate
- (void)requestDidFinish:(SKRequest *)request {
[SVProgressHUD dismiss];
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
[SVProgressHUD showErrorWithStatus:@"支付失敗"];
}
- SKPaymentTransactionObserver監(jiān)聽購(gòu)買結(jié)果
// 監(jiān)聽購(gòu)買結(jié)果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray
<
SKPaymentTransaction *
>
*)transactions {
for (SKPaymentTransaction *tran in transactions) {
switch (tran.transactionState) {
case SKPaymentTransactionStatePurchased: //交易完成
// 發(fā)送到蘋果服務(wù)器驗(yàn)證憑證
[self verifyPurchaseWithPaymentTrasaction];
[[SKPaymentQueue defaultQueue]finishTransaction:tran];
break;
case SKPaymentTransactionStatePurchasing: //商品添加進(jìn)列表
break;
case SKPaymentTransactionStateRestored: //購(gòu)買過(guò)
// 發(fā)送到蘋果服務(wù)器驗(yàn)證憑證
[[SKPaymentQueue defaultQueue]finishTransaction:tran];
break;
case SKPaymentTransactionStateFailed: //交易失敗
[[SKPaymentQueue defaultQueue]finishTransaction:tran];
[SVProgressHUD showErrorWithStatus:@"購(gòu)買失敗"];
break;
default:
break;
}
}
}
- 發(fā)送到蘋果服務(wù)器驗(yà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)買
- (void)verifyPurchaseWithPaymentTrasaction {
// 驗(yàn)證憑據(jù)绞愚,獲取到蘋果返回的交易憑據(jù)
// appStoreReceiptURL iOS7.0增加的,購(gòu)買交易完成后颖医,會(huì)將憑據(jù)存放在該地址
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 從沙盒中獲取到購(gòu)買憑據(jù)
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// 發(fā)送網(wǎng)絡(luò)POST請(qǐng)求位衩,對(duì)購(gòu)買憑據(jù)進(jìn)行驗(yàn)證
//測(cè)試驗(yàn)證地址:https://sandbox.itunes.apple.com/verifyReceipt
//正式驗(yàn)證地址:https://buy.itunes.apple.com/verifyReceipt
NSURL *url = [NSURL URLWithString:SANDBOX];
NSMutableURLRequest *urlRequest =
[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
urlRequest.HTTPMethod = @"POST";
NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
urlRequest.HTTPBody = payloadData;
// 提交驗(yàn)證請(qǐng)求,并獲得官方的驗(yàn)證JSON結(jié)果 iOS9后更改了另外的一個(gè)方法
NSData *result = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];
// 官方驗(yàn)證結(jié)果為空
if (result == nil) {
NSLog(@"驗(yàn)證失敗");
return;
}
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
if (dict != nil) {
// 比對(duì)字典中以下信息基本上可以保證數(shù)據(jù)安全
// bundle_id , application_version , product_id , transaction_id
NSLog(@"驗(yàn)證成功熔萧!購(gòu)買的商品是:%@", @"_productName");
}
}
- 移動(dòng)觀察者
- (void)dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
測(cè)試內(nèi)購(gòu)
必須是沒(méi)有越獄的真機(jī)
測(cè)試之前現(xiàn)在iPhone上的Apple id 注銷
- 使用現(xiàn)有Apple id
使用在沙箱測(cè)試員中添加的賬號(hào)即可
賬號(hào)
- 購(gòu)買
購(gòu)買
- 完成購(gòu)買
完成
- 2017.03.15更新
APP Store首發(fā)以為會(huì)卡在內(nèi)購(gòu)上,但是順利的審核過(guò)了,但是版本更新的時(shí)候,審核員如何做內(nèi)購(gòu)測(cè)試呢? 首先你要了解xcode運(yùn)行的APP只能用沙盒測(cè)試賬號(hào)進(jìn)行購(gòu)買,不能使用真實(shí)的Apple id. 而你在應(yīng)用商店里下載的只能使用真實(shí)的Apple id.
解決方案:
進(jìn)行二次驗(yàn)證:測(cè)試用沙盒驗(yàn)證糖驴,App Store審核的時(shí)候也使用的是沙盒購(gòu)買,所以驗(yàn)證購(gòu)買憑證的時(shí)候需要判斷返回Status Code決定是否去沙盒進(jìn)行二次驗(yàn)證佛致,為了線上用戶的使用贮缕,驗(yàn)證的順序肯定是先驗(yàn)證正式環(huán)境,此時(shí)若返回值為21007俺榆,就需要去沙盒二次驗(yàn)證感昼,因?yàn)榇速?gòu)買的是在沙盒進(jìn)行的
注意:
驗(yàn)證操作讓后臺(tái)去驗(yàn)證
丟單處理詳看下篇博客