请尊重知识,请尊重原创 更多资料参考请见 http://www.cezuwang.com/listFilm?page=1&areaId=906&filmTypeId=1
微信app支付 签名错误 以及 访问https 的解决办法
微信支付的接口不同于支付宝等其他第三方接口足够友好,所以这里有必要对 微信签名错误和访问https接口做一些小结以供参考。
签名错误:
首先总结原因,可能发生签名错误的原因如下:
1 密钥错误,密钥是32位长的一串字符,类似于 f0fnf5872825aien55end044e092le39 ,如果需要重新设置 ,位置在 设置位置:账户设置-安全设置-API安全
2 本地签名程序
基本遵照微信官方文档说明即可 https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=4_3
传递哪些参数 需要根据文档说明 https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1
参考(内部的一些关键参数只提供参考,位数不对):
sb 字符串 appid=wx5382e5300d7f6e555f&body=Corsair Neutron Series GTX 480GB 固态硬盘&mch_id=1237315833041&nonce_str=1B72746255EF01F9D75400995C62EA12
¬ify_url=http://m.dahongwa.com/pay/notify&out_trade_no
=151023113401857821&spbill_create_ip=10.244.1.171&total_fee=84462&trade_type=APP&key=f0fn3f5872825ai4en55end044e092le39
再对此字符串进行md5加密之后调成大写,即为sign签名
生成的xml文档:
<xml> <appid>wx5382e5300d7f6e555f</appid> <body><![CDATA[Corsair Neutron Series GTX 480GB 固态硬盘]]></body> <mch_id>1237315833041</mch_id> <nonce_str>1B72746255EF01F9D75400995C62EA12</nonce_str> <notify_url>http://m.dahongwa.com/pay/notify</notify_url> <out_trade_no>151023113401857821</out_trade_no> <sign><![CDATA[CD0DCCA447A6C0B0482C4D43A545A0BA]]></sign> <spbill_create_ip>10.244.1.171</spbill_create_ip> <total_fee>84462</total_fee> <trade_type>APP</trade_type> </xml>
生成的xml是提交给 微信的参数,必须和签名的字符串里的值相同
如果返回的微信参数提示 签名错误,可以到微信官方测试测试地址测试
https://pay.weixin.qq.com/wiki/tools/signverify/
微信返回信息中,如果出现签名错误,可以把自己的资料填写在上面的测试用例中获取微信生成的签名,
如果测试sign与自己生成的不同 返回上步检查,如果微信生成的和自己生成的签名相同,但是微信还是返回签名错误,则一定是商品中文(body)编码。
有几个地方的编码必须注意.
设置 sb 字符串 的时候 body一定为utf-8,sb字符串md5加密的时候 必须为utf-8,
传递给 微信的时候 ,此参数也必须为 utf-8 :entity = new StringEntity(xml,"utf-8");
httpclient 头部和参数 也设置成utf-8: httpPost.setEntity(entity); httpPost.addHeader("Content-Type", "text/html;charset=UTF-8"); httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); httpPost.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
这几个编码优先级逐步提高,也就是说后面的会覆盖前面的。
请尊重知识,请尊重原创 更多资料参考请见 http://www.cezuwang.com/listFilm?page=1&areaId=906&filmTypeId=1
由于微信的接口是https,在生产环境又只能通过代理访问,所以通常的http接口访问会返回错误信息:
WARN,http-apr-9002-exec-4,10-22 20:21:30.393,httpclient.HttpMethodDirector.authenticateHost:288 - Required credentials not available for BASIC <any realm>@api.mch.weixin.qq.com:443 WARN,http-apr-9002-exec-4,10-22 20:21:30.393,httpclient.HttpMethodDirector.authenticateHost:290 - Preemptive authentication requested but no default credentials available INFO,http-apr-9002-exec-4,10-22 20:21:30.583,httpclient.HttpMethodDirector.executeWithRetry:439 - I/O exception (java.net.ConnectException) caught when processing request: Connection refused INFO,http-apr-9002-exec-4,10-22 20:21:30.583,httpclient.HttpMethodDirector.executeWithRetry:445 - Retrying request INFO,http-apr-9002-exec-4,10-22 20:21:30.591,httpclient.HttpMethodDirector.executeWithRetry:439 - I/O exception (java.net.ConnectException) caught when processing request: Connection refused INFO,http-apr-9002-exec-4,10-22 20:21:30.592,httpclient.HttpMethodDirector.executeWithRetry:445 - Retrying request INFO,http-apr-9002-exec-4,10-22 20:21:30.594,httpclient.HttpMethodDirector.executeWithRetry:439 - I/O exception (java.net.ConnectException) caught when processing request: Connection refused INFO,http-apr-9002-exec-4,10-22 20:21:30.595,httpclient.HttpMethodDirector.executeWithRetry:445 - Retrying request java.net.ConnectException: Connection refused at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:579) at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:618) at com.legendshop.model.app.wxpay.MySSLProtocolSocketFactory.createSocket(MySSLProtocolSocketFactory.java:92) at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
这是因为代理访问被微信拒绝,所以需要重新设置访问程序:
StringEntity entity; HttpResponse httpResponse; int proxyPortCon = 0; DefaultHttpClient httpClient = new DefaultHttpClient(); //创建默认的httpClient实例 try { entity = new StringEntity(xml,"utf-8"); if("true".equalsIgnoreCase(useProxy) ){ X509TrustManager xtm = new X509TrustManager(){ //创建TrustManager public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return null; } }; X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() { public boolean verify(String arg0, SSLSession arg1) { return true; } public void verify(String arg0, SSLSocket arg1) throws IOException {} public void verify(String arg0, String[] arg1, String[] arg2) throws SSLException {} public void verify(String arg0, X509Certificate arg1) throws SSLException {} }; //TLS1.0与SSL3.0基本上没有太大的差别,可粗略理解为TLS是SSL的继承者,但它们使用的是相同的SSLContext SSLContext ctx = SSLContext.getInstance("TLS"); //使用TrustManager来初始化该上下文,TrustManager只是被SSL的Socket所使用 ctx.init(null, new TrustManager[] { xtm }, null); //创建SSLSocketFactory SSLSocketFactory socketFactory = new SSLSocketFactory(ctx); socketFactory.setHostnameVerifier(hostnameVerifier); //通过SchemeRegistry将SSLSocketFactory注册到我们的HttpClient上 httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", socketFactory, 443)); proxyPortCon = Integer.parseInt(proxyPort); HttpHost proxy = new HttpHost(proxyHost, proxyPortCon); httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } HttpPost httpPost = new HttpPost(unifiedorder); //创建HttpPost httpPost.setEntity(entity); httpPost.addHeader("Content-Type", "text/html;charset=UTF-8"); httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); //httpPost.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); httpResponse = httpClient.execute(httpPost); //执行POST请求 if (AppUtils.isNotBlank(httpResponse)) { HttpEntity httpEntity = httpResponse.getEntity(); String result = EntityUtils.toString(httpEntity, "UTF-8"); }
下面贴一些代码 供参考:
app前段调用微信统一下单接口
/** * 微信支付统一下单接口 * @param orderInfoJson 请求参数json * @return * @throws UnsupportedEncodingException */ @RequestMapping(value = "/pay/unifiedorder", method =RequestMethod.POST) @ResponseBody public Result getOrderInfo(HttpServletRequest request, HttpServletResponse response,@RequestParam("code") String code, @RequestParam("orderInfoJson") String orderInfoJson) throws UnsupportedEncodingException { Result result = null; //日志记录 AppServiceLog.info("orderInfoJson is {}", orderInfoJson); AppServiceLog.visit(AppInterfaceEnum.WECHAT_PAY, "/pay/unifiedorder", getUserName(request)); Map<?, ?> paramMap=JsonToMap.getBody(orderInfoJson); final Gson gson =new Gson(); WXPrepayVO orderInfo = gson.fromJson(gson.toJson(paramMap),WXPrepayVO.class); WXPrepay prePay = new WXPrepay(); //获取订单信息 result = orderService.payUnifiedorder(request,orderInfo,prePay); return result; }
服务器构造对象 向微信服务器发起https访问,以获取预支付id
public Result payUnifiedorder(HttpServletRequest request,WXPrepayVO orderInfo,WXPrepay prePay) throws UnsupportedEncodingException { Result result = new Result(); Double totalAmount = new Double(0); OrderTemp orderTemp = orderTempDao.getOrderByOrderNum(orderInfo.getOut_trade_no()); Order order = null; if(AppUtils.isBlank(orderTemp)){ order = orderDao.getOrderByOrderNumLimitOne(orderInfo.getOut_trade_no()); if(AppUtils.isNotBlank(order)){ totalAmount = order.getTotalAmount(); } }else{ totalAmount = orderTemp.getTotalAmount(); } if(AppUtils.isBlank(orderTemp) && AppUtils.isBlank(order)){ result.setCode(ReturnCode.orderIsNotExist.value()); result.setMessage(ReturnCode.orderIsNotExist.desc()); return result; } //商品描述 String bodyStr = Base64Decoder.Decoder(orderInfo.getBody()); String spbill_create_ip = request.getRemoteAddr(); prePay.setAppid(appId); prePay.setBody(bodyStr); prePay.setPartnerKey(appKey); prePay.setMch_id(mchId); prePay.setNotify_url(notifyUrl); prePay.setOut_trade_no(orderInfo.getOut_trade_no()); prePay.setSpbill_create_ip(spbill_create_ip); DecimalFormat df = new DecimalFormat("#"); prePay.setTotal_fee(df.format(totalAmount * 10 * 10)); //prePay.setTotal_fee("1"); prePay.setTrade_type(PayTypeEnum.WX_APP_PAY.value()); //代理 String useProxyConfig = PropertiesUtil.getUseProxy(); String proxyHostConfig = PropertiesUtil.getProxyHost(); String proxyPortConfig = PropertiesUtil.getProxyPort(); //此处添加获取openid的方法,获取预支付订单需要此参数!!!!!!!!!!! // 获取预支付订单号 WePayResponse wePayResponse = prePay.submitXmlGetPrepayId(useProxyConfig,proxyHostConfig,proxyPortConfig); wePayResponse.setPartnerId(mchId); wePayResponse.setPackageS("Sign=WXPay"); wePayResponse.setNonceStr(OrderUtil.CreateNoncestr()); wePayResponse.setTimeStamp(new Date().getTime()); if(wePayResponse.getResultCode().equals("SUCCESS")){ result.setCode(ReturnCode.OK.value()); result.setMessage(wePayResponse.getReturnMsg()); result.setSuccess(true); }else{ result.setMessage(wePayResponse.getErrCodeDes()); } result.setObject(wePayResponse); return result; }
/** * 生成预支付订单 * * @return * @throws UnsupportedEncodingException */ @SuppressWarnings("deprecation") public WePayResponse submitXmlGetPrepayId(String useProxy,String proxyHost,String proxyPort) throws UnsupportedEncodingException { System.out.println(useProxy +"--"+ proxyHost +"---"+ proxyPort); String xml = getPackage(); WePayResponse response = null; StringEntity entity; HttpResponse httpResponse; int proxyPortCon = 0; DefaultHttpClient httpClient = new DefaultHttpClient(); //创建默认的httpClient实例 try { entity = new StringEntity(xml,"utf-8"); if("true".equalsIgnoreCase(useProxy) ){ /** 下面这段代码 用来处理访问https的请求 **/ X509TrustManager xtm = new X509TrustManager(){ //创建TrustManager public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return null; } }; X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() { public boolean verify(String arg0, SSLSession arg1) { return true; } public void verify(String arg0, SSLSocket arg1) throws IOException {} public void verify(String arg0, String[] arg1, String[] arg2) throws SSLException {} public void verify(String arg0, X509Certificate arg1) throws SSLException {} }; //TLS1.0与SSL3.0基本上没有太大的差别,可粗略理解为TLS是SSL的继承者,但它们使用的是相同的SSLContext SSLContext ctx = SSLContext.getInstance("TLS"); //使用TrustManager来初始化该上下文,TrustManager只是被SSL的Socket所使用 ctx.init(null, new TrustManager[] { xtm }, null); //创建SSLSocketFactory SSLSocketFactory socketFactory = new SSLSocketFactory(ctx); socketFactory.setHostnameVerifier(hostnameVerifier); //通过SchemeRegistry将SSLSocketFactory注册到我们的HttpClient上 httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", socketFactory, 443)); /**** 下面这段代码 使用代理访问https外部接口 ****/ proxyPortCon = Integer.parseInt(proxyPort); HttpHost proxy = new HttpHost(proxyHost, proxyPortCon); httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } HttpPost httpPost = new HttpPost(unifiedorder); //创建HttpPost httpPost.setEntity(entity); httpPost.addHeader("Content-Type", "text/html;charset=UTF-8"); httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); //httpPost.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); httpResponse = httpClient.execute(httpPost); //执行POST请求 if (AppUtils.isNotBlank(httpResponse)) { HttpEntity httpEntity = httpResponse.getEntity(); String result = EntityUtils.toString(httpEntity, "UTF-8"); // 过滤 result = result.replaceAll("<![CDATA[|]]>", ""); String prepay_id = Jsoup.parse(result).select("prepay_id").html(); String trade_type = Jsoup.parse(result).select("trade_type").html(); String returnCode = Jsoup.parse(result).select("return_code").html(); String returnMsg = Jsoup.parse(result).select("return_msg").html(); String resultCode = Jsoup.parse(result).select("result_code").html(); String errCode = Jsoup.parse(result).select("err_code").html(); String errCodeDes = Jsoup.parse(result).select("err_code_des").html(); response = WePayResponse.newInstance(); response.setPrepayId(prepay_id); response.setTradeType(trade_type); response.setReturnCode(returnCode); response.setReturnMsg(returnMsg); response.setResultCode(resultCode); response.setErrCode(errCode); response.setErrCodeDes(errCodeDes); if (response != null) return response; } // 释放资源 } catch (Exception e) { e.printStackTrace(); } return response; }
相关推荐
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(USERNAME, PASSWORD)); httpClient.setCredentialsProvider(credentialsProvider); // 创建POST请求 ...
SVN 错误提示产生原因及处理方法大全 SVN(Subversion)是一种版本控制系统,广泛应用于软件开发、文档管理等领域。然而,在使用 SVN 过程中,可能会遇到各种错误提示,影响工作效率。本文将对 SVN 中常见的错误...
第三方登录-微信扫码登录 微信扫码登录是当前最流行的第三方登录方式之一,通过微信扫码,用户可以快速登录到第三方应用,提高用户体验,简化登录过程,降低注册门槛,获取海量用户,有效降低用户流失。微信扫码...
Invalid Login Credentials(解决方案).md
credentials-java-0.2.4.jar
grantType = 'client_credentials', secretKey = '替换成自己的secretKey', url = `https://aip.baidubce.com/oauth/2.0/token`小程序中有用到云开发,具体介绍请参考微信小程序官方文档,初始化云开发后, 替换app....
Credentials Plugin version:1.11 download from github,and have build it by: Run mvn clean package to create the plugin .hpi file. To install: 1. copy the resulting ./target/credentials.hpi file ...
<END><br>47 , email1mapi.zip<br>Visual Basic code for Sending email using MAPI control.<END><br>48 , Dan.zip<br>Dan's All purpose masterful program <END><br>49 , metasite.zip<br>this vb code executes...
### 运维OpenStack常见错误排除 #### 一、OpenStack错误排除方法 在运维OpenStack过程中,遇到问题时常见的排除方法主要包括查看日志和使用debug模式两种。 **方法1:查看日志** 查看日志是排查问题的第一步。...
python库。 资源全名:alibabacloud_credentials-0.0.3.tar.gz
- **错误处理**:你可以通过监听`401 Unauthorized`状态码来自定义错误处理。 - **多级授权**:可以结合其他中间件实现更复杂的权限控制。 - **加密密码**:为了安全起见,实际应用中不应明文存储密码,可以使用哈希...
"WebClient 访问间歇性返回 403 解决方案" 在本解决方案中,我们将讨论 WebClient 访问间歇性返回 403 的问题及其解决方法。首先,让我们来分析错误信息。WebClient 是一个常用的网络访问类,它可以模拟浏览器的...
Support for the "Prompt for Credentials on Client" RDP file setting when NLA is not negotiated. Support for smart card-based login via smart card redirection at the Winlogon prompt when NLA is not ...
这个压缩包包含的项目"SpringMVCSecurity-master"很可能是用来演示如何配置和使用Spring Security来实现自定义登录表单、处理无效凭证、基于角色的访问控制以及自定义访问拒绝错误消息的示例代码。 在Spring ...
"Laravel开发-credentials"指的是Laravel 5版本中引入的一种高效的身份验证机制,它旨在简化和加强用户认证流程。让我们深入探讨一下这个话题。 首先,Laravel的凭据(Credentials)主要涉及到用户登录时输入的...
垃圾分类小程序 小程序实现介绍: 小程序中有用到百度ai的...小程序中有用到云开发,具体介绍请参考微信小程序官方文档,初始化云开发后, 替换app.js中env的值。 wx.cloud.init({ env: '替换成自己的云开发环境id',
总之,解决Silverlight跨域访问自托管WCF服务的问题,主要涉及配置WCF服务的行为、添加跨域策略文件、以及正确配置Silverlight客户端。理解并实施这些步骤,可以有效地打破同源策略的限制,实现跨域TCP通信。
### 跨域访问解决方案与Cookie处理 在现代Web开发中,跨域问题一直是困扰开发者的一大难题。当浏览器出于安全考虑阻止不同源之间的数据交互时,跨域问题便产生了。为了解决这一问题,并确保在跨域场景下可以正确地...
add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET,POST'; 使用以下配置,生效。 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-...