Share via


Xamarin.iOS 中的交易和驗證

還原過去的交易

如果您的應用程式支援可還原的產品類型,您必須包含一些使用者介面元素,以允許使用者還原這些購買。 這項功能可讓客戶將產品新增至其他裝置,或在清除或移除並重新安裝應用程式之後,將產品還原至相同的裝置。 下列產品類型是可還原的:

  • 非消費性產品
  • 自動續約訂閱
  • 免費訂用帳戶

還原程式應更新您保留在裝置上的記錄,以履行您的產品。 客戶可以選擇隨時在其任何裝置上還原。 還原程式會重新傳送該使用者的所有先前交易;然後,應用程式程式代碼必須決定該資訊要採取的動作(例如,檢查裝置上是否有該購買記錄,如果沒有,請建立購買記錄,併為使用者啟用產品)。

實作還原

使用者介面 [還原] 按鈕會呼叫下列方法,這會觸發 上的 SKPaymentQueueRestoreCompletedTransactions。

public void Restore()
{
   // theObserver will be notified of when the restored transactions start arriving <- AppStore
   SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();​​​
}

StoreKit 會以異步方式將還原要求傳送至 Apple 的伺服器。

CustomPaymentObserver因為 註冊為交易觀察者,所以會在 Apple 的伺服器回應時收到訊息。 回應會包含此使用者在此應用程式中執行的所有交易(在其所有裝置上)。 程式代碼會迴圈處理每個交易、偵測還原的狀態,並呼叫 UpdatedTransactions 方法來處理它,如下所示:

// called when the transaction status is updated
public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
   foreach (SKPaymentTransaction transaction in transactions)
   {
       switch (transaction.TransactionState)
       {
       case SKPaymentTransactionState.Purchased:
          theManager.CompleteTransaction(transaction);
           break;
       case SKPaymentTransactionState.Failed:
          theManager.FailedTransaction(transaction);
           break;
       case SKPaymentTransactionState.Restored:
           theManager.RestoreTransaction(transaction);
           break;
​default:
           break;
       }
   }
}

如果使用者沒有可還原的產品, UpdatedTransactions 則不會呼叫 。

在範例中還原指定交易的最簡單程式代碼會執行與購買時相同的動作,不同之處在於 OriginalTransaction 屬性是用來存取產品標識碼:

public void RestoreTransaction (SKPaymentTransaction transaction)
{
   // Restored Transactions always have an 'original transaction' attached
   var productId = transaction.OriginalTransaction.Payment.ProductIdentifier;
   // Register the purchase, so it is remembered for next time
   PhotoFilterManager.Purchase(productId); // it's as though it was purchased again
   FinishTransaction(transaction, true);
}

更複雜的實作可能會檢查其他 transaction.OriginalTransaction 屬性,例如原始日期和收據號碼。 這項信息對於某些產品類型(例如訂用帳戶)很有用。

還原完成

CustomPaymentObserver 兩個額外的方法,會在還原程式完成時由 StoreKit 呼叫(成功或失敗),如下所示:

public override void PaymentQueueRestoreCompletedTransactionsFinished (SKPaymentQueue queue)
{
   Console.WriteLine(" ** RESTORE Finished ");
}
public override void RestoreCompletedTransactionsFailedWithError (SKPaymentQueue queue, NSError error)
{
   Console.WriteLine(" ** RESTORE FailedWithError " + error.LocalizedDescription);
}

在範例中,這些方法不會執行任何動作,不過實際應用程式可能會選擇對使用者或其他功能實作訊息。

保護購買

本檔中的兩個範例會使用 NSUserDefaults 來追蹤購買:

消費性 – 點數購買的「餘額」是隨每個購買遞增的簡單 NSUserDefaults 整數值。

非消費性 – 每個相片篩選購買都會儲存為 中的 NSUserDefaults索引鍵/值組。

使用 NSUserDefaults 可讓範例程式代碼保持簡單,但不會提供非常安全的解決方案,因為技術上考慮的使用者可能會更新設定(略過付款機制)。

注意:真實世界應用程式應採用安全機制來儲存不受使用者竄改的已購買內容。 這可能涉及加密和/或其他技術,包括遠端伺服器驗證。

機制也應該設計為利用 iOS、iTunes 和 iCloud 的內建備份和復原功能。 這可確保在使用者還原備份之後,其先前的購買將立即可供使用。

如需更多 iOS 特定指導方針,請參閱 Apple 的安全編碼指南。

收據驗證和伺服器交付的產品

到目前為止,本檔中的範例只包含與 App Store 伺服器直接通訊的應用程式,以進行購買交易,以解除鎖定已編碼到應用程式的特性或功能。

Apple 提供額外的購買安全性,方法是允許另一部伺服器獨立驗證購買收據,這在提供數位內容作為購買(例如數位書籍或雜誌)的一部分之前,驗證要求很有用。

內建產品 – 如同本檔中的範例,所購買的產品會以應用程式隨附的功能的形式存在。 應用程式內購買可讓使用者存取此功能。 產品標識碼會硬式編碼。

伺服器交付的產品 – 產品包含可下載的內容,該內容會儲存在遠端伺服器上,直到交易成功導致下載內容為止。 範例可能包括書籍或雜誌問題。 產品標識碼通常來自外部伺服器(其中也裝載產品內容)。 當交易完成時,應用程式必須實作健全的錄製方式,如此一來,如果內容下載失敗,就可以重新嘗試,而不會混淆使用者。

伺服器交付的產品

某些產品的內容,例如書籍和雜誌(甚至遊戲層級)必須在購買過程中從遠端伺服器下載。 這表示在購買產品內容之後,需要額外的伺服器來儲存並傳遞產品內容。

取得伺服器交付產品的價格

由於產品是遠端交付的,因此也可以隨著時間增加更多產品(而不更新應用程式程式代碼),例如新增更多書籍或雜誌的新問題。 因此,應用程式可以探索這些新聞產品,並將其顯示給使用者,額外的伺服器應該儲存並傳遞此資訊。

Getting Prices for Server-Delivered Products

  1. 產品信息必須儲存在多個位置:在您的伺服器上和iTunes 連線。 此外,每個產品都會有與其相關聯的內容檔案。 成功購買之後,將會傳遞這些檔案。

  2. 當使用者想要購買產品時,應用程式必須判斷有哪些產品可供使用。 此資訊可能會快取,但應該從儲存產品主要清單的遠端伺服器傳遞。

  3. 伺服器會傳回應用程式要剖析的產品標識符清單。

  4. 然後,應用程式會決定要傳送至 StoreKit 的這些產品識別碼中的哪一個,以擷取價格和描述。

  5. StoreKit 會將產品標識碼清單傳送至 Apple 的伺服器。

  6. iTunes 伺服器會回應有效的產品資訊(描述和目前價格)。

  7. 應用程式的 SKProductsRequestDelegate 會傳遞要向用戶顯示的產品資訊。

購買伺服器交付的產品

因為遠端伺服器需要某種方式驗證內容要求是否有效(即已支付),因此收據資訊會隨著驗證一起傳遞。 遠端伺服器會將該資料轉送至 iTunes 以進行驗證,如果成功,則會在回應應用程式時包含產品內容。

Purchasing Server-Delivered Products

  1. 應用程式會將 新增 SKPayment 至佇列。 如果需要,系統會提示使用者輸入其 Apple ID,並要求確認付款。

  2. StoreKit 會將要求傳送至伺服器進行處理。

  3. 當交易完成時,伺服器會以交易收據回應。

  4. SKPaymentTransactionObserver 類別會接收收據並加以處理。 由於產品必須從伺服器下載,因此應用程式會起始對遠端伺服器的網路要求。

  5. 下載要求會伴隨收據數據,讓遠端伺服器可以確認它已獲授權存取內容。 應用程式的網路用戶端會等候此要求的回應。

  6. 當伺服器收到內容要求時,它會剖析收據數據,並將要求直接傳送至iTunes伺服器,以確認收據適用於有效的交易。 伺服器應該使用一些邏輯來判斷是否要將要求傳送至生產環境或沙箱 URL。 如果您收到狀態為 21007(傳送至生產伺服器的沙箱收據),Apple 建議一律使用生產 URL 並切換至沙箱。 如需詳細資訊,請參閱Apple的 收據驗證程序設計指南

  7. 如果收據有效,iTunes 會檢查收據,並傳回零的狀態。

  8. 伺服器會等候 iTunes 的回應。 如果收到有效的回應,程式代碼應該會找出相關聯的產品內容檔案,以包含在應用程式的回應中。

  9. 應用程式會接收並剖析回應,並將產品內容儲存至裝置的檔案系統。

  10. 應用程式會啟用產品,然後呼叫 StoreKit 的 FinishTransaction。 然後,應用程式可以選擇性地顯示已購買的內容(例如,顯示已購買書籍或雜誌發行的第一頁)。

非常大型產品內容檔案的替代實作可能牽涉到將交易收據儲存在步驟 9 中,以便快速完成交易,並提供使用者介面,讓使用者稍後下載實際的產品內容。 後續的下載要求可以重新傳送預存收據,以存取所需的產品內容檔案。

撰寫伺服器端收據驗證碼

您可以使用簡單的 HTTP POST 要求 /回應來完成伺服器端程式代碼中的收據,其中包含工作流程圖表中的步驟 #5 到 #8。

SKPaymentTansaction.TransactionReceipt擷取應用程式中的屬性。 這是需要傳送至 iTunes 以進行驗證的數據(步驟 #5)。

Base64 編碼交易收據數據(步驟 #5 或 #6)。

建立簡單的 JSON 承載,如下所示:

{
   "receipt-data" : "(base-64 encoded receipt here)"
}

HTTP 將 JSON 張貼至 https://buy.itunes.apple.com/verifyReceipt 生產環境或 https://sandbox.itunes.apple.com/verifyReceipt 進行測試。

JSON 回應將包含下列金鑰:

{
   "status" : 0,
   "receipt" : { (receipt repeated here) }
}

零的狀態表示有效的收據。 您的伺服器可以繼續履行所購買產品的內容。 收據索引鍵包含 JSON 字典,其屬性與 SKPaymentTransaction 應用程式接收的物件相同,因此伺服器程式代碼可以查詢此字典以擷取購買product_id和數量等資訊。

如需詳細資訊,請參閱Apple的 收據驗證程序設計指南 檔。