標籤:app store
使用者在購買蘋果的商品的過程如下:
- 1.應用發送請求到伺服器,擷取所有的Products ID列表
- 2.伺服器返回Products ID列表
- 3.應用發送請求至App Store,擷取Products的資訊
- 4.App Store返回Product資訊
- 5.應用使用這些資訊,向使用者顯示一個Store介面
- 6.使用者從Store中選擇一項
- 7.應用向App Store發送payment請求
- 8.App Store處理該payment,並返回完成的transaction
- 9.應用從transaction中擷取receipt資料,並將其發送給伺服器
- 10.伺服器記錄receipt資料,並建立一個audit trail(審查跟蹤)
- 11.伺服器發送receipt資料到App Store,以驗證是否合法的transaction
- 12.App Store解析receipt資料,並返回receipt,以及驗證結果(是否合法)
- 13.伺服器讀取返回的receipt資料,並確定哪個使用者已經完成購買
- 14.伺服器交付已購買的內容至iOS應用
Purchase(購買)當使用者準備好購買product時,應用請求App Store來完成支付。App Store會建立一個持久化的transaction,即使使用者退出和重新啟動應用,也會繼續地處理該支付交易。App Store將未決交易列表同步給應用,並且在任何交易狀態變化時,遞送更新資訊給應用。說到purchase我不得不提之前讓我頭疼的一個問題就是驗證了:static public function getReceiptData($receipt, $isSandbox = false) { if ($isSandbox) { $endpoint = 'https://sandbox.itunes.apple.com/verifyReceipt'; } else { $endpoint = 'https://buy.itunes.apple.com/verifyReceipt'; } error_log(date("Y-m-d h:i:s")." procAppstoreNotification request error data " . serialize($receipt) ."\r\n", 3 , 'appstore.log'); $postData = json_encode(array('receipt-data' => $receipt)); error_log(date("Y-m-d h:i:s")." procAppstoreNotification request error data " . serialize($postData) ."\r\n", 3 , 'appstore.log'); $ch = curl_init($endpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); //?芒?陸???祿露簍?陋錄?攏盧虜祿錄?祿謾鹵簍SSL 麓鉚?貿 curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); $response = curl_exec($ch); $errno = curl_errno($ch); $errmsg = curl_error($ch); curl_close($ch); //??露??鹵潞貌魯枚麓鉚攏盧??魯枚?矛魯攏 if ($errno != 0) { throw new Exception($errmsg, $errno); } $data = json_decode($response); error_log(date("Y-m-d h:i:s")." procAppstoreNotification request error data " . serialize($data) ."\r\n", 3 , 'appstore.log'); //??露?路碌祿?碌??媒戮???路帽??露??貿 if (!is_object($data)) { throw new Exception('Invalid response data'); } //??露?鹿潞?貌?鹵潞貌魯?鹿婁 if (!isset($data->status) || $data->status != 0) { throw new Exception('Invalid receipt'); } error_log(date("Y-m-d h:i:s")." procAppstoreNotification request error data " . serialize($data) ."\r\n", 3 , 'appstore.log'); //路碌祿?虜煤?路碌????壟 return array( 'quantity' => $data->receipt->quantity, 'product_id' => $data->receipt->product_id, 'transaction_id' => $data->receipt->transaction_id, 'purchase_date' => $data->receipt->purchase_date, 'app_item_id' => $data->receipt->app_item_id, 'bid' => $data->receipt->bid, 'bvrs' => $data->receipt->bvrs );}之前是有部分賬單驗證未通過,後來查了下是在給蘋果發驗證資料的時候需要用base64進行編碼的,後來我就改了$postData = json_encode(array('receipt-data' => base64_encode($receipt)));
Store Receipt你發送給App Store的receipt資料編碼了交易的資訊。當App Store驗證receipt時,會先解碼receipt資料,並在響應中返回。receipt響應是一個JSON dictionary,包含了應用中SKPaymentTransaction對象的所有資訊。因此伺服器可以查詢這些JSON域,來擷取使用者購買的詳細資料。蘋果推薦iOS應用只發送receipt資料給伺服器,不發送交易資料給伺服器,然後伺服器再到App Store去驗證receipt。App Store會驗證receipt資料沒有被篡改。伺服器從App Store響應的receipt資料中擷取交易資訊,而不是由iOS應用直接發送交易資訊給伺服器,會更加安全。下表列出了你可以從響應receipt中擷取的資訊,許多鍵直接對應於SKPaymentTransaction類的屬性。表中沒有指定的鍵都被蘋果保留,不得使用。
| 鍵 | 描述 |
| quantity | 購買的數量,對應於transaction.payment.quantity屬性 |
| product_id | product ID標識,對應於transaction.payment.productIdentifier屬性 |
| transaction_id | transaction ID標識,對應於transaction.transactionIdentifier屬性 |
| purchase_date | 交易發生的日期和時間,對應於transaction.transactionDate屬性 |
| original_transaction_id | 對於還原交易,這個值儲存了原始交易ID |
| original_purchase_date | 對於還原交易,這個值儲存了原始交易日期 |
| app_item_id | 字串,App Store用來唯一地標識一個建立了支付交易的iOS應用。如果你的伺服器支援多個iOS應用,你可以使用這個值來區分不同的應用。在sandbox中啟動並執行應用沒有app_item_id,因此這個鍵也不存在 |
| version_external_identifier | 唯一標識你的應用修訂版本的任意數值。sandbox應用沒有這個鍵 |
| bid | iOS應用的Bundle ID |
| bvrs | iOS應用的版本號碼 |
關於蘋果purchase的驗證