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

测试白名单也已设置。

请求路径:https://api.mch.weixin.qq.com/pay/unifiedorder
1、参数拼接(回车排序一下方便看):
appid=wxb5e39527f2f3eb32
&body=SourceTest
&mch_id=1271438801
&nonce_str=ns64Mu07nTYX2iPZ
¬ify_url=http://fanbingjiang.gicp.net/s/store/front/wxpay
&openid=oi18Jv38WxdxKEXF9ER-8mIyYya4
&out_trade_no=1234567891
&spbill_create_ip=58.42.242.98
&total_fee=1123
&trade_type=JSAPI
&key=36cd38f49b9afa08222c0dc9ebfe35eb
2、生成sign:54511A905603EDE7CED60F5643845EC7
3、拼接请求xml文件(顺序与第1步参数拼接一样):















4、请求返回值:


5、到https://pay.weixin.qq.com/wiki/tools/signverify/ 接口测试去验证了一下,结果与我的一样。


globals这个类是读取配置文件的类

参考jeesite


微信支付工具类

package com.thinkgem.jeesite.common.wechat;

import com.thinkgem.jeesite.common.config.Global;

import java.text.DecimalFormat;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

/**
 * 微信支付
 * Created by yuhaiming on 2016/11/18 0018.
 */
public class WeChatUtil {
    /**
     * 基本常量设置
     */

    /**
     * APPID
     */
    public static String APP_ID = Global.getConfig("wechat.appid");
    /**
     * 微信支付商户号
     */
    public static String MCH_ID= Global.getConfig("wechat.mch_id");
    /**
     * 请求路径
     */
    public static String UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    /**
     * 密匙
     */
    public static String API_KEY = Global.getConfig("wechat.key");
    /**
     * 发起支付IP
     */
    public static String CREATE_IP = "112.117.94.77";
    /**
     * 回调url
     */
    public static String NOTIFY_URL = "http%3a%2f%2fqqz33fe9841.ngrok.wendal.cn%2fapp%2fhome%2f";

    /**
     * 生成微信签名
     * @param order_id
     *         订单ID
     * @param body
     *         描述
     * @param order_price
     *         价格
     * @return
     */
    public static  String GetWeChatXML(String order_id, String body, double order_price ){
        String currTime = PayCommonUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = PayCommonUtil.buildRandom(4) + "";
        //随机字符串
        String nonce_str = strTime + strRandom;//UUID.randomUUID().toString();
        nonce_str=nonce_str.substring(0,16);
        // 获取发起电脑 ip
        String spbill_create_ip = WeChatUtil.CREATE_IP;
        // 回调接口
        String notify_url = WeChatUtil.NOTIFY_URL;
        //交易类型
        String trade_type = "JSAPI";
        //微信价格最小单位分 转换为整数
        DecimalFormat df = new DecimalFormat("#######.##");
        order_price = order_price * 100;
        order_price = Math.ceil(order_price);
        String price = df.format(order_price);
        SortedMap packageParams = new TreeMap();
        packageParams.put("appid", APP_ID);
        packageParams.put("body", body);
        packageParams.put("mch_id", MCH_ID);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("notify_url", notify_url);
        packageParams.put("out_trade_no", order_id);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("total_fee", price);
        packageParams.put("trade_type", trade_type);
        packageParams.put("openid", "o_6gNwi23RLC97cSPfHE-DEg3OLA");
        String sign = PayCommonUtil.createSign("UTF-8", packageParams,API_KEY);
        packageParams.put("sign", sign);
        String requestXML = PayCommonUtil.getRequestXml(packageParams);
        System.out.println(requestXML);
        return requestXML;
    }


}


package com.thinkgem.jeesite.common.wechat;

import java.text.SimpleDateFormat;
import java.util.*;

public class PayCommonUtil {
	/** 
     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 
     * @return boolean 
     */  
    @SuppressWarnings("unchecked")
	public static boolean isTenpaySign(String characterEncoding, SortedMap packageParams, String API_KEY) {  
        StringBuffer sb = new StringBuffer();  
        Set es = packageParams.entrySet();  
        Iterator it = es.iterator();  
        while(it.hasNext()) {  
            Map.Entry entry = (Map.Entry)it.next();  
            String k = (String)entry.getKey();  
            String v = (String)entry.getValue();  
            if(!"sign".equals(k) && null != v && !"".equals(v)) {  
                sb.append(k + "=" + v + "&");  
            }  
        }  
          
        sb.append("key=" + API_KEY);  
          
        //算出摘要  
        String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();  
        String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();  
          
        //System.out.println(tenpaySign + "    " + mysign);  
        return tenpaySign.equals(mysign);  
    }  

    /**
     * @Description:sign签名
     * @param characterEncoding
     *          编码格式
     * @param packageParams
     *          请求参数
     * @param API_KEY
     * @return
     */
    @SuppressWarnings("unchecked")
	public static String createSign(String characterEncoding, SortedMap packageParams, String API_KEY) {  
        StringBuffer sb = new StringBuffer();  
        Set es = packageParams.entrySet();  
        Iterator it = es.iterator();  
        while (it.hasNext()) {  
            Map.Entry entry = (Map.Entry) it.next();  
            String k = (String) entry.getKey();  
            String v = (String) entry.getValue();  
//            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k) && !"notify_url".equals(k)&& !"out_trade_no".equals(k)&& !"spbill_create_ip".equals(k)&& !"total_fee".equals(k)&& !"trade_type".equals(k)) { 
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k) ) {  
                sb.append(k + "=" + v + "&");  
            }  
        }  
        sb.append("key=" + API_KEY);  
//        String stringA="appid=wxc7b425229b570867&mch_id=1406330002&nonce_str=1702585759&key=ab42e0b7aa6bce35164a2d14855d7264";
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();  
//        String sign = MD5Util.MD5Encode(stringA, characterEncoding).toUpperCase();
//        System.out.println(sign);
//        System.out.println(MD5Util.MD5Encode("appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA&key=192006250b4c09247ec02edce69f6a2d", characterEncoding).toUpperCase());
//        System.out.println(sign);
        return sign;  
    }  
  
    /** 
     * @author 
     * @date 2016-4-22 
     * @Description:将请求参数转换为xml格式的string 
     * @param parameters 
     *            请求参数 
     * @return 
     */  
    @SuppressWarnings("unchecked")
	public static String getRequestXml(SortedMap parameters) {  
        StringBuffer sb = new StringBuffer();  
        sb.append("");  
        Set es = parameters.entrySet();  
        Iterator it = es.iterator();  
        while (it.hasNext()) {  
            Map.Entry entry = (Map.Entry) it.next();  
            String k = (String) entry.getKey();  
            String v = (String) entry.getValue();  
            if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {  
                sb.append("<" + k + ">" + "");  
            } else {  
                sb.append("<" + k + ">" + v + "");  
            }  
        }  
        sb.append("");  
        return sb.toString();  
    }  
  
    /** 
     * 取出一个指定长度大小的随机正整数. 
     *  
     * @param length 
     *            int 设定所取出随机数的长度。length小于11 
     * @return int 返回生成的随机数。 
     */  
    public static int buildRandom(int length) {  
        int num = 1;  
        double random = Math.random();  
        if (random < 0.1) {  
            random = random + 0.1;  
        }  
        for (int i = 0; i < length; i++) {  
            num = num * 10;  
        }  
        return (int) ((random * num));  
    }  
  
    /** 
     * 获取当前时间 yyyyMMddHHmmss 
     *  
     * @return String 
     */  
    public static String getCurrTime() {  
        Date now = new Date();  
        SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");  
        String s = outFormat.format(now);  
        return s;  
    }
}

发送请求 工具类

package com.thinkgem.jeesite.common.wechat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;

public class HttpUtil {
//	private static final Log logger = Logs.get();  
    private final static int CONNECT_TIMEOUT = 5000; // in milliseconds  
    private final static String DEFAULT_ENCODING = "UTF-8";  
      
    public static String postData(String urlStr, String data){  
        return postData(urlStr, data, null);  
    }  
      
    public static String postData(String urlStr, String data, String contentType){  
        BufferedReader reader = null;  
        try {  
            URL url = new URL(urlStr);  
            URLConnection conn = url.openConnection();  
            conn.setDoOutput(true);  
            conn.setConnectTimeout(CONNECT_TIMEOUT);  
            conn.setReadTimeout(CONNECT_TIMEOUT);  
            if(contentType != null)  
                conn.setRequestProperty("content-type", contentType);  
            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);  
            if(data == null)  
                data = "";  
            writer.write(data);   
            writer.flush();  
            writer.close();    
  
            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));  
            StringBuilder sb = new StringBuilder();  
            String line = null;  
            while ((line = reader.readLine()) != null) {  
                sb.append(line);  
                sb.append("\r\n");  
            }  
            return sb.toString();  
        } catch (IOException e) {  
//            logger.logError("Error connecting to " + urlStr + ": " + e.getMessage());  
        } finally {  
            try {  
                if (reader != null)  
                    reader.close();  
            } catch (IOException e) {  
            }  
        }  
        return null;  
    }  
}

调用方法

 String order_id="e3177146e5";
        String body="彼得潘";
        Double order =0.01;
        Map xmlMap = new HashMap<>();
        Map resMap = new HashMap<>();
        //生成签名
        String xml = WeChatUtil.GetWeChatXML(order_id,body,order);
        xmlMap = XMLUtil.doXMLParse(xml);

        //统一下单
        String SubmitResult = HttpUtil.postData(WeChatUtil.UFDODER_URL,xml);
        SortedMap SubmitMap = new TreeMap();
        //解析XML
        resMap = XMLUtil.doXMLParse(SubmitResult);
        String result_code  = resMap.get("result_code");
        if("SUCCESS".equals(result_code)) {
            //appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay
            SubmitMap.put("appid", WeChatUtil.APP_ID);
            SubmitMap.put("partnerid", WeChatUtil.MCH_ID);
            SubmitMap.put("prepayid", resMap.get("prepay_id"));
            SubmitMap.put("noncestr", resMap.get("nonce_str"));
            Long time = (System.currentTimeMillis() / 1000);
            SubmitMap.put("timestamp", time.toString());
            SubmitMap.put("package", "Sign=WXPay");
            //第二次生成签名
            String sign = PayCommonUtil.createSign("UTF-8", SubmitMap, WeChatUtil.API_KEY);
            SubmitMap.put("sign", sign);
        }


在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

最后 提醒各位 注意一下几点

1.支付签名是需要签名两次

2.检查key设置是否正确

尝试很多种方法都是签名错误 最后怀疑是不是KEY的问题 没想到真是
key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置

你可能感兴趣的:(Java,WeChat)