前言
目前有很多關于iOS內購帖子及開源項目,但是沒有一個相對合適自己項目的,所以就多研究下.主要還是因為蘋果的IAP太坑了,所以筆者自己基于目前網上的部分代碼以及平時項目的BUG反饋封裝了一套內購方案和大家分享探討.
內購的坑
其實蘋果的IAP還是做了很多操作了,但是現實用起來發現還是有很多坑爹的地方,防不勝防.由于自己項目須在IAP進行前就需要獲取一個自己服務器的訂單才能進行IAP購買驗證,所以會出現以下幾個問題:
- 用戶購買,IAP無回調響應,用戶退出程序導致定單異常.
- 原因:用戶雖然點擊了購買就儲存了訂單,但是還沒有進入了蘋果的內購隊列,所以用戶退出后再次進入本地就會有個僵尸訂單,無法清除.所以儲存訂單應該在
- 解決辦法:SKPaymentTransactionStatePurchasing時才儲存.
- 用戶完成蘋果購買,自己的服務器網絡發生錯誤,無法及時到賬.
- 原因:一般是因為在SKPaymentTransactionStatePurchased后就結束訂單了,自己的儲存方案有異常.
- 解決辦法:在沒有自己服務器得到驗證訂單狀態前就不finish訂單,程序再啟動或者再次監聽IPA時蘋果會再次通過
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction
回調未結束的訂單,即使重新安裝程序也會有回調.
- SKPaymentTransaction.applicationUsername丟失,程序崩潰.
- 原因:applicationUsername丟失的問題相信很多開發者都遇到過...蘋果坑逼.
- 解決辦法:通過對比UserID以及productIdentifier來確定一個以前在SKPaymentTransactionStatePurchasing時儲存的訂單.看似有點問題,但是因為蘋果的交易是串行的,如果自己驗證也是串行驗證,那么通過UserID和productIdentifier就能確定為同一個訂單了.
- 用戶卸載程序導致本地訂單號丟失.
- 原因:購買訂單時的數據存儲在本地,刪除應用就丟失.
- 解決辦法:通過儲存在keychain里面防止丟失.
- 獲取本地蘋果票據為空.
- 原因:有可能刪除應用后重新安裝,這個時候本地票據可能是空的,導致驗證失敗.
- 解決方法:通過SKReceiptRefreshRequest刷新票據得到最新的蘋果票據.
由于內購的地方很多,為此封裝了一套JKIAPHelp用于快速接入.
JKIAPHelp基本邏輯:
- 用戶注冊后,開始購買商品,把自己服務器上的訂單號傳給JKIAPHelp.
- JKIAPHelp在系統支付回調
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction
SKPaymentTransactionStatePurchasing時將訂單相關信息(訂單號以及物品價格)加入到鑰匙串中保證訂單信息的完整性與可靠性.
- 在SKPaymentTransactionStatePurchased的時候來驗證訂單.驗證是通過開發者實現JKIAPHelp代理
-(void)verifyWithModel:(JKIAPTransactionModel *)model resultAction:(VerifyRsultBlock)resultAction
來向開發者自己的服務器完成訂單的驗證.(開發者通過調用resultAction回調服務器驗證狀態).
- 如果驗證出現失效或者完成,那么就判斷當前的用戶是否和創建訂單時候的用戶一致,如果一致那么久刪除鑰匙串里對應的訂單完成購買,不一致的話就將狀態同步到鑰匙串里,當下一次用戶注冊時通過補發貨的回調來通知開發者.
- 如果服務器驗證網絡錯誤,就同步鑰匙串訂單狀態.當用戶點擊購買,從后臺進入程序,重新注冊JKIAP時就會檢測當前未完成的訂單,將未完成的訂單再次驗證,如果再次發生錯誤就下一次再驗證,有多個未完成的話就繼續驗證下一個訂單.