热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

h5微信支付报错:商家参数格式有误,请联系商家解决

问题h5微信支付报错:商家参数格式有误,请联系商家解决解决官方给的解决方案是:https:pay.weixin.qq.comwiki

问题

h5微信支付报错:商家参数格式有误,请联系商家解决

解决

官方给的解决方案是:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4
在这里插入图片描述
因为我用的是 react native,改的话需要去改 node_modules里面的 react-native-webview 包的源码。

网上也有人说,直接这样设置:

<WebViewstyle&#61;{{ width: &#39;100%&#39;, height: &#39;100%&#39; }}source&#61;{{uri: payUrl, //跳转链接headers: {Referer: &#39;http://www.baidu.com&#39;, // 此处设置},}}onMessage&#61;{(event) &#61;> {// 此处可以拿到我从h5传过来的参数console.log(&#39;&#61;&#61;&#61;&#61;>&#39; &#43; event.nativeEvent.data)}}
/>

但是我亲测&#xff0c;这样设置 Referer 没有生效。
所以&#xff0c;我就按照官方文档改源码

安卓

路径&#xff1a;node_modules/react-native-webview/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java

&#64;Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {final RNCWebView rncWebView &#61; (RNCWebView) view;final boolean isJsDebugging &#61; ((ReactContext) view.getContext()).getJavascriptContextHolder().get() &#61;&#61; 0;// -------开始-------Map extraHeaders &#61; new HashMap(); extraHeaders.put("Referer", "https://baidu.com");if (url.startsWith("weixin://")) { Intent intent &#61; new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); view.getContext().startActivity(intent); return true; }view.loadUrl(url, extraHeaders);// -------结束-------if (!isJsDebugging && rncWebView.mCatalystInstance !&#61; null) {...}
}

ios

路径&#xff1a;node_modules/react-native-webview/apple/RNCWebView.m

{
...if (_onLoadingStart) {// We have this check to filter out iframe requests and whatnotif (isTopFrame) {NSMutableDictionary<NSString *, id> *event &#61; [self baseEvent];[event addEntriesFromDictionary: &#64;{&#64;"url": (request.URL).absoluteString,&#64;"navigationType": navigationTypes[&#64;(navigationType)]}];_onLoadingStart(event);}
}// -------开始-------
//拦截微信h5支付
if ([[request.URL absoluteString] hasPrefix:&#64;"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"]) {NSDictionary *headers &#61; [request allHTTPHeaderFields]; NSString *newUrl &#61; nil;NSString *absoluteString &#61; [request.URL absoluteString];//两种方法&#xff1a;//1.将链接中的redirect_url替换为自己定义的URL Schemes&#xff0c;//2.直接将redirect_url去掉&#xff0c;系统会用Referer填充redirect_urlif ([absoluteString containsString:&#64;"redirect_url&#61;"]) {NSRange redirectRange &#61; [absoluteString rangeOfString:&#64;"redirect_url"];newUrl &#61; [[absoluteString substringToIndex:redirectRange.location] stringByAppendingString:[NSString stringWithFormat:&#64;"redirect_url&#61;baidu.com://wxpayh5/"]];} else {newUrl &#61; [absoluteString stringByAppendingString:[NSString stringWithFormat:&#64;"redirect_url&#61;baidu.com://wxpayh5/"]];}//如果Referer不是自己定义的URL Schemes,则替换&#xff0c;其中wxpayh5为回传参数if (![[headers objectForKey:&#64;"Referer"] isEqualToString:&#64;"baidu.com://wxpayh5/"]) {//拦截该请求&#xff0c;创建一个新的请求&#xff0c;将Referer设置为定义的URL Schemes&#xff0c;在重新加载新的请求dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{dispatch_async(dispatch_get_main_queue(), ^{// NSURL *url &#61; [request URL];NSMutableURLRequest* request &#61; [NSMutableURLRequest requestWithURL:[NSURL URLWithString:newUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];[request setHTTPMethod:&#64;"POST"];//修改Referer&#xff0c;当作告诉浏览器&#xff0c;跳回我的app[request setValue:&#64;"baidu.com://wxpayh5/" forHTTPHeaderField: &#64;"Referer"];[_webView loadRequest:request];});});}
}
// -------结束-------decisionHandler(WKNavigationActionPolicyAllow);
}

这个时候可以支付了&#xff0c;但是调回来是一个空白页&#xff0c;还需要增加
路径 app项目/ios/项目名/AppDelegate.m

#import "AppDelegate.h"#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "RNSplashScreen.h" // here
#import <React/RCTLinkingManager.h>
#import "Orientation.h"// UniModules per https://docs.expo.io/bare/installing-unimodules/
#import <UMCore/UMModuleRegistry.h>
#import <UMReactNativeAdapter/UMNativeModulesProxy.h>
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.h>#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>static void InitializeFlipper(UIApplication *application) {FlipperClient *client &#61; [FlipperClient sharedClient];SKDescriptorMapper *layoutDescriptorMapper &#61; [[SKDescriptorMapper alloc] initWithDefaults];[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];[client addPlugin:[FlipperKitReactPlugin new]];[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];[client start];
}
#endif&#64;interface AppDelegate () <RCTBridgeDelegate>&#64;property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter;&#64;end&#64;implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLEDInitializeFlipper(application);
#endifself.moduleRegistryAdapter &#61; [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]];RCTBridge *bridge &#61; [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];RCTRootView *rootView &#61; [[RCTRootView alloc] initWithBridge:bridgemoduleName:&#64;"wiseDerma"initialProperties:nil];if (&#64;available(iOS 13.0, *)) {rootView.backgroundColor &#61; [UIColor systemBackgroundColor];} else {rootView.backgroundColor &#61; [UIColor whiteColor];}self.window &#61; [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];UIViewController *rootViewController &#61; [UIViewController new];rootViewController.view &#61; rootView;self.window.rootViewController &#61; rootViewController;[self.window makeKeyAndVisible];[RNSplashScreen show]; // herereturn YES;
}- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
{NSArray<id<RCTBridgeModule>> *extraModules &#61; [_moduleRegistryAdapter extraModulesForBridge:bridge];// If you&#39;d like to export some custom RCTBridgeModules that are not Expo modules, add them here!return extraModules;
}- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUGreturn [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:&#64;"index" fallbackResource:nil];
#elsereturn [[NSBundle mainBundle] URLForResource:&#64;"main" withExtension:&#64;"jsbundle"];
// return [CodePush bundleURL]; // 热更新
#endif
}- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {return [WXApi handleOpenURL:url delegate:self];
}- (BOOL)application:(UIApplication *)applicationcontinueUserActivity:(NSUserActivity *)userActivityrestorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullablerestorableObjects))restorationHandler {// 触发回调方法[RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];return [WXApi handleOpenUniversalLink:userActivitydelegate:self];
}- (BOOL)application:(UIApplication *)application openURL:(NSURL *)urloptions:(NSDictionary<NSString*, id> *)options
{// -------开始-------if([url.host isEqualToString:&#64;"wxpayh5"]){//微信h5支付&#xff0c;发起广播&#xff0c;通知React Native层处理相应逻辑[[NSNotificationCenter defaultCenter] postNotificationName:&#64;"WxPayBoardcast" object:&#64;"1"];return YES;}// -------结束-------// Triggers a callback event.// 触发回调事件[RCTLinkingManager application:application openURL:url options:options];return [WXApi handleOpenURL:url delegate:self];
}- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {return [Orientation getOrientation];
}&#64;end

最后

因为我们是直接改 node_modules 里的文件&#xff0c;这样别人接手这个项目的时候肯定不知道&#xff0c;那么我们需要用一个脚本来把代码 copy 到 node_modules 里

const path &#61; require(&#39;path&#39;);
const fs &#61; require(&#39;./libs/fs&#39;);const nodeModules &#61; path.resolve(__dirname, &#39;../node_modules&#39;);const reactNativeWebviewPatch &#61; async () &#61;> {const reactNativeWebviewPath &#61; path.resolve(nodeModules, &#39;react-native-webview&#39;);const RNCWebViewPathPatch &#61; path.resolve(__dirname, &#39;patch/react-native-webview/RNCWebView.m&#39;);const RNCWebViewManagerPathPatch &#61; path.resolve(__dirname, &#39;patch/react-native-webview/RNCWebViewManager.java&#39;);const RNCWebViewPathRNW &#61; path.resolve(reactNativeWebviewPath, &#39;apple/RNCWebView.m&#39;);const RNCWebViewManagerPathRNW &#61; path.resolve(reactNativeWebviewPath, &#39;android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java&#39;);await fs.copyFile(RNCWebViewPathPatch, RNCWebViewPathRNW);await fs.copyFile(RNCWebViewManagerPathPatch, RNCWebViewManagerPathRNW);
};const patch &#61; () &#61;> {reactNativeWebviewPatch();
};patch();

参考文档

https://blog.csdn.net/silently_frog/article/details/108315421


推荐阅读
  • 做好了项上,其中包含有一个上传的功能。在开发环境和测试环境运行、测试都没什么问题。也许是由于本地的局域网的问题,一切都运行的比较快,但把它发布到外网的服务器上去时。就特别的慢。上传小的文件还算比 ... [详细]
  • JNI技术实践小结转自http:sett ... [详细]
  • Java开发框架!Alibaba高并发业务秒杀系统落地实战文档,砥砺前行!
    接口概述:接口是Java语言中的一种引用类型,是方法的集合,所以接口的内部主要就是定义方法,包含常量,抽象方法(JDK ... [详细]
  • Android 自定义控件基础 canvas paint
    1、首先说一下canvas类:ClassOverviewTheCanvasclassholdsthedrawcalls.Todrawsomething,youne ... [详细]
  • 软件自动化测试的学习路线
    软件自动化测试的学习步骤软件测试交流群关注软件测试技术公众号获取阅读目录软件自动化测试的学习步骤自动化测试的本质自动化测试学习的误区自动化测试的职位自动化测试分类Web自动化 ... [详细]
  • 在MirrorAPI中,我们可以使用以下内容: ... [详细]
  • 下面是一个用openssl实现获取https网页内容的demo,整个流程比较简单,主要封装的API如下staticinthttps_init(http ... [详细]
  • Shiro 简单了解
    Shiro简单了解简单用过SpringSecurity安全框架后,再试试另一个安全框架——Shiro。1.Shiro简介ApacheShiro是一个强大且易用的Java安全框架:S ... [详细]
  • 一、使用ContentProvider(内容提供者)共享数据ContentProvider在android中的作用是对外共享数据,也就是说 ... [详细]
  • Spark 贝叶斯分类算法
    一、贝叶斯定理数学基础我们都知道条件概率的数学公式形式为即B发生的条件下A发生的概率等于A和B同时发生的概率除以B发生的概率。根据此公式变换,得到贝叶斯公式:即贝叶斯定律是关于随机 ... [详细]
  • 一、在androidStudio中实现tabs比较简单,新建项目就可以选择tabs模板进行创建,默认实现tabs功能:直接运行项目就可以看到效果:可以说非常简单,但是我们在实际开发 ... [详细]
  • UDP协议开发
    UDP是用户数据报协议(UserDatagramProtocol,UDP)的简称,其主要作用是将网络数据流量压缩成数据报形式,提供面向事务的简单信息传送服务。与TCP协议不同,UD ... [详细]
  • Android JNI学习之Concepts
    2019独角兽企业重金招聘Python工程师标准ConceptsBeforeBeginningThisguideassumesthatyouare:Alreadyfamili ... [详细]
  • 看完这篇还搞不懂HTTPS,就来找我!
    本文将为大家详细梳理一下H ... [详细]
  • 【scrapy】爬取汽车车型数据
    汽车最近想在工作相关的项目上做技术改进,需要全而准的车型数据,寻寻觅觅而不得,所以就只能自己动手丰衣足食,到网上获(窃)得(取)数据了。汽车之家是大家公认的数据做的比较好的汽车网站 ... [详细]
author-avatar
手机用户2602920263
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有