首先,你要想找到這個SDK,都得費點功夫。如今的SDK更名叫移動支付集成開發包了。web
https://b.alipay.com/order/productDetail.htm?productId=2013080604609654&tabId=4#ps-tabinfo-hash算法
Baidu和Googlep排在前面的支付寶開放平臺,裏面的SDK已是2年前的版本了,並且還不支持64位架構。
壓縮包裏有兩個相關文檔 :安全
《支付寶錢包支付接口開發包2.0標準版.pdf》服務器
《支付寶錢包支付接口開發包2.0標準版接入與使用規則.pdf》網絡
iOS相關內容能夠主要看第一個文檔,第二個文檔名字和裏面寫的不同,內容實際上是個附錄;文檔裏面多個平臺都涉及到了,內容有些雜亂。下面先解釋下總體SDK的流程和要作的事,就好對症下藥找文檔內相應的內容了。架構
摘自第一個文檔《支付寶錢包支付接口開發包2.0標準版.pdf》app
圖中的「商戶客戶端」就是咱們的iOS客戶端須要作的事情:測試
調用支付寶支付接口編碼
處理支付寶返回的支付結果加密
在調用支付寶支付接口前,咱們還須要先生成一個訂單,文檔中描述時,是將這步也放在客戶端來作了,但也能夠在服務器端生成這個訂單(圖中支付寶會在支付成功後通知服務器端,因此在服務器端生成訂單的話,你能夠掌握全部訂單,並且也會更安全):
生成訂單(能夠在iOS客戶端內生成,也能夠在服務器端生成)
調用支付寶支付接口,發送訂單
處理支付寶返回的支付結果
其實對於業務來講,這些步驟已經夠了,可是有一個安全性問題,你確定不但願你接收到的支付結果被截獲修改,因此,這就須要在生成訂單和處理支付結果的時候作一個安全性校驗:
生成訂單時對數據簽名,收到支付結果時對數據進行簽名驗證,以檢驗數據是否被篡改過。
支付寶目前只支持採用RSA加密方式作簽名驗證。
RSA加密算法 除了可加解密外,還可用來做簽名校驗。 簡單的說,RSA會生成一個私鑰和一個公鑰,私鑰你應該獨自保管,公鑰你能夠分發出去。 作簽名驗證時,你能夠用私鑰對須要傳輸的數據作簽名加密,生成一個簽名值,以後分發數據,接收方經過公鑰對簽名值作校驗,若是一致則認爲數據無篡改。
具體到支付寶使用RSA作簽名驗證,就是在生產訂單時,須要使用私鑰生成簽名值;在處理返回的支付結果時,須要使用公鑰驗證返回結果是否被篡改了。
具體須要對哪些值,怎樣生成簽名,對哪些值最簽名驗證,能夠在第一個文檔中找找,後面我會簡單提一下,但仍是以文檔或實踐爲準吧。
清楚了流程後,就好理解怎麼集成了。
若是隻須要發送訂單和處理支付返回結果,只須要添加AlipaySDK.bundle和AlipaySDK.framework就好了。
這裏再吐槽下,以前用的舊版本,和如今的版本相比,還不光是把類名字給改了,原先是用的類方法,如今新版又給改爲了單例了。。還真是任性啊,這要是哪家小廠的SDK,估計早被棄用了把。。
發送訂單的方法:
- (void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;
若是手機內沒安裝支付寶的app,會直接展示支付寶web支付界面,經過callback返回支付結果;
若是手機內安裝了支付寶的app,會跳轉到支付寶的app支付,而後經過openURL的回調返回支付結果。
支付寶的SDK只給了一個處理返回結果的方法,而不像其餘第三方的SDK提供一個處理openURL的方法,因此你須要經過DEMO或者在第二個文檔裏找處處理openURL的方式:
if ([url.host isEqualToString:@"safepay"]) { [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { NSLog(@"result = %@",resultDic); }]; }
SDK也提供了一個處理openURL返回結果的方法
- (void)processOrderWithPaymentResult:(NSURL *)resultUrl standbyCallback:(CompletionBlock)completionBlock;
兩個回調block都統必定義爲typedef void(^CompletionBlock)(NSDictionary *resultDic);,
返回了一個字典,可是SDK裏徹底沒有提示有哪些key。。
你能夠在文檔裏找到,或者本身實際試一下,返回的信息以下:
resultStatus,狀態碼,SDK裏沒對應信息,第一個文檔裏有提到:
9000 訂單支付成功 8000 正在處理中 4000 訂單支付失敗 6001 用戶中途取消 6002 網絡鏈接出錯
memo, 提示信息,好比狀態碼爲6001時,memo就是「用戶中途取消」。但千萬別徹底依賴這個信息,若是未安裝支付寶app,採用網頁支付時,取消時狀態碼是6001,但這個memo是空的。。(當我發現這個問題的時候,我就決定,對於這麼不靠譜的SDK,仍是儘可能靠本身吧。。)
result,訂單信息,以及簽名驗證信息。若是你不想作簽名驗證,那這個字段能夠忽略了。。
若是你對支付的安全性不那麼在乎或重視的話,到這裏就能夠完成支付寶的集成了。
若是想更加安全,仍是須要增長下面的簽名驗證的。
首先,RSA只是一種算法,因此你可使用任何一種開源的、或者本身去實現這個算法來實現簽名和驗證的目的。
在整個流程當中,由於涉及到了RSA公鑰、私鑰的生產,RSA的簽名、驗證簽名,SHA1值的計算,base64和URL編碼,因此支付寶用了一個開源的代碼來統一解決這些問題,就是openssl(順便再吐槽下,這DEMO裏一放openssl,不知道又會引來多少公司的產品裏使用openssl了,估計阿里本身也沒少用,何時都能跟老羅、華爲同樣去贊助點呢。。)
若是你想省事,也用openssl,那你須要把這些東西都加入到項目中:DEMO中的openssl目錄頭文件,兩個庫文件libcrypto.a libssl.a,DEMO裏支付寶本身寫的Util目錄
上面說了,訂單簽名應該用私鑰,可是把私鑰放到app裏其實自己就不安全,由於你的app是分發到用戶手裏的,私鑰應該放在本身的手裏,分發出去的應該是公鑰。
因此私鑰最好是放在本身的服務器上,訂單加密這個工做放在服務器端來作,服務器將包含簽名的訂單信息返回給app,app再經過SDK發送給支付寶,這樣會更安全些;並且服務器也能掌握全部的訂單情況。
若是你非要將私鑰集成到app裏,那能夠參考SDK的DEMO,由於這個DEMO就是在app本地經過私鑰作的訂單簽名。。
上面的回調block提到了返回的內容,返回的支付結果中的result字段裏是帶有訂單信息和簽名信息的,因此簽名驗證就是須要這個字段的值。
文檔中有一個這個字段的例子,實際結果沒有換行,我換一下行便於閱讀:
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後面雙引號內的內容,注意簽名的結尾也是=,因此不要用split字符串的方式提取
若是你想簡單,能夠直接使用Util目錄下的DataVerifier來做簽名驗證
- (BOOL)verifyString:(NSString *)string withSign:(NSString *)signString; 第一個參數就是訂單信息,第二個參數就是簽名值。
其實不使用openssl,用其餘第三方RSA的開源代碼也是能夠的。能夠看下DEMO裏openssl_wrapper的源碼和SDK的文檔。
對於訂單信息,先作一個base64編碼(DEMO中這個還要調openssl來實現。。),再計算SHA1的值(這個也能夠徹底不用openssl,蘋果的庫中都有的。。),而後再簽名比對。
對於公鑰,若是使用其餘第三方代碼,須要注意格式問題。支付寶的DEMO實現中,是把這個公鑰又轉回成openssl生成的本地文件格式,而後再寫入本地文件,再讓openssl讀取出來使用。。
以上,就是支付寶 iOS SDK的一些介紹。
整體來講,我以爲能靠本身處理的地方仍是儘可能不要依賴這個不太靠譜的SDK了。