說說IOS內購那些事

weixin_34107955發表於2016-09-13

1.支付類和協議

Store Kit框架下提供用來處理應用內購大致的類可以分為兩部分:1.請求商品,2.購買商品。具體如下:
  • SKMutablePayment:該類為App Store定義了使用者的付費請求功能,通過封裝特定產品名稱和購買數量,用來處理應用程式內購。

  • SKPayment:該類為App Store定義了使用者的付費請求功能,通過封裝特定產品名稱和購買數量,用來處理應用程式內購。

  • SKPaymentQueue:該類為App Store交易支付提供了一個佇列,使用者可以通過它來校驗支付。

  • SKPaymentTransaction:該類定義了支付佇列物件。每當一個付款被新增到支付佇列時就會建立一個該支付交易物件。當App Store已處理完支付交易時,該物件被回傳到應用程式。完成的支付交易物件提供了收據,應用程式可以用它作為支付識別符號,用來儲存處理後支付的交易記錄。

  • SKProduct:該類是作為SKProductsResponse的返回物件的一部分。每個產品物件提供有關您先前在iTunes Connect註冊的產品資訊。

  • SKProductsRequest:該類物件用於檢索從App Store的產品列表本地化的資訊。應用程式使用此請求提出區域性價格等資訊給使用者,而無需維護該列表本身。

  • SKProductsResponse:該類物件是App Store在響應有關的產品的列表資訊的請求時被返回。

  • SKReceiptRefreshRequest:該類允許應用程式重新整理其收據。如果收據是無效或丟失,應用程式可以通過該類申請一個新的收據。在沙箱環境,您可以要求收據性質的任意組合進行測試與批量購買計劃收益的狀態轉換。

  • SKRequest:該類是App Store的請求的抽象類。 SKRequest的子類代表不同型別的請求。

  • SKStoreProductViewController:該類物件提供了一個商店,允許使用者從App Store購買其他媒體。

  • SKCloudServiceController:主要是針對Apple Music購買.

  • SKDownload:主要是針對Tunes購買.

Store Kit框架下提供以下協議用來處理請求事件
  • SKPaymentTransactionObserver:該協議為一個SKPaymentQueue物件的觀察者提供方法。
  • SKProductsRequestDelegate:該協議宣告由一個SKProductsRequest物件的委託實現的方法。委託收到該產品的資訊請求是感興趣的東西。
  • SKRequestDelegate:該協議宣告瞭一個由SKRequest抽象類的任何子類實現的常用方法。
  • SKStoreProductViewControllerDelegate:當使用者退出商店螢幕實現該協議的物件稱為。通常情況下,這個協議是由您的應用程式最初顯示的螢幕專賣店檢視控制器實現的。

2.一般的內購流程

2.1 場景

使用者點選進入一個內購頁面,頁面重新整理當前版本支援的內購商品列表,使用者點選商品列表中的一個商品,彈出app strore帳號校驗,完成校驗後,彈出提示框詢問使用者是否購買,點選購買或是取消。

2.2 流程

  1. 獲取商品列表:這裡獲取商品列表,分兩步,首先是從自己的伺服器獲取,其次是從app store獲取。最終都是以app store獲取為準。具體過程有以下幾步:

  2. 每次進入商品列表介面都會直接去自己的伺服器拉取。

  3. 拉取列表成功後,查詢本地是否快取了商品列表中的每一個商品id,

  4. 如果所有商品都已經快取了,則直接返回商品列表,

  5. 如果校驗發現有商品沒有快取(商品更新),此時,清空當前快取,

  6. 並且直接去app store拉取商品列表,拉取成功後快取再返回。

  7. 購買商品:點選某個商品程式購買,具體流程有以下幾步:

  8. 檢驗當前是否支援內購(網路環境,許可權等)

  9. 根據當前點選的商品,向自己的伺服器去申請訂單,如果申請訂單成功

  10. 向app store發起支付請求,如果申請訂單失敗,直接返回提示資訊

  11. 監聽並等待app store返回支付交易資訊。

  12. 如果交易完成,向自己的伺服器更新訂單狀態,並結束完成app store交易。

  13. 如果交易失敗,並結束完成app store交易。

  14. 如果交易取消,向自己的伺服器取消訂單,並結束完成app store交易。

2.3 狀態處理

整個內購流程裡面可分為兩種型別的狀態,一種是支付行為狀態,就是從想蘋果發起支付請求開始,中間包括支付校驗的取消,確定兩種行為狀態,最後返回的支付交易完成和失敗。一種是針對自己伺服器的訂單校驗的狀態,主要是開始校驗,成功,失敗,已校驗,無法校驗幾種。

  1. 支付行為狀態:該狀態是通過監聽app store回撥來做區別處理。
  • 交易完成:獲取交易憑證,如果蘋果返回了交易憑證,需要更具該交易憑證去和本地伺服器做校驗,校驗成功,說明本次交易成功了,如果校驗失敗了,(驗證找不到訂單號)需要更具本次交易重新向伺服器申請訂單,並校驗該訂單憑證。
  • 交易失敗:如果是使用者取消交易,直接向伺服器取消本次訂單。如果是交易失敗,更新當前訂單憑證到快取中,用於下次校驗。
  • 已購買過:更新當前訂單憑證到快取中,標緻成功。
  • 交易加入佇列:無處理。
  1. 本地訂單校驗憑證狀態:該狀態是根據支付行為狀態用來對伺服器的訂單憑證進行管理。
  • 校驗成功:交易完成後,通過app store返回的憑證資訊,去向伺服器進行校驗,校驗成功後,更新當前訂單憑證到快取中,標緻成功。
  • 校驗失敗:嘗試多次校驗。

細節處理

1.快取

主要快取:商品列表資訊,支付憑證資訊。

  1. 商品列表資訊:每次進入內購介面時,根據從伺服器拉取的商品資訊與本地快取做比較後,如果保持一直,則直接返回,如果存在差異,則還需要從app store拉取商品資訊,再更新本地快取後返回。

  2. 支付憑證資訊:快取每次交易支付憑證,用來與伺服器訂單進行校驗。針對校驗失敗的憑證,會採取多次校驗。每次進入商品購買時,需要對上次快取的未成功的支付憑證進行再次校驗。以確保伺服器訂單狀態正確。

2.流程順序

具體流程以虛擬碼

  1. 獲取商品列表

      - (void)fetchProducts:(xxxCompletBlock)complete {
          if (![netWork isAvalabel]) {
          if (complete)
            complete(....);
        }
    
          [[ProductsOrderModel shareInstance] fetchProductsFromServer:xxxx complete:^(BOOL success, NSArry* products,.....) {
          if (success) {
          // 檢驗本地快取
          NSArry* cacheProducts = [[ProductOrderCache shareInstance] cacheProducte];
          ......
    
        //快取與伺服器一直
        if (complete) 
          complete(....);
    
        //如果不一致,再去app store拉取
        [ProductOrderCache shareInstance] cleanCacheProducte];
        [[ProductsOrderModel shareInstance] fetchProductsFromApple:xxxx     complete:^(BOOL success, NSArry* products,.....) {
            if (complete) 
              complete(....);
              ...
            }]; 
          } else {
          .....
        }
      }]; 
    }
    
  2. 支付

  - (void)orderProduct:(NSString*)id complete:(xxxCompletBlock)complete {
     //先去伺服器獲取訂單
    [[ProductsOrderModel shareInstance] fetchOrderFromServer:id  complete:^(BOOL success, ...) {
        if (success) {
       //發起蘋果支付

       SKPayment * payment = [SKPayment paymentWithProduct:product];
       [[SKPaymentQueue defaultQueue] addPayment:payment];
     } else {
         ....
     }
   }];
 }

 //蘋果支付回撥
 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {

 for (SKPaymentTransaction *transaction in transactions)
 {
     switch (transaction.transactionState)
     {
         case SKPaymentTransactionStatePurchased:
             [self completeTransaction:transaction state:xxx_Succeed];
             break;
         case SKPaymentTransactionStateFailed:
             [self completeTransaction:transaction state:xxx_Failed];
             break;
         case SKPaymentTransactionStateRestored:
             [self completeTransaction:transaction state:xxx_Succeed];
             break;
         case SKPaymentTransactionStatePurchasing:
             break;
         default:
             break;
     }
   }
 }

 - (void)completeTransaction:transaction state:(xxx_State)state {
   switch(state) {
     case xxx_Succeed:
     {
     //拿到蘋果返回的憑證去和服務進行校驗
     [ProductsOrderModel shareInstance] verifyTransactionReceipt:xxx orderId:xxx complete:^(BOOL success, xxxx) {
     if (success) {
     // 更新快取狀態
          [[ProductOrderCache shareInstance] updateOrderState:xxxid state:YES];
           ...
          } else {
         // 再次校驗
          ...
         }
       }];
       }
     break;

   case xxx_Failed:
   {
   // 更新快取狀態
     [[ProductOrderCache shareInstance] updateOrderState:xxxid state:NO];
    }
   break;
   default:
       break;
     }
   }

3.其他

  1. 每次進行購買時,需要對本地快取的上一次失敗憑證進行再次校驗。
  2. 商品列表資訊,支付憑證資訊需要做檔案快取。

相關文章