公司項目中有虛擬產品,所以要使用蘋果內購.自此記錄一下蘋果內購的流程.前提是已有開發者賬號
協議,稅務和銀行業務
- 協議,稅務和銀行業務
協議,稅務和銀行業務
申請合同
- 這里提示地址太長,按照要求重新填寫一下就可以
添加聯系人
- 同意協議并提交
- 設置相關信息
- 聯系人信息
添加相關聯系人信息之后,注意在role(角色)中,為聯系人選擇身份(高級管理人員 ,金融,技術,法律,營銷),點擊Done保存
聯系人
- 銀行信息
- 添加銀行信息
添加銀行
2.選擇國家
選擇國家
3.填寫CNAPS
CNAPS 銀行網點聯行號.我們可以直接到銀行客服電話查詢 CNAPS, 快速便捷.還可以通過下圖的Look up CNAPS Code 查詢. 不過有的查詢不到
CNAPS
Look up CNAPS Code
4.確認銀行信息
銀行信息
5.填寫公司銀行賬號信息
公司銀行信息
- 稅務信息
稅務信息有三個選項:美國稅務、澳大利亞稅務、加拿大稅務。我們在這里選擇美國稅務就可以
稅務信息
這里有兩個問題:如下圖.我選擇的都是NO
填寫稅務相關信息
9b.Foreign TIN 是填寫公司稅務識別碼.公司營業執照上同意社會信用代碼去掉前兩位和最后一位就是公司稅務識別碼(15位)
點擊提交之后會讓你確認信息,確認無誤后再次點擊提交(提交后無法修改)
創建測試APP
新建APP在這里就不詳細描述了
添加內購
- 選擇功能,我們添加一個app內購項目
添加內購
- 根據項目需求,選擇內購項目
消耗性項目
- 填寫內購項目的相關信息
- 商品名稱根據你的消費道具的實際意義來說明
- 產品ID是比較重要的,只要唯一即可,在實際應用中,一定要認真填寫。
- 選擇價格
- 本地化版本
將在 App Store 上可見的 App 內購買項目名稱。可以參考App Store中其他應用的內購項目描述
描述不得少于10個字符.沒有重新截圖
本地化
- 審核信息
1.只會在審核中使用屏幕快照,不會將其顯示在 App Store 上。屏幕快照必須具有適合您 App 平臺的有效尺寸。
2.能夠有助于我們進行審核的關于您的 App 內購買項目的其他信息,如測試帳戶(包括用戶名、密碼等)。審核備注不得超過 4000 個字符。
審核信息
- 內購項目則添加完成
申請沙盒測試賬號(用來測試購買項目)
我們不必用真實的人民幣測試購買內購項目
- 首先我們回到iTunes Connect中,在這里我們選擇用戶和職能。
- 添加沙箱技術測試員
測試人員
- 添加測試員詳細信息
所有信息都可以隨意填寫,不用管是否真實。但是App Store地區必須對應
注意: 郵件地址不能填寫與 Apple ID 關聯的, 密碼保護問題必須在 6 到 35 個字符之間。密碼必須包含至少一個大寫字母。
信息
所有準備工作都已完成.打開項目開始擼代碼
在項目中實現購買
首先在項目工程中加入
storekit.framework
,加入頭文件#import <StoreKit/StoreKit.h>
遵守代理SKPaymentTransactionObserver
,SKProductsRequestDelegate
//添加一個交易隊列觀察者
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
//self.productIds是在開發者平臺填寫的產品id
self.productId = @"701";
if ([SKPaymentQueue canMakePayments]) {
[self requestProductData:self.productId];
}else{
DLog(@"不允許程序內付費");
}
- 去蘋果服務器請求產品信息
// 去蘋果服務器請求產品信息
- (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
// 收到產品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *productArr = response.products;
if ([productArr count] == 0) {
[SVProgressHUD dismiss];
DLog(@"沒有該商品");
return;
}
DLog(@"productId = %@",response.invalidProductIdentifiers);
DLog(@"產品付費數量 = %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];
//發送內購請求
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- SKRequestDelegate
- (void)requestDidFinish:(SKRequest *)request {
[SVProgressHUD dismiss];
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
[SVProgressHUD showErrorWithStatus:@"支付失敗"];
}
- SKPaymentTransactionObserver監聽購買結果
// 監聽購買結果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray
<
SKPaymentTransaction *
>
*)transactions {
for (SKPaymentTransaction *tran in transactions) {
switch (tran.transactionState) {
case SKPaymentTransactionStatePurchased: //交易完成
// 發送到蘋果服務器驗證憑證
[self verifyPurchaseWithPaymentTrasaction];
[[SKPaymentQueue defaultQueue]finishTransaction:tran];
break;
case SKPaymentTransactionStatePurchasing: //商品添加進列表
break;
case SKPaymentTransactionStateRestored: //購買過
// 發送到蘋果服務器驗證憑證
[[SKPaymentQueue defaultQueue]finishTransaction:tran];
break;
case SKPaymentTransactionStateFailed: //交易失敗
[[SKPaymentQueue defaultQueue]finishTransaction:tran];
[SVProgressHUD showErrorWithStatus:@"購買失敗"];
break;
default:
break;
}
}
}
- 發送到蘋果服務器驗證憑證
>
//沙盒測試環境驗證
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式環境驗證
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
// 驗證購買
- (void)verifyPurchaseWithPaymentTrasaction {
// 驗證憑據,獲取到蘋果返回的交易憑據
// appStoreReceiptURL iOS7.0增加的,購買交易完成后,會將憑據存放在該地址
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 從沙盒中獲取到購買憑據
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// 發送網絡POST請求,對購買憑據進行驗證
//測試驗證地址:https://sandbox.itunes.apple.com/verifyReceipt
//正式驗證地址: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;
// 提交驗證請求,并獲得官方的驗證JSON結果 iOS9后更改了另外的一個方法
NSData *result = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];
// 官方驗證結果為空
if (result == nil) {
NSLog(@"驗證失敗");
return;
}
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
if (dict != nil) {
// 比對字典中以下信息基本上可以保證數據安全
// bundle_id , application_version , product_id , transaction_id
NSLog(@"驗證成功!購買的商品是:%@", @"_productName");
}
}
- 移動觀察者
- (void)dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
測試內購
必須是沒有越獄的真機
測試之前現在iPhone上的Apple id 注銷
- 使用現有Apple id
使用在沙箱測試員中添加的賬號即可
賬號
- 購買
購買
- 完成購買
完成
- 2017.03.15更新
APP Store首發以為會卡在內購上,但是順利的審核過了,但是版本更新的時候,審核員如何做內購測試呢? 首先你要了解xcode運行的APP只能用沙盒測試賬號進行購買,不能使用真實的Apple id. 而你在應用商店里下載的只能使用真實的Apple id.
解決方案:
進行二次驗證:測試用沙盒驗證,App Store審核的時候也使用的是沙盒購買,所以驗證購買憑證的時候需要判斷返回Status Code決定是否去沙盒進行二次驗證,為了線上用戶的使用,驗證的順序肯定是先驗證正式環境,此時若返回值為21007,就需要去沙盒二次驗證,因為此購買的是在沙盒進行的
注意:
驗證操作讓后臺去驗證
丟單處理詳看下篇博客