沒(méi)想到法精,支付寶的SDK是我目前用過(guò)的所有第三方SDK中最難用的一個(gè)了。
下載
首先系馆,你要想找到這個(gè)SDK送漠,都得費(fèi)點(diǎn)功夫。現(xiàn)在的SDK改名叫移動(dòng)支付集成開(kāi)發(fā)包了由蘑,下載頁(yè)面在 這里 的 “請(qǐng)點(diǎn)此下載集成開(kāi)發(fā)包”
Baidu和Googlep排在前面的支付寶開(kāi)放平臺(tái)闽寡,里面的SDK已經(jīng)是2年前的版本了,而且還不支持64位架構(gòu)尼酿。
文檔
壓縮包里有兩個(gè)相關(guān)文檔 :
《支付寶錢包支付接口開(kāi)發(fā)包2.0標(biāo)準(zhǔn)版.pdf》
《支付寶錢包支付接口開(kāi)發(fā)包2.0標(biāo)準(zhǔn)版接入與使用規(guī)則.pdf》
iOS相關(guān)內(nèi)容可以主要看第一個(gè)文檔爷狈,第二個(gè)文檔名字和里面寫的不一樣,內(nèi)容其實(shí)是個(gè)附錄裳擎;文檔里面多個(gè)平臺(tái)都涉及到了涎永,內(nèi)容有些雜亂。下面先解釋下整體SDK的流程和要做的事鹿响,就好對(duì)癥下藥找文檔內(nèi)相應(yīng)的內(nèi)容了羡微。
流程
摘自第一個(gè)文檔《支付寶錢包支付接口開(kāi)發(fā)包2.0標(biāo)準(zhǔn)版.pdf》
圖中的“商戶客戶端”就是我們的iOS客戶端需要做的事情:
- 調(diào)用支付寶支付接口
- 處理支付寶返回的支付結(jié)果
在調(diào)用支付寶支付接口前,我們還需要先生成一個(gè)訂單惶我,文檔中描述時(shí)拷淘,是將這步也放在客戶端來(lái)做了,但也可以在服務(wù)器端生成這個(gè)訂單(圖中支付寶會(huì)在支付成功后通知服務(wù)器端指孤,所以在服務(wù)器端生成訂單的話启涯,你可以掌握所有訂單,而且也會(huì)更安全):
- 生成訂單(可以在iOS客戶端內(nèi)生成恃轩,也可以在服務(wù)器端生成)
- 調(diào)用支付寶支付接口结洼,發(fā)送訂單
- 處理支付寶返回的支付結(jié)果
其實(shí)對(duì)于業(yè)務(wù)來(lái)說(shuō),這些步驟已經(jīng)夠了叉跛,但是有一個(gè)安全性問(wèn)題松忍,你肯定不希望你接收到的支付結(jié)果被截獲修改,所以筷厘,這就需要在生成訂單和處理支付結(jié)果的時(shí)候做一個(gè)安全性校驗(yàn):
生成訂單時(shí)對(duì)數(shù)據(jù)簽名鸣峭,收到支付結(jié)果時(shí)對(duì)數(shù)據(jù)進(jìn)行簽名驗(yàn)證宏所,以檢驗(yàn)數(shù)據(jù)是否被篡改過(guò)。
支付寶目前只支持采用RSA加密方式做簽名驗(yàn)證摊溶。
RSA加密算法 除了可加解密外爬骤,還可用來(lái)作簽名校驗(yàn)。
簡(jiǎn)單的說(shuō)莫换,RSA會(huì)生成一個(gè)私鑰和一個(gè)公鑰霞玄,私鑰你應(yīng)該獨(dú)自保管,公鑰你可以分發(fā)出去拉岁。
做簽名驗(yàn)證時(shí)坷剧,你可以用私鑰對(duì)需要傳輸?shù)臄?shù)據(jù)做簽名加密,生成一個(gè)簽名值喊暖,之后分發(fā)數(shù)據(jù)惫企,接收方通過(guò)公鑰對(duì)簽名值做校驗(yàn),如果一致則認(rèn)為數(shù)據(jù)無(wú)篡改陵叽。
具體到支付寶使用RSA做簽名驗(yàn)證雅任,就是在生產(chǎn)訂單時(shí),需要使用私鑰生成簽名值咨跌;在處理返回的支付結(jié)果時(shí)沪么,需要使用公鑰驗(yàn)證返回結(jié)果是否被篡改了。
具體需要對(duì)哪些值锌半,怎樣生成簽名禽车,對(duì)哪些值最簽名驗(yàn)證,可以在第一個(gè)文檔中找找刊殉,后面我會(huì)簡(jiǎn)單提一下殉摔,但還是以文檔或?qū)嵺`為準(zhǔn)吧。
集成
清楚了流程后记焊,就好理解怎么集成了逸月。
支付SDK
如果只需要發(fā)送訂單和處理支付返回結(jié)果,只需要添加AlipaySDK.bundle
和AlipaySDK.framework
就行了遍膜。
這里再吐槽下碗硬,之前用的舊版本,和現(xiàn)在的版本相比瓢颅,還不光是把類名字給改了恩尾,原先是用的類方法,現(xiàn)在新版又給改成了單例了挽懦。翰意。還真是任性啊,這要是哪家小廠的SDK,估計(jì)早被棄用了把冀偶。醒第。
發(fā)送訂單的方法:
- (void)payOrder:(NSString *)orderStr
fromScheme:(NSString *)schemeStr
callback:(CompletionBlock)completionBlock;
- 如果手機(jī)內(nèi)沒(méi)安裝支付寶的app,會(huì)直接展現(xiàn)支付寶web支付界面进鸠,通過(guò)callback返回支付結(jié)果稠曼;
- 如果手機(jī)內(nèi)安裝了支付寶的app,會(huì)跳轉(zhuǎn)到支付寶的app支付堤如,然后通過(guò)openURL的回調(diào)返回支付結(jié)果蒲列。
支付寶的SDK只給了一個(gè)處理返回結(jié)果的方法窒朋,而不像其他第三方的SDK提供一個(gè)處理openURL的方法搀罢,所以你需要通過(guò)DEMO或者在第二個(gè)文檔里找到處理openURL的方式:
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url
standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
}]; }
SDK也提供了一個(gè)處理openURL返回結(jié)果的方法
- (void)processOrderWithPaymentResult:(NSURL *)resultUrl
standbyCallback:(CompletionBlock)completionBlock;
兩個(gè)回調(diào)block都統(tǒng)一定義為typedef void(^CompletionBlock)(NSDictionary *resultDic);
,
返回了一個(gè)字典侥猩,但是SDK里完全沒(méi)有提示有哪些key榔至。。
你可以在文檔里找到欺劳,或者自己實(shí)際試一下唧取,返回的信息如下:
- resultStatus,狀態(tài)碼划提,SDK里沒(méi)對(duì)應(yīng)信息枫弟,第一個(gè)文檔里有提到:
- 9000 訂單支付成功
- 8000 正在處理中
- 4000 訂單支付失敗
- 6001 用戶中途取消
- 6002 網(wǎng)絡(luò)連接出錯(cuò)
- memo, 提示信息鹏往,比如狀態(tài)碼為6001時(shí)淡诗,memo就是“用戶中途取消”。但千萬(wàn)別完全依賴這個(gè)信息伊履,如果未安裝支付寶app韩容,采用網(wǎng)頁(yè)支付時(shí),取消時(shí)狀態(tài)碼是6001唐瀑,但這個(gè)memo是空的群凶。。(當(dāng)我發(fā)現(xiàn)這個(gè)問(wèn)題的時(shí)候哄辣,我就決定请梢,對(duì)于這么不靠譜的SDK,還是盡量靠自己吧力穗。溢陪。)
- result,訂單信息睛廊,以及簽名驗(yàn)證信息形真。如果你不想做簽名驗(yàn)證,那這個(gè)字段可以忽略了。咆霜。
如果你對(duì)支付的安全性不那么在意或重視的話邓馒,到這里就可以完成支付寶的集成了。
如果想更加安全蛾坯,還是需要增加下面的簽名驗(yàn)證的光酣。
簽名驗(yàn)證
首先,RSA只是一種算法脉课,所以你可以使用任何一種開(kāi)源的救军、或者自己去實(shí)現(xiàn)這個(gè)算法來(lái)實(shí)現(xiàn)簽名和驗(yàn)證的目的。
在整個(gè)流程當(dāng)中倘零,因?yàn)樯婕暗搅薘SA公鑰唱遭、私鑰的生產(chǎn),RSA的簽名呈驶、驗(yàn)證簽名拷泽,SHA1值的計(jì)算,base64和URL編碼袖瞻,所以支付寶用了一個(gè)開(kāi)源的代碼來(lái)統(tǒng)一解決這些問(wèn)題司致,就是openssl(順便再吐槽下,這DEMO里一放openssl
聋迎,不知道又會(huì)引來(lái)多少公司的產(chǎn)品里使用openssl
了脂矫,估計(jì)阿里自己也沒(méi)少用,什么時(shí)候都能跟老羅霉晕、華為一樣去贊助點(diǎn)呢庭再。。)
如果你想省事娄昆,也用openssl
佩微,那你需要把這些東西都加入到項(xiàng)目中:DEMO中的openssl目錄
頭文件,兩個(gè)庫(kù)文件libcrypto.a libssl.a
萌焰,DEMO里支付寶自己寫的Util目錄
訂單簽名
上面說(shuō)了哺眯,訂單簽名應(yīng)該用私鑰,但是把私鑰放到app里其實(shí)本身就不安全扒俯,因?yàn)槟愕腶pp是分發(fā)到用戶手里的奶卓,私鑰應(yīng)該放在自己的手里,分發(fā)出去的應(yīng)該是公鑰撼玄。
所以私鑰最好是放在自己的服務(wù)器上夺姑,訂單加密這個(gè)工作放在服務(wù)器端來(lái)做,服務(wù)器將包含簽名的訂單信息返回給app掌猛,app再通過(guò)SDK發(fā)送給支付寶盏浙,這樣會(huì)更安全些;而且服務(wù)器也能掌握所有的訂單狀況。
如果你非要將私鑰集成到app里废膘,那可以參考SDK的DEMO竹海,因?yàn)檫@個(gè)DEMO就是在app本地通過(guò)私鑰做的訂單簽名。丐黄。
支付結(jié)果簽名驗(yàn)證
上面的回調(diào)block提到了返回的內(nèi)容斋配,返回的支付結(jié)果中的result
字段里是帶有訂單信息和簽名信息的,所以簽名驗(yàn)證就是需要這個(gè)字段的值灌闺。
文檔中有一個(gè)這個(gè)字段的例子艰争,實(shí)際結(jié)果沒(méi)有換行,我換一下行便于閱讀:
partner="2088101568358171"&seller_id="xxx@alipay.com"&out_trade_no="0819145412-6177"&subject="測(cè)試"&body="測(cè)試測(cè)試"&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="
總共分為三個(gè)部分
- 第一部分是訂單信息桂对,每個(gè)字段的具體含義可以在文檔里找甩卓;
- 中間
sign_type
是簽名用的算法,文檔里說(shuō)了接校,目前只支持RSA猛频; - 最后的
sign
就是簽名值狮崩。
驗(yàn)證的步驟如下:
- 首先把訂單信息和簽名值分別提取出來(lái)(SDK居然都不給處理好蛛勉。。)
- 訂單信息就是
sign_type
的連字符&
之前的所有字符串 - 簽名值是
sign
后面雙引號(hào)內(nèi)的內(nèi)容睦柴,注意簽名的結(jié)尾也是=
诽凌,所以不要用split字符串的方式提取
- 訂單信息就是
- 如果你想簡(jiǎn)單,可以直接使用
Util目錄
下的DataVerifier
來(lái)作簽名驗(yàn)證- (BOOL)verifyString:(NSString *)string withSign:(NSString *)signString;
- 第一個(gè)參數(shù)就是訂單信息坦敌,第二個(gè)參數(shù)就是簽名值侣诵。
其實(shí)不使用
openssl
,用其他第三方RSA的開(kāi)源代碼也是可以的狱窘《潘常可以看下DEMO里openssl_wrapper
的源碼和SDK的文檔。
- 對(duì)于訂單信息蘸炸,先做一個(gè)base64編碼(DEMO中這個(gè)還要調(diào)
openssl
來(lái)實(shí)現(xiàn)躬络。。)搭儒,再計(jì)算SHA1的值(這個(gè)也可以完全不用openssl
穷当,蘋果的庫(kù)中都有的。淹禾。)馁菜,然后再簽名比對(duì)。- 對(duì)于公鑰铃岔,如果使用其他第三方代碼汪疮,需要注意格式問(wèn)題。支付寶的DEMO實(shí)現(xiàn)中,是把這個(gè)公鑰又轉(zhuǎn)回成
openssl
生成的本地文件格式智嚷,然后再寫入本地文件躲胳,再讓openssl
讀取出來(lái)使用。纤勒。
以上坯苹,就是支付寶 iOS SDK的一些介紹。
總體來(lái)說(shuō)摇天,我覺(jué)得能靠自己處理的地方還是盡量不要依賴這個(gè)不太靠譜的SDK了粹湃。。