悠閑時(shí)光, 順便將開(kāi)發(fā)過(guò)程中, 經(jīng)常使用到的一些功能, 記錄分享出來(lái),比如支付!
本想寫(xiě)一篇銀聯(lián)支付,不過(guò)看了之前轉(zhuǎn)載過(guò)一篇關(guān)于銀聯(lián)支付的文章寫(xiě)得很詳細(xì),我就不再重復(fù)了, 有興趣的童鞋可以去看一下; 戳這里
首先介紹一下微信支付的實(shí)現(xiàn)流程:
- 注冊(cè)微信開(kāi)放平臺(tái)对途,創(chuàng)建應(yīng)用獲取appid政基,appSecret,申請(qǐng)支付功能(需要花費(fèi)300大洋進(jìn)行開(kāi)發(fā)者資質(zhì)認(rèn)證)冕碟,申請(qǐng)成功之后會(huì)返回一些參數(shù).
- 下載微信支付sdk
- 客戶端請(qǐng)求訂單鄙煤,后臺(tái)與微信后臺(tái)交互,返回給客戶端支付參數(shù)
- 調(diào)用微信客戶端,由微信客戶端和微信服務(wù)器打交道梯轻;
- 客戶端和服務(wù)端都會(huì)收到支付結(jié)果;(前臺(tái)消息不可靠尽棕,我們需要去后臺(tái)驗(yàn)證喳挑,如果后臺(tái)沒(méi)有收到支付通知,后臺(tái)去微信服務(wù)器驗(yàn)證然后將結(jié)果返回給客戶端)
開(kāi)發(fā)步驟
在微信開(kāi)放平臺(tái)注冊(cè)應(yīng)用, 并開(kāi)通支付功能之后(期間各種認(rèn)證, 確認(rèn)信息等操作按照流程走就可以, 在此省略)
第一步: 下載微信 SDK
在這里下載微信 SDK
第二步: 集成 SDK
當(dāng)下載 SDK 之后, 會(huì)看到其中有一個(gè)** read_me.txt ** 文件, 其實(shí)里面就是講了最近幾個(gè)版本的更新中解決的問(wèn)題,以及使用該SDK的注意事項(xiàng)伊诵,所以這個(gè) read_me 文件是很重要的单绑。
- 將 SDK 拖入工程
- 導(dǎo)入一下框架和鏈接庫(kù):
SystemConfiguration.framework,
libz.dylib, libsqlite3.0.dylib,
libc++.dylib, Security.framework,
CoreTelephony.framework,
CFNetwork.framework
注: 如果是XCode 7之前,估計(jì)還需要手動(dòng)導(dǎo)入Foundation.framework曹宴、UIKit.framework等框架;
- 將微信支付要用到的APPID設(shè)置為URL Schemes
第三步: 就是寫(xiě)代碼了
- 注冊(cè)APPID
商戶APP工程中引入微信lib庫(kù)和頭文件搂橙,調(diào)用API前,需要先向微信注冊(cè)您的APPID笛坦,代碼如下:
#pragma mark 微信支付
- (void)wxPay {
/**
* 微信支付
* APPID:
*/
//向微信注冊(cè)
BOOL isok = [WXApi registerApp:@"項(xiàng)目 APPID" withDescription:@"項(xiàng)目名稱"];
if (isOk) {
TY_Log(@"注冊(cè)微信成功");
}else{
TY_Log(@"注冊(cè)微信失敗");
}
}
- 調(diào)起支付
商戶服務(wù)器生成支付訂單区转,先調(diào)用【統(tǒng)一下單API】生成預(yù)付單,獲取到prepay_id后將參數(shù)再次簽名傳輸給APP發(fā)起支付版扩。以下是調(diào)起微信支付的關(guān)鍵代碼:
現(xiàn)在我們只需要在控制器上添加一個(gè)button, 名字改成微信支付就可以了
button事件:
- (void)wxPayBtnClick:(UIButton *)sender {
if (![WXApi isWXAppInstalled]){ // 是否安裝了微信
UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"提示" message:@"沒(méi)有安裝微信" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alter show];
} else if (![WXApi isWXAppSupportApi]){ // 是否支持微信支付
UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"提示" message:@"不支持微信支付" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alter show];
}else{ //已安裝微信, 進(jìn)行支付
[self WXPay];
}
}
#pragma mark 微信支付方法
- (void)WXPay{
//將微信支付所需參數(shù)信息,傳給服務(wù)器
[BusinessEngine getWXPayParameteFlowCode:self.flowCode Body:self.storeName Price:self.orderValue Completion:^(NSDictionary *aDic) {
//需要?jiǎng)?chuàng)建這個(gè)支付對(duì)象
PayReq* req= [[PayReq alloc]init];
//由用戶微信號(hào)和AppID組成的唯一標(biāo)識(shí)废离,用于校驗(yàn)微信用戶
//req.openID = [aDic objectForKey:@"appid"];
// 商家id,在注冊(cè)的時(shí)候給的
req.partnerId = [aDic objectForKey:@"partnerid"];
// 預(yù)支付訂單這個(gè)是后臺(tái)跟微信服務(wù)器交互后资厉,微信服務(wù)器傳給你們服務(wù)器的厅缺,你們服務(wù)器再傳給你
req.prepayId = [aDic objectForKey:@"prepayid"];
// 根據(jù)財(cái)付通文檔填寫(xiě)的數(shù)據(jù)和簽名
//這個(gè)比較特殊,是固定的宴偿,只能是即req.package = Sign=WXPay
req.package = @"Sign=WXPay";
// 隨機(jī)編碼湘捎,為了防止重復(fù)的,在后臺(tái)生成
req.nonceStr = [aDic objectForKey:@"noncestr"];
// 這個(gè)是時(shí)間戳窄刘,也是在后臺(tái)生成的窥妇,為了驗(yàn)證支付的
NSString * stamp = [aDic objectForKey:@"timestamp"];
req.timeStamp = stamp.intValue;
// 這個(gè)簽名也是后臺(tái)做的
req.sign = [aDic objectForKey:@"sign"];
//日志輸出
//NSLog(@"appid=%@\npartid=%@\nprepayid=%@\nnoncestr=%@\ntimestamp=%ld\nsign=%@",[aDic objectForKey:@"appid"],req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.sign );
//發(fā)送請(qǐng)求到微信,等待微信返回onResp
[WXApi sendReq:req];
}];
}
3 . 支付結(jié)果回調(diào)
按照微信SDKSample娩践,在類(lèi)實(shí)現(xiàn)onResp函數(shù)活翩,支付完成后,微信APP會(huì)返回到商戶APP并回調(diào)onResp函數(shù)翻伺,開(kāi)發(fā)者需要在該函數(shù)中接收通知材泄,判斷返回錯(cuò)誤碼,如果支付成功則去后臺(tái)查詢支付結(jié)果再展示用戶實(shí)際支付結(jié)果吨岭。
注意:
一定不能以客戶端返回作為用戶支付的結(jié)果拉宗,應(yīng)以服務(wù)器端的接收的支付通知或查詢API返回的結(jié)果為準(zhǔn)。
這是最后一步了, 我們?cè)谥Ц俄?yè)面支付完成以后呢要知道支付結(jié)果, 怎么做呢?
首先, 在 AppDelegate.m 里面實(shí)現(xiàn)該方法
#pragma mark 跳轉(zhuǎn)支付寶, 微信 進(jìn)行支付辣辫,處理支付結(jié)果
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
NSString *urlStr = [NSString stringWithFormat:@"%@",url];
if ([url.host isEqualToString:@"safepay"]) { //判斷支付寶回調(diào)
//跳轉(zhuǎn)支付寶錢(qián)包進(jìn)行支付旦事,處理支付結(jié)果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
//TYLLog(@"result = %@",resultDic);
//TYLLog(@"result", resultDic)
}];
}else if ([sourceApplication isEqualToString:@"com.tencent.xin"] && [urlStr containsString:@"pay"]){ //判斷微信回調(diào)
TY_Log(@"跳轉(zhuǎn)微信支付處理支付方式結(jié)果");
return [WXApi handleOpenURL:url delegate:self];
}
return YES;
}
接下來(lái)我們需要遵守下協(xié)議
#pragma mark 微信支付回調(diào)
-(void)onResp:(BaseResp*)resp{
//NSString * strMsg = [NSString stringWithFormat:@"errorCode: %d",resp.errCode];
//TY_Log(@"微信 = strMsg:", strMsg)
//NSString * errStr = [NSString stringWithFormat:@"errStr: %@",resp.errStr];
//TY_Log(@"微信 = errStr:", errStr)
NSString *strTitle;
if ([resp isKindOfClass:[SendMessageToWXResp class]]) {
strTitle = [NSString stringWithFormat:@"發(fā)送媒體消息結(jié)果"];
}
NSString * wxPayResult;
if ([resp isKindOfClass:[PayResp class]]) {
strTitle = [NSString stringWithFormat:@"支付結(jié)果"];
switch (resp.errCode) {
case WXSuccess:
{
TYLLog(@"支付結(jié)果: 成功!");
wxPayResult = @"success";
}
break;
case WXErrCodeCommon:
{ //簽名錯(cuò)誤、未注冊(cè)APPID急灭、項(xiàng)目設(shè)置APPID不正確姐浮、注冊(cè)的APPID與設(shè)置的不匹配、其他異常等
TYLLog(@"支付結(jié)果: 失敗!");
wxPayResult = @"faile";
}
break;
case WXErrCodeUserCancel:
{ //
TYLLog(@"用戶點(diǎn)擊取消并返回");
wxPayResult = @"cancel";
}
break;
case WXErrCodeSentFail:
{ //發(fā)送失敗
TYLLog(@"發(fā)送失敗");
wxPayResult = @"faile";
}
break;
case WXErrCodeUnsupport:
{ //微信不支持
TYLLog(@"微信不支持");
wxPayResult = @"faile";
}
break;
case WXErrCodeAuthDeny:
{ //授權(quán)失敗
TYLLog(@"授權(quán)失敗");
wxPayResult = @"faile";
}
break;
default:
break;
}
//發(fā)出通知 從微信回調(diào)回來(lái)之后,發(fā)一個(gè)通知,讓請(qǐng)求支付的頁(yè)面接收消息,并且展示支付結(jié)果,或者進(jìn)行一些自定義的展示或者跳轉(zhuǎn)
NSNotification * notification = [NSNotification notificationWithName:@"WXPay" object:wxPayResult];
[[NSNotificationCenter defaultCenter] postNotification:notification];
//------------------------
}
}
其實(shí)移動(dòng)端實(shí)現(xiàn)起來(lái)還是很簡(jiǎn)單的, 至于各種驗(yàn)證還是后臺(tái)辛苦下了??
如果這篇文章對(duì)您有些許幫助 請(qǐng)給我點(diǎn)個(gè)心吧葬馋。