ios 內(nèi)購(gòu)

從開(kāi)發(fā)iOS到現(xiàn)在,內(nèi)購(gòu)app也做過(guò)兩個(gè)了,現(xiàn)在好好記錄下這個(gè)流程。

首先需要在所屬的app下創(chuàng)建物品,這個(gè)流程網(wǎng)上很多也不難。這邊就詳細(xì)說(shuō)明了,可參考下面網(wǎng)址。
http://blog.csdn.net/shenjie12345678/article/details/40978977/

我們定義好一個(gè)或多個(gè)product 后 每個(gè)product id對(duì)應(yīng)著一個(gè)product。 我們拿到一個(gè)或多個(gè)product id,數(shù)據(jù)處理后對(duì)appstore 發(fā)起購(gòu)物請(qǐng)求,等待appstore處理后的響應(yīng)(之間很多操作,都是appStore和用戶之間,客戶端無(wú)法干預(yù)), 客戶端對(duì)購(gòu)物成功的回執(zhí)單進(jìn)行校驗(yàn)。


內(nèi)購(gòu)流程示意圖.png

這個(gè)流程基本就是這樣,如上圖所示。

理清整個(gè)流程后,我們對(duì)內(nèi)購(gòu)就非常清晰了,要注意的就是細(xì)節(jié)了,對(duì)各種異常情況的處理。各種case 見(jiàn)下列枚舉,基本和app的sdk保持一致

typedef enum : NSUInteger {
    EPaymentTransactionStateNoPaymentPermission, //沒(méi)有Payment權(quán)限
    EPaymentTransactionStateAddPaymentFailed, //addPayment失敗
    EPaymentTransactionStatePurchasing,//正在購(gòu)買(mǎi)
    EPaymentTransactionStatePurchased,//購(gòu)買(mǎi)完成(銷(xiāo)毀交易)
    EPaymentTransactionStateFailed, //購(gòu)買(mǎi)失敗(銷(xiāo)毀交易)
    EPaymentTransactionStateCancel,//用戶取消
    EPaymentTransactionStateRestored,//恢復(fù)購(gòu)買(mǎi)(銷(xiāo)毀交易)
    EPaymentTransactionStateDeferred, //最終狀態(tài)未確定
} EPaymentTransactionState;

內(nèi)購(gòu)有個(gè)重要的協(xié)議 SKPaymentTransactionObserver
需要特殊特殊處理,不多說(shuō)廢話 直接附上代碼

#pragma mark - SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
{
    for (SKPaymentTransaction *transaction in transactions)
    {
        EPaymentTransactionState state;
        switch (transaction.transactionState){
            case SKPaymentTransactionStatePurchasing:
            {
                // 連接appStore
                state = EPaymentTransactionStatePurchasing;
            }
                break;
            case SKPaymentTransactionStatePurchased:
            {
                state = EPaymentTransactionStatePurchased;
                //交易完成
                if (isServiceVerify) {
                    [self completeTransaction:transaction];
                }
                else
                {
                    //本地作校驗(yàn)
                    [self verifyPurchase:transaction];
                }
            }
                break;
                
            case SKPaymentTransactionStateFailed:
            {
                //交易失敗
                if (transaction.error.code != SKErrorPaymentCancelled)
                {
                    state = EPaymentTransactionStateFailed;
                }else
                {
                    state = EPaymentTransactionStateCancel;
                }

                [self finshTransaction:transaction];
            }
                break;
                
            case SKPaymentTransactionStateRestored:
            {
                state = EPaymentTransactionStateRestored;
                //已經(jīng)購(gòu)買(mǎi)過(guò)該商品
        
                [self finshTransaction:transaction];
            }
                break;
            case SKPaymentTransactionStateDeferred:
            {
                state = EPaymentTransactionStateDeferred;
            }
                break;
            default:
                break;
        }
        if (self.delegate && [self.delegate respondsToSelector:@selector(updatedTransactions:)]) {
            [self.delegate updatedTransactions:state];
        }

    }
}

補(bǔ)充一點(diǎn) :一旦啟動(dòng)了開(kāi)始購(gòu)買(mǎi)流程,必須要調(diào)用

    //結(jié)束交易
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

來(lái)結(jié)束購(gòu)買(mǎi)流程,否者在下一次調(diào)用到 方法

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

還是會(huì)觸發(fā)繼續(xù)購(gòu)買(mǎi)流程,這個(gè)特性可以解決購(gòu)買(mǎi)過(guò)程中出現(xiàn)的各種異常場(chǎng)景,比如購(gòu)買(mǎi)完成app crash(沒(méi)網(wǎng)絡(luò)了),在下一次啟動(dòng)app時(shí)調(diào)用上面的方法可以回復(fù)購(gòu)買(mǎi)。
具體類(lèi) 放在gitHub下
https://github.com/weskhen/InAppPurchasing

貼上一段蘋(píng)果本地校驗(yàn)成功的json返回 估計(jì)服務(wù)器也是相同的

Printing description of jsonResponse:
{
    environment = Sandbox; //購(gòu)買(mǎi)環(huán)境 
    receipt =     {
        "adam_id" = 0;
        "app_item_id" = 0;
        "application_version" = 30;
        "bundle_id" = "com.wesk.PaoBa";
        "download_id" = 0;
        "in_app" =         (
                        {
                "is_trial_period" = false;
                "original_purchase_date" = "2016-09-27 04:52:58 Etc/GMT";
                "original_purchase_date_ms" = 1474951978000;
                "original_purchase_date_pst" = "2016-09-26 21:52:58 America/Los_Angeles";
                "original_transaction_id" = 1000000238538249;
                "product_id" = “com.PaoBa.Product.001";
                "purchase_date" = "2016-09-27 04:52:58 Etc/GMT";
                "purchase_date_ms" = 1474951978000;
                "purchase_date_pst" = "2016-09-26 21:52:58 America/Los_Angeles";
                quantity = 1;
                "transaction_id" = 1000000238538249;
            }
        );
        "original_application_version" = "1.0";
        "original_purchase_date" = "2013-08-01 07:00:00 Etc/GMT";
        "original_purchase_date_ms" = 1375340400000;
        "original_purchase_date_pst" = "2013-08-01 00:00:00 America/Los_Angeles";
        "receipt_creation_date" = "2016-09-27 07:42:18 Etc/GMT";
        "receipt_creation_date_ms" = 1474962138000;
        "receipt_creation_date_pst" = "2016-09-27 00:42:18 America/Los_Angeles";
        "receipt_type" = ProductionSandbox;
        "request_date" = "2016-09-27 07:43:44 Etc/GMT";
        "request_date_ms" = 1474962224281;
        "request_date_pst" = "2016-09-27 00:43:44 America/Los_Angeles";
        "version_external_identifier" = 0;
    };
    status = 0;
}

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

21000 App Store無(wú)法讀取你提供的JSON數(shù)據(jù)
21002 收據(jù)數(shù)據(jù)不符合格式 (踩過(guò)坑,越獄機(jī)會(huì)出現(xiàn))
21003 收據(jù)無(wú)法被驗(yàn)證
21004 你提供的共享密鑰和賬戶的共享密鑰不一致
21005 收據(jù)服務(wù)器當(dāng)前不可用
21006 收據(jù)是有效的,但訂閱服務(wù)已經(jīng)過(guò)期。當(dāng)收到這個(gè)信息時(shí),解碼后的收據(jù)信息也包含在返回內(nèi)容中
21007 收據(jù)信息是測(cè)試用(sandbox),但卻被發(fā)送到產(chǎn)品環(huán)境中驗(yàn)證
21008 收據(jù)信息是產(chǎn)品環(huán)境中使用,但卻被發(fā)送到測(cè)試環(huán)境中驗(yàn)證

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

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

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