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

2 篇文章 0 订阅

测试白名单也已设置。

请求路径:https://api.mch.weixin.qq.com/pay/unifiedorder
1、参数拼接(回车排序一下方便看):
appid=wxb5e39527f2f3eb32
&body=SourceTest
&mch_id=1271438801
&nonce_str=ns64Mu07nTYX2iPZ
&notify_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步参数拼接一样):

<xml>
<appid><![CDATA[wxb5e39527f2f3eb32]]></appid>
<body><![CDATA[SourceTest]]></body>
<mch_id><![CDATA[1271438801]]></mch_id>
<nonce_str><![CDATA[ns64Mu07nTYX2iPZ]]></nonce_str>
<notify_url><![CDATA[http://fanbingjiang.gicp.net/s/store/front/wxpay]]></notify_url>
<openid><![CDATA[oi18Jv38WxdxKEXF9ER-8mIyYya4]]></openid>
<out_trade_no><![CDATA[1234567891]]></out_trade_no>
<spbill_create_ip><![CDATA[58.42.242.98]]></spbill_create_ip>
<total_fee><![CDATA[1123]]></total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<sign><![CDATA[54511A905603EDE7CED60F5643845EC7]]></sign>
</xml>


4、请求返回值:
<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名错误]]></return_msg></xml>


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<Object,Object> packageParams = new TreeMap<Object,Object>();
        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<Object, Object> 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<Object, Object> 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<Object, Object> parameters) {  
        StringBuffer sb = new StringBuffer();  
        sb.append("<xml>");  
        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 + ">" + "<![CDATA[" + v + "]]></" + k + ">");  
            } else {  
                sb.append("<" + k + ">" + v + "</" + k + ">");  
            }  
        }  
        sb.append("</xml>");  
        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<String,String> xmlMap = new HashMap<>();
        Map<String,String> resMap = new HashMap<>();
        //生成签名
        String xml = WeChatUtil.GetWeChatXML(order_id,body,order);
        xmlMap = XMLUtil.doXMLParse(xml);

        //统一下单
        String SubmitResult = HttpUtil.postData(WeChatUtil.UFDODER_URL,xml);
        SortedMap<Object,Object> SubmitMap = new TreeMap<Object,Object>();
        //解析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安全-->密钥设置

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
FastAdmin 是一款开源的后台管理系统框架,它支持集成微信支付和支付宝支付功能。当我们在FastAdmin中进行统一下单操作后,会返回一些数据。 对于微信支付来说,统一下单接口会返回一个包含支付链接的二维码图片地址,我们可以通过访问这个地址来获取支付二维码,用户扫描该二维码后就可以进行支付。同时,还会返回一些其他的数据,如交易订单号、总金额、支付结果等,以便我们在后续的操作中进行查询和处理。 对于支付宝支付来说,统一下单接口会返回一个form表单,其中包含了支付宝支付页面的跳转URL和一些订单信息。我们可以将这个form表单输出到页面上,用户点击提交后就会跳转到支付宝支付页面进行支付操作。支付宝返回的支付结果会通过前台的同步通知或后台的异步通知来确认,以保证支付结果的准确性。 FastAdmin提供了相应的回调函数和接口,我们可以根据支付结果的通知进行订单状态的更新和后续的业务处理。在接收到支付宝或微信支付的异步通知后,我们可以通过验证通知的签名和订单信息来确保支付结果和订单的安全性。根据不同的支付状态,我们可以更新订单的状态、生成发货通知、发送邮件等。 总之,FastAdmin的微信支付和支付宝支付统一下单返回的数据包含了支付相关的信息和链接,方便我们在后续操作中进行查询、处理和回调。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值