iOS內(nèi)購(gòu)(IAP)流程記錄(代碼篇)

iOS內(nèi)購(gòu)(IAP)流程記錄(業(yè)務(wù)篇)
之前已經(jīng)寫(xiě)過(guò)內(nèi)購(gòu)前期準(zhǔn)備資料的文章,這篇文章梳理下業(yè)務(wù)實(shí)現(xiàn)邏輯能岩。

前期需求:公司是有自己的訂單系統(tǒng),所以我們需要在發(fā)起支付的時(shí)候需要先去后臺(tái)獲取訂單號(hào)伐憾,拿到訂單號(hào)后再調(diào)用蘋(píng)果內(nèi)購(gòu)流程措拇,最后把訂單號(hào)和支付憑證返回給后臺(tái),由后臺(tái)去和蘋(píng)果再次校驗(yàn)交易結(jié)果了赵,最后返回訂單支付結(jié)果給我們潜支。(這是正常流程,內(nèi)購(gòu)存在漏單柿汛,異常訂單稍后講)冗酿。

支付流程圖:

支付流程圖

了解流程之后,我們就開(kāi)始編寫(xiě)代碼了,我這邊是把內(nèi)購(gòu)的代碼封裝了一個(gè)單例

準(zhǔn)備:

需導(dǎo)入庫(kù):
StoreKit
頭文件需要引用:
#import <StoreKit/StoreKit.h>
代理添加:
<SKPaymentTransactionObserver,SKProductsRequestDelegate>

代碼實(shí)現(xiàn):

1.先去拿到后臺(tái)訂單號(hào)裁替,有了后臺(tái)訂單號(hào)之后再判斷是否有購(gòu)買(mǎi)權(quán)限

[SKPaymentQueue canMakePayments]

2.如果有購(gòu)買(mǎi)權(quán)限项玛,則通過(guò)產(chǎn)品id去獲取內(nèi)購(gòu)項(xiàng)目信息

SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
                   request.delegate = self;
                   [request start];

3.通過(guò)蘋(píng)果內(nèi)購(gòu)回調(diào)函數(shù)去處理

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    // 商品數(shù)組
    NSArray *productArr = response.products;
    if (productArr.count > 0) {
        SKProduct *product = nil;
        for (SKProduct *p in productArr) {
            if ([p.productIdentifier isEqualToString:_productID]) {
                product = p;
                break;
            }
        }
       // 發(fā)起內(nèi)購(gòu)
        SKPayment *payMent = [SKPayment paymentWithProduct:product];
        [[SKPaymentQueue defaultQueue] addPayment:payMent];
        
    } else {
        //項(xiàng)目id錯(cuò)誤
    }
}

4.判斷交易狀態(tài):

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
// 獲取結(jié)果
    // 驗(yàn)證成功與否都注銷交易,否則會(huì)出現(xiàn)虛假憑證信息一直驗(yàn)證不通過(guò),每次進(jìn)程序都得輸入蘋(píng)果賬號(hào)
    for (SKPaymentTransaction *trans in transactions) {
        
        switch (trans.transactionState) {
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"商品添加進(jìn)列表");
                break;
            case SKPaymentTransactionStatePurchased:
                NSLog(@"交易完成");
                //自己可添加驗(yàn)證
                [self completeTransaction:trans];
                [[SKPaymentQueue defaultQueue] finishTransaction:trans];
                break;
            case SKPaymentTransactionStateFailed:
                NSLog(@"交易失敗");
                [self failedTransaction:trans];//處理失敗邏輯
                [[SKPaymentQueue defaultQueue] finishTransaction:trans];
                break;
            case SKPaymentTransactionStateRestored:
                NSLog(@"已經(jīng)購(gòu)買(mǎi)過(guò)商品");
                [[SKPaymentQueue defaultQueue] finishTransaction:trans]; //消耗型商品不用寫(xiě)
                break;
            case SKPaymentTransactionStateDeferred:
                break;
            default:
                break;
        }
    }
}

5.收到支付成功后把訂單號(hào)和交易憑證拋給后臺(tái):

- (void) completeTransaction:(SKPaymentTransaction *)transaction{
      //這里要把SKPaymentTransaction整個(gè)對(duì)象給后臺(tái),記得攜帶訂單號(hào)弱判,先驗(yàn)證正式服務(wù)器,如果正式服務(wù)器返回21007再去蘋(píng)果測(cè)試服務(wù)器驗(yàn)證,沙盒測(cè)試環(huán)境蘋(píng)果用的是測(cè)試服務(wù)器
//正式環(huán)境:https://buy.itunes.apple.com/verifyReceipt
//沙箱環(huán)境:https://sandbox.itunes.apple.com/verifyReceipt
}
整合好之后襟沮,拿到后臺(tái)返回的訂單號(hào)每次發(fā)起內(nèi)購(gòu)調(diào)用下面這個(gè)函數(shù)就可以了
- (void)startIAPWithProductID:(NSString *)productID andOrderNo:(NSString *)orderNo completeHandle: (IAPCompletionHandle)handle{
    _handle = handle;
    _orderNo = orderNo;
    if(productID && productID.length > 0) {
        if ([SKPaymentQueue canMakePayments]) {
            // 允許內(nèi)購(gòu)
            _productID = productID;
            NSSet *set = [NSSet setWithObjects:productID, nil];
            SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
            request.delegate = self;
            // 獲取內(nèi)購(gòu)項(xiàng)目信息
            [request start];
        } else {
            // 不允許內(nèi)購(gòu)
        }
    } else {
        NSLog(@"內(nèi)購(gòu)項(xiàng)目ID錯(cuò)誤");
    }
}

不出意外,正常流程就是這樣了昌腰,但是為了防止漏單的情況开伏,所以增加了漏單機(jī)制。

異常訂單處理

我的處理邏輯是把蘋(píng)果返回成功但是后臺(tái)返回失敗的訂單存到異常隊(duì)列遭商,每次啟動(dòng)APP的時(shí)候把異常隊(duì)列輪詢一次固灵,就是把訂單數(shù)據(jù)再發(fā)送給后臺(tái),讓后臺(tái)再去校驗(yàn)株婴,如果校驗(yàn)成功怎虫,則在隊(duì)列中移除異常訂單,后臺(tái)添加購(gòu)買(mǎi)數(shù)據(jù)困介,更新訂單狀態(tài)大审。

//array是異常數(shù)組,包含訂單號(hào)座哩、交易憑據(jù)
-(void)anomalyOrderVerify:(NSMutableArray * )array{
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    for (int i = array.count; i > 0 ; i-- ) {
       //循環(huán)判斷徒扶,通過(guò)信號(hào)量控制
        dispatch_semaphore_signal(semaphore);
    }
}

這只是一種異常訂單處理方法,還有其他的暫時(shí)沒(méi)有添加根穷,網(wǎng)上大神這么多姜骡,我也在借鑒他們漏單處理的方式,后面也還會(huì)再完善這方面內(nèi)容屿良,畢竟涉及到支付圈澈。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市尘惧,隨后出現(xiàn)的幾起案子康栈,更是在濱河造成了極大的恐慌,老刑警劉巖喷橙,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啥么,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贰逾,警方通過(guò)查閱死者的電腦和手機(jī)悬荣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疙剑,“玉大人氯迂,你說(shuō)我怎么就攤上這事践叠。” “怎么了囚戚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵酵熙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我驰坊,道長(zhǎng)匾二,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任拳芙,我火速辦了婚禮察藐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舟扎。我一直安慰自己分飞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布睹限。 她就那樣靜靜地躺著譬猫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羡疗。 梳的紋絲不亂的頭發(fā)上染服,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音叨恨,去河邊找鬼柳刮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛痒钝,可吹牛的內(nèi)容都是我干的秉颗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼送矩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蚕甥!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起栋荸,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤梢灭,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蒸其,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡库快,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年摸袁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片义屏。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡靠汁,死狀恐怖蜂大,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝶怔,我是刑警寧澤奶浦,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站踢星,受9級(jí)特大地震影響澳叉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沐悦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一成洗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧藏否,春花似錦瓶殃、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至淆储,卻和暖如春冠场,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遏考。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工慈鸠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人灌具。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓青团,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親咖楣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子督笆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容