微信支付集成
前段時(shí)間,公司突然要在App中集成支付功能蛋哭。毫無(wú)意外的選擇了支付寶
县习、微信
- 支付寶,這里就不多說(shuō)了谆趾。按照官方的SDK文檔躁愿,一步一步,很清晰沪蓬,還有Demo演示彤钟。
- 微信,集成就比較麻煩了跷叉。沒(méi)有系統(tǒng)的文檔逸雹,沒(méi)有官方的Demo,說(shuō)明也是這里一句性芬,那里一句峡眶,坑得要死。這里就記錄一下微信支付的集成流程植锉,以及當(dāng)中遇到的問(wèn)題。
PS:這里只介紹如何在App端完成整個(gè)支付流程峭拘,實(shí)際支付時(shí)俊庇,簽名啥的應(yīng)該是放在服務(wù)器的狮暑。
前置條件準(zhǔn)備: 申請(qǐng)開(kāi)發(fā)者賬號(hào)->注冊(cè)應(yīng)用->申請(qǐng)開(kāi)通支付功能(300/年)
支付時(shí)序圖
- SDK導(dǎo)入應(yīng)用(這一步應(yīng)該不需要多說(shuō))。
-
預(yù)支付,微信與支付寶不一樣的地方辉饱,它先得向微信服務(wù)器進(jìn)行一個(gè)
預(yù)支付
操作搬男,獲取預(yù)支付id
,prepay_id
彭沼。而這個(gè)預(yù)支付id
則是用來(lái)進(jìn)行實(shí)際支付時(shí)的一個(gè)必填參數(shù)缔逛。
// 微信的預(yù)支付接口地址
NSString *urlString = @"https://api.mch.weixin.qq.com/pay/unifiedorder";
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"appid"] = @"應(yīng)用id";
params[@"mch_id"] = @"商戶id";
params[@"trade_type"] = @"APP";
params[@"body"] = [NSString stringWithFormat:@"支付測(cè)試"];
params[@"out_trade_no"] = number;
params[@"total_fee"] = @((int)(price.doubleValue * 100)).description;
params[@"notify_url"] = @"http://api.cloud.com";
params[@"nonce_str"] = @"5K8264ILTKCH16CQ2502SI8ZNMTM67VS";
params[@"attach"] = @"杭州分店";
params[@"spbill_create_ip"] = @"192.168.1.1";
params[@"device_info"] = @"WEB";
params[@"sign"] = [self sign];
[self.manager POST:urlString parameters:[WXPayHelper toXML:params] progress:nil success:^(NSURLSessionDataTask *_Nonnull task, NSData *data) {
NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
BOOL success = [parser parse];
NSLog(@"解析:%d", success);
} failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
NSLog(@"%@", error);
self.req = nil;
PayResp *resp = [PayResp new];
resp.errCode = (int)error.code;
resp.errStr = error.localizedDescription;
}];
預(yù)支付返回內(nèi)容
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[返回的appid]]></appid>
<mch_id><![CDATA[商戶id]]></mch_id>
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id> <![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
<trade_type><![CDATA[APP]]></trade_type>
</xml>
注意,你在調(diào)試的時(shí)候姓惑,可能會(huì)發(fā)現(xiàn)此事返回的sign簽名與請(qǐng)求時(shí)傳上去的不一樣褐奴,沒(méi)關(guān)系,可能時(shí)他那邊后臺(tái)做過(guò)處理于毙。此時(shí)你只需要解析prepay_id字段就好了敦冬。
-
支付,利用第二步獲取到的
預(yù)支付id
,發(fā)起支付請(qǐng)求。
PayReq *request = [[PayReq alloc] init];
request.partnerId = @"商戶id";
request.prepayId= @"上一步返回的預(yù)支付id";
request.package = @"Sign=WXPay";
request.nonceStr= @"隨機(jī)字符串";
request.timeStamp = @"時(shí)間戳";
request.sign= [self sign]; // 簽名
[WXApi sendReq:request];
不得不吐槽的是微信的支付回調(diào)居然是delegate
唯沮,而沒(méi)有用上現(xiàn)在主流的block
脖旱。
-(void)onResp:(BaseResp*)resp
{
if ([respisKindOfClass:[PayRespclass]])
{
PayResp*response=(PayResp*)resp;
switch(response.errCode){
caseWXSuccess:
//服務(wù)器端查詢(xún)支付通知或查詢(xún)API返回的結(jié)果再提示成功
NSlog(@"支付成功");
break;
default:
NSlog(@"支付失敗,retcode=%d",resp.errCode);
break;
}
}
}
基本上這到這一步就沒(méi)啥問(wèn)題了介蛉。
- 遇到的問(wèn)題