iOS開發(fā)支付篇——內(nèi)購(IAP)詳解

1內(nèi)購所需要的資料整理總結(jié)

思維導圖

image

重點總結(jié):

1.獲取內(nèi)購列表(從App內(nèi)讀取或從自己服務器讀取)

2.App Store請求可用的內(nèi)購列表

3.向用戶展示內(nèi)購列表

4.用戶選擇了內(nèi)購列表跪者,再發(fā)個購買請求棵帽,收到購買完成的回調(diào)(購買完成后會把錢打給申請內(nèi)購的銀行卡內(nèi))

5.購買流程結(jié)束后, 向服務器發(fā)起驗證憑證以及支付結(jié)果的請求

6.自己的服務器將支付結(jié)果信息返回給前端并發(fā)放虛擬產(chǎn)品

7.服務端的工作比較簡單,分4步:

7.1.接收ios端發(fā)過來的購買憑證坑夯。

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

7.3.將該憑證發(fā)送到蘋果的服務器驗證柜蜈,并將驗證結(jié)果返回給客戶端仗谆。

7.4.如果需要,修改用戶相應的會員權(quán)限淑履。

7.5.考慮到網(wǎng)絡異常情況隶垮,服務器的驗證應該是一個可恢復的隊列,如果網(wǎng)絡失敗了秘噪,應該進行重試狸吞。

簡單來說就是將該購買憑證用Base64編碼,然后POST給蘋果的驗證服務器指煎,蘋果將驗證結(jié)果以JSON形式返回蹋偏。

|

一、使用注意事項及遇到的坑

  1.使用注意
1\. 代碼中的_currentProId所填寫的是你的購買項目的的ID至壤,這個和第二步創(chuàng)建的內(nèi)購的productID要一致威始,產(chǎn)品id與_currentProId一致。

2\. 在監(jiān)聽購買結(jié)果后像街,一定要調(diào)用[[SKPaymentQueue defaultQueue] finishTransaction:tran];來允許你從支付隊列中移除交易黎棠。

3\. 真機測試的時候,一定要退出原來的賬號(app store 登錄的賬號退出)镰绎,才能用沙盒測試賬號脓斩。

4\. 請務必使用真機來測試,一切以真機為準畴栖。

5\. 項目的Bundle identifier需要與您申請AppID時填寫的bundleID一致随静,不然會無法請求到商品信息。

6\. 沙盒環(huán)境測試appStore內(nèi)購流程的時候吗讶,請使用沒越獄的設備燎猛。

7\. 二次驗證叼丑,請注意區(qū)分宏, 測試用沙盒驗證扛门,App Store審核的時候也使用的是沙盒購買,所以驗證購買憑證的時候需要判斷返回Status Code決定是否去沙盒進行二次驗證纵寝,為了線上用戶的使用论寨,驗證的順序肯定是先驗證正式環(huán)境,此時若返回值為21007爽茴,就需要去沙盒二次驗證葬凳,因為此購買的是在沙盒進行的。

8.貨幣類型(Bank Account Currency) :填CNY(如果你的app在中國使用的話)室奏。

2.獲取不到商品信息

1.確定配置環(huán)節(jié)正確火焰。

2.確定是真機測試且手機沒有越獄。

3.確定內(nèi)購商品添加到了需要內(nèi)購功能的App中胧沫。

4.確定當前運行的App的Bundle ID和后臺配置的App的Bundle ID是一致的昌简。

5.可以嘗試先刪除舊App,再重新編譯生成新的绒怨,避免新App未覆蓋錯誤纯赎。

6.這里要提一點,沙盒的測試賬號和你請求商品信息沒有關(guān)系南蹂。請求商品信息的流程是犬金,你在后臺配置好了內(nèi)購商品,并且將其添加到了需要集成內(nèi)購功能的App中六剥,然后你請求商品晚顷。請求到商品后的流程是這樣的,蘋果系統(tǒng)會自動彈出登錄框讓你登錄賬號疗疟。然后根據(jù)提示操作進行購買该默,這里的賬號就是你配置的沙盒測試賬號。

二秃嗜、為什么要使用內(nèi)購权均?(why)和內(nèi)購是什么?(what)

1.如果你購買的商品锅锨,是在本app中使用和消耗的叽赊,就一定要用內(nèi)購,否則會被拒絕上線必搞,例如:游戲幣必指,在線書籍

app中使用的道具等。本例中恕洲,就是直播中你用來打賞用的金幣塔橡,那東西可就屬于消耗型的梅割。

2.如果是直接購買商城之類的快遞包郵的那些東東,那就直接調(diào)用支付寶葛家,微信啦户辞,之類的三方支付就好了,淘寶癞谒,京東都玩過哈底燎!

比較坑的一點就是,內(nèi)購的話弹砚,還要和蘋果3/7分成双仍,那就可以說,充值相同的錢桌吃,相對來說朱沃,iOS是比安卓虧的!

三茅诱、怎樣使用內(nèi)購逗物?(how)

1.使用內(nèi)購需要哪些資料<br>   1張visa銀行卡,appid瑟俭,1張銀行卡與蘋果三七分打錢用

(1)協(xié)議敬察、稅務和銀行業(yè)務

聯(lián)系人信息:(appid賬號人)姓名,郵箱尔当,電話號碼莲祸,地址(城市、具體街道分行寫)

visa銀行卡信息:開戶行椭迎,開戶行所在地址锐帜,開戶行的郵政編碼,開戶行持有人卡號畜号,開戶行持有人姓名

稅務信息:1.會問你是不是美國居民選擇NO. 2\. 有沒有在美國從事商業(yè)性活動缴阎,選擇NO. 之后填寫個人或組織名稱,所在國家简软,受益方式(獨立開發(fā)者選擇個人)蛮拔,居住地址,郵寄地址痹升,聲明人建炫,頭銜

(2)內(nèi)購產(chǎn)品id的配置 (開發(fā)人員配置)

如果是金幣或其它消耗品的產(chǎn)品的話用消耗性型項目,參考名稱(內(nèi)購項目疼蛾,比如金幣100),產(chǎn)品id,定價信息肛跌,使用內(nèi)購的快照,顯示名稱,描述衍慎。

(3)用戶職能

測試員:添加水箱測試員及沙箱賬號转唉,水箱測試賬號不能是正常使用的appid賬號,直接使用一個沒有注冊過的郵箱賬號即可稳捆。

姓名赠法,測試賬號密碼,appstore地區(qū)(必須填對)乔夯。

|
四期虾、操作流程圖解與代碼

1.創(chuàng)建app后填寫用戶信息

image

功能簡介 :

1.我的App主要用于管理自己的App應用,例如編輯資料驯嘱,上架,下架等喳坠。

2.銷售和趨勢主要是來查看App在各個平臺的下載量,收入等方面數(shù)據(jù)鞠评,里面有曲線圖等圖文結(jié)合的方式給我們參考。

3.付款和財務報告顯示的是你的收入以及付款等相關(guān)信息壕鹉。

4.iAd主要是跟廣告有關(guān)剃幌,開發(fā)者可以登錄到Workbench,通過iAd對應用的廣告進行控制晾浴。

5.用戶和職能用于生成相應賬號负乡,例如蘋果沙盒測試賬號。

6.協(xié)議脊凰,稅務和銀行業(yè)務則是你銀行相關(guān)賬戶的信息設置抖棘。

流程

1.注冊app,填寫協(xié)議、稅務和銀行業(yè)務

注冊app,需要設置Bundle identifier狸涌,此個步驟這里就不在寫了

填寫協(xié)議切省、稅務和銀行業(yè)務

|

image

|

<strong>選擇申請合同類型</strong>

頁面內(nèi)容:

Request Contracts(申請合同)

Contracts In Effect(已生效合同)。

合同類型:

iOS Free Application(免費應用合同)

iOS Paid Application(付費應用合同)

iAd App NetNetwork(廣告合同)

|

  1.申請iOS Paid Application合同

image

image

 2. 設置協(xié)議稅務帕胆、銀行卡信息

當我們點擊申請iOS Paid Application合同后朝捆,該合同的狀態(tài)會變成如下的樣子,我們可以看到其中Status為Contact懒豹, Bank, Pending Tax,

意思是聯(lián)系方式芙盘、銀行和稅務信息沒有填寫。

|

image

2.1設置聯(lián)系人信息

|

如果你沒有添加過聯(lián)系人脸秽,你需要通過Add New Contact按鈕來添加一個新的聯(lián)系人儒老。然后指定聯(lián)系人的職務,職務如下:

Senior Management:高管

Financial:財務

Technical:技術(shù)支持

Legal:法務

Marketing:市場推廣

如果你是獨立開發(fā)者记餐,可以全部填你自己一個人贷盲。

|

新增聯(lián)系人

image

通過新增或之前增加的聯(lián)系人設置高管等信息

image

待完成后點擊Done,返回后狀態(tài)會變成Edit狀態(tài)

2.2設置銀行卡信息(可以通過銀行名稱和地址直接上網(wǎng)查詢CNAPS Code號,不要問我上那查)

image
image

確認銀行卡信息

image
image

2.3設置稅務信息(1.是美國稅務,只需要這個就行巩剖,后面的澳大利亞和日本的和我們沒的關(guān)系)

image

選擇U.S Tax Forms铝穷,選擇后會問你兩個問題,第一個問題如下:詢問你是否是美國居民佳魔,有沒有美國伙伴關(guān)系或者美國公司曙聂,如果沒有直接選擇No。

|

image

|

接下來第二個問題如下:詢問你有沒有在美國的商業(yè)性活動鞠鲜,沒有也直接選No宁脊。

|

image

然后填寫稅務信息

|

然后填寫你的稅務信息,包括以下幾點:

Individual or Organization Name:個人或者組織名稱

Country of incorporation: 所在國家

Type of Beneficial Owner:受益方式贤姆,獨立開發(fā)者選個人

Permanent Residence:居住地址

Mailing address:郵寄地址

Name of Person Making ``this Declaration:聲明人

Title:頭銜

當你填寫完所有資料后榆苞,合同狀態(tài)就會變成Processing,筆者凌晨1點左右提交霞捡,下午就通過了坐漏。

|
具體填寫見下圖(以下是確認稅務信息圖)

image

填寫完成后效果

image

** 3.配置內(nèi)購產(chǎn)品ID**

|

完成以上操作,并且蘋果審核完畢之后碧信,就可以配置內(nèi)購產(chǎn)品了赊琳。

登錄 iTunesConnect -->我的App 模塊找到需要內(nèi)購的App,最后找到頁面如下:

|

image
image
image
image

|
填寫沙箱測試員和添加內(nèi)購產(chǎn)品注意事項

1砰碴、郵箱必須是沒有注冊或者說關(guān)聯(lián)過appstore的郵箱躏筏。

2、密碼必須有一個是大寫字母有一個是小寫字母(蘋果規(guī)定的,理解)呈枉。

3趁尼、內(nèi)購屏幕截圖規(guī)格必須是312*290,且最低分辨率是72ppi猖辫。

4弱卡、內(nèi)購的價格是蘋果規(guī)定的不能自定義(坑啊)。

|
4.增加內(nèi)購測試賬號

** 4.1 內(nèi)購測試之前準備**

|

1住册、什么是內(nèi)購測試賬號(what)及為什么使用內(nèi)購測試賬號(why)?

iOS應用里面用到了蘋果應用內(nèi)付費(IAP)功能婶博,在項目上線前一定要進行功能測試。測試肯定是需要的荧飞,何況這個跟money有關(guān)凡人。。叹阔。開發(fā)完成了之后挠轴,如何進行測試呢?難道我測試個內(nèi)購功能要自己掏錢耳幢?就算是也是公司掏錢岸晦,但是蘋果要吃掉3成的啊欧啤,想想如果是99刀的商品,點下購買的時候心里都有點發(fā)慌启上。邢隧。。

蘋果當然沒這么坑了冈在,測試內(nèi)購倒慧,蘋果提供了沙盒賬號(也叫沙箱賬號)的方式。這個沙箱賬號其實是虛擬的AppleID包券,在開發(fā)者賬號后臺的iTune Connect上配置了之后就能使用沙盒賬號測試內(nèi)購纫谅,有了沙盒賬號,就能體驗一把土豪的感覺了溅固,游戲鉆石什么的隨便充付秕,反正不用我的錢。

注意:你可以把沙盒賬號看做是一個虛擬的AppleID侍郭,這個AppleID只有進行內(nèi)購測試的功能询吴。重要,重要励幼,重要,這個虛擬的賬號只能在自己的測試號中使用口柳,如果在其它地方如appstore使用的話會提示賬號無效之類的話苹粟。

2、如何使用內(nèi)購測試賬號(how)跃闹?

2.1作用內(nèi)購賬號的前提

1)內(nèi)購的商品ID嵌削,價格等相關(guān)信息已經(jīng)錄入到開發(fā)者后臺了(不然那你買什么)

2)開發(fā)者后臺已經(jīng)創(chuàng)建好沙盒測試賬號了(下面我們會將如何創(chuàng)建)

3)你要有一部真機(iPhone或iPad都行,別用模擬器就好望艺。而且不能是越獄機)

4)bundleID別搞錯了苛秕,開發(fā)者賬號、證書找默、bundleID要一致

5)如果你是第一次在這個開發(fā)者賬號上集成內(nèi)購功能艇劫,

請先將iTune Connect上的稅務協(xié)議都填寫好,否則內(nèi)購時會發(fā)現(xiàn)商品ID無效惩激。

重要店煞,如果不添加稅務協(xié)議會報錯,找不到商品风钻。

|

選擇用戶和職能就是在協(xié)議顷蟀、稅務和銀行業(yè)務左側(cè)

image
image

4.2內(nèi)購測試開始

|
1.在iPhone上安裝測試包(必須是打包簽名證書或者develop簽名證書打的包,不能是從App Store上下載的)

2.退出iPhone的App Store賬號(因為我們需要使用沙盒賬號登錄)骡技。

操作方法一:打開App Store應用首頁滑到最下方--選中AppleID--注銷

操作方法二:設置--iTunes Store與App Store--選中AppleID--注銷

3.不能用沙盒測試帳號來登錄appstore官網(wǎng)或去其它已上線平臺去支付詳見圖4.21

4.運行下面代碼的demo,傳入你創(chuàng)建的產(chǎn)品id(就是在app iTunes Connect ->我的app ->功能 ->app內(nèi)購買項目添加的商品)鸣个,點擊充值跳轉(zhuǎn)開始購買詳見圖4.22

5.再次購買時需要輸入測試沙盒賬號密碼(在用戶和職能->沙箱技術(shù)測試員創(chuàng)建的測試賬號)詳見圖4.23

6.購買成功反饋詳見圖4.24

|

4.21 圖

image

4.22 圖

image

4.23 圖

image

4.24 圖

5.代碼及業(yè)務邏輯
業(yè)務邏輯

  1. 獲取內(nèi)購列表(從App內(nèi)讀取或從自己服務器讀取)

  2. App Store請求可用的內(nèi)購列表

  3. 向用戶展示內(nèi)購列表

  4. 用戶選擇了內(nèi)購列表,再發(fā)個購買請求囤萤,收到購買完成的回調(diào)(購買完成后會把錢打給申請內(nèi)購的銀行卡內(nèi))

  5. 購買流程結(jié)束后, 向服務器發(fā)起驗證憑證以及支付結(jié)果的請求

  6. 自己的服務器將支付結(jié)果信息返回給前端并發(fā)放虛擬產(chǎn)品

  7. 服務端的工作比較簡單昼窗,分4步:

    1. 接收ios端發(fā)過來的購買憑證。
    2. 判斷憑證是否已經(jīng)存在或驗證過阁将,然后存儲該憑證膏秫。
    3. 將該憑證發(fā)送到蘋果的服務器驗證,并將驗證結(jié)果返回給客戶端。
    4. 如果需要,修改用戶相應的會員權(quán)限加叁。

    考慮到網(wǎng)絡異常情況剩拢,服務器的驗證應該是一個可恢復的隊列,如果網(wǎng)絡失敗了倚喂,應該進行重試。

    簡單來說就是將該購買憑證用Base64編碼,然后POST給蘋果的驗證服務器帅刀,蘋果將驗證結(jié)果以JSON形式返回。

image

代碼如下 :
/*注意事項:
1.沙盒環(huán)境測試appStore內(nèi)購流程的時候远剩,請使用沒越獄的設備扣溺。
2.請務必使用真機來測試,一切以真機為準瓜晤。
3.項目的Bundle identifier需要與您申請AppID時填寫的bundleID一致锥余,不然會無法請求到商品信息。
4.如果是你自己的設備上已經(jīng)綁定了自己的AppleID賬號請先注銷掉,否則你哭爹喊娘都不知道是怎么回事痢掠。
5.訂單校驗 蘋果審核app時驱犹,仍然在沙盒環(huán)境下測試,所以需要先進行正式環(huán)境驗證足画,如果發(fā)現(xiàn)是沙盒環(huán)境則轉(zhuǎn)到沙盒驗證雄驹。
識別沙盒環(huán)境訂單方法:
1.根據(jù)字段 environment = sandbox。
2.根據(jù)驗證接口返回的狀態(tài)碼,如果status=21007淹辞,則表示當前為沙盒環(huán)境医舆。
蘋果反饋的狀態(tài)碼:
21000App Store無法讀取你提供的JSON數(shù)據(jù)
21002 訂單數(shù)據(jù)不符合格式
21003 訂單無法被驗證
21004 你提供的共享密鑰和賬戶的共享密鑰不一致
21005 訂單服務器當前不可用
21006 訂單是有效的,但訂閱服務已經(jīng)過期象缀。當收到這個信息時彬向,解碼后的收據(jù)信息也包含在返回內(nèi)容中
21007 訂單信息是測試用(sandbox),但卻被發(fā)送到產(chǎn)品環(huán)境中驗證
21008 訂單信息是產(chǎn)品環(huán)境中使用攻冷,但卻被發(fā)送到測試環(huán)境中驗證
*/

import <Foundation/Foundation.h>

typedef enum {
SIAPPurchSuccess = 0, // 購買成功
SIAPPurchFailed = 1, // 購買失敗
SIAPPurchCancle = 2, // 取消購買
SIAPPurchVerFailed = 3, // 訂單校驗失敗
SIAPPurchVerSuccess = 4, // 訂單校驗成功
SIAPPurchNotArrow = 5, // 不允許內(nèi)購
}SIAPPurchType;

typedef void (^IAPCompletionHandle)(SIAPPurchType type,NSData *data);

@interface STRIAPManager : NSObject

  • (instancetype)shareSIAPManager;
    //開始內(nèi)購
  • (void)startPurchWithID:(NSString *)purchID completeHandle:(IAPCompletionHandle)handle;
    @end
    .m

import "STRIAPManager.h"

import <StoreKit/StoreKit.h>

@interface STRIAPManager()<SKPaymentTransactionObserver,SKProductsRequestDelegate>{
NSString *_purchID;
IAPCompletionHandle _handle;
}
@end
@implementation STRIAPManager

pragma mark - ??life cycle

  • (instancetype)shareSIAPManager{

    static STRIAPManager *IAPManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
    IAPManager = [[STRIAPManager alloc] init];
    });
    return IAPManager;
    }

  • (instancetype)init{
    self = [super init];
    if (self) {
    // 購買監(jiān)聽寫在程序入口,程序掛起時移除監(jiān)聽,這樣如果有未完成的訂單將會自動執(zhí)行并回調(diào) paymentQueue:updatedTransactions:方法
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
    return self;
    }

  • (void)dealloc{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    }

pragma mark - ??public

  • (void)startPurchWithID:(NSString *)purchID completeHandle:(IAPCompletionHandle)handle{
    if (purchID) {
    if ([SKPaymentQueue canMakePayments]) {
    // 開始購買服務
    _purchID = purchID;
    _handle = handle;
    NSSet *nsset = [NSSet setWithArray:@[purchID]];
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
    request.delegate = self;
    [request start];
    }else{
    [self handleActionWithType:SIAPPurchNotArrow data:nil];
    }
    }
    }

pragma mark - ??private

  • (void)handleActionWithType:(SIAPPurchType)type data:(NSData *)data{

if DEBUG

switch (type) {
    case SIAPPurchSuccess:
        NSLog(@"購買成功");
        break;
    case SIAPPurchFailed:
        NSLog(@"購買失敗");
        break;
    case SIAPPurchCancle:
        NSLog(@"用戶取消購買");
        break;
    case SIAPPurchVerFailed:
        NSLog(@"訂單校驗失敗");
        break;
    case SIAPPurchVerSuccess:
        NSLog(@"訂單校驗成功");
        break;
    case SIAPPurchNotArrow:
        NSLog(@"不允許程序內(nèi)付費");
        break;
    default:
        break;
}

endif

if(_handle){
    _handle(type,data);
}

}

pragma mark - ??delegate

// 交易結(jié)束

  • (void)completeTransaction:(SKPaymentTransaction *)transaction{
    // Your application should implement these two methods.
    NSString * productIdentifier = transaction.payment.productIdentifier;
    NSString * receipt = [transaction.transactionReceipt base64EncodedString];
    if ([productIdentifier length] > 0) {
    // 向自己的服務器驗證購買憑證
    }

    [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:NO];
    }

// 交易失敗

  • (void)failedTransaction:(SKPaymentTransaction *)transaction{
    if (transaction.error.code != SKErrorPaymentCancelled) {
    [self handleActionWithType:SIAPPurchFailed data:nil];
    }else{
    [self handleActionWithType:SIAPPurchCancle data:nil];
    }

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    }

  • (void)verifyPurchaseWithPaymentTransaction:(SKPaymentTransaction *)transaction isTestServer:(BOOL)flag{
    //交易驗證
    NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receipt = [NSData dataWithContentsOfURL:recepitURL];

    if(!receipt){
    // 交易憑證為空驗證失敗
    [self handleActionWithType:SIAPPurchVerFailed data:nil];
    return;
    }
    // 購買成功將交易憑證發(fā)送給服務端進行再次校驗
    [self handleActionWithType:SIAPPurchSuccess data:receipt];

    NSError *error;
    NSDictionary *requestContents = @{
    @"receipt-data": [receipt base64EncodedStringWithOptions:0]
    };
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
    options:0
    error:&error];

    if (!requestData) { // 交易憑證為空驗證失敗
    [self handleActionWithType:SIAPPurchVerFailed data:nil];
    return;
    }

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

    NSString *serverString = @"https://buy.itunes.apple.com/verifyReceipt";
    if (flag) {
    serverString = @"https://sandbox.itunes.apple.com/verifyReceipt";
    }
    NSURL *storeURL = [NSURL URLWithString:serverString];
    NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
    completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    if (connectionError) {
    // 無法連接服務器,購買校驗失敗
    [self handleActionWithType:SIAPPurchVerFailed data:nil];
    } else {
    NSError *error;
    NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
    if (!jsonResponse) {
    // 蘋果服務器校驗數(shù)據(jù)返回為空校驗失敗
    [self handleActionWithType:SIAPPurchVerFailed data:nil];
    }

                                 // 先驗證正式服務器,如果正式服務器返回21007再去蘋果測試服務器驗證,沙盒測試環(huán)境蘋果用的是測試服務器
                                 NSString *status = [NSString stringWithFormat:@"%@",jsonResponse[@"status"]];
                                 if (status && [status isEqualToString:@"21007"]) {
                                     [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:YES];
                                 }else if(status && [status isEqualToString:@"0"]){
                                     [self handleActionWithType:SIAPPurchVerSuccess data:nil];
                                 }
    

if DEBUG

                               NSLog(@"----驗證結(jié)果 %@",jsonResponse);

endif

                           }
                       }];
 
 
// 驗證成功與否都注銷交易,否則會出現(xiàn)虛假憑證信息一直驗證不通過,每次進程序都得輸入蘋果賬號
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}

pragma mark - SKProductsRequestDelegate

  • (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    NSArray *product = response.products;
    if([product count] <= 0){

if DEBUG

    NSLog(@"--------------沒有商品------------------");

endif

    return;
}
 
SKProduct *p = nil;
for(SKProduct *pro in product){
    if([pro.productIdentifier isEqualToString:_purchID]){
        p = pro;
        break;
    }
}

if DEBUG

NSLog(@"productID:%@", response.invalidProductIdentifiers);
NSLog(@"產(chǎn)品付費數(shù)量:%lu",(unsigned long)[product count]);
NSLog(@"%@",[p description]);
NSLog(@"%@",[p localizedTitle]);
NSLog(@"%@",[p localizedDescription]);
NSLog(@"%@",[p price]);
NSLog(@"%@",[p productIdentifier]);
NSLog(@"發(fā)送購買請求");

endif

SKPayment *payment = [SKPayment paymentWithProduct:p];
[[SKPaymentQueue defaultQueue] addPayment:payment];

}

//請求失敗

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

if DEBUG

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

endif

}

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

if DEBUG

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

endif

}

pragma mark - SKPaymentTransactionObserver

  • (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    for (SKPaymentTransaction *tran in transactions) {
    switch (tran.transactionState) {
    case SKPaymentTransactionStatePurchased:
    [self completeTransaction:tran];
    break;
    case SKPaymentTransactionStatePurchasing:

if DEBUG

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

endif

            break;
        case SKPaymentTransactionStateRestored:

if DEBUG

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

endif

            // 消耗型不支持恢復購買
            [[SKPaymentQueue defaultQueue] finishTransaction:tran];
            break;
        case SKPaymentTransactionStateFailed:
            [self failedTransaction:tran];
            break;
        default:
            break;
    }
}

}
@end
在控制器中調(diào)用娃胆,導入頭文件
調(diào)用方法

  • (void)purchaseAction{

    if (!_IAPManager) {
    _IAPManager = [STRIAPManager shareSIAPManager];
    }
    // iTunesConnect 蘋果后臺配置的產(chǎn)品ID
    [_IAPManager startPurchWithID:@"com.bb.helper_advisory" completeHandle:^(SIAPPurchType type,NSData *data) {
    //請求事務回調(diào)類型,返回的數(shù)據(jù)

    }];
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末等曼,一起剝皮案震驚了整個濱河市里烦,隨后出現(xiàn)的幾起案子凿蒜,更是在濱河造成了極大的恐慌,老刑警劉巖胁黑,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废封,死亡現(xiàn)場離奇詭異,居然都是意外死亡丧蘸,警方通過查閱死者的電腦和手機漂洋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來力喷,“玉大人刽漂,你說我怎么就攤上這事〉苊希” “怎么了贝咙?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拂募。 經(jīng)常有香客問我庭猩,道長,這世上最難降的妖魔是什么陈症? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任蔼水,我火速辦了婚禮,結(jié)果婚禮上录肯,老公的妹妹穿的比我還像新娘趴腋。我一直安慰自己,他們只是感情好嘁信,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布于样。 她就那樣靜靜地躺著疏叨,像睡著了一般潘靖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚤蔓,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天卦溢,我揣著相機與錄音,去河邊找鬼秀又。 笑死单寂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的吐辙。 我是一名探鬼主播宣决,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼昏苏!你這毒婦竟也來了尊沸?” 一聲冷哼從身側(cè)響起威沫,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎洼专,沒想到半個月后棒掠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡屁商,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年烟很,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜡镶。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡雾袱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出帽哑,到底是詐尸還是另有隱情谜酒,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布妻枕,位于F島的核電站僻族,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏屡谐。R本人自食惡果不足惜述么,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望愕掏。 院中可真熱鬧度秘,春花似錦、人聲如沸饵撑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滑潘。三九已至垢乙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間语卤,已是汗流浹背追逮。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留粹舵,地道東北人钮孵。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像眼滤,于是被迫代替她去往敵國和親巴席。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353