关闭

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

标签: 支付微信乱码中文参数
129人阅读 评论(0) 收藏 举报
分类:
  • 在做微信公众号支付和H5支付时发现支付参数带中文就会签名失败,试过很多种办法如:
new String(xml.toString().getBytes(), "ISO8859-1");

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

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

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

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

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

@Override
    public 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\": \"http://www.test.com\",\"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=http://h5.ccac7.com/api/login");
            }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>>() {
                @Override
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(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.rw.common.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;
        }
    }
}
  • 这是最后执行结果:
    这里写图片描述
0
0
查看评论

微信支付一直签名错误

这两天无数次在做微信支付的时候出现签名错误,都快崩溃了。明明我自己生成的签名是没得问题的。自己手动生成的签名,和官方的微信支付接口测试结果是一样的。 后来无意中提到了  postMethod.setRequestEntity(new StringRequestEntity(x...
  • qq_25821067
  • qq_25821067
  • 2017-02-16 11:25
  • 6170

微信支付统一下单,签名错误

微信支付统一下单,签名错误
  • ZaiYiNiDeZaiYi
  • ZaiYiNiDeZaiYi
  • 2017-04-19 15:03
  • 7816

微信支付签名错误

之前写了一些支付宝和微信支付集成的文章,收到了广大网友的关注和讨论,感到非常开心。最近做了支付宝和微信支付的二次升级,支付宝的API调用有了些许变化,支付宝官方放出了2.0,在此也强烈建议大家使用新版的支付宝支付API。这个讲在后续博文中公开。今天主要说说微信支付出现的签名错误问题。其实是一个很小的...
  • xinluqishi123
  • xinluqishi123
  • 2017-07-06 19:04
  • 492

微信支付有汉字时出现签名错误的解决办法

微信支付有汉字时出现签名错误的解决办法 最近发现在win2003开发微信支付时,有汉字时出现签名错误,但在win7上不会出错, 最后发现是字符编码不一致造成的。 解决办法 改正wxpay-scanpay-java-sdk-1.0.jar中的md5.java文件, /** ...
  • yjg428
  • yjg428
  • 2015-03-06 23:44
  • 17041

如何集成android微信支付及各种问题(-1,签名错误,无法获得预支付id)的解决办法。

集成微信支付遇到的各种问题
  • gaoqingliang521
  • gaoqingliang521
  • 2017-05-31 16:12
  • 2485

微信支付后台总是返回数据签名错误篇一

String appid = CommonsUtil.appid; // 公众账号 ID String mch_id = CommonsUtil.mchId;// 商户号 String body = "蒙坤尚烤牛肉干";// 商品描述 String total_fee = &qu...
  • safedriver
  • safedriver
  • 2014-11-15 15:35
  • 5456

微信小程序支付签名失败,错误的解决方法,小程序支付签名paySign开发demo

微信小程序支付开发, 其实这里的接口, 大部分跟微信公众号支付接口类似, 包括 1、 签名 2、 提交证书 3、 统一下单 4、 订单查询 5、 退款处理 … 今天子恒老师带你实现怎么...
  • towtotow
  • towtotow
  • 2018-01-13 10:39
  • 226

微信支付——支付签名验证失败的坑

只讲几个微信支付开发中的签名问题!(JAVA版的公众号支付) 在调起支付页面时,就会要你自己生成2个sign(建议全部用MD5): 第一个是获取订单数据时生成,然后通过这些数据生成预支付订单(通过 统一下单 方法取得),微信官方返回一串xml数据,告诉你是否成功。 第二个是需要把数据传给前端调...
  • qq_35641337
  • qq_35641337
  • 2018-01-11 00:25
  • 77

Android微信支付签名错误解决方法

整体流程:1.拼接商品的信息List<NameValuePair> packageParams = new LinkedList<NameValuePair>(); packageParams.add(new BasicNameValuePair(&q...
  • guoh_
  • guoh_
  • 2016-01-25 12:03
  • 9068

微信公众号支付签名验证错误

微信公从号支付,其坑之多,搜索一下可见一斑。 签名验证错误,除了告诉你签名验证错误之外,没有任何更多提示。 可能的原因:安全域名、目录未正确设置,参与签名的值与调用的值不一致(如timestamp签名时动态取,回显时也动态取)等。 但当你每纠正一步,仍然看到的是签名验证错误时,你会开始怀疑自己...
  • triplestudio
  • triplestudio
  • 2017-09-11 10:22
  • 1339
    个人资料
    • 访问:216068次
    • 积分:2769
    • 等级:
    • 排名:第15322名
    • 原创:136篇
    • 转载:0篇
    • 译文:0篇
    • 评论:54条
    jvm
    jvm