本篇记录ios使用ReactNative完成微信h5支付的一些注意事项。
a. 支付完成或者取消微信h5支付,会跳转到手机默认的浏览器中(safari),无法回到原App.
b. 如何获得支付状态???
1. 微信sdk与微信h5支付链接的不同
微信sdk:
{"package":"Sign=WXPay","appid":"wx41647c3ca4a4c6de","sign":"735D651D1BA5733EC12AC2B9218CC6DA","prepayid":"wx19105425889487ab4f70f0d5ec60920000","partnerid":"1500210432","noncestr":"s8tqy0wTNBA8p7nk","timestamp":"1597805512"}
微信h5支付:( A链接)
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx1716451470364793c6d22eeee8f3040000&package=602473332&redirect_url=https%3A%2F%2Fmp.weixin.qq.com/intp/nontax%2Fmwebpay%3Faction%3Dpage%26order_id%3DZWJoYW5EcW8rTWYyNW1vWEIyNkUnXyMwQWBIJ3lRMGZRZnZgVSE-WVYoaEJ3RmdQdUglZDkqXzh1OzN5KkxdeXcoRCwkKngtSyhRIldOVw%26from_mwebpay%3D1%26auto_call_pay%3D0%26auto_jump_result_page%3D0
2. React Native微信h5支付流程:
通过React Native 的WebView加载 A链接,微信会返回给我门一个调起微信支付的链接(B链接),然后通过React Native 桥接的方法Linking.openURL(B链接),调起微信支付。
B链接如下:
weixin://wap/pay?prepayid%3Dwx24143958550903678a2224c0957e420000&package=1666328792&noncestr=1598251198&sign=1933725ad49c94e84c52703b436fb857
3. 微信h5支付需要解决的问题(只针对ios)
a. 支付完成或者取消微信h5支付,会跳转到手机默认的浏览器中(safari),无法回到原App.
b. 如何获得支付状态???
解决a:
参考文档:https://www.jianshu.com/p/90db7dfb075c
在网上找了一堆关于a问题的博客,基本上都和上面的参考文档一样,只给出了原生ios UIWebView或者WKWebView的解决方法。很少有React Native的WebView的解决方法,但是我都试过,没用。
例如添加WebView 添加请求头:
source={{
uri:this.url+'&redirect_url=https%3A%2F%2Fapi.jingtaomall.cn%2Fhtml%2Fwxpay.html',
headers: {Referer:'https://api.jingtaomall.cn' }
}}
经过多次实验:React Native层的WebView貌似修改链接中的redirect_url和请求头中的Referer不起作用。
最终的解决思路:
还是的参照参考文档,修改React Native(版本0.44.3)的源码-------RCTWebView.m。
一、在React Native的源码-------RCTWebView.m中,拦截 A链接,修改链接中的redirect_url和请求头中的Referer。
由于React Native 0.44.3使用的还是iOS UIWebView, 所以在RCTWebView.m中的shouldStartLoadWithRequest方法中添 加了如下内容
//拦截微信h5支付
if ([[request.URL absoluteString] hasPrefix:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"]) {
NSDictionary *headers = [request allHTTPHeaderFields];
NSString *newUrl = nil;
NSString *absoluteString = [request.URL absoluteString];
//两种方法:
//1.将链接中的redirect_url替换为自己定义的URL Schemes,
//2.直接将redirect_url去掉,系统会用Referer填充redirect_url
if ([absoluteString containsString:@"redirect_url="]) {
NSRange redirectRange = [absoluteString rangeOfString:@"redirect_url"];
newUrl = [[absoluteString substringToIndex:redirectRange.location] stringByAppendingString:[NSString stringWithFormat:@"redirect_url=a1.mp.weixin.qq.com://wxpayh5/"]];
} else {
newUrl = [absoluteString stringByAppendingString:[NSString stringWithFormat:@"redirect_url=a1.mp.weixin.qq.com://wxpayh5/"]];
}
//如果Referer不是自己定义的URL Schemes,则替换,其中wxpayh5为回传参数
if (![[headers objectForKey:@"Referer"] isEqualToString:@"a1.mp.weixin.qq.com://wxpayh5/"]) {
//拦截该请求,创建一个新的请求,将Referer设置为定义的URL Schemes,在重新加载新的请求
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
// NSURL *url = [request URL];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:newUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:@"POST"];
//修改Referer,当作告诉浏览器,跳回我的app
[request setValue:@"a1.mp.weixin.qq.com://wxpayh5/" forHTTPHeaderField: @"Referer"];
[_webView loadRequest:request];
});
});
return NO;
}
}
二、 创建info---->URL Types
到这里我们已经将问题a解决了。
下面解决问题b:由于没法知道微信h5的支付状态。我的解决方法是:在每次调起微信支付回到原app之后,调一下自己的订单查询接口,来判断订单状态。
三、在AppDelegate.m的openURL方法中通过回传参数--wxpayh5,处理微信支付回到原app的逻辑。
if([url.host isEqualToString:@"wxpayh5"]){
//微信h5支付,发起广播,通知React Native层处理相应逻辑
[[NSNotificationCenter defaultCenter] postNotificationName:@"WxPayBoardcast" object:@"1"];
return YES;
}
最后再给一个React Native 的微信支付的封装:
//直接调起微信h5支付
export function DIRECT_NATIVE_WX(payInfo) {
if (payInfo.indexOf("weixin://wap/pay?") != -1) {
Linking.canOpenURL(payInfo).then(supported => {
if (!supported) {
TOAST_SHOW_FAIL("未检查到微信客户端,请确认是否安装???");
} else {
// let url = payInfo.replace("alipays", "jszk");
return Linking.openURL(payInfo);
}
}).catch(err => {
console.log('微信支付错误');
});
return true;
}
return false;
}
//桥接原生微信支付
export function BRIDGE_NATIVE_WXPAY(object, payInfo) {
console.log('开启微信支付');
//创建监听器监听native端的广播
object.wxay_subscription = global.NativeBoardcastEmitter.addListener(
'Native_PushTo_RN_WxPayBoardcast', //广播名称
(result) => {
if (object._handleWxPayComplete) {
object._handleWxPayComplete();
}
if (result == 1) {
console.log('微信SDK支付成功,或者h5支付返回')
if (object._handleWxPaySuccess) {
object._handleWxPaySuccess();
}
} else {
console.log('微信支付失败')
if (object._handleWxPayFailed) {
object._handleWxPayFailed();
}
}
//删除监听
// global.NativeBoardcastEmitter.removeAllListeners('Native_PushTo_RN_WxPayBoardcast')
//删除监听
if (object.wxay_subscription) {
object.wxay_subscription.remove();
object.wxay_subscription = null;
}
}
);
// 判断是否是微信h5支付
if (!DIRECT_NATIVE_WX(payInfo)) {
// 调起微信SDK支付
global.NativeBridge.NATIVE_wxPay(payInfo);
}
}