iOS內(nèi)購—— In-App Purchase(消耗型)

iOS應(yīng)用如果涉及到支付功能,分為兩類:第三方支付和蘋果內(nèi)購。那么什么情況下選擇使用第三方支付,又在什么情況下選擇蘋果內(nèi)購呢?讓我們先來簡單了解一下:

Understanding What You Can Sell Using In-App Purchase

You can use In-App Purchase to sell content, app functionality, and services.

App functionality.Unlock behavior and expand features you’ve already delivered. Examples include a free game that offers multiplayer mode as an in-app purchase and a free weather app that lets users make a one-time purchase to remove ads.

Services.Have users pay for one-time services such as voice transcription and for ongoing services such as access to a collection of data.

You can’t use In-App Purchase to sell real-world goods and services or to sell unsuitable content.

Real-world goods and services.You must deliver a digital good or service within your app when using In-App Purchase. Use a different payment mechanism to let your users buy real-world goods and services in your app, such as a credit card or payment service.

Unsuitable content.Don’t use In-App Purchase to sell content that the isn’t allowed by the App Review Guidelines—for example, pornography, hate speech, or defamation.

開發(fā)文檔的這里:Understanding What You Can Sell Using In-App Purchase

開發(fā)者中心的這里:https://developer.apple.com/app-store/review/guidelines/#payments

```

購買的內(nèi)容如果要在 app 內(nèi)部使用,必須使用 IAP ,但是你要買的東西與 app 本身無關(guān),就不能使用 IAP 。For Example:你用淘寶、京東的 app 買個鼠標(biāo),真實物品就不能使用IAP。但是要想在斗魚app內(nèi)買虛擬物品來送主播禮物,則必須使用 IAP ,不走內(nèi)購就不行。

```


一、先到iTunes Connect上填寫協(xié)議、稅務(wù)和銀行業(yè)務(wù)


如果你是外包公司,那么你可以讓你的客戶填寫這一堆信息;如果你只是是產(chǎn)品公司的技術(shù)開發(fā)人員,那么你可以讓項目負(fù)責(zé)人填寫這一堆信息;如果沒有如果,兄弟辛苦了,自己動手來吧。

第一步


第二步


第三步


第四步


第五步


先點擊Contact Info 的Set Up

第六步


第七步


第八步


第九步


第十步


第十一步


第十二步

進(jìn)行十二步的時候可能有些銀行通過下面的Look up CNAPS Code方法查不到,就需要借助百度了,一定要準(zhǔn)確查詢,否則會有問題。推薦一個地址

https://e.czbank.com/CORPORBANK/query_unionBank_index.jsp

第十三步


這一步需要注意的是,貨幣類型可能有歧義,看你是想收美元還是人民幣了,都說美元合適。不過,我做的時候為了避免事情,還是選擇了CNY,支持國產(chǎn)。還有一點,銀行賬號如果是對公的賬號,需要填寫公司的英文名稱,如果沒有的話,上拼音!然后點擊保存銀行信息就算ok了,然后退回到最開始的頁面

第十四步


第十五步


第十六步


第十七步


第十八步


第十九步


第二十步


第二十一步(完成)


二、為app添加內(nèi)購產(chǎn)品

在iTunes Connect在你要添加內(nèi)購的app中,進(jìn)入到功能頁面

添加內(nèi)購項目


在你點擊添加內(nèi)購產(chǎn)品按鈕后會有彈框,提示你選擇類型,這個就要看你app的需求了

選擇類型


名稱和定價
本地化版本(可以“+”添加語言)
填寫審核信息(現(xiàn)在的圖)

填寫完審核信息后,點擊右上角的“存儲”按鈕,就添加了一個內(nèi)購產(chǎn)品~


三、添加沙盒技術(shù)測試員

在iTunes Connect的用戶和智能中選擇“沙盒技術(shù)測試員”,填寫信息保存以后就有一個測試員了

添加沙盒測試員


四、代碼部分

首先是.h文件

#import <UIKit/UIKit.h>

#import <StoreKit/StoreKit.h>

#import "MBProgressHUD.h"


@interface GiftChartViewController :UIViewController<SKPaymentTransactionObserver,SKProductsRequestDelegate>

@end

然后是.m文件


//下面的字符串就是你在iTunes Connect上的內(nèi)購項目的產(chǎn)品ID,

static const NSString *productCoin60 =@"隨便寫的60";

static const NSString *productCoin300 =@"隨便寫的300";

static const NSString *productCoin600 =@"隨便寫的600";

static const NSString *productCoin980 =@"隨便寫的980";

static const NSString *productCoin1280 =@"隨便寫的1280";

static const NSString *productCoin2580 =@"隨便寫的2580";


typedefNS_ENUM(NSInteger,coinType) {

coinType60,/** 60金幣*/

coinType300,/** 300金幣*/

coinType600,/** 600金幣*/

coinType980,/** 980金幣*/

coinType1280,/** 1280金幣*/

coinType2580/** 2580金幣*/

};


#pragma mark - lifecycle

- (void)viewDidLoad {

[super viewDidLoad];

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

}

//支付的點擊事件

- (void)payAction:(id)sender{

NSLog(@"pay pay pay");

NSLog(@"-------------請求對應(yīng)的產(chǎn)品信息----------------");

if([SKPaymentQueue canMakePayments]) {

[self requestProductData];

}else{

//做一些提示

}

}

- (void)requestProductData{

NSArray *product;

switch(_buyCoinType) {

case:coinType60:

product =@[productCoin60];

break;

case:coinType300:

product =@[productCoin300];

break;

case:coinType600:

product =@[productCoin600];

break;

case:coinType980:

product =@[productCoin980];

break;

case:coinType1280:

product =@[productCoin1280];

break;

case:coinType2580:

product =@[productCoin2580];

break;

default:

break;

}

NSLog(@"請求的產(chǎn)品%@",product);

NSSet *nsset = [NSSet setWithArray:product];

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

request.delegate =self;

[request start];

[MBProgressHUD showHUDAddedTo:self.view animated:YES];

}


#pragma mark - SKProductsRequestDelegate

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{

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

NSArray *myProduct = response.products;

NSLog(@"產(chǎn)品Product ID:%@",response.invalidProductIdentifiers);

NSLog(@"產(chǎn)品付費數(shù)量: %d", (int)[myProduct count]);

// populate UI

for(SKProduct *productinmyProduct){

NSLog(@"product info");

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

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

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

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

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

[MBProgressHUD hideHUDForView:self.view animated:YES];

SKPayment *payment = [SKPayment paymentWithProduct:product];

[[SKPaymentQueue defaultQueue] addPayment:payment];

//addPayment 將支付信息添加進(jìn)蘋果的支付隊列后,蘋果會自動完成后續(xù)的購買請求,在用戶購買成功或者點擊取消購買的選項后回調(diào)

}

//payment = [SKPayment paymentWithProductIdentifier:coin60];這個方法不要使用了

//+ (id)paymentWithProductIdentifier:(NSString*)identifier NS_DEPRECATED_IOS(3_0,5_0,"Use +paymentWithProduct: after fetching the available products using SKProductsRequest");

};

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{

NSLog(@"------------------錯誤-----------------:%@", error);

}

- (void)requestDidFinish:(SKRequest *)request{

NSLog(@"------------反饋信息結(jié)束-----------------");

}


//監(jiān)聽購買結(jié)果的回調(diào)

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{

for(SKPaymentTransaction *tranintransaction){

switch(tran.transactionState) {

case:SKPaymentTransactionStatePurchased:{

NSLog(@"交易完成");

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

[self verifyTransactionResult];

break;

?}

case:SKPaymentTransactionStatePurchasing:

NSLog(@"商品添加進(jìn)列表");

break;

case:SKPaymentTransactionStateRestored:

NSLog(@"已經(jīng)購買過商品");

break;

case:SKPaymentTransactionStateFailed:{

NSLog(@"交易失敗");

[MyTaShowMessageView showMessage:@"交易失??!"];

[[SKPaymentQueue defaultQueue] finishTransaction:tran];

break;

}

default:

break;

}

}

}

- (void)dealloc{

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

}


購買成功后我們iOS前端可以單獨在客戶端完成訂單正確性的驗證。但是因為有的項目后臺要Android和iOS兩端生成賬單便于對賬。所以我們請求后臺接口,服務(wù)器處驗證是否支付成功,依據(jù)后臺返回結(jié)果做相應(yīng)邏輯處理。

(PS:訂單正確性的驗證本來可以是:iOS客戶端(購買成功)→ 前端到蘋果服務(wù)器驗證→處理蘋果返回結(jié)果做相應(yīng)邏輯處理; 現(xiàn)在:iOS客戶端(購買成功)→ 后臺→后臺到蘋果服務(wù)器驗證→處理后臺返回結(jié)果做相應(yīng)邏輯處理)

服務(wù)器要做的是:

1.接收iOS前端發(fā)過來的購買憑證。

2.判斷憑證是否已經(jīng)存在或驗證過,然后存儲該憑證。

3.將該憑證發(fā)送到對應(yīng)環(huán)境下的蘋果服務(wù)器驗證,并將驗證結(jié)果返回給客戶端。

4.根據(jù)需求,是否修改用戶相應(yīng)信息。

官方文檔應(yīng)該也是支持的這么做的→In-App Purchase Programming Guide

- (void)verifyTransactionResult{

//驗證憑據(jù),獲取到蘋果返回的交易憑據(jù)

// appStoreReceiptURL iOS7.0增加的,購買交易完成后,會將憑據(jù)存放在該地址

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];

//從沙盒中獲取到購買憑據(jù)

NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];

//傳輸?shù)氖荁ASE64編碼的字符串

/**

BASE64常用的編碼方案,通常用于數(shù)據(jù)傳輸,以及加密算法的基礎(chǔ)算法,傳輸過程中能夠保證數(shù)據(jù)傳輸?shù)姆€(wěn)定性,BASE64是可以編碼和解碼的。

*/

NSDictionary *requestDict =@{@"receipt-data": [receipt base64EncodedStringWithOptions:0],@"sandbox":@"1"};

/**

請求后臺接口,服務(wù)器處驗證是否支付成功,依據(jù)返回結(jié)果做相應(yīng)邏輯處理

與后臺協(xié)調(diào)好,讓后臺根據(jù)你的“sandbox”字段的1,0來區(qū)分請求是正式環(huán)境還是測試環(huán)境

(當(dāng)然“sandbox”這個字段也可以替換為你想要的,但是“receipt-data”不能替換,要注意?。?/p>

詳情點這里→蘋果官方文檔

*/

//請求成功的response自己輸出看一下吧,status是0就成功了,這里就不貼出來了,因為有一些敏感數(shù)據(jù),比如你的bundleID,product_id之類的

}

下面是兩種環(huán)境下的蘋果服務(wù)器驗證地址

// Create a POST request with the receipt data.

//In the test environment, use https://sandbox.itunes.apple.com/verifyReceipt

//In?the?real?environment,?use?https://buy.itunes.apple.com/verifyReceipt

到這里最基本的內(nèi)購流程就可以跑通了~

五、要注意的事項!

1.bundleID要與iTunes Connect上你App的相同,不然是請求不到產(chǎn)品信息的

2.在沙盒環(huán)境進(jìn)行測試內(nèi)購的時候,要使用沒有越獄的蘋果手機(jī)。

3.在沙盒環(huán)境下真機(jī)測試內(nèi)購時,請去app store中注銷你的apple ID,不然發(fā)起支付購買請求后會直接case:SKPaymentTransactionStateFailed。使用沙盒測試員的賬號時不需要真正花錢的。

4.如果只添加了一個沙盒測試員賬號,當(dāng)一個真機(jī)已經(jīng)使用了這個賬號,另一個真機(jī)再使用這個賬號支付也是會發(fā)生錯誤的。那就去多建幾個沙盒測試員賬號使用不同的,反正也是免費的,填寫也很快。

5.監(jiān)聽購買結(jié)果,當(dāng)失敗和成功時代碼中要調(diào)用:

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

該方法通知蘋果支付隊列該交易已完成,不然就會已發(fā)起相同 ID 的商品購買就會有此項目將免費恢復(fù)的提示。


六、請在本地做一下憑證存儲!

現(xiàn)在訂單正確性的驗證是:iOS客戶端(購買成功)→ 后臺→后臺到蘋果服務(wù)器驗證→處理后臺返回結(jié)果做相應(yīng)邏輯處理。

頭疼的情況

針對圖上的情況:當(dāng)我們前端購買成功后,憑證本地保留一份,當(dāng)與后臺驗證成功后,再將本地保留的憑證刪除。否者一直使用本地已經(jīng)保留的憑證與后臺交互。


七、最后

在第一節(jié) :先到iTunes Connect上填寫協(xié)議、稅務(wù)和銀行業(yè)務(wù)中,因為我自己的開發(fā)者賬號已經(jīng)填寫過一遍這個信息了,步驟無法復(fù)現(xiàn)。所以在征得簡書作者:睡不著的葉-《iOS開發(fā) 內(nèi)購流程 手把手教你還不學(xué)?》的同意后,轉(zhuǎn)用了部分圖片,在此表示感謝。


寫的第一篇文章,寫的不好的地方,大家多多包涵,在作為iOS開發(fā)者的路上我們一起奔跑~

最后編輯于
?著作權(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)容

  • iOS應(yīng)用內(nèi)付費(IAP)開發(fā)步驟 1.蘋果iTunes Connect內(nèi)購產(chǎn)品信息錄入。 1)創(chuàng)建app內(nèi)購買項...
    MillerWang閱讀 11,317評論 0 7
  • iOS支付 iOS支付分為兩類,第三方支付和應(yīng)用內(nèi)支付(內(nèi)購)。 第三方支付包括:支付寶支付、微信支付、銀聯(lián)支付、...
    請輸入賬號名閱讀 6,472評論 3 22
  • 在我們應(yīng)用開發(fā)中我們經(jīng)常在自己的項目中使用到支付,下面我們來談?wù)刬OS這塊的支付;iOS支付主要分為兩類,第三方支...
    Hither閱讀 8,497評論 9 42
  • 是運(yùn)氣也好,天道酬勤也罷,前天下午,中國隊在中國杯上打破了國家隊552分鐘的進(jìn)球荒,同時在點球大戰(zhàn)中依仗門...
    十三貓叔閱讀 449評論 0 3
  • 上一篇介紹“網(wǎng)游動作設(shè)計師”的推文一推出,后臺就有不少“小鮮肉”給我留言了:“張官,我們倒是想把游戲當(dāng)成職業(yè),...
    張官禮待閱讀 835評論 0 1

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