參考鏈接
iOS開發(fā)之內(nèi)購-AppStore
iOS App提交指南(二)-協(xié)議柬帕、稅務(wù)和銀行業(yè)務(wù)
iOS應(yīng)用內(nèi)付費(IAP)開發(fā)步驟列表
一速种、創(chuàng)建App
首先你需要登錄 App的ItunesConnection侣颂,你會看到如下界面
簡單的介紹一下這幾個選項
- 我的App主要用于管理自己的App應(yīng)用供屉,例如編輯資料往产,上架陌粹,下架等撒犀。
- 銷售和趨勢主要是來查看App在各個平臺的下載量,收入等方面數(shù)據(jù),里面有曲線圖等圖文結(jié)合的方式給我們參考。
- 付款和財務(wù)報告顯示的是你的收入以及付款等相關(guān)信息或舞。
- iAd主要是跟廣告有關(guān)荆姆,開發(fā)者可以登錄到Workbench,通過iAd對應(yīng)用的廣告進行控制映凳。
- 用戶和職能用于生成相應(yīng)賬號胆筒,例如蘋果沙河測試賬號。
- 協(xié)議诈豌,稅務(wù)和銀行業(yè)務(wù)則是你銀行相關(guān)賬戶的信息設(shè)置仆救。
在這里我們選擇第一個選項,我的App矫渔,然后點擊左上角的加號彤蔽,新建一個用來測試用的App。
點新建 App蚌斩,會出現(xiàn)新建窗口铆惑;
在這里有幾個需要填寫的地方,名稱自己取送膳,平臺IOS员魏,語言選擇了簡體中文,套裝ID也就是你的Bundle Identifier叠聋,需要你在Certificates頁面 申請BundleID,SKU可以理解為用戶看一看到的唯一標(biāo)示撕阎,會體現(xiàn)在你的app的App Store的鏈接中。
申請BundleID
打開Certificates頁面,在左側(cè)選擇Identifiers碌补,并點擊加號虏束,申請一個新的Identifiers。
在這里Name可以隨意填寫厦章,我填寫的是TestAppStroeTestDemo镇匀,而用來使用的BundleID,我們在這里必須選擇第一個選項唯一的袜啃,不用選擇通配汗侵。在下面的選項中, 我們只需要勾選一個 Apple Pay即可群发,其他選項看自己需求晰韵,我在這里只選擇了它谒养。
之后我們回到創(chuàng)建App鹏倘,選擇好自己剛創(chuàng)建的 BundleID ,填寫SKU渤刃, SKU是你App的專用ID起愈,我在這里隨意填寫只恨,直接復(fù)制了App名译仗。點擊創(chuàng)建,我們的測試App則創(chuàng)建成功坤次。
二古劲、協(xié)議、稅務(wù)和銀行業(yè)務(wù)
進入?yún)f(xié)議缰猴、稅務(wù)和銀行業(yè)務(wù)頁面
進入?yún)f(xié)議、稅務(wù)和銀行業(yè)務(wù)頁面后滑绒,會有3種合同類型闷堡,如果你之前沒有主動申請過去合同,那么一般你現(xiàn)在激活的合同只有iOS Free Application一種疑故。
頁面內(nèi)容分為兩塊:
- Request Contracts(申請合同)
- Contracts In Effect(已生效合同)杠览。
合同類型分為3種:
- iOS Free Application(免費應(yīng)用合同)
- iOS Paid Application(付費應(yīng)用合同)
- iAd App NetNetwork(廣告合同)
筆者暫時只申請過付費應(yīng)用合同,所以下面主要講一下付費應(yīng)用合同的申請流程纵势。
當(dāng)我們點擊申請iOS Paid Application合同后踱阿,該合同的狀態(tài)會變成如下的樣子,我們可以看到其中Status為Pending Tax, Bank, Contact钦铁。意思是聯(lián)系方式软舌、銀行和稅務(wù)信息沒有填寫。
1牛曹、填寫聯(lián)系方式
我們點擊Contact Info下方的Set Up按鈕可以進入聯(lián)系方式填寫頁面佛点,如下圖:
如果你沒有添加過聯(lián)系人,你需要通過Add New Contact按鈕來添加一個新的聯(lián)系人黎比。然后指定聯(lián)系人的職務(wù)超营,職務(wù)如下:
- Senior Management:高管
- Financial:財務(wù)
- Technical:技術(shù)支持
- Legal:法務(wù)
- Marketing:市場推廣
如果你是獨立開發(fā)者,可以全部填你自己一個人阅虫。
2演闭、填寫銀行卡信息
我們點擊Bank Info下方的Set Up按鈕可以進入聯(lián)系方式填寫頁面,如下圖:
選擇你的銀行賬戶颓帝,如果你沒有米碰,點擊旁邊的Add Bank Account添加一個賬戶。
下面是添加一個賬戶的流程躲履。
2-1、選擇銀行所在的國家
2-2聊闯、填寫銀行CNAPS Code
如果你不知道CNAPS Code是多少工猜,可以點擊Look up Transit Number來查詢,查詢時會根據(jù)3個關(guān)鍵信息來查詢菱蔬,如下:
- Bank Name:銀行的英文名稱(不能是拼音)
- City:銀行所在的城市英文名稱(中國的城市用拼音)
- Postal Code:郵編
-
然后在下面就會出來備選的銀行篷帅,選擇正確的銀行后史侣,點擊next,進入下一步魏身。
2-3惊橱、確認銀行信息
2-4、填寫銀行賬號信息
- Bank Account Number:銀行賬號
- Confirm Bank Account Number:再次輸入銀行賬號
- Account Holder Name:持卡人姓名箭昵,中文名用拼寫税朴,名在前,姓在后
-
Bank Account Currency:貨幣類型家制,一般國內(nèi)的開發(fā)者選擇CNY
2-5正林、確認所有信息
3、填寫稅務(wù)信息
稅務(wù)信息這一塊了解不是很多颤殴,不過因為是國內(nèi)開發(fā)者觅廓,可以不用太費心,稅務(wù)信息分3種:
- U.S Tax Forms: 美國稅務(wù)
- Australia Tax Forms:澳大利亞稅務(wù)
-
Canada Tax Forms: 加拿大稅務(wù)
筆者選擇的是U.S Tax Forms涵但,選擇后會問你兩個問題杈绸,第一個問題如下:詢問你是否是美國居民,有沒有美國伙伴關(guān)系或者美國公司矮瘟,如果沒有直接選擇No瞳脓。
接下來第二個問題如下:詢問你有沒有在美國的商業(yè)性活動,沒有也直接選No芥永。
然后填寫你的稅務(wù)信息篡殷,包括以下幾點:
- Individual or Organization Name:個人或者組織名稱
- Country of incorporation: 所在國家
- Type of Beneficial Owner:受益方式,獨立開發(fā)者選個人
- Permanent Residence:居住地址
- Mailing address:郵寄地址
- Name of Person Making this Declaration:聲明人
- Title:頭銜
填寫完這些信息后就可以提交了
4埋涧、等待審核
當(dāng)你填寫完所有資料后板辽,合同狀態(tài)就會變成Processing,筆者凌晨1點左右提交棘催,下午就通過了劲弦。
三、添加內(nèi)購買項目
App創(chuàng)建好之后醇坝,我們打開創(chuàng)建的App,在左上角選擇功能邑跪,會看到左側(cè)的App 內(nèi)購買項目。我們點擊右下角的加號呼猪,為App添加內(nèi)購項目画畅。
虛擬物品添加分為如下幾種:
- 消耗品(Consumable products):比如游戲內(nèi)金幣等。
- 不可消耗品(Non-consumable products):簡單來說就是一次購買宋距,終身可用(用戶可隨時從App Store restore)轴踱。
- 自動更新訂閱品(Auto-renewablesubscriptions):和不可消耗品的不同點是有失效時間。比如一整年的付費周刊谚赎。在這種模式下淫僻,開發(fā)者定期投遞內(nèi)容诱篷,用戶在訂閱期內(nèi)隨時可以訪問這些內(nèi)容。訂閱快要過期時雳灵,系統(tǒng)將自動更新訂閱(如果用戶同意)棕所。
- 非自動更新訂閱品(Non-renewablesubscriptions):一般使用場景是從用戶從IAP購買后,購買信息存放在自己的開發(fā)者服務(wù)器上悯辙。失效日期/可用是由開發(fā)者服務(wù)器自行控制的琳省,而非由AppStore控制,這一點與自動更新訂閱品有差異笑撞。
- 免費訂閱品(Free subscriptions):在Newsstand中放置免費訂閱的一種方式岛啸。免費訂閱永不過期。只能用于Newsstand-enabled apps茴肥。
類型2坚踩、3、5都是以Apple ID為粒度的瓤狐。比如小張有三個iPad瞬铸,有一個Apple ID購買了不可消耗品础锐,則三個iPad上都可以使用嗓节。
類型1、4一般來說則是現(xiàn)買現(xiàn)用皆警。如果開發(fā)者自己想做更多控制拦宣,一般選4
之后我們會看到類型的選項,如下圖
官方的注釋寫的很清楚了信姓,只在這里簡單的說下前兩種:
- 消耗型項目 就像你玩游戲需要買金幣鸵隧,買鉆石等,只要花錢就可以無限次的購買
-
非消耗型項目 就像你在App Store購買App意推,買了一次之后就不用再買第二次豆瘫,你擁有永久使用權(quán)。
在我們的app中菊值,是充值會員外驱,所以選擇的是第一種,可以無限次購買腻窒。
這里有幾個選項昵宇,需要填寫商品名稱,產(chǎn)品ID以及價格等級儿子,簡單說明一下
- 商品名稱根據(jù)你的消費道具的實際意義來說明瓦哎,比如“100顆寶石”,“100金幣”等。
- 產(chǎn)品ID是比較重要的杭煎,由項目自定義,只要唯一即可卒落,因為測試羡铲,我在這里隨便填寫的123,在實際應(yīng)用中儡毕,一定要認真填寫也切。
-
價格等級的話“查看價格表”中有對應(yīng)的說明,可以對照著表中每個國家的貨幣價格與等級來選擇
接下來是語言選擇腰湾,和上傳快照如下圖
點擊添加語言雷恃,填寫名稱和描述,這里我們依然選擇簡體中文费坊,如下
審核備注倒槐,根據(jù)實際情況填寫,可以不填附井。而下面的屏幕快照讨越,則是商品圖片,以像素為單位永毅,最低尺寸為321把跨,390,尺寸需求如下圖沼死,上傳即可着逐。
到這里為止, 我們的內(nèi)購項目則添加完成意蛀。接下來則是測試階段了耸别。
四、申請沙盒測試賬號(用來測試購買項目)
這個賬號浸间,是利用蘋果的沙盒測試環(huán)境來模擬AppStore的購買流程太雨,你肯定不會想要用真實RMB去購買測試吧?
首先我們回到iTunes Connect中,在這里我們選擇用戶和職能魁蒜。
然后在上面的第三個選項沙箱技術(shù)測試員中點擊加號囊扳,添加測試員。
在信息填寫頁面只簡單說兩句兜看。
所有信息都可以隨意填寫锥咸,不用管是否真實。
App Store地區(qū)選擇细移,一定要選對搏予,它對應(yīng)的是你創(chuàng)建的App的地區(qū), 你App是中國的話弧轧, 在這里我們依然選擇中國雪侥。
此賬號只能用來測試碗殷,不要在正式的appstore上使用
填寫完畢,點擊保存后速缨,我們則生成一個測試賬號锌妻,當(dāng)然這個賬號是可以隨時刪除和添加的。
五旬牲、大致流程
IAP流程分為兩種仿粹,一種是直接使用Apple的服務(wù)器進行購買和驗證,另一種就是自己假設(shè)服務(wù)器進行驗證原茅。由于國內(nèi)網(wǎng)絡(luò)連接Apple服務(wù)器驗證非常慢吭历,而且也為了防止黑客偽造購買憑證,通用做法是自己架設(shè)服務(wù)器進行驗證擂橘。
下面我們通過圖來看看兩種方式的差別:
5.1晌区、使用Apple服務(wù)器
5.2、自己架設(shè)服務(wù)器
簡單說下第二中情況的流程:
- 用戶進入購買虛擬物品頁面通贞,App從后臺服務(wù)器獲取產(chǎn)品列表然后顯示給用戶
- 用戶點擊購買購買某一個虛擬物品契讲,APP就發(fā)送該虛擬物品的productionIdentifier到Apple服務(wù)器
- Apple服務(wù)器根據(jù)APP發(fā)送過來的productionIdentifier返回相應(yīng)的物品的信息(描述,價格等)
- 用戶點擊確認鍵購買該物品滑频,購買請求發(fā)送到Apple服務(wù)器
- Apple服務(wù)器完成購買后捡偏,返回用戶一個完成購買的憑證
- APP發(fā)送這個憑證到后臺服務(wù)器驗證
- 后臺服務(wù)器把這個憑證發(fā)送到Apple驗證,Apple返回一個字段給后臺服務(wù)器表明該憑證是否有效
- 后臺服務(wù)器把驗證結(jié)果在發(fā)送到APP峡迷,APP根據(jù)驗證結(jié)果做相應(yīng)的處理
六银伟、大致代碼
#import "ViewController.h"
#import <StoreKit/StoreKit.h>
@interface ViewController () <SKPaymentTransactionObserver, SKProductsRequestDelegate>
@property (nonatomic, strong) NSString * receipt;
@end
@implementation ViewController
/**
* 開發(fā)流程:
* 1、引入頭文件 #import <StoreKit/StoreKit.h>
* 2绘搞、檢查用戶是否允許使用 內(nèi)置購買 [SKPaymentQueue canMakePayments]
* 3彤避、如果允許:獲取所有付費Product ID(productionIdentifier)列表『幌剑可以用常量保存在本地琉预,也可以自己服務(wù)器返回(原因:連接蘋果服務(wù)器比較慢)
* 4、先查詢是否有該productionIdentifier的商品信息蒿褂,獲取SKPayment實例圆米,然后通過SKPaymentQueue的 addPayment方法發(fā)起一個購買的操作。
* 5啄栓、監(jiān)聽購買結(jié)果 [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
* 6娄帖、購買完成回調(diào)- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
* 7、服務(wù)器驗證憑證(Optional)昙楚。如果購買成功近速,我們需要將憑證發(fā)送到服務(wù)器上進行驗證。
* 服務(wù)器工作:
* 7.1 接收ios端發(fā)過來的購買憑證。
* 7.2 判斷憑證是否已經(jīng)存在或驗證過削葱,然后存儲該憑證奖亚。
* 7.3 將該憑證發(fā)送到蘋果的服務(wù)器驗證,并將驗證結(jié)果返回給客戶端析砸。
* 7.4 如果需要遂蛀,修改用戶相應(yīng)的會員權(quán)限。
* 8干厚、網(wǎng)絡(luò)異常、崩潰等導(dǎo)致無法驗證螃宙,將購買憑證持久化蛮瞄。用戶下次啟動的時候,再發(fā)一次驗證
* 8.1 保存數(shù)據(jù)(日期谆扎、用戶挂捅、憑證receipt)
* 8.2 重新啟動,讀取數(shù)據(jù)堂湖,發(fā)送網(wǎng)絡(luò)請求
* 8.3 如果成功闲先,刪除文件
*/
- (void)viewDidLoad {
[super viewDidLoad];
// 監(jiān)聽購買結(jié)果
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
- (void)buyProdutin:(UIButton *)sender
{
// 確認用戶是否允許使用 內(nèi)置購買
if([SKPaymentQueue canMakePayments]){
// 獲取商品的productionIdentifier
NSString * productIdentifier = @""; //用戶選擇
[self getProductInfo:productIdentifier];
}else{
}
}
#pragma mark - 查詢productIdentifier 的商品信息
- (void)getProductInfo:(NSString *)productIdentifier
{
NSArray * product = [[NSArray alloc] initWithObjects:productIdentifier, nil];
NSSet * set = [NSSet setWithArray:product];
// 請求蘋果服務(wù)器,是否有該商品
SKProductsRequest * request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
request.delegate = self;
[request start];
// 這里可彈出提示信息 : 正在購買无蜂,請稍后
}
// 查詢該產(chǎn)品信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray * myProduct = response.products;
if(myProduct.count == 0){
// 說明沒有該商品伺糠,或查詢失敗
return;
}
// 如果有,發(fā)起購買操作
SKPayment * payment = [SKPayment paymentWithProduct:myProduct[0]];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
// 查詢失敗
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
// 提示信息
}
#pragma mark - 購買回調(diào)
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
{
for(SKPaymentTransaction * transaction in transactions){
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
// 交易成功
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
// 交易失敗
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
// 已經(jīng)購買過該商品
[self restoreTransaction:transaction];
break;
case SKPaymentTransactionStatePurchasing:
// 商品添加進列表
break;
default:
break;
}
}
}
//沙盒測試環(huán)境驗證
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式環(huán)境驗證
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
/**
* 驗證購買斥季,避免越獄軟件模擬蘋果請求達到非法購買問題
// 交易結(jié)束后训桶,驗證票據(jù)信息是否正確,之后才可以給用戶商品
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
// 測試環(huán)境
self.receipt = [[NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]] base64EncodedStringWithOptions:0];
NSError *error;
NSDictionary *requestContents = @{
@"receipt-data": self.receipt
};
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
options:0
error:&error];
// 設(shè)置URL
NSURL *storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
[storeRequest setHTTPMethod:@"POST"];
[storeRequest setHTTPBody:requestData];
// 網(wǎng)絡(luò)請求酣倾,驗證
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
// 交易失敗后舵揭,回調(diào)
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if(transaction.error.code != SKErrorPaymentCancelled) {
// 購買失敗
} else {
// 用戶取消交易
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
// 已購買過商品回調(diào)
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
#pragma mark - 發(fā)送憑證失敗的處理
/**
* 1 保存數(shù)據(jù)(日期、用戶躁锡、憑證receipt)
* 2 重新啟動午绳,讀取數(shù)據(jù),發(fā)送網(wǎng)絡(luò)請求
* 3 如果成功映之,刪除文件
*/
- (void)dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
@end
需要注意以下幾點:
- 代碼中的self.profuctIdArr所填寫的是你的購買項目的的ID拦焚,我這里是當(dāng)時填寫的ID 123。
- 在監(jiān)聽購買結(jié)果后杠输,一定要調(diào)用[[SKPaymentQueue defaultQueue] finishTransaction:tran];來允許你從支付隊列中移除交易耕漱。
- 沙盒環(huán)境測試appStore內(nèi)購流程的時候,請使用沒越獄的設(shè)備抬伺。
- 請務(wù)必使用真機來測試螟够,一切以真機為準(zhǔn)。
- 項目的Bundle identifier需要與您申請AppID時填寫的bundleID一致,不然會無法請求到商品信息妓笙。
- 真機測試的時候若河,一定要退出原來的賬號,才能用沙盒測試賬號
- 二次驗證寞宫,請注意區(qū)分宏萧福, 測試用沙盒驗證