IAP簡介
在應用中內嵌Store,在iOS應用中使用Store Kit framework來實現In-App Purchase。Store Kit會串連App Store,代替應用安全地完成使用者支付。Store Kit提示使用者授權支付,然後通知應用“使用者已經完成支付”,這樣應用就可以提供使用者購買的東西。使用iap可以為應用的增強功能,或額外內容進行收費,如以下情境:
- 基礎版本的應用,購買額外的特性
- 書籍閱讀器應用,允許使用者購買和下載新的書籍
- 遊戲,提供新的環境(情境、關卡、等級等)
- 線上遊戲,允許玩家購買虛擬財產(金幣、道具、裝備等)
- 數字雜誌或newsletter訂閱
Products
可在iTunes Connect中定義,iap支援四種類型的product:
- Content(內容):包括數字圖書、雜誌、照片、封面、遊戲等級、遊戲角色、以及其它應用可交付的數字內容
- Functionality(功能):解鎖或擴充應用當前已交付的特性。例如遊戲中的多個小遊戲,使用者可單獨購買
- Service(服務):允許應用提供收費的一次性服務,每次使用服務都需要單獨購買
- Subscription(訂閱):以擴充的方式,提供使用者對內容或服務的訪問。如應用提供每月財報或線上門戶網站訪問
所有的Product都必須先在App Store中通過iTunes Connect註冊,你需要提供一個唯一的product identifier,以及許多其它資訊應用使用Store Kit與App Store通訊時;以及使用者購買後,應用處理這個購買並提供product,都使用這個ID進行標識product還可以分為以下類型:
- 消耗型,每次使用者需要該產品時都需要購買。一次性服務通常都是消耗型
- 非消耗型,每個使用者只需要購買一次,一旦購買,使用者帳號相關聯的所有裝置都可以使用。Store Kit提供內建的支援,可在多個裝置中使用非消耗型產品
- 自動再生訂閱,和非消耗型一樣遞送至使用者的所有裝置。但是自動再生訂閱在iTunes Connect中需指定訂閱的期間。App Store在到期後自動更新該訂閱。如果使用者選擇不允許訂閱自動更新,在訂閱到期後將自動取消,使用者不能再訪問該產品。應用負責驗證某個訂閱當前是否有效,並且可以獲得最近交易的receipt
- 免費訂閱,在Newsstand中提供免費訂閱。使用者一旦註冊了免費訂閱,帳號相關的所有裝置都可以訪問該訂閱的內容。免費訂閱不會到期,而且只能在啟用Newsstand的應用中提供
- 非自動再生訂閱,建立受限期間訂閱的舊機制,應使用自動再生訂閱代替該機制。與自動再生訂閱的區別有三點:
-
- iTunes Connect中不指定訂閱協議,應用負責提供這個資訊給使用者
- 可以被購買多次,App Store不會自動更新該訂閱。應用負責實現訂閱更新,檢測到期,提示使用者重新購買。
- 應用必須將非自動再生訂閱遞送至使用者的所有裝置。Store Kit不會進行自動同步。
如何交付已購買的iap特性應用需要設計和實現提供iap產品給使用者的交付機制。目前主要有兩種:內建模型、伺服器模型。在這兩種模型中,你都必須跟蹤Store中已提供的products列表,並交付給使用者使用。內建模型
所有需要交付的products都已經包含在應用中。這個模型主要用於應用解鎖相關的功能。也可以使用這個模型來交付應用Bundle中已經提供的內容。內建模型的主要優點是可以快速地交付products給使用者,多數內建型Products都應該是非消耗型的應用可以在Application Bundle中儲存Product Identifier,從而標識出相應的iap product。蘋果推薦使用plist來記錄所有內建特性的product ID。基於內容的應用可以使用這個技術來增加新的內容,而不需要修改應用的代碼。在使用者成功購買product之後,應用必須解鎖該特性,並且交付給使用者使用。解鎖特性最簡單的方法是修改應用參數。應用參數在使用者備份iOS裝置時會自動備份,應用在使用者購買product之後可以考慮推薦使用者進行備份操作。內建模型:
- 應用從Bundle中擷取product ID列表
- 應用向App Store發送請求,以擷取products的資訊
- App Store返回Products資訊
- 應用使用這些資訊來顯示一個Store給使用者
- 使用者從顯示的Store中選擇一項
- 應用向App Store發送payment請求
- App Store處理這個payment,並返回一個完成的transaction
- 應用讀取transaction資訊,並交付使用者已購買的內容
伺服器模型在伺服器模型中,我們提供一個獨立的伺服器,來交付Products給iOS應用。伺服器交付適合於訂閱、服務、內容,因為這些Products可以按資料來交付,而不需要修改iOS應用bundle。遊戲也可以使用伺服器來交付新的遊戲環境(謎題、等級、或關卡)。Store Kit不管你的伺服器與iOS應用之間如何互動;Store Kit也不提供標識特定使用者的機制。你需要自己提供一個使用者機制,來標識你iOS應用的使用者(例如你提供訂閱服務,需要與使用者相關聯,就需要自己實現使用者機制)。伺服器模型:
- 應用發送請求到伺服器,擷取所有的Products ID列表
- 伺服器返回Products ID列表
- 應用發送請求至App Store,擷取Products的資訊
- App Store返回Product資訊
- 應用使用這些資訊,向使用者顯示一個Store介面
- 使用者從Store中選擇一項
- 應用向App Store發送payment請求
- App Store處理該payment,並返回完成的transaction
- 應用從transaction中擷取receipt資料,並將其發送給伺服器
- 伺服器記錄receipt資料,並建立一個audit trail(審查跟蹤)
- 伺服器發送receipt資料到App Store,以驗證是否合法的transaction
- App Store解析receipt資料,並返回receipt,以及驗證結果(是否合法)
- 伺服器讀取返回的receipt資料,並確定哪個使用者已經完成購買
- 伺服器交付已購買的內容至iOS應用
應用最好通過你的伺服器來擷取Products標識,而不是直接存放在plist檔案中。這樣可以增加新Products,而無需更新應用。在伺服器模型中,應用擷取transaction相關聯的簽名receipt,並且發送給伺服器。伺服器然後驗證該receipt並對其進行解碼,以確定需要嚮應用交付什麼內容。非消耗型products可以使用Store Kit內建的功能恢複,但是非自動再生訂閱必須由你的伺服器來還原。你負責記錄非自動再生訂閱的資訊,並且還原給使用者使用。消耗型Products也可以在伺服器中記錄,例如允許使用者在多個裝置上擷取服務的結果。
擷取Product資訊應用在顯示Store給使用者時,必須在介面上顯示App Store中擷取的資訊。
向App Store發送請求Store Kit提供通用的機制,向App Store發送請求。應用建立和初始化請求對象,指定一個delegate,就可以發起請求。App Store處理請求後,會非同步地調用delegate來通知應用請求結果。如所示:
SKRequestSKRequest是一個抽象基類,用於向Store發送請求
SKRequestDelegateSKRequestDelegate是一個protocol,應用實現該介面,來處理Store成功或失敗的結果
擷取Products的資訊應用使用
Products請求來擷取本地化的product資訊。應用建立一個請求,包含products ID字串的列表。發起請求後,products ID會傳輸至App Store。App Store會返回你之前在iTunes Connect中註冊的本地化的products資訊。應用使用這些資訊來顯示Store允許使用者購買products之前,必須先使用該product ID向App Store查詢詳細的資訊,這樣才能確保product ID合法,而且在iTunes Connect中標記為可以銷售。
SKProductsRequestSKProductsRequest對象使用一組product ID來建立,這些是你想要顯示給使用者的product列表
SKProductsRequestDelegateSKProductsRequestDelegate協議需要應用來實現,用於擷取Store的響應資訊。請求成功處理後,會非同步地接收App Store的響應資訊
SKProductsResponseSKProductsResponse對象是返回的結果資訊,請求列表中的每個合法的product ID都有一個相應的SKProduct對象;同時還包含Store不能識別的一組product ID列表。不能識別的原因有許多:ID拼字錯誤、標記為不可銷售、iTunes Connect中的修改還沒有傳送到其它App Store伺服器等
SKProductSKProduct對象提供你在App Store中註冊的product的詳細本地化資訊
Purchase(購買)當使用者準備好購買product時,應用請求App Store來完成支付。App Store會建立一個持久化的transaction,即使使用者退出和重新啟動應用,也會繼續地處理該支付交易。App Store將未決交易列表同步給應用,並且在任何交易狀態變化時,遞送更新資訊給應用。
收集支付應用建立一個payment對象,並將其添加到payment隊列中,如所示:payment添加到隊列中時,會建立一個持久化的交易來儲存它。在payment處理完之後,交易會更新為收集支付之後的狀態資訊。應用實現observer來接收交易更新資訊。observer負責提供已購買內容給使用者,並且從payment隊列中移除該交易
SKPayment
使用payment對象來收集支付。payment對象包含一個product ID,以及一個可選的購買數量。你可以把同一個payment對象排隊多次,每排隊一次都將導致一次單獨的請求。使用者可以在"設定"中禁用應用中購買。在排隊一個購買請求之前,應用需要首先確認payment能夠被處理,調用payment隊列的canMakePayments方法。
SKPaymentQueuepayment隊列用來與App Store通訊。當payment添加到隊列中時,Store Kit傳輸這個請求到App Store。Store Kit會顯示對話方塊詢問使用者授權支付。完成的transaction會返回到應用的observer,以便應用處理。
SKPaymentTransaction每個payment被添加到隊列時,都會建立一個相應的transaction。每個transaction都有一些屬性,允許應用確定該交易的狀態。當支付收集完成後,transaction對象還包含額外的交易成功詳細資料。雖然應用可以從payment隊列中擷取未決交易的列表,更通用的做法是應用等待,直到payment隊列主動通知observer,並傳遞更新交易的列表。
SKPaymentTransactionObserver應用的某個對象實現SKPaymentTransactionObserver協議,並把該對象添加為payment隊列的observer。observer的主要責任是檢查已完成的交易;遞送已經成功購買的product;然後將這些完成交易從payment隊列中移除。應用應該在啟動時就關聯observer到payment隊列,而不是等到使用者試圖購買時才關聯。transaction在應用終止後並不會丟失,下次應用啟動時,Store Kit會繼續處理這些交易。在應用初始化階段添加observer,可確保所有交易都成功傳遞到應用。
還原交易一旦交易處理完成,並從隊列中移除,應用通常不會再看到它。但是如果應用支援的product類型必須可還原,你就必須包含一個介面,允許使用者還原這些購買。這個介面允許使用者把已購買的product添加到其它裝置,或者原始裝置重設後,也需還原交易。Store Kit提供內建的機制,用於還原非消耗型、自動再生訂閱、免費訂閱等product的交易。應用調用payment隊列的restoreCompletedTransactions方法,payment隊列就會發送一個請求到App Store來還原交易。而App Store則對所有之前已經完成的交易產生一個新的還原交易。還原交易對象的originalTransaction屬性儲存了原始的交易。應用對還原交易進行處理,從中擷取原始交易,然後使用這個原始交易對象來解鎖使用者已購買的內容。在Store
Kit還原了之前完成的交易時,會通知payment隊列的observer對象,並調用它的paymentQueueRestoreCompletedTransactionsFinished: 方法。如果使用者試圖購買一個可還原的product(而不是使用你實現的還原介面),應用會接收到一個正常的交易,而不是可還原交易。但是使用者不需要再次為這個product支付。應用應該把這些交易當作原始交易一樣來處理。非自動再生訂閱和可消耗型product不會被Store Kit自動還原。但是非自動再生訂閱又必須可還原,因此在購買這些product時,你必須在自己的伺服器上記錄這些交易,並提供自己的機制來還原這些交易給使用者的所有裝置。
應用中添加Store(內建模型)首先確保項目連結了StoreKit.framework,應用中添加Store的詳細步驟如下:
1. 定義應用需要遞送的products。
Store Kit對products有一些限制,不允許應用對自己打補丁,或者下載額外的代碼。products要麼已經在應用的現有代碼中,要麼從遠程伺服器下載資料檔案來實現。如果應用增加特性需要修改現有代碼,必鬚髮布一個新版本的應用。2. 在iTunes Connect中為每個product註冊詳細資料每次應用Store要增加一個新的product,都需要先在iTunes Connect中進行註冊。每個product都需要一個唯一的ID字串。App Store使用這個字串來尋找product資訊以及處理支付請求。product ID特定於iTunes Connect帳號,註冊的方式與註冊應用類似。3. 確定系統能夠處理支付使用者可以禁止在應用程式內購買,因此你的應用需要先檢查當前是否支援在應用程式內購買。應用可以在顯示Store給使用者之前,或者在實際發起購買請求之前,進行這項檢查。後者允許使用者查看能夠購買的products,即使在應用程式內購買當前被禁止。if ([SKPaymentQueue canMakePayments]){ ... // 向使用者顯示Store}else{ ... // 警告使用者當前禁止在應用程式內購買}4. 擷取products的資訊應用建立一個SKProductsRequest對象,並初始化為一組你想要銷售的product ID,添加一個delegate處理請求返回結果,然後就可以發起這個請求。響應結果儲存了所有合法的products的本地化資訊。應用必須首先獲得product的資訊,然後才能建立payment請求。- (void) requestProductData{ SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: kMyFeatureIdentifier]]; request.delegate = self; [request start];}- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{ NSArray *myProduct = response.products; // 把資訊顯示到Store介面 [request autorelease];}5. 增加一個使用者介面,顯示products給使用者Store Kit不提供使用者介面類,如何顯示Store給使用者是應用的事情。6. 註冊一個transaction observer到payment隊列應用執行個體化一個transaction observer,並將其註冊到payment隊列。MyStoreObserver *observer = [[MyStoreObserver alloc] init];[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];如前所述,應用最好在啟動時註冊observer。交易完成之前應用退出,App Store也仍然記得這些交易。啟動時註冊observer確保所有之前排隊交易的結果都能夠被應用接收到。7. 在應用的MyStoreObserver對象中實現paymentQueue:updatedTransactions: 方法observer的paymentQueue:updatedTransactions: 方法在新交易被建立或更新時都會被調用- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{ for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: [self completeTransaction:transaction]; break; case SKPaymentTransactionStateFailed: [self failedTransaction:transaction]; break; case SKPaymentTransactionStateRestored: [self restoreTransaction:transaction]; default: break; } }}8. observer在使用者成功購買後提供相應的product- (void) completeTransaction: (SKPaymentTransaction *)transaction{// 應用需要實現這兩個方法:記錄交易、提供內容 [self recordTransaction: transaction]; [self provideContent: transaction.payment.productIdentifier];// 從payment隊列中刪除交易 [[SKPaymentQueue defaultQueue] finishTransaction: transaction];}成功的交易包含一個transactionIdentifier屬性和一個transactionReceipt屬性,記錄了已處理支付的詳細資料。應用不需要對這些資訊做任何處理。當然你可能希望記錄這些資訊並為交易建立一個審查跟蹤(audit trail)。如果使用伺服器來遞送內容,應用可以把receipt發送到伺服器,然後由伺服器向App Store驗證該交易。一旦你完成交付product給使用者,應用必須調用finishTransaction: 來完成交易,交易將從payment隊列中移除。為了確保products不會丟失,應用應該在調用finishTransaction: 之前交付內容。9. 處理還原購買,結束交易- (void) restoreTransaction: (SKPaymentTransaction *)transaction{ [self recordTransaction: transaction]; [self provideContent: transaction.originalTransaction.payment.productIdentifier]; [[SKPaymentQueue defaultQueue] finishTransaction: transaction];}這個方法類似於上面的購買。還原購買是一個新的交易,擁有不同的transaction ID和receipt。你可以單獨儲存這些資訊,並建立審查跟蹤。但是當完成交易時,你還是要還原原始的交易,那裡面儲存了實際的payment對象和product ID。10. 處理失敗購買,結束交易- (void) failedTransaction: (SKPaymentTransaction *)transaction{ if (transaction.error.code != SKErrorPaymentCancelled) { // 可以顯示一個錯誤(可選的) } [[SKPaymentQueue defaultQueue] finishTransaction: transaction];}通常交易失敗都是使用者決定不購買。應用可以讀取失敗交易的error域,從而瞭解為何交易失敗。對於失敗的交易,應用唯一需要做的是從隊列中移除它。如果應用在交易失敗後顯示一個對話方塊告訴使用者交易出錯,應該避免在使用者主動取消時也顯示該錯誤。11. 做完上面所有以後,你就可以顯示使用者介面。當使用者在Store中選擇一項時,應用就建立一個payment對象,並將其添加到payment隊列中。SKPayment *payment = [SKPayment paymentWithProductIdentifier:kMyFeatureIdentifier];[[SKPaymentQueue defaultQueue] addPayment:payment];如果Store提供一次購買多個product的功能,你可以建立一個payment對象,並指定quantity屬性SKMutablePayment *payment = [SKMutablePayment paymentWithProductIdentifier:kMyFeatureIdentifier];payment.quantity = 3;[[SKPaymentQueue defaultQueue] addPayment:payment];以上的程式碼範例主要用於內建product模型。如果你的應用使用伺服器來交付內容,你需要設計和實現iOS應用與伺服器之間通訊的協議。你的伺服器還需要在交付products給應用之前,先驗證receipts。
驗證Store receipt應該接收到Apple Store Kit的receipt後,應該執行額外的receipt檢查,來驗證交易的合法性。如果應用依賴於獨立的伺服器來提供訂閱、服務、可下載內容,驗證receipt就非常重要。伺服器驗證receipt可確保iOS應用向伺服器的請求是合法的。Store receipt的內容和格式是私人的,並且有可能變化。應用不能試圖直接解析receipt資料。使用下面描述的機制來驗證receipt,並獲得receipt中儲存的資訊。
向App Store驗證一個Receipt當Store Kit返回一個完成的購買到payment隊列的observer時,交易的transactionReceipt屬性包含一個簽名的receipt,記錄了所有關鍵的交易資訊。伺服器可以post這個receipt到App Store,來驗證receipt是合法的,沒有被篡改。向App Store查詢使用JSON dictionary直接發送和接收,由RFC 4627定義。執行以下步驟,來驗證receipt:1. 從transaction的transactionReceipt屬性擷取receipt資料,並使用Base64對其進行編碼2. 建立一個JSON對象,只有一個名為"receipt-data"的鍵,它的值是步驟1建立的字串。JSON對象如下:{ "receipt-data" : "(actual receipt bytes here)"}3. 使用HTTP POST請求,Post這個JSON對象到App Store,URL為:https://buy.itunes.apple.com/verifyReceipt4. 從App Store接收到的響應也是一個JSON對象,有兩個鍵:status和receipt。如下所示:{ "status" : 0, "receipt" : { ... }}如果status的值為0,表示是一個合法的receipt。否則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應用的版本號碼 |
測試Store在開發過程中,你需要測試應用Store來確保正常工作。但是又不能進行實際的使用者支付,因此需要使用蘋果提供的sandbox Store測試。Store Kit不能在iOS模擬器中使用,測試Store必須在真機上進行。
Sandbox環境從Xcode啟動應用時,Store Kit不會串連到App Store。相反會串連到特殊的Sandbox Store環境。Sandbox環境使用了App Store的基礎架構,但是不會發生實際的支付。Sandbox環境返回成功的支付,就好像實際上購買了一樣。Sandbox環境使用特殊的iTunes Connect帳號,只能用於測試In-App Purchase。不能使用普通的iTunes
Connect帳號在Sandbox中測試。你需要在iTunes Connect中建立一個或多個特殊的測試帳號,至少每個本地化地區需要一個單獨的測試帳號。詳細的資訊可參考iTunes Connect Developer Guide.
Testing in the Sandbox按以下步驟,在Sandbox中進行測試:1. 在測試的iOS裝置中退出當前iTunes帳號在測試應用之前,必須首先退出普通的iTunes帳號。iOS 3.0在設定程式中包含了一個Store類別,你可以在裡面退出當前帳號切記:不要在設定中登入你的測試帳號,否則測試帳號將失效2. 運行你的應用一旦你退出了普通帳號,就可以在Xcode中運行你的應用。在應用中提交支付時,Store Kit會提示你授權交易。使用測試帳號登入並同意支付。這時候不會發生扣款,但是交易會正常完成。
在Sandbox中驗證Receipts你也可以在Sandbox中驗證receipt,執行驗證的代碼和普通App Store是一樣的,但是Sandbox環境的URL不一樣:NSURL *sandboxStoreURL = [[NSURL alloc] initWithString: @"https://sandbox.itunes.apple.com/verifyReceipt"];
Auto-Renewable訂閱In-App Purchase提供標準化的方式,來實現自動再生訂閱。自動再生訂閱擁有以下特性:1. 在iTunes Connect中配置自動再生訂閱時,需要指定訂閱的期間,以及其它選項。2. Auto-renewable訂閱會自動還原,而且和非消耗型product一樣,都使用相同的Store Kit函數。原始交易,和每次的再生交易都會發送到應用。3. 伺服器向App Store驗證receipt時,如果訂閱活躍,並且被App Store自動再生過,App Store會返回一個更新的receipt
添加自動再生訂閱到Store按以下步驟實現auto-renewable訂閱:1. 串連到iTunes Connect,並建立一個新的"shared secret"。shared secret是一個密碼,伺服器在驗證auto-renewable訂閱的receipt時必須提供此密碼。這樣在與App Store之間就增加了一層額外的安全保護。2. 在iTunes Connect中新增並配置一項新的auto-renewable訂閱類型3. 修改伺服器的receipt驗證代碼,在發送到App Store的receipt JSON資料中增加shared secret。伺服器的驗證代碼必須解析App Store的響應資料,以確定訂閱是否到期。如果訂閱被使用者更新,App Store會返回最新的receipt給你的伺服器。
設計你的iOS用戶端應用多數情況下,iOS應用只需要很小的修改,就能支援auto-renewable訂閱。實際上,用戶端應用現在變得更加簡單,因為你可以使用相同的代碼還原auto-renewable訂閱,做法和還原非消耗型product一樣:應用在訂閱更新時,會接收到獨立的transaction,應用只需單獨驗證每個receipt即可。
驗證Auto-renewable訂閱Receipt和前面驗證Store Receipts幾乎相同。建立JSON對象,並POST到App Store。唯一的區別是增加第二個域:shared secret,也就是你在iTunes Connect建立的那個{ "receipt-data" : "(actual receipt bytes here)" "password" : "(shared secret bytes here)"}響應包含一個status域,表示receipt是否通過驗證{ "status" : 0, "receipt" : { ... } "latest_receipt" : "(base-64 encoded receipt)" "latest_receipt_info" : { ... }}如果使用者的receipt合法,而且是活躍的訂閱,status域為0,receipt域包含解碼後的receipt資料。如果伺服器接收到的status為非0值,可對應以下錯誤碼,來解析相應的錯誤。
| Status |
描述 |
| 21000 |
App Store不能讀取你提供的JSON對象 |
| 21002 |
receipt-data域的資料有問題 |
| 21003 |
receipt無法通過驗證 |
| 21004 |
提供的shared secret不匹配你帳號中的shared secret |
| 21005 |
receipt伺服器當前不可用 |
| 21006 |
receipt合法,但是訂閱已到期。伺服器接收到這個狀態代碼時,receipt資料仍然會解碼並一起發送 |
| 21007 |
receipt是Sandbox receipt,但卻發送至生產系統的驗證服務 |
| 21008 |
receipt是生產receipt,但卻發送至Sandbox環境的驗證服務 |
注意:這裡的狀態代碼只能用於Auto-renewable訂閱,其它類型的product不能使用這些狀態代碼進行判斷App Store返回給你的伺服器的JSON對象的receipt資料中,除了前面說過的幾個鍵,增加或修改了以下幾個鍵:
| 鍵 |
描述 |
| expires_date |
訂閱receipt的到期日期,GMT至今的秒數,還原交易時不包含這個鍵 |
| original_transaction_id |
最初購買時的transaction ID,隨後的訂閱更新和還原都共用這個ID |
| original_purchase_date |
最初購買的日期,表示訂閱的起始日期 |
| purchase_date |
交易支付發生的日期,對於renewable訂閱,這也可能是最近一次訂閱更新的日期。 |
另外JSON還包含兩個額外的域:latest_receipt、latest_expired_receipt_info,這兩個都是receipt對象,你的伺服器可以使用這兩個域來記錄最近的訂閱更新。
還原Auto-Renewable訂閱App Store在每次更新訂閱時都會建立獨立的transaction。你的應用還原之前的購買時,Store Kit會把所有transaction都傳遞給應用。因此應用需要組合每個transaction的購買日期與訂閱長度,然後確定該receipt是否合法。FROM:http://blog.csdn.net/kevin_zqw/article/details/6973473