最近看了內購相關的東西,發現坑還真是不少,這裡做個總結。
蘋果內購的主要流程:
獲取商品資訊 --> 建立交易 --> 把交易新增到佇列 --> 交易成功獲取憑證 --> 拿著憑證做二次驗證 --> 交易成功通過產品id獲取商品資訊(skproduct)。
#import //把商品id資訊放入乙個集合中
nsset *sets = [nsset setwithobjects:@"phonicsphase1", nil];
//請求內購商品資訊,只返回你請求的產品(主要用於驗證商品的有效性)
skproductsrequest *productrequest = [[skproductsrequest alloc] initwithproductidentifiers:sets];
productrequest.delegate = self;
[productrequest start];
#pragma mark - 獲取商品id成功的**方法
- (void)productsrequest:(skproductsrequest *)request didreceiveresponse:(skproductsresponse *)response
拿到商品資訊,建立支付物件(skmutablepayment)。
- (void)startpaymentwithproduct:(skproduct *)product
把當前交易新增到交易佇列中去(上面的addpayment:方法)。
//首先我們要在 viewdidload 方法中新增監聽物件
[[skpaymentqueue defaultqueue] addtransactionobserver:self];
#pragma mark - 監聽的**方法
- (void)paymentqueue:(skpaymentqueue *)queue updatedtransactions:(nsarray *)transactions
break;
case skpaymenttransactionstatepurchased:
break;
case skpaymenttransactionstatefailed:
break;
case skpaymenttransactionstaterestored:
break;
case skpaymenttransactionstatedeferred:
break;
default:
break;
}}];
}
注意:
[[skpaymentqueue defaultqueue] finishtransaction:transation]
如果不呼叫這個方法,那麼transation
就永遠不會結束。也就是說每次進來都會重新呼叫updatedtransactions
這個方法,就算你做過二次校驗都沒用。
二次校驗只會校驗你的憑證是不是有效,不會關心你這個憑證是不是校驗過了,所以說,乙個憑證可以被校驗多次(這是刷單方法之一)
上面說過,如果不finishtransaction
,每次進入這個介面都會呼叫監聽方法,但是注意了每次返回的 reciptdata都是不一樣,即使是同乙個訂單。也就是說,同乙個訂單也有可能有多個reciptdata
,所以它並不能用來確定是哪個訂單。
我們從沙盒中取到憑證(recipt),傳送給我們自己後台進行二次驗證,驗證成功表示支付成功。
- (void)checkreceipt:(nsstring *)receipt else
} failure:^(id error) ];
}
,]}
}
當status
不為0的時候,是沒有其餘的json資料的。
21002 receipt-data 域的資料有問題
21003 receipt 無法通過驗證
21004 提供的 shared secret 不匹配你賬號中的 shared secret
21005 receipt 伺服器當前不可用
21006 receipt 合法, 但是訂閱已過期. 伺服器接收到這個狀態碼時, receipt 資料仍然會解碼並一起傳送
21007 receipt 是 sandbox receipt, 但卻傳送至生產系統的驗證服務
21008 receipt 是生產 receipt, 但卻傳送至 sandbox 環境的驗證服務
蘋果的iap缺陷還是很明顯的,但是沒辦法,誰讓蘋果一家獨大呢,我們也只能吐吐槽,想盡一切辦法防止掉單的發生。
掉單的原因是有多方面的,我們乙個個來說。
可以傳遞給後台未知訂單
,但客戶投訴的時候,我們從未知訂單裡面找到符合條件的給恢復訂單資訊(這樣做顯然效率很低)
常用的做法是:
其實這個問題始終沒有乙個很好的解決方案,只能靠蘋果的優化了。
由於蘋果的伺服器在美帝,所以延遲的情況還是很嚴重的,這時候如果是請求超時,我們伺服器又沒有收到**,那麼就會產生掉單。比較坑的是,updatedtransactions:
注意:
掉單問題都是出現在支付完成之後,沒有通過二次校驗的時候。因為一旦我們得到了recipt
,就說明蘋果已經扣款成功了。但是為什麼我們不能以這個作為支付成功的標準呢,請看下面的刷單系列。
針對上面第二種recipt
存本地的方法,其實沒有必要,蘋果自己的補單措施基本上是夠用了。
刷單的**這篇部落格,我在這裡簡述一下,做個小結。
刷單主要有以下幾種方式:
破解iap
重複使用recipt-data
信用卡黑卡
外幣差價
以及蘋果對小額消費不做驗證規則的「36技術」
我們這裡只討論 1 和 2 ,因為下面三種跟我們開發者沒有關係,想要詳細了解的可以去開頭的部落格上了解一下。
1. 破解iap
2. 重複使用recipt-data
我們直到,recipt-data
是支付成功返回給我們的校驗憑證,前面說過,蘋果校驗的時候只負責校驗recipt的有效性和真假,並不負責這個憑證是否被用過。如果我們在後台只判斷status == 0
,而不去做其他判斷的話,非法使用者會儲存recipt-data
,然後多次使用,因為每次都是校驗通過的。
我們也不能判斷recipt-data
是否被使用,因為上面已經說過,同乙個訂單也會有多個recipt-data
返回的。
防範的方法是在確定status值為0後,進一步解析出資料中的transaction_id並存入資料庫。每次發貨前先檢查資料庫中是否已經有本次的transaction_id存在,如果已存在則拒絕發貨。
到了這裡iap基本上已經結束了,這裡只是把iap的流程以及需要注意的點列出來,以上的方法只是作為總結,並不適用於所有狀況,我們在開發中還要具體問題具體分析。希望大家開發中都不會掉單
PHP實現蘋果 IOS 內購 IAP
反反覆覆經過多次重寫 內部需要 發現蘋果使用php來驗證蘋果內購資料是否正確並不是一件很難的事情。我把我的一些心得寫出來,以供以後有這方面需求的小夥伴參考,以php語言為例,誰讓php是最好的語言呢!首先要知道蘋果內購分沙箱環境和正式環境,兩者區別就是名字不同,請求是需要攜帶的引數是相同的。最重要的...
iOS應用內支付 IAP 的那些坑
猿題庫現在推出了公 行測和申論2個產品,均包括web,ios和android三個平台。這次我們嘗試做乙個收費的產品,所以在ios端整合了應用內支付 iap 功能。在開發過程中和上線後,我們遇到了iap中的一些坑,在此分享給各位。iap 審核相關的坑 iap開發的詳細步驟我寫在另一篇部落格中了。在此主...
ios 內購資料
如果您正在尋找乙份手把手教你實現iap的教程的話,這篇文章不是您的菜。關於iap的實現和步驟,可以參考下面的教程 和相應的 ray wenderlich的 一篇 並茂的 中文教程 直接使用大神們封好的store有關的庫,比如 mattt cargobay robotmedia rmstore 或者m...