簡單-微信支付寶支付

自己總結(jié)的微信支付寶支付流程和注意點(diǎn):

準(zhǔn)備工作:

需要公司的營業(yè)執(zhí)照,稅務(wù)信息,等老板的身份證信息等,我記得,用這些材料,去支付寶注冊一個(gè)商家賬戶(審核周期大概5個(gè)工作日),或者微信的開發(fā)者賬號(hào)(審核周期大概5個(gè)工作日,300元費(fèi)用),微信的話,需要你的app已經(jīng)上架有了APPID,才能開通;大概也是5個(gè)工作日

用微信支付時(shí):用戶點(diǎn)擊支付按鈕時(shí)要先判斷有沒有安裝微信,以及當(dāng)前的微信版本是否支持支付,都滿足則進(jìn)入到微信界面,調(diào)起微信支付,在進(jìn)行微信支付的

支付文檔鏈接:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1

支付寶支付分為:支付寶有“移動(dòng)快捷支付”(支付時(shí)跳轉(zhuǎn)到支付寶APP,需要用戶安裝支付寶APP),或者“移動(dòng)WAP網(wǎng)頁支付”(支付時(shí)打開一個(gè)WebView里邊登陸支付寶進(jìn)行支付)我看到大部分app美團(tuán)大眾點(diǎn)評(píng)支付寶支付都是第二種

支付寶支付步驟:

1.先與支付寶簽約,獲得商戶ID(partner)和賬號(hào)ID(seller)

2.下載相應(yīng)的公鑰私鑰文件(用來加密簽名)

3.下載支付寶SDK

4.生產(chǎn)訂單信息(客戶端或放在服務(wù)端生成訂單號(hào),支付寶支付成功后會(huì)通知服務(wù)端,這樣在服務(wù)端生成訂單的話,可以掌握所有的訂單,而且還會(huì)更加安全)

5.調(diào)用支付寶支付接口發(fā)送訂單,由支付寶客戶端跟支付寶安全服務(wù)器打交道

6.支付完畢后返回支付結(jié)果給商戶客戶端,進(jìn)行結(jié)構(gòu)處理

安全問題:接收到的支付結(jié)果可能被截獲修改。所以,就需要在生成訂單和處理支付結(jié)果時(shí)做安全性校驗(yàn)

生成訂單時(shí)對(duì)數(shù)據(jù)簽名,收到支付結(jié)果時(shí)對(duì)數(shù)據(jù)進(jìn)行簽名驗(yàn)證,以檢驗(yàn)數(shù)據(jù)是否被篡改過。

支付寶目前只支持采用RSA加密方式做簽名驗(yàn)證。

RSA加密算法除了可加解密外,還可用來作簽名校驗(yàn)。

簡單的說,RSA會(huì)生成一個(gè)私鑰和一個(gè)公鑰,私鑰你應(yīng)該獨(dú)自保管,公鑰你可以分發(fā)出去。

做簽名驗(yàn)證時(shí),你可以用私鑰對(duì)需要傳輸?shù)臄?shù)據(jù)做簽名加密,生成一個(gè)簽名值,之后分發(fā)數(shù)據(jù),接收方通過公鑰對(duì)簽名值做校驗(yàn),如果一致則認(rèn)為數(shù)據(jù)無篡改

具體到支付寶使用RSA做簽名驗(yàn)證,就是在生產(chǎn)訂單時(shí),需要使用私鑰生成簽名值;在處理返回的支付結(jié)果時(shí),需要使用公鑰驗(yàn)證返回結(jié)果是否被篡改了。

實(shí)例代碼:

@WeakObj(self);

NDHttpRequestManage*request = [NDHttpRequestManagerequestManage];

//需要傳給支付寶的AppScheme

NSString*appScheme =@"aaa2015080600202133";

[requestuserObtainAliSign:[self.user.userIDndValue]

AndTradeNo:_tradeNo

complete:^(idcompleteObject,NSError*error )

{

@StrongObj(self);

[self.indicationstopAnimationWithLoadText:@"finish"withType:YES];

self.indication=nil;

if(!error){

//簽名信息以及訂單信息

NSString*String = [completeObjectobjectForKey:@"sign"];

NSString*orderSpec = [completeObjectobjectForKey:@"content"];

if([signisKindOfClass:[NSNullclass]] || sign ==nil){

[selfshowDissmissSelfAlertViewTitle:@""message:@"支付失敗,請(qǐng)重新嘗試。"complete:^{

}];

return;}

//urlcode加密

NSString*signedString = [selfurlEncodedString:String];

NSString*orderString ?=nil;

if(signedString !=nil){

//生成訂單信息及簽名請(qǐng)求參數(shù)

orderString = [NSStringstringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",

orderSpec, signedString,@"RSA"];

}

//調(diào)用支付寶的SDK[[AlipaySDKdefaultService]payOrder:orderStringfromScheme:appSchemecallback:^(NSDictionary*resultDic){

//resultDic ?這個(gè)字典是返回我所有的支付成功或者失敗的信息

NSString* key =@"ResultStatus";

if(![[resultDicallKeys]containsObject:key]) {

key =@"resultStatus";

}

if(key !=nil){

//返回9000 就是成功

if([[resultDicobjectForKey:key]integerValue] ==9000) {

//訂單成功.

[selfpaySuccess];

}else{

//訂單失敗.

[selfpayFailed];

}

}

}];

}

}];

-(NSString*)urlEncodedString:(NSString*)string

{

NSString* encodedString = (__bridge_transferNSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridgeCFStringRef)string,NULL, (__bridgeCFStringRef)@"!*'();:@&=+$,/?%#[]",kCFStringEncodingUTF8);

returnencodedString;

}

集成

清楚了流程后,就好理解怎么集成了。

支付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)沒安裝支付寶的app,會(huì)直接展現(xiàn)支付寶web支付界面,通過callback返回支付結(jié)果;

如果手機(jī)內(nèi)安裝了支付寶的app,會(huì)跳轉(zhuǎn)到支付寶的app支付,然后通過openURL的回調(diào)返回支付結(jié)果。

支付寶的SDK只給了一個(gè)處理返回結(jié)果的方法,而不像其他第三方的SDK提供一個(gè)處理openURL的方法,所以你需要通過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里完全沒有提示有哪些key。。

你可以在文檔里找到,或者自己實(shí)際試一下,返回的信息如下:

resultStatus,狀態(tài)碼,SDK里沒對(duì)應(yīng)信息,第一個(gè)文檔里有提到:

9000 訂單支付成功

8000 正在處理中

4000 訂單支付失敗

6001 用戶中途取消

6002 網(wǎng)絡(luò)連接出錯(cuò)

memo, 提示信息,比如狀態(tài)碼為6001時(shí),memo就是“用戶中途取消”。但千萬別完全依賴這個(gè)信息,如果未安裝支付寶app,采用網(wǎng)頁支付時(shí),取消時(shí)狀態(tài)碼是6001,但這個(gè)memo是空的。。(當(dāng)我發(fā)現(xiàn)這個(gè)問題的時(shí)候,我就決定,對(duì)于這么不靠譜的SDK,還是盡量靠自己吧。。)

result,訂單信息,以及簽名驗(yàn)證信息。如果你不想做簽名驗(yàn)證,那這個(gè)字段可以忽略了。。

如果你對(duì)支付的安全性不那么在意或重視的話,到這里就可以完成支付寶的集成了。

如果想更加安全,還是需要增加下面的簽名驗(yàn)證的。

簽名驗(yàn)證

首先,RSA只是一種算法,所以你可以使用任何一種開源的、或者自己去實(shí)現(xiàn)這個(gè)算法來實(shí)現(xiàn)簽名和驗(yàn)證的目的。

在整個(gè)流程當(dāng)中,因?yàn)樯婕暗搅薘SA公鑰、私鑰的生產(chǎn),RSA的簽名、驗(yàn)證簽名,SHA1值的計(jì)算,base64和URL編碼,所以支付寶用了一個(gè)開源的代碼來統(tǒng)一解決這些問題,就是openssl(順便再吐槽下,這DEMO里一放openssl,不知道又會(huì)引來多少公司的產(chǎn)品里使用openssl了,估計(jì)阿里自己也沒少用,什么時(shí)候都能跟老羅、華為一樣去贊助點(diǎn)呢。。)

如果你想省事,也用openssl,那你需要把這些東西都加入到項(xiàng)目中:DEMO中的openssl目錄頭文件,兩個(gè)庫文件libcrypto.a libssl.a,DEMO里支付寶自己寫的Util目錄

訂單簽名

上面說了,訂單簽名應(yīng)該用私鑰,但是把私鑰放到app里其實(shí)本身就不安全,因?yàn)槟愕腶pp是分發(fā)到用戶手里的,私鑰應(yīng)該放在自己的手里,分發(fā)出去的應(yīng)該是公鑰。

所以私鑰最好是放在自己的服務(wù)器上,訂單加密這個(gè)工作放在服務(wù)器端來做,服務(wù)器將包含簽名的訂單信息返回給app,app再通過SDK發(fā)送給支付寶,這樣會(huì)更安全些;而且服務(wù)器也能掌握所有的訂單狀況。

如果你非要將私鑰集成到app里,那可以參考SDK的DEMO,因?yàn)檫@個(gè)DEMO就是在app本地通過私鑰做的訂單簽名。。

支付結(jié)果簽名驗(yàn)證

上面的回調(diào)block提到了返回的內(nèi)容,返回的支付結(jié)果中的result字段里是帶有訂單信息和簽名信息的,所以簽名驗(yàn)證就是需要這個(gè)字段的值。

文檔中有一個(gè)這個(gè)字段的例子,實(shí)際結(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="

總共分為三個(gè)部分

第一部分是訂單信息,每個(gè)字段的具體含義可以在文檔里找;

中間sign_type是簽名用的算法,文檔里說了,目前只支持RSA;

最后的sign就是簽名值。

驗(yàn)證的步驟如下:

首先把訂單信息和簽名值分別提取出來(SDK居然都不給處理好。。)

訂單信息就是sign_type的連字符&之前的所有字符串

簽名值是sign后面雙引號(hào)內(nèi)的內(nèi)容,注意簽名的結(jié)尾也是=,所以不要用split字符串的方式提取

如果你想簡單,可以直接使用Util目錄下的DataVerifier來作簽名驗(yàn)證

- (BOOL)verifyString:(NSString *)string withSign:(NSString *)signString;

第一個(gè)參數(shù)就是訂單信息,第二個(gè)參數(shù)就是簽名值。

其實(shí)不使用openssl,用其他第三方RSA的開源代碼也是可以的??梢钥聪翫EMO里openssl_wrapper的源碼和SDK的文檔。

對(duì)于訂單信息,先做一個(gè)base64編碼(DEMO中這個(gè)還要調(diào)openssl來實(shí)現(xiàn)。。),再計(jì)算SHA1的值(這個(gè)也可以完全不用openssl,蘋果的庫中都有的。。),然后再簽名比對(duì)。

對(duì)于公鑰,如果使用其他第三方代碼,需要注意格式問題。支付寶的DEMO實(shí)現(xiàn)中,是把這個(gè)公鑰又轉(zhuǎn)回成openssl生成的本地文件格式,然后再寫入本地文件,再讓openssl讀取出來使用。。

以上,就是支付寶 iOS SDK的一些介紹。

總體來說,我覺得能靠自己處理的地方還是盡量不要依賴這個(gè)不太靠譜的SDK了。

微信支付步驟:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1#

郵件中參數(shù)API參數(shù)名詳細(xì)說明

APPIDappidappid是微信公眾賬號(hào)或開放平臺(tái)APP的唯一標(biāo)識(shí),在公眾平臺(tái)申請(qǐng)公眾賬號(hào)或者在開放平臺(tái)申請(qǐng)APP賬號(hào)后,微信會(huì)自動(dòng)分配對(duì)應(yīng)的appid,用于標(biāo)識(shí)該應(yīng)用??稍谖⑿殴娖脚_(tái)-->開發(fā)者中心查看,商戶的微信支付審核通過郵件中也會(huì)包含該字段值。

微信支付商戶號(hào)mch_id商戶申請(qǐng)微信支付后,由微信支付分配的商戶收款賬號(hào)。

API密鑰key交易過程生成簽名的密鑰,僅保留在商戶系統(tǒng)和微信支付后臺(tái),不會(huì)在網(wǎng)絡(luò)中傳播。商戶妥善保管該Key,切勿在網(wǎng)絡(luò)中傳輸,不能在其他客戶端中存儲(chǔ),保證key不會(huì)被泄漏。商戶可根據(jù)郵件提示登錄微信商戶平臺(tái)進(jìn)行設(shè)置。也可按一下路徑設(shè)置:微信商戶平臺(tái)(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置

AppsecretsecretAppSecret是APPID對(duì)應(yīng)的接口密碼,用于獲取接口調(diào)用憑證access_token時(shí)使用。

商戶系統(tǒng)和微信支付系統(tǒng)主要交互說明:

步驟1:用戶在商戶APP中選擇商品,提交訂單,選擇微信支付。

步驟2:商戶后臺(tái)收到用戶支付單,調(diào)用微信支付統(tǒng)一下單接口。參見【統(tǒng)一下單API】。

步驟3:統(tǒng)一下單接口返回正常的prepay_id,再按簽名規(guī)范重新生成簽名后,將數(shù)據(jù)傳輸給APP。參與簽名的字段名為appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式為Sign=WXPay

以上信息都是有后臺(tái)服務(wù)器調(diào)用微信的支付接口獲得并返給App端的

步驟4:商戶APP調(diào)起微信支付。api參見本章節(jié)【app端開發(fā)步驟說明

步驟5:商戶后臺(tái)接收支付通知。api參見【支付結(jié)果通知API

步驟6:商戶后臺(tái)查詢支付結(jié)果。,api參見【查詢訂單API

例子

NDHttpRequestManage*request = [NDHttpRequestManagerequestManage];

[requestuserGetWeiXinSign:[self.user.userIDndValue]AndTradeNo:_tradeNocomplete:^(idcompleteObject,NSError*error)

{

@StrongObj(self);

[self.indicationstopAnimationWithLoadText:@"finish"withType:YES];

self.indication=nil;

if(!error)

{

appDelegate.loginDone=nil;

NSString*str = completeObject[@"sign"];

[selfcheckSignFromSign:str];

NSData*jsonData = [strdataUsingEncoding:NSUTF8StringEncoding];

NSError*err;

NSDictionary*dict = [NSJSONSerializationJSONObjectWithData:jsonData

options:NSJSONReadingMutableContainers

error:&err];

NSMutableString*prepayId = [dictobjectForKey:@"prepayid"];

if(prepayId){

NSMutableString*stamp ?= [dictobjectForKey:@"timestamp"];

//調(diào)起微信支付

PayReq* req ? ? ? ? ? ? = [[PayReqalloc]init];

req.openID=[dictobjectForKey:@"appid"];

req.partnerId= [dictobjectForKey:@"partnerid"];

req.prepayId= [dictobjectForKey:@"prepayid"];

req.nonceStr= [dictobjectForKey:@"noncestr"];

req.timeStamp= stamp.intValue;

req.package=@"Sign=WXPay";

req.sign= [dictobjectForKey:@"sign"];

BOOLret = ? [WXApisendReq:req];

if(ret ==NO)

{

[selfshowDissmissSelfAlertViewTitle:@""message:@"支付失敗,請(qǐng)重新嘗試。"complete:^{

}];

}

}

}

}];

以下項(xiàng)目開發(fā)環(huán)境以Xcode10.0,運(yùn)行環(huán)境為IOS7.0為例,說明其開發(fā)中需要的操作。

1、項(xiàng)目設(shè)置APPID

商戶在微信開放平臺(tái)申請(qǐng)開發(fā)APP應(yīng)用后,微信開放平臺(tái)會(huì)生成APP的唯一標(biāo)識(shí)APPID。在Xcode中打開項(xiàng)目,設(shè)置項(xiàng)目屬性中的URL Schemes為您的APPID。如圖8.7標(biāo)紅位置所示。

圖8.7

2、注冊APPID

商戶APP工程中引入微信lib庫和頭文件,調(diào)用API前,需要先向微信注冊您的APPID,代碼如下:

[WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"demo 2.0"];

3、調(diào)起支付

商戶服務(wù)器生成支付訂單,先調(diào)用【統(tǒng)一下單API】生成預(yù)付單,獲取到prepay_id后將參數(shù)再次簽名傳輸給APP發(fā)起支付。以下是調(diào)起微信支付的關(guān)鍵代碼:

PayReq *request = [[[PayReq alloc] init] autorelease];

request.partnerId = @"10000100";

request.prepayId= @"1101000000140415649af9fc314aa427";

request.package = @"Sign=WXPay";

request.nonceStr= @"a462b76e7436e98e0ed6e13c64b4fd1c";

request.timeStamp= @"1397527777";

request.sign= @"582282D72DD2B03AD892830965F428CB16E7A256";

[WXApi sendReq:request];

注意:該sign生成字段名列表見調(diào)起支付API

4、支付結(jié)果回調(diào)

照微信SDK Sample,在類實(shí)現(xiàn)onResp函數(shù),支付完成后,微信APP會(huì)返回到商戶APP并回調(diào)onResp函數(shù),開發(fā)者需要在該函數(shù)中接收通知,判斷返回錯(cuò)誤碼,如果支付成功則去后臺(tái)查詢支付結(jié)果再展示用戶實(shí)際支付結(jié)果。注意 一定不能以客戶端返回作為用戶支付的結(jié)果,應(yīng)以服務(wù)器端的接收的支付通知或查詢API返回的結(jié)果為準(zhǔn)。代碼示例如下:

-(void)onResp:(BaseResp*)resp{

if ([respisKindOfClass:[PayRespclass]]){

PayResp*response=(PayResp*)resp;

switch(response.errCode){

caseWXSuccess:

//服務(wù)器端查詢支付通知或查詢API返回的結(jié)果再提示成功

NSlog(@"支付成功");

break;

default:

NSlog(@"支付失敗,retcode=%d",resp.errCode);

break;

}

}

}

回調(diào)中errCode值列表:

名稱描述解決方案

0成功展示成功頁面

-1錯(cuò)誤可能的原因:簽名錯(cuò)誤、未注冊APPID、項(xiàng)目設(shè)置APPID不正確、注冊的APPID與設(shè)置的不匹配、其他異常等。

-2用戶取消無需處理。發(fā)生場景:用戶不支付了,點(diǎn)擊取消,返回APP。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容