沒想到,支付寶的SDK是我目前用過的所有第三方SDK中最難用的一個了。
下載
首先,你要想找到這個SDK,都得費點功夫。現(xiàn)在的SDK改名叫移動支付集成開發(fā)包了,下載頁面在 這里 的 “請點此下載集成開發(fā)包”
Baidu和Googlep排在前面的支付寶開放平臺,里面的SDK已經(jīng)是2年前的版本了,而且還不支持64位架構(gòu)。
文檔
壓縮包里有兩個相關(guān)文檔 :
《支付寶錢包支付接口開發(fā)包2.0標(biāo)準(zhǔn)版.pdf》
《支付寶錢包支付接口開發(fā)包2.0標(biāo)準(zhǔn)版接入與使用規(guī)則.pdf》
iOS相關(guān)內(nèi)容可以主要看第一個文檔,第二個文檔名字和里面寫的不一樣,內(nèi)容其實是個附錄;文檔里面多個平臺都涉及到了,內(nèi)容有些雜亂。下面先解釋下整體SDK的流程和要做的事,就好對癥下藥找文檔內(nèi)相應(yīng)的內(nèi)容了。
流程
摘自第一個文檔《支付寶錢包支付接口開發(fā)包2.0標(biāo)準(zhǔn)版.pdf》

圖中的“商戶客戶端”就是我們的iOS客戶端需要做的事情:
- 調(diào)用支付寶支付接口
- 處理支付寶返回的支付結(jié)果
在調(diào)用支付寶支付接口前,我們還需要先生成一個訂單,文檔中描述時,是將這步也放在客戶端來做了,但也可以在服務(wù)器端生成這個訂單(圖中支付寶會在支付成功后通知服務(wù)器端,所以在服務(wù)器端生成訂單的話,你可以掌握所有訂單,而且也會更安全):
- 生成訂單(可以在iOS客戶端內(nèi)生成,也可以在服務(wù)器端生成)
- 調(diào)用支付寶支付接口,發(fā)送訂單
- 處理支付寶返回的支付結(jié)果
其實對于業(yè)務(wù)來說,這些步驟已經(jīng)夠了,但是有一個安全性問題,你肯定不希望你接收到的支付結(jié)果被截獲修改,所以,這就需要在生成訂單和處理支付結(jié)果的時候做一個安全性校驗:
生成訂單時對數(shù)據(jù)簽名,收到支付結(jié)果時對數(shù)據(jù)進(jìn)行簽名驗證,以檢驗數(shù)據(jù)是否被篡改過。
支付寶目前只支持采用RSA加密方式做簽名驗證。
RSA加密算法 除了可加解密外,還可用來作簽名校驗。
簡單的說,RSA會生成一個私鑰和一個公鑰,私鑰你應(yīng)該獨自保管,公鑰你可以分發(fā)出去。
做簽名驗證時,你可以用私鑰對需要傳輸?shù)臄?shù)據(jù)做簽名加密,生成一個簽名值,之后分發(fā)數(shù)據(jù),接收方通過公鑰對簽名值做校驗,如果一致則認(rèn)為數(shù)據(jù)無篡改。
具體到支付寶使用RSA做簽名驗證,就是在生產(chǎn)訂單時,需要使用私鑰生成簽名值;在處理返回的支付結(jié)果時,需要使用公鑰驗證返回結(jié)果是否被篡改了。
具體需要對哪些值,怎樣生成簽名,對哪些值最簽名驗證,可以在第一個文檔中找找,后面我會簡單提一下,但還是以文檔或?qū)嵺`為準(zhǔn)吧。
集成
清楚了流程后,就好理解怎么集成了。
支付SDK
如果只需要發(fā)送訂單和處理支付返回結(jié)果,只需要添加AlipaySDK.bundle和AlipaySDK.framework就行了。
這里再吐槽下,之前用的舊版本,和現(xiàn)在的版本相比,還不光是把類名字給改了,原先是用的類方法,現(xiàn)在新版又給改成了單例了。。還真是任性啊,這要是哪家小廠的SDK,估計早被棄用了把。。
發(fā)送訂單的方法:
- (void)payOrder:(NSString *)orderStr
fromScheme:(NSString *)schemeStr
callback:(CompletionBlock)completionBlock;
- 如果手機內(nèi)沒安裝支付寶的app,會直接展現(xiàn)支付寶web支付界面,通過callback返回支付結(jié)果;
- 如果手機內(nèi)安裝了支付寶的app,會跳轉(zhuǎn)到支付寶的app支付,然后通過openURL的回調(diào)返回支付結(jié)果。
支付寶的SDK只給了一個處理返回結(jié)果的方法,而不像其他第三方的SDK提供一個處理openURL的方法,所以你需要通過DEMO或者在第二個文檔里找到處理openURL的方式:
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url
standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
}]; }
SDK也提供了一個處理openURL返回結(jié)果的方法
- (void)processOrderWithPaymentResult:(NSURL *)resultUrl
standbyCallback:(CompletionBlock)completionBlock;
兩個回調(diào)block都統(tǒng)一定義為typedef void(^CompletionBlock)(NSDictionary *resultDic);,
返回了一個字典,但是SDK里完全沒有提示有哪些key。。
你可以在文檔里找到,或者自己實際試一下,返回的信息如下:
- resultStatus,狀態(tài)碼,SDK里沒對應(yīng)信息,第一個文檔里有提到:
- 9000 訂單支付成功
- 8000 正在處理中
- 4000 訂單支付失敗
- 6001 用戶中途取消
- 6002 網(wǎng)絡(luò)連接出錯
- memo, 提示信息,比如狀態(tài)碼為6001時,memo就是“用戶中途取消”。但千萬別完全依賴這個信息,如果未安裝支付寶app,采用網(wǎng)頁支付時,取消時狀態(tài)碼是6001,但這個memo是空的。。(當(dāng)我發(fā)現(xiàn)這個問題的時候,我就決定,對于這么不靠譜的SDK,還是盡量靠自己吧。。)
- result,訂單信息,以及簽名驗證信息。如果你不想做簽名驗證,那這個字段可以忽略了。。
如果你對支付的安全性不那么在意或重視的話,到這里就可以完成支付寶的集成了。
如果想更加安全,還是需要增加下面的簽名驗證的。
簽名驗證
首先,RSA只是一種算法,所以你可以使用任何一種開源的、或者自己去實現(xiàn)這個算法來實現(xiàn)簽名和驗證的目的。
在整個流程當(dāng)中,因為涉及到了RSA公鑰、私鑰的生產(chǎn),RSA的簽名、驗證簽名,SHA1值的計算,base64和URL編碼,所以支付寶用了一個開源的代碼來統(tǒng)一解決這些問題,就是openssl(順便再吐槽下,這DEMO里一放openssl,不知道又會引來多少公司的產(chǎn)品里使用openssl了,估計阿里自己也沒少用,什么時候都能跟老羅、華為一樣去贊助點呢。。)
如果你想省事,也用openssl,那你需要把這些東西都加入到項目中:DEMO中的openssl目錄頭文件,兩個庫文件libcrypto.a libssl.a,DEMO里支付寶自己寫的Util目錄
訂單簽名
上面說了,訂單簽名應(yīng)該用私鑰,但是把私鑰放到app里其實本身就不安全,因為你的app是分發(fā)到用戶手里的,私鑰應(yīng)該放在自己的手里,分發(fā)出去的應(yīng)該是公鑰。
所以私鑰最好是放在自己的服務(wù)器上,訂單加密這個工作放在服務(wù)器端來做,服務(wù)器將包含簽名的訂單信息返回給app,app再通過SDK發(fā)送給支付寶,這樣會更安全些;而且服務(wù)器也能掌握所有的訂單狀況。
如果你非要將私鑰集成到app里,那可以參考SDK的DEMO,因為這個DEMO就是在app本地通過私鑰做的訂單簽名。。
支付結(jié)果簽名驗證
上面的回調(diào)block提到了返回的內(nèi)容,返回的支付結(jié)果中的result字段里是帶有訂單信息和簽名信息的,所以簽名驗證就是需要這個字段的值。
文檔中有一個這個字段的例子,實際結(jié)果沒有換行,我換一下行便于閱讀:
partner="2088101568358171"&seller_id="xxx@alipay.com"&out_trade_no="0819145412-6177"&subject="測試"&body="測試測試"&total_fee="0.01"¬ify_url="http://notify.msp.hk/notify.htm"&service="mobile.securitypay.pay"&payment_type="1"&_input_charset="utf-8"&it_b_pay="30m"&success="true"
&sign_type="RSA"
&sign="hkFZr+zE9499nuqDNLZEF7W75RFFPsly876QuRSeN8WMaUgcdR00IKy5ZyBJ4eldhoJ/2zghqrD4E2G2mNjs3aE+HCLiBXrPDNdLKCZ gSOIqmv46TfPTEqopYfhs+o5fZzXxt34fwdrzN4mX6S13cr3UwmEV4L3Ffir/02RBVtU="
總共分為三個部分
- 第一部分是訂單信息,每個字段的具體含義可以在文檔里找;
- 中間
sign_type是簽名用的算法,文檔里說了,目前只支持RSA; - 最后的
sign就是簽名值。
驗證的步驟如下:
- 首先把訂單信息和簽名值分別提取出來(SDK居然都不給處理好。。)
- 訂單信息就是
sign_type的連字符&之前的所有字符串 - 簽名值是
sign后面雙引號內(nèi)的內(nèi)容,注意簽名的結(jié)尾也是=,所以不要用split字符串的方式提取
- 訂單信息就是
- 如果你想簡單,可以直接使用
Util目錄下的DataVerifier來作簽名驗證- (BOOL)verifyString:(NSString *)string withSign:(NSString *)signString;- 第一個參數(shù)就是訂單信息,第二個參數(shù)就是簽名值。
其實不使用
openssl,用其他第三方RSA的開源代碼也是可以的??梢钥聪翫EMO里openssl_wrapper的源碼和SDK的文檔。
- 對于訂單信息,先做一個base64編碼(DEMO中這個還要調(diào)
openssl來實現(xiàn)。。),再計算SHA1的值(這個也可以完全不用openssl,蘋果的庫中都有的。。),然后再簽名比對。- 對于公鑰,如果使用其他第三方代碼,需要注意格式問題。支付寶的DEMO實現(xiàn)中,是把這個公鑰又轉(zhuǎn)回成
openssl生成的本地文件格式,然后再寫入本地文件,再讓openssl讀取出來使用。。
以上,就是支付寶 iOS SDK的一些介紹。
總體來說,我覺得能靠自己處理的地方還是盡量不要依賴這個不太靠譜的SDK了。。