iOS應(yīng)用內(nèi)付費(IAP)開發(fā)步驟

iOS應(yīng)用內(nèi)付費(IAP)開發(fā)步驟

1.蘋果iTunes Connect內(nèi)購產(chǎn)品信息錄入。

1)創(chuàng)建app內(nèi)購買項目(Create New),選擇類型:

1.消耗型項目

對于消耗型 App 內(nèi)購買項目,用戶每次下載時都必須進行購買。一次性服務(wù)通常屬于消耗型項目,例如釣魚App 中的魚餌。

2.非消耗型項目

對于非消耗型 App 內(nèi)購買項目,用戶僅需要購買一次。不會過期或隨使用而減少的服務(wù)通常為非消耗型項目,例如游戲App 的新跑道。

3.自動續(xù)訂訂閱

通過自動續(xù)訂訂閱,用戶可以購買指定時間期限內(nèi)的更新和動態(tài)內(nèi)容。除非用戶取消選擇,否則訂閱(例如雜志訂閱等)會自動續(xù)訂。

4.免費訂閱

通過免費訂閱,開發(fā)者可以將免費訂閱內(nèi)容放入“報刊雜志”。用戶注冊免費訂閱后,該訂閱內(nèi)容將會出現(xiàn)在與該用戶Apple ID 關(guān)聯(lián)的所有設(shè)備上。請注意,免費訂閱不會過期,并且僅在支持報刊雜志功能的 App 中提供。

5.非續(xù)訂訂閱

非續(xù)訂訂閱允許有時限性的營銷服務(wù)。對于 App 內(nèi)購買項目中的限時訪問內(nèi)容,就需使用非續(xù)訂訂閱。例如,導航App 中語音導航功能的一周訂閱,或者年度訂閱已存檔的視頻或音頻的在線目錄。

一定要根據(jù)自己應(yīng)用的情況選擇正確,不然會被App Store審核團隊拒絕。應(yīng)用內(nèi)的虛擬幣要采用消耗型的,有固定時限的會員選擇自動續(xù)訂訂閱。也可以只選擇虛擬幣充值自己后臺購買的情況解決會員問題。

2)生成共享密鑰

共享密鑰是在您聯(lián)系我們的服務(wù)器獲取 App 內(nèi)購買項目收據(jù)時使用的唯一代碼。沒有共享密鑰,您將無法在沙箱技術(shù)模式下測試自動續(xù)訂 App 內(nèi)購買項目。另外,共享密鑰不能在 App Store 使用。

注:無論與哪個 App 相關(guān)聯(lián),您的所有自動續(xù)訂訂閱都將使用同一共享密鑰。

此共享密鑰用于后臺服務(wù)器驗證用戶購買項目的憑證,生成新密要服務(wù)器也立即改變驗證密鑰。共享密鑰在驗證自動續(xù)訂訂閱類型項目的時候必須需要。

3)內(nèi)購項目的狀態(tài)

A) Pending Developer Approval – Your in apppurchase has been created but has not been tested in a sandbox environment andapproved by you.

B) Approved By Developer – Your in apppurchase has been tested in a sandbox environment and has been approved by you.

C) Waiting For Review – You have submittedyour in app purchase to be reviewed by Apple.

D) In Review – Your in app purchase iscurrently being reviewed by Apple no edits can be made.

E) Developer Action Required – In app purchasedetail changes that you submitted have been rejected. You are required to takeaction to edit the detail information or cancel the request to change thedetail information before this in app purchase can be reviewed again.(內(nèi)購項目詳情界面會提示那個地方出現(xiàn)了問題,稍微修改一下再次提交就行了)

F) Ready for Sale – Apple has approved your inapp purchase to go live on the App Store with its associated application. Thein app purchase must be cleared for sale in iTunes Connect to be Ready forSale.

G) Rejected – Apple has rejected your in apppurchase during the review process. If you have not already been contacted byApple with more information about your rejection, you may inquire through theContact Us section of iTunes Connect. A rejected in app purchase cannot bereinstated. You must create a new in app purchase if you still wish for it tobe sold.

H) Developer Removed from Sale – You havemarked your in app purchase as not cleared for sale in iTunes Connect.

2.app端程序代碼編寫(代碼僅供參考)

#pragma mark - 支付以單利的形式展開

+(PurchasesObject*)SharePurchases

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

if (_purchase == nil) {

_purchase = [[super alloc]init];

[[SKPaymentQueue defaultQueue]addTransactionObserver:_purchase];

}

});

return _purchase;

}

+(id)allocWithZone:(struct _NSZone *)zone

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

if (_purchase == nil) {

_purchase = [[super allocWithZone:zone]init];

}

});

return _purchase;

}

+(id)alloc

{

return _purchase;

}

#pragma mark -支付鉆石會員

_alter = [[UIAlertView alloc]initWithTitle:@游客模式購買僅限當前設(shè)備使用所購買的權(quán)限,推薦您登錄購買 message:nil delegate:self cancelButtonTitle:@取消 otherButtonTitles:@登陸購買(推薦),@游客模式購買 ,nil];

//游客購買很重要,會被AppStore審核團隊拒絕。

#pragma mark -開始支付,根據(jù)錄入內(nèi)購項目的產(chǎn)品id去AppStore請求產(chǎn)品信息。

if ([SKPaymentQueue canMakePayments]) {

NSSet * set = [NSSet setWithArray:@[ProductID]];

SKProductsRequest * request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];

request.delegate = self;

[request start];

}

else

{

NSLog(@無權(quán)限購買);

}

#pragma mark -SKProductsRequestDelegate 獲取appstroe產(chǎn)品信息

- (void)productsRequest:(SKProductsRequest *)requestdidReceiveResponse:(SKProductsResponse *)response {

self.mySelfView.userInteractionEnabled = NO;

[AFTools showHUD:@獲取產(chǎn)品信息 atView:self.mySelfView];

NSLog(@-----------收到產(chǎn)品反饋信息--------------);

NSArray *myProduct = response.products;

if (myProduct.count == 0) {

[AFTools alertWithTitle:@購買失敗 message:@無法獲取產(chǎn)品信息];

NSLog(@無法獲取產(chǎn)品信息,購買失敗。);

return;

}

NSLog(@產(chǎn)品products==%@,myProduct);

NSLog(@產(chǎn)品id==%@,response.invalidProductIdentifiers);

NSLog(@產(chǎn)品數(shù)量==========%lu,(unsigned long)myProduct.count);

for(SKProduct *product in myProduct){

// SKMutablePayment

NSLog(@SKProduct描述信息%@, [product description]);

NSLog(@產(chǎn)品標題 %@ , product.localizedTitle);

NSLog(@產(chǎn)品描述信息: %@ , product.localizedDescription);

NSLog(@價格: %@ , product.price);

NSLog(@Product id: %@ , product.productIdentifier);

SKMutablePayment *MpayMent = [SKMutablePayment paymentWithProduct:product];

NSLog(@===%@,MpayMent.requestData);

if ([[SKPaymentQueue defaultQueue]respondsToSelector:@selector(addPayment:)]){

[[SKPaymentQueue defaultQueue] addPayment:MpayMent];

}

else

{

}

}

}

#pragmamark-SKPaymentTransactionObserver支付結(jié)果

- (void)paymentQueue:(SKPaymentQueue *)queueupdatedTransactions:(NSArray *)transactions

{

for (SKPaymentTransaction *transaction in transactions)

{

switch (transaction.transactionState)

{

case SKPaymentTransactionStatePurchased://交易完成

NSLog(@交易完成transactionIdentifier= %@, transaction.transactionIdentifier);

[self completeTransaction:transaction];

break;

case SKPaymentTransactionStateFailed://交易失敗

[self failedTransaction:transaction];

NSLog(@交易失敗);

break;

case SKPaymentTransactionStateRestored://已經(jīng)購買過該商品

[self restoreTransaction:transaction];

NSLog(@已買過商品);

break;

case SKPaymentTransactionStatePurchasing://商品添加進列表

NSLog(@商品添加進列表);

break;

default:

break;

}

}

}

- (void)paymentQueue:(SKPaymentQueue *)queueremovedTransactions:(NSArray *)transactions

{

NSLog(@---------------移除-------------);

}

- (void)paymentQueue:(SKPaymentQueue *)queuerestoreCompletedTransactionsFailedWithError:(NSError *)error

{

NSLog(@---------------重復支付失敗-------------);

}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {

NSLog(@-------------------支付完成--------------------);

[self commitSeversSucceeWithTransaction:transaction];

}

-(void)restoreTransaction: (SKPaymentTransaction *)transaction

{

NSLog(@----------------重復支付-----------------);

[self commitSeversSucceeWithTransaction:transaction];

}

- (void)commitSeversSucceeWithTransaction:(SKPaymentTransaction *)transaction

{

NSString * productIdentifier = transaction.payment.productIdentifier;

NSString *transactionReceiptString= nil;

//系統(tǒng)IOS7.0以上獲取支付驗證憑證的方式應(yīng)該改變,切驗證返回的數(shù)據(jù)結(jié)構(gòu)也不一樣了。

if(IOSSystemVersion>=7.0)

{

NSURLRequest*appstoreRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle]appStoreReceiptURL]];

NSError *error = nil;

NSData * receiptData = [NSURLConnection sendSynchronousRequest:appstoreRequestreturningResponse:nil error:&error];

transactionReceiptString = [receiptDatabase64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];

}

else

{

NSData * receiptData = transaction.transactionReceipt;

transactionReceiptString = [receiptDatabase64EncodedString];

}

// 向自己的服務(wù)器驗證購買憑證

}

- (void)failedTransaction:(SKPaymentTransaction *)transaction {

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

最好在客戶端上鍵一個數(shù)據(jù)庫,跟蹤訂單的狀態(tài),防止用戶訂單在某個環(huán)節(jié)出現(xiàn)問題時無法尋找到訂單進行二次處理。

去AppStore請求數(shù)據(jù)時有時候會出現(xiàn)錯誤,你可以iTunes connect里的connect us去給他們寫郵件反饋問題。但是大部分時間你等等就能解決了,對就是什么也不做等著。也許那一天他就好了。

3.后臺服務(wù)器驗證

IOS 內(nèi)支付有兩種模式:

1) 內(nèi)置模式

2) 服務(wù)器模式

內(nèi)置模式的流程可以簡單的總結(jié)為以下幾步:

1) app從app store 獲取產(chǎn)品信息

2) 用戶選擇需要購買的產(chǎn)品

3) app發(fā)送支付請求到app store

4) app store 處理支付請求,并返回transaction信息

5) app將購買的內(nèi)容展示給用戶

服務(wù)器模式的主要流程如下所示:

1) app從服務(wù)器獲取產(chǎn)品標識列表

2) app從app store 獲取產(chǎn)品信息

3) 用戶選擇需要購買的產(chǎn)品

4) app 發(fā)送 支付請求到app store

5) app store 處理支付請求,返回transaction信息

6) app 將transaction receipt 發(fā)送到服務(wù)器

7) 服務(wù)器收到收據(jù)后發(fā)送到app stroe驗證收據(jù)的有效性

8) app store 返回收據(jù)的驗證結(jié)果

9) 根據(jù)app store 返回的結(jié)果決定用戶是否購買成功

上述兩種模式的不同之處主要在于:交易的收據(jù)驗證,內(nèi)建模式?jīng)]有專門去驗證交易收據(jù),而服務(wù)器模式會使用獨立的服務(wù)器去驗證交易收據(jù)。內(nèi)建模式簡單快捷,但容易被破解。服務(wù)器模式流程相對復雜,但相對安全。

開發(fā)之初,蘋果方就很負責的告知:我們的服務(wù)器不穩(wěn)定。真正開發(fā)之后,發(fā)現(xiàn)蘋果方果然是很負責的,不僅是不穩(wěn)定,而且足夠慢。app store server驗證一個收據(jù)需要3-6s時間。

1.用戶能否忍受3-6s的等待時間

2.如果app store server 宕機,如何確保成功付費的用戶能夠得到正常服務(wù)。

對于第一個問題,我們有理由相信用戶完全無法忍受,所以采用異步驗證的方式,服務(wù)器收到客戶端的請求后,就將請求放到MCQ中去處理。

對于第二個問題,由于蘋果人員很負責人的告知:我們的服務(wù)器不穩(wěn)定,所以不排除收據(jù)驗證超時的情況。對于驗證超時的收據(jù),保存到數(shù)據(jù)庫中并標記為驗證超時,定時任務(wù)每隔一定的時間去app store驗證,確保能夠獲取收據(jù)的驗證結(jié)果。

在開發(fā)過程中,需要測試應(yīng)用是否能夠正常的進行支付,但是又不能進行實際的支付,因此需要使用蘋果提供的sandbox Store測試。Store Kit不能在iOS模擬器中使用,測試Store必須在真機上進行。

在sandbox中驗證receipt

https://sandbox.itunes.apple.com/verifyReceipt

在生產(chǎn)環(huán)境中驗證receipt

https://buy.itunes.apple.com/verifyReceipt

在實際開發(fā)過程中,服務(wù)器端通過issandbox字段標識客戶端傳遞的收據(jù)是沙盒環(huán)境中的收據(jù)還是生產(chǎn)環(huán)境中的收據(jù)。在提交蘋果審核前,沙盒測試均無問題。提交蘋果審核后,被告知購買失敗,審核未通過。通過查詢?nèi)罩景l(fā)現(xiàn),客戶端發(fā)送的交易收據(jù)為沙盒收據(jù),但是issandbox字段卻標識為生產(chǎn)環(huán)境。

結(jié)論:蘋果審核app時,仍然在沙盒環(huán)境下測試。但是客戶端同事在app提交蘋果審核時,將issandbox字段寫死,設(shè)置為生產(chǎn)環(huán)境。這樣就導致沙盒收據(jù)發(fā)送到https://buy.itunes.apple.com/verifyReceipt去驗證。

那么如何自動的識別收據(jù)是否是sandbox receipt呢?

識別沙盒環(huán)境下收據(jù)的方法有兩種:

1.根據(jù)收據(jù)字段 environment = sandbox。

2.根據(jù)收據(jù)驗證接口返回的狀態(tài)碼

如果status=21007,則表示當前的收據(jù)為沙盒環(huán)境下收據(jù), t進行驗證。

蘋果反饋的狀態(tài)碼;

21000App Store無法讀取你提供的JSON數(shù)據(jù)

21002 收據(jù)數(shù)據(jù)不符合格式

21003 收據(jù)無法被驗證

21004 你提供的共享密鑰和賬戶的共享密鑰不一致

21005 收據(jù)服務(wù)器當前不可用

21006 收據(jù)是有效的,但訂閱服務(wù)已經(jīng)過期。當收到這個信息時,解碼后的收據(jù)信息也包含在返回內(nèi)容中

21007 收據(jù)信息是測試用(sandbox),但卻被發(fā)送到產(chǎn)品環(huán)境中驗證

21008 收據(jù)信息是產(chǎn)品環(huán)境中使用,但卻被發(fā)送到測試環(huán)境中驗證

先生產(chǎn)驗證后測試驗證,可以避免來回切換接口的麻煩。測試驗證只要用你自己申請的測試appid的時候才會用到,用戶不會擁有測試appid,所以不會走到測試驗證這一步。即使生產(chǎn)驗證出錯,應(yīng)該也不回返回21007狀態(tài)嗎。測試驗證通過的用戶名,和充值金額最好用數(shù)據(jù)庫記錄下來,方便公司資金核對。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在我們應(yīng)用開發(fā)中我們經(jīng)常在自己的項目中使用到支付,下面我們來談?wù)刬OS這塊的支付;iOS支付主要分為兩類,第三方支...
    Hither閱讀 8,486評論 9 42
  • App Store 審核指南2017/07/27 簡介 App 正在改變世界,豐富人們的生活,并為像您一樣的開發(fā)者...
    小白沐春風閱讀 3,736評論 0 2
  • 服務(wù)器模式: 使用這種方式,要提供另外的服務(wù)器將產(chǎn)品發(fā)送給程序。 服務(wù)器交付適用于訂閱、內(nèi)容類商品和服務(wù),因為商品...
    水晶蘭閱讀 1,701評論 1 3
  • 簡介 App 正在改變世界,豐富人們的生活,并為像您一樣的開發(fā)者提供前所未有的創(chuàng)新機會。因此,App Store ...
    o0_0o閱讀 3,713評論 2 48
  • 【作者】王紅雨 【導師】王玉印 袁文魁 【分舵】天地會 【舵主】王雅葉 【導圖解說】《海洋奇緣》觀感 動畫片中的精...
    王紅雨閱讀 1,052評論 7 1

友情鏈接更多精彩內(nèi)容