微信支付中文乱码,带中文签名不成功

编程入门 行业动态 更新时间:2024-10-15 00:23:01

微信支付<a href=https://www.elefans.com/category/jswz/34/1769975.html style=中文乱码,带中文签名不成功"/>

微信支付中文乱码,带中文签名不成功

  • 在做微信公众号支付和H5支付时发现支付参数带中文就会签名失败,试过很多种办法如:
new String(xml.toString().getBytes(), "ISO8859-1");

把xml转为ISO8859-1提交到微信统一下单接口签名不正确,网上一般都是说这种做法。

  • 后面我用这样的方式能签名成功,也能支付
paraMap.put("body", URLEncoder.encode("棋牌", "UTF-8")); 

但是这样编码后,微信支付显示的body是编码后的一串乱码。

  • 最后终于查到是需要改md5签名前字符串的编码。

  • 统一下单的代码:WeChatH5PayImpl.java 微信h5支付

@Overridepublic JsonObject gateway(PayPlatform payPlatform, PayOrder order, Map<String, String> params) {JsonObject result = new JsonObject();try {//字典序列排序//第一次签名Map<String, String> paraMap = new HashMap<>();// paraMap.put("total_fee", order.getPrice().toString());paraMap.put("total_fee", "1");paraMap.put("appid", APPID);paraMap.put("out_trade_no", order.getMerchantOrderNo());paraMap.put("attach", order.getMerchantOrderNo());//TODO 中文编码有问题paraMap.put("body", "棋牌" );  //如果不转码,参数带中文会签名失败paraMap.put("mch_id", MCH_ID);paraMap.put("nonce_str", WeChatPublicNumberPayImpl.getNonceStr());paraMap.put("notify_url", notifyUrl);//paraMap.put("openid", params.getOrDefault("operId", ""));//"oPKW80lcsqmHLWvPLElQoN2p6Eow");String spbill_create_ip = params.getOrDefault("spbillCreateIp","127.0.0.1");if(-1 != spbill_create_ip.indexOf(",")){spbill_create_ip = spbill_create_ip.split(",")[0];}paraMap.put("spbill_create_ip",  spbill_create_ip);paraMap.put("trade_type", "MWEB");paraMap.put("scene_info","{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"\",\"wap_name\": \"棋牌\"}} ");//字典序列排序String url = WeChatPublicNumberPayImpl.formatUrlMap(paraMap, false, true);url = url + "&key=" + MCH_ID_KEY;String sign = MD5Utils.MD5Encoding(url).toUpperCase();StringBuffer xml = new StringBuffer();xml.append("<xml>");for (Map.Entry<String, String> entry : paraMap.entrySet()) {xml.append("<" + entry.getKey() + ">");xml.append(entry.getValue());xml.append("</" + entry.getKey() + ">" + "\n");}xml.append("<sign>");xml.append(sign);xml.append("</sign>");xml.append("</xml>");log.info("xml \n {} ", xml.toString());String responseBosy = HttpUtils.sentPost(PAYURL, xml.toString(), "UTF-8");log.info("responseBosy \n {}  " , responseBosy );Map<String,String> respBodyMap = WeChatPublicNumberPayImpl.readStringXmlOut(responseBosy);String return_code = respBodyMap.getOrDefault("return_code","");if(null != return_code && "SUCCESS".equals(return_code)){//成功result.put("code", 1);result.put("type", ReturnType.JUMP_PAGE_TYPE.getCode());result.put("redirect", respBodyMap.getOrDefault("mweb_url","")+"&redirect_url=");}else{//失败result.put("code",0);result.put("message","sign error");}} catch (Exception e) {result.put("code", 0);result.put("message","创建订单失败");}return result;}
  • WeChatPublicNumberPayImpl.java ASCII 码从小到大排序的代码
 /*** 方法用途: 对所有传入参数按照字段名的Unicode码从小到大排序(字典序),并且生成url参数串<br>   特别注意如果是微信公众号第二次签名使用这个 (prepay_id=wx2018011916085772ffb69ce20165288425)拼接出来的url package会有问题* 实现步骤: <br>** @param paraMap    要排序的Map对象* @param urlEncode  是否需要URLENCODE* @param keyToLower 是否需要将Key转换为全小写*                   true:key转化成小写,false:不转化* @return*/public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {String buff = "";Map<String, String> tmpMap = paraMap;try {List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {@Overridepublic int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {return (o1.getKey()).toString()pareTo(o2.getKey());}});// 构造URL 键值对的格式StringBuilder buf = new StringBuilder();for (Map.Entry<String, String> item : infoIds) {if (StringUtils.isNotBlank(item.getKey())) {String key = item.getKey();String val = item.getValue();if (urlEncode) {val = URLEncoder.encode(val, "utf-8");}if (keyToLower) {buf.append(key.toLowerCase() + "=" + val);} else {buf.append(key + "=" + val);}buf.append("&");}}buff = buf.toString();if (buff.isEmpty() == false) {buff = buff.substring(0, buff.length() - 1);}} catch (Exception e) {return null;}return buff;}
  • MD5Utils.java
package com.rwmon.utils;import java.security.MessageDigest;public class MD5Utils {private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};//重要的就是这里,要调这个方法签名才可以public static String MD5Encoding(String s) {byte[] btInput = null;try {btInput = s.getBytes("UTF-8");}catch (Exception e){}return MD5(btInput, 32);}public static String MD5(String s) {byte[] btInput = s.getBytes();return MD5(btInput, 32);}public static String MD5_16(String str) {byte[] btInput = str.getBytes();return MD5(btInput, 16);}private static String MD5(byte[] btInput, int length) {try {// 获得MD5摘要算法的 MessageDigest 对象MessageDigest mdInst = MessageDigest.getInstance("MD5");// MessageDigest mdInst = MessageDigest.getInstance("SHA-1");// 使用指定的字节更新摘要mdInst.update(btInput);// 获得密文byte[] md = mdInst.digest();// 把密文转换成十六进制的字符串形式int j = md.length;char str[] = new char[j * 2];int k = 0;for (byte byte0 : md) {str[k++] = hexDigits[byte0 >>> 4 & 0xf];str[k++] = hexDigits[byte0 & 0xf];}String result = new String(str);return length == 16 ? result.substring(8, 24) : result;} catch (Exception e) {e.printStackTrace();return null;}}
}
  • 这是最后执行结果:

  • 还有注意的:微信公众号支付的支付授权地址路径不能只写域名地址

更多推荐

微信支付中文乱码,带中文签名不成功

本文发布于:2024-02-25 01:07:02,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1697284.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:中文   乱码   不成功

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!