點擊IOS IAP APP內支付 Java服務端代碼直接跳轉到示例點擊直接跳轉到示例
iap簡介
在應用中內嵌Store,在iOS應用中使用Store Kit framework來實現In-App Purchase。Store Kit會連接App Store,代替應用安全地完成用戶支付。Store Kit提示用戶授權支付,然后通知應用“用戶已經完成支付”,這樣應用就可以提供用戶購買的東西。
使用iap可以為應用的增強功能,或額外內容進行收費,如以下場景:
- 基礎版本的應用,購買額外的特性
- 書籍閱讀器應用,允許用戶購買和下載新的書籍
- 游戲,提供新的環境(場景、關卡、等級等)
- 在線游戲,允許玩家購買虛擬財產(金幣、道具、裝備等)
- 數字雜志或newsletter訂閱
Products
- 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都已經包含在應用中。這個模型主要用於應用解鎖相關的功能。也可以使用這個模型來交付應用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來通知應用請求結果。如下圖所示:

SKRequest
SKRequest是一個抽象基類,用於向Store發送請求
SKRequestDelegate
SKRequestDelegate是一個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中標記為可以銷售。
SKProductsRequest
SKProductsRequest對象使用一組product ID來創建,這些是你想要顯示給用戶的product列表
SKProductsRequestDelegate
SKProductsRequestDelegate協議需要應用來實現,用於獲取Store的響應信息。請求成功處理后,會異步地接收App Store的響應信息
SKProductsResponse
SKProductsResponse對象是返回的結果信息,請求列表中的每個合法的product ID都有一個相應的SKProduct對象;同時還包含Store不能識別的一組product ID列表。不能識別的原因有許多:ID拼寫錯誤、標記為不可銷售、iTunes Connect中的修改還沒有傳送到其它App Store服務器等
SKProduct
SKProduct對象提供你在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方法。
SKPaymentQueue
payment隊列用來與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的詳細步驟如下:
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/verifyReceipt
4. 從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創建的那個
shared secret的具體位置:
進入iTunes- 應用 - manage In-App Purchases - 點擊下方的
View or generate a shared secret
{
"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是否合法。
上面內容基本來自iOS Developer Library的《In-App Purchase Programming Guide》
這里再附上一篇CocoaChina論壇版主lvyile寫的《關於IAP防止破解的幾點》