(一)微信支付流程:

簡(jiǎn)略版的

詳細(xì)的支付過程
1.用戶使用APP客戶端,選擇商品下單。
商戶客戶端(就是你做的APP)將用戶的商品數(shù)據(jù)傳給商戶服務(wù)器,請(qǐng)求生成支付訂單。
2.商戶后臺(tái)調(diào)用統(tǒng)一下單API向微信的服務(wù)器發(fā)送請(qǐng)求。
3.微信服務(wù)器生成預(yù)付單,并生成一個(gè)prepay_id返回給商戶后臺(tái)。
4.商戶后臺(tái)生成帶簽名的客戶端支付信息,并將(prepay_id,sign等)返回給客戶端。
5.用戶點(diǎn)擊確認(rèn)支付,這時(shí)候商戶客戶端調(diào)用SDK打開微信客戶端,進(jìn)行微信支付。
6.微信客戶端向微信服務(wù)器發(fā)起支付請(qǐng)求并返回支付結(jié)果(他們之間交互用的就是prepay_id這個(gè)參數(shù),微信的服務(wù)器要驗(yàn)證微信客戶端傳過去的參數(shù)是否跟第三步中生成的那個(gè)id一致)。
用戶輸入支付密碼后,微信客戶端提交支付授權(quán),跟微信服務(wù)器交互,完成支付。
7.微信服務(wù)器給微信客戶端發(fā)送支付結(jié)果提示。
8.并異步給商戶服務(wù)器發(fā)送支付結(jié)果通知。
9.從微信點(diǎn)擊返回app返回app(這一步可能沒有)
10.商戶客戶端通過支付結(jié)果回調(diào)接口查詢支付結(jié)果,并向后臺(tái)檢查支付結(jié)果是否正確,后臺(tái)返回支付結(jié)果。
11.商戶客戶端顯示支付結(jié)果,完成訂單,發(fā)貨。
Tips1:
- 2個(gè)返回結(jié)果:(8和9)
1 )微信返回結(jié)果代表扣款成功(你微信的錢沒有了);
2 )App返回結(jié)果代表真實(shí)的扣款成功(你的app后臺(tái)收到了錢);
為了安全起見,應(yīng)該以第2個(gè)為準(zhǔn),因?yàn)榭赡艹霈F(xiàn)微信已經(jīng)扣款,但是你的app還沒有收到錢的情況出現(xiàn);
Tips2:
- 調(diào)用微信支付前,需要下單、簽名等操作,以便獲取微信支付所必要的參數(shù)。為了提高安全性,下單、簽名操作一般是在后臺(tái)完成,在前臺(tái)做的話可能被捕獲該信息。
需要的參數(shù)包括:appid、partid(商戶號(hào))、prepayid(預(yù)支付訂單ID)、noncestr(參與簽名的隨機(jī)字符串)、timestamp(參與簽名的時(shí)間戳)、sign(簽名字符串)這六個(gè)。
(二)iOS端的代碼
注1:其中前4步用戶是無法看到的。
上面是完整的一個(gè)支付的流程,但是對(duì)于iOS開發(fā)者來說,其實(shí)并沒有這么復(fù)雜,你需要做的就3步
1.注冊(cè)微信Appkey
2.從App服務(wù)器獲取預(yù)支付信息的Prepay_id,調(diào)起微信客戶端,完成支付。
3.設(shè)置微信回調(diào)代理,打開你的app;
4.接收回調(diào)信息,對(duì)回調(diào)結(jié)果進(jìn)行處理。
注2:導(dǎo)入微信SDK我是使用Cocoapods做的,總體來說比較簡(jiǎn)單,但是需要注意的是你需要在Linked Frameworks and Libraries 中導(dǎo)入CoreTelephone.framework,不然會(huì)出問題。
準(zhǔn)備工作:注冊(cè)微信Appkey
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"測(cè)試demo"];
return YES;
}
2.獲取服務(wù)器發(fā)來的prepayid和sign簽名等信息后調(diào)用下面的方法去喚起微信SDK支付
- (void)wxPay:(NSDictionary *)info{
NSString *appid = info[@"appid"];
BOOL isok = [WXApi registerApp:appid?:kWXAppID];
if (isok) {
NSLog(@"注冊(cè)微信成功");
}else{
NSLog(@"注冊(cè)微信失敗");
}
//構(gòu)造支付請(qǐng)求
PayReq *request = [[PayReq alloc]init];
request.partnerId = [info objectForKey:@"partnerid"];
request.prepayId = [info objectForKey:@"prepayid"];
request.package = [info objectForKey:@"package"];
request.nonceStr = [info objectForKey:@"noncestr"];
request.timeStamp = [[info objectForKey:@"timestamp"] integerValue];
request.sign = [info objectForKey:@"sign"];
//調(diào)用這個(gè)方法之后,app會(huì)調(diào)起微信客戶端(對(duì)應(yīng)第5步)
BOOL paySucceed = [WXApi sendReq:request];
if(paySucceed == NO){
BSLog(@"支付失敗");
}
}
2.微信回調(diào)代理設(shè)置,打開你的app
//9.0前的方法,為了適配低版本 保留
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
return [WXApi handleOpenURL:url delegate:self];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
return [WXApi handleOpenURL:url delegate:self];
}
//9.0后的方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
//這里判斷是否發(fā)起的請(qǐng)求為微信支付,如果是的話,用WXApi的方法調(diào)起微信客戶端的支付頁(yè)面(://pay 之前的那串字符串就是你的APPID,)
//處理微信通過URL啟動(dòng)App時(shí)傳遞的數(shù)據(jù),delegate代表在哪個(gè)類接收返回的請(qǐng)求,有時(shí)為了簡(jiǎn)化AppDelegate可以delegate設(shè)置為一個(gè)單利類,在單獨(dú)的一個(gè)類處理微信回調(diào)的數(shù)據(jù)
//這個(gè)方法調(diào)起之后在點(diǎn)擊返回商戶之后會(huì)打開你的app,(對(duì)應(yīng)第9步)
return [WXApi handleOpenURL:url delegate:self];
}
4.微信回調(diào)信息接收的地方
//微信SDK自帶的方法,處理從微信客戶端完成操作后返回程序之后的回調(diào)方法,顯示支付結(jié)果的
-(void) onResp:(BaseResp*)resp
{
//啟動(dòng)微信支付的response
NSString *payResoult = [NSString stringWithFormat:@errcode:%d, resp.errCode];
if([resp isKindOfClass:[PayResp class]]){
//支付返回結(jié)果,實(shí)際支付結(jié)果需要去微信服務(wù)器端查詢
switch (resp.errCode) {
case 0:
payResoult = @支付結(jié)果:成功!;
break;
case -1:
payResoult = @支付結(jié)果:失敗!;
break;
case -2:
payResoult = @用戶已經(jīng)退出支付!;
break;
default:
payResoult = [NSString stringWithFormat:@支付結(jié)果:失??!retcode = %d, retstr = %@, resp.errCode,resp.errStr];
break;
}
}
}
注:第三步需要注意的是:在最新的系統(tǒng)中只有點(diǎn)擊微信界面的返回商戶才會(huì)執(zhí)行(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options這個(gè)方法,所以還是需要在重新喚起app的方法中去服務(wù)器請(qǐng)求下支付信息。