iOS-IAP內購的那些事(iOS內購漏單的問題)


前言

說起內購,其實挺令開發者厭煩的,原因呢,先不說漏單的問題,首先蘋果要扣除30%的銷售額哦,可恨不?(我覺得可恨),有些想辦法先隱藏掉第三方支付(支付寶、微信等),等項目上線了,再跳過內購使用第三方支付,emmmm.......這個方法確實不錯,但是如果被蘋果發現了,APP內虛擬產品調用第三方支付,那好吧,直接下架吧(或許沒這么慘,但會慘不忍睹),不要說發現不了,會有人舉報哦(別問我怎么知道的);其次就是漏單問題的處理,這一直是個問題,我的項目里雖然做了處理,但是還是會避免不了漏單的,只是把漏單的幾率降到了很小,以確保我們維護,給大家分享下內購及漏單的處理。

 

內購集成

內購集成並不難,這里我用了一個Git上封裝好的(IAPHelper),自己封裝也簡單(不想造那么多輪子了),封裝的話,建議結合單例封裝,充值驗證都在單例里面進行;當然也可以不封裝直接就用的,這里不多說了;建議最好根據服務器的驗證方式與邏輯自己寫個單利工具。

支付邏輯

1.臨時單號

首先根據內購商品ID(此商品ID是在蘋果后台建好的內購商品)、用戶信息(后台要求),傳給服務器獲取一個臨時單號,然后先將該臨時單號保存到一個變量里。在此之前,需要用數據持久化,對用戶最后一次選擇的內功商品ID進行永久儲存,就算用戶付款成功卻充值失敗了,即使App卸載了,也可以拿到最后一次請求的內購商品ID 。

///獲取充值臨時單號
- (void)iapGetTemOrderIdWithProductId:(NSString *)productId{
    self.productId = productId;
    [SVProgressHUD showWithStatus:@"請稍后..." ];
    NSString *urlString = @"";
    [HttpTools getHttpRequestURL:urlString RequestSuccess:^(id repoes, NSURLSessionDataTask *task) {
        [SVProgressHUD dismiss];
        NSDictionary *dicTem = [HttpTools respoesToDic:repoes];
        if ([dicTem[@"code"] integerValue] == 1) {
            ///保存臨時單號
             self.temporaryOrderId = dicTem[@"data"];
             ///發起內購支付
             [self iapStartRecharge];
            
        }
        else{
            [SVProgressHUD showErrorWithStatus:dicTem[@"errmsg"]];
            [self errorPost:nil];
        }
        
    } RequestFaile:^(NSError *error) {
        [SVProgressHUD showErrorWithStatus:[HttpTools error:error]];
        [self errorPost:nil];
    }];
}

 

2.蘋果充值

通過商品ID調取蘋果內購支付,蘋果充值成功后,在返回成功的方法里,首先將上一步中的臨時單號、用戶信息(這里我取userId)、蘋果充值成功返回的data,三個參數一起存入本地(我采用數據庫存儲)后,然后驗證服務器充值(如果蘋果充值驗證失敗,不必做任何操作)。

///發起內購支付
- (void)iapStartRecharge{
    [SVProgressHUD showWithStatus:@"請稍后..."];
    NSSet* dataSet = [[NSSet alloc] initWithObjects:self.productId, nil];
    [IAPShare sharedHelper].iap = [[IAPHelper alloc] initWithProductIdentifiers:dataSet];
    // 請求商品信息
    [[IAPShare sharedHelper].iap requestProductsWithCompletion:^(SKProductsRequest* request,SKProductsResponse* response){
        
        if(response.products.count > 0 ) {
            SKProduct *product = response.products[0];
            [[IAPShare sharedHelper].iap buyProduct:product onCompletion:^(SKPaymentTransaction* trans){
                if(trans.error){
                    [SVProgressHUD showErrorWithStatus:trans.error.userInfo.allValues[0]];
                    [self errorPost:nil];
                }
                else if(trans.transactionState == SKPaymentTransactionStatePurchased) {
                    NSLog(@"*********內部支付成功*********");
                    
                    ///將臨時單號存在本地【此處做返回信息保存(臨時單號、用戶信息、返回的data)】
                    
                    ///去服務器驗證充值

/// 備注:這里要做兩個判斷,一是直接支付成功后回調的,二是App打開后,對上次驗證失敗回調到這里的
} else if(trans.transactionState == SKPaymentTransactionStateFailed) { NSLog(@"*********支付失敗*********"); if (trans.error.code == SKErrorPaymentCancelled) { } else if (trans.error.code == SKErrorClientInvalid) { } else if (trans.error.code == SKErrorPaymentInvalid) { } else if (trans.error.code == SKErrorPaymentNotAllowed) { } else if (trans.error.code == SKErrorStoreProductNotAvailable) { } else{ } [SVProgressHUD showErrorWithStatus:trans.error.userInfo.allValues[0]]; [self errorPost:nil]; } }]; }else{ // ..未獲取到商品 [SVProgressHUD showErrorWithStatus:@"暫未獲取到商品"]; [self errorPost:nil]; } }]; }

 

3.服務器驗證充值(上一步成功后驗證)

在蘋果充值成功后,根據充值成功返回的數據data、臨時單號、用戶信息(后台要求)去服務器驗證充值,如果驗證成功,將上一步存在本地數據庫的數據(臨時單號、用戶信息(這里我取userId)、蘋果充值成功返回的data)刪除;如果充值失敗,即為漏單,但是已經將驗證服務器充值的數據存在了本地數據庫,可再次嘗試,或者稍候嘗試,根據自己的提示操作而定。

///向服務器驗證進行充值
- (void)iapPayOValidData:(NSString *)strReceipt temOrder:(NSString *)temOrder{
    ///驗證充值
    [SVProgressHUD showWithStatus:@"正在為您充值..."];
    NSString *urlSting = @"";
    ///post data【驗證參數】
    NSMutableDictionary *dicPost = [NSMutableDictionary dictionary];
    [HttpTools postHttpRequestURL:urlSting RequestPram:dicPost RequestSuccess:^(id respoes) {
        [SVProgressHUD dismiss];
        NSDictionary *dicValid = [HttpTools respoesToDic:respoes];
        if ([dicValid[@"code"] integerValue] == 1) {
///刪除本地存的驗證信息【臨時單號、用戶信息、蘋果支付成功返回的data】 } else{ [self errorPost:dicValid[@"errmsg"]]; } } RequestFaile:^(NSError *erro) { [SVProgressHUD dismiss]; [self errorPost:[HttpTools error:erro]]; }]; }

 

結束

至此,整個內購充值流程已完畢,以上傳遞的參數、存儲的參數,是根據服務器后台要求,可根據自己服務器后台商量,怎么做更好,如果大家有更好的方案,希望能借鑒!謝謝!

最后還是要說說,不管怎么做漏單處理,總會有幾個漏單的,但是幾率很小,而且還想說,什么時候可以有辦法躲過這30%的抽成.......


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM