微信支付

来源:互联网 发布:果蔬清洗机有用吗 知乎 编辑:程序博客网 时间:2024/06/05 09:06
package com.hzbuvi.pay.wechat.controller;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.hzbuvi.pay.wechat.utils.HttpRequest;import com.hzbuvi.pay.wechat.utils.PayCommonUtil;import com.hzbuvi.pay.wechat.utils.WechatUtils;import com.hzbuvi.pay.wechat.utils.XmlUtils;import com.hzbuvi.util.basic.ValueUtil;import com.hzbuvi.util.date.DateUtil;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.*;/** * Created by SJQ on 2017/2/17. */@RestController@RequestMapping("/wechat")public class WechatPay{    private static final Logger log = LoggerFactory.getLogger(WechatPay.class);    private static String APPID = "wx29983132bd04dca9";//AppID(应用ID)    private static String MCHID= "1435678702";      private static String KEY= "eidiwoeid483";  //32位API密钥    private static String BODY= "order pay";//    private static String BODY= "订单支付";    private static String out_trade_no= DateUtil.toString(new Date(),"yyyyMMddHHmmss");    private static String product_id= DateUtil.toString(new Date(),"yyyyMMddHHmmss")+1;    private static String notify_url= "http://88.88.88.211:8095/backUrl/wechatPay";   //回调地址。测试回调必须保证外网能访问到此地址    @RequestMapping(value = "/pay",method = RequestMethod.GET)    public String pay(@RequestParam Map<String,String> params){        JSONObject retJson = new JSONObject();        try {            String jsonStr = ValueUtil.toJson(params);            JSONObject requestObj = JSON.parseObject(jsonStr);//            String out_trade_no = requestObj.getString("out_trade_no");//            String order_price = requestObj.getString("order_price");            // 正式上线的时候价格根据订单id查询            String order_price = "1"; // 价格 注意:价格的单位是分            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();            //商户信息            packageParams.put("appid", APPID);      //公众账号ID            packageParams.put("mch_id", MCHID);     //商户号            packageParams.put("nonce_str", WechatUtils.getNonce_str());      //随机字符串            packageParams.put("body",new String(BODY.getBytes("utf-8"))  );        //商品描述  eg:腾讯充值中心-QQ会员充值            packageParams.put("trade_type", "NATIVE");      //交易类型  JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里            packageParams.put("spbill_create_ip", "123.12.12.123");     //终端IP  eg:123.12.12.123            packageParams.put("notify_url", notify_url);        //通知地址  异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。            packageParams.put("out_trade_no", out_trade_no);        //商户订单号            packageParams.put("total_fee", order_price);        //标价金额  订单总金额,单位为分,详见支付金额                                                                //MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口            packageParams.put("product_id", product_id);        //商品ID trade_type=NATIVE时(即扫码支付),此参数必传。此参数为二维码中包含的商品ID,商户自行定义。            Calendar nowTime = Calendar.getInstance();            packageParams.put("time_start", DateUtil.toString(      //交易起始时间  订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。                    nowTime.getTime(), "yyyyMMddHHmmss"));//            packageParams.put("time_expire", DateUtil.toString(     //交易结束时间  订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。//                    nowTime.getTime(), "yyyyMMddHHmmss"));            //生成签名字符串            String sign = PayCommonUtil.createSign("UTF-8", packageParams, KEY);            packageParams.put("sign", sign);    //签名            String requestXML = PayCommonUtil.getRequestXml(packageParams);            log.info("支付请求:" + requestXML);            long startTime=System.currentTimeMillis();            String resXml = HttpRequest.post(                    "https://api.mch.weixin.qq.com/pay/unifiedorder",                    requestXML);            log.info("请求结果:" + resXml);            long endTime=System.currentTimeMillis();            Integer execute_time = (int) ((endTime-startTime)/1000);            SortedMap map = XmlUtils.parseXmlStr(resXml);            Boolean validateCallback = PayCommonUtil.isTenpaySign("utf-8",map,KEY);            log.info("验证返回签名结果:" + validateCallback);            if (!validateCallback){                return ValueUtil.toError("999","回掉签名验证失败");            }            JSONObject reportParams = new JSONObject();            reportParams.put("url", "https://api.mch.weixin.qq.com/pay/unifiedorder");            reportParams.put("execute_time", execute_time);            reportParams.put("return_code", map.get("return_code").toString());            reportParams.put("return_msg", map.get("return_msg").toString());            reportParams.put("result_code", map.get("result_code").toString());            if (map.get("err_code") != null) {                reportParams.put("err_code", map.get("err_code").toString());                reportParams.put("err_code_des", map.get("err_code_des").toString());            }            reportParams.put("out_trade_no", out_trade_no);            //交易保障//            report(reportParams.toString());            if (map.get("return_code").toString().equals("SUCCESS") && map.get("result_code").toString().equals("SUCCESS")) {                String urlCode = (String) map.get("code_url"); //微信二维码短链接                retJson.put("code", 0);                retJson.put("message", "下单成功.");                retJson.put("data", urlCode);            } else {                retJson.put("code", 1);                retJson.put("message", map.get("err_code_des").toString());                retJson.put("data", "");            }            return retJson.toString();        } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }        return null;    }}
package com.hzbuvi.pay.wechat.utils;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.apache.http.ProtocolException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.net.ssl.HttpsURLConnection;import java.io.*;import java.net.ConnectException;import java.net.MalformedURLException;import java.net.URL;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.text.SimpleDateFormat;import java.util.*;/** * Created by SJQ on 2017/2/17. */public class PayCommonUtil {    public static Logger log = LoggerFactory.getLogger(PayCommonUtil.class);    /**     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。     * @return boolean     */    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 = MD5.MD5Encode(sb.toString()).toLowerCase();        String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();        //System.out.println(tenpaySign + "    " + mysign);        return tenpaySign.equals(mysign);    }/**     * @author     * @date 2016-4-22     * @Description:sign签名     * @param characterEncoding     *            编码格式     * @params parameters     *            请求参数     * @return     */    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 = "";            try {                v = (String) entry.getValue();            } catch (Exception e) {                // TODO: handle exception                v = entry.getValue() + "";            }            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {                sb.append(k + "=" + v + "&");            }        }        sb.append("key=" + API_KEY);        System.out.println("ASCII字典序排序::::"+sb.toString());        String sign = MD5.MD5Encode(sb.toString()).toUpperCase();        return sign;    }    /**     * @author     * @date 2016-4-22     * @Description:将请求参数转换为xml格式的string     * @param parameters     *            请求参数     * @return     */    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 = "";            try {                v = (String) entry.getValue();            } catch (Exception e) {                // TODO: handle exception                v = 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;    }    public static JSONObject httpsRequestToJsonObject(String requestUrl,                                                      String requestMethod, String outputStr) {        JSONObject jsonObject = null;        try {            StringBuffer buffer = httpsRequest(requestUrl, requestMethod,                    outputStr);            jsonObject = JSON.parseObject(buffer.toString());        } catch (ConnectException ce) {            log.error("连接超时:" + ce.getMessage());        } catch (Exception e) {            log.error("https请求异常:" + e.getMessage());        }        return jsonObject;    }    private static StringBuffer httpsRequest(String requestUrl,                                             String requestMethod, String output)            throws NoSuchAlgorithmException, NoSuchProviderException,            KeyManagementException, MalformedURLException, IOException,            ProtocolException, UnsupportedEncodingException {        URL url = new URL(requestUrl);        HttpsURLConnection connection = (HttpsURLConnection) url                .openConnection();        connection.setDoOutput(true);        connection.setDoInput(true);        connection.setUseCaches(false);        connection.setRequestMethod(requestMethod);        if (null != output) {            OutputStream outputStream = connection.getOutputStream();            outputStream.write(output.getBytes("UTF-8"));            outputStream.close();        }        // 从输入流读取返回内容        InputStream inputStream = connection.getInputStream();        InputStreamReader inputStreamReader = new InputStreamReader(                inputStream, "utf-8");        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);        String str = null;        StringBuffer buffer = new StringBuffer();        while ((str = bufferedReader.readLine()) != null) {            buffer.append(str);        }        bufferedReader.close();        inputStreamReader.close();        inputStream.close();        inputStream = null;        connection.disconnect();        return buffer;    }}
package com.hzbuvi.pay.wechat.utils;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.DocumentHelper;import org.dom4j.Element;import java.util.*;import static javax.swing.text.html.HTML.Tag.BODY;import static javax.swing.text.html.HTML.Tag.HEAD;/** * Created by SJQ on 2017/2/17. */public class XmlUtils {    /**     * 解析XML字符串     *     * @param xml     * @return     * @throws     */    public static SortedMap<String,Object> parseXmlStr(String xml){        SortedMap<String,Object> map = new TreeMap<String, Object>();        try {            Document document = DocumentHelper.parseText(xml);            Element root = document.getRootElement();            Iterator<Element> it = root.elementIterator();            while (it.hasNext()) {                Element element = it.next();                map.put(element.getName(), element.getTextTrim());            }        } catch (DocumentException e) {            e.printStackTrace();        }        return map;    }}
package com.hzbuvi.pay.wechat.utils;import java.security.MessageDigest;/** * User: rizenguo * Date: 2014/10/23 * Time: 15:43 */public class MD5 {    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",            "8", "9", "a", "b", "c", "d", "e", "f"};    /**     * 转换字节数组为16进制字串     * @param b 字节数组     * @return 16进制字串     */    public static String byteArrayToHexString(byte[] digest) {        StringBuffer hexValue = new StringBuffer();        for (int i = 0; i < digest.length; i++) {            int val = ((int) digest[i]) & 0xff;            if (val < 16)                hexValue.append("0");            hexValue.append(Integer.toHexString(val));        }        return hexValue.toString();    }    /**     * 转换byte到16进制     * @param b 要转换的byte     * @return 16进制格式     */    private static String byteToHexString(byte b) {        int n = b;        if (n < 0) {            n = 256 + n;        }        int d1 = n / 16;        int d2 = n % 16;        return hexDigits[d1] + hexDigits[d2];    }    /**     * MD5编码     * @param origin 原始字符串     * @return 经过MD5加密之后的结果     */    public static String MD5Encode(String origin) {        String resultString = null;        try {            resultString = origin;            MessageDigest md = MessageDigest.getInstance("MD5");            // resultString = byteArrayToHexString(md.digest(resultString.getBytes()));//原文件内容,可能原因是:win2003时系统缺省编码为GBK,win7为utf-8            resultString = byteArrayToHexString(md.digest(resultString.getBytes("utf-8")));//正确的写法        } catch (Exception e) {            e.printStackTrace();        }        return resultString;    }}
package com.hzbuvi.pay.wechat.utils;import java.io.*;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLConnection;import java.util.List;import java.util.Map;/** * Created by SJQ on 2017/2/17. */public class HttpRequest {    public static String post(String url,String pama) throws IOException{        URL postUrl = new URL(url);        // 打开连接        HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();        // 设置是否向connection输出,因为这个是post请求,参数要放在        // http正文内,因此需要设为true        connection.setDoOutput(true);        //设置超时时间        connection.setConnectTimeout(10000);        // Read from the connection. Default is true.        connection.setDoInput(true);        // 默认是 GET方式        connection.setRequestMethod("POST");        // Post 请求不能使用缓存        connection.setUseCaches(false);        connection.setInstanceFollowRedirects(true);        // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的        // 意思是正文是urlencoded编码过的form参数,下面我们可以看到我们对正文内容使用URLEncoder.encode        // 进行编码        connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");        // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,        // 要注意的是connection.getOutputStream会隐含的进行connect。        connection.connect();        DataOutputStream out = new DataOutputStream(connection                .getOutputStream());        // The URL-encoded contend        // 正文,正文内容其实跟get的URL中 '? '后的参数字符串一致        // DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写到流里面        out.writeBytes(pama);        out.flush();        out.close();        int status =  connection.getResponseCode();        if(status==200){            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));            String line;            StringBuffer sb = new StringBuffer("");            while ((line = reader.readLine()) != null){                line = new String(line);                sb.append(line);            }            reader.close();            connection.disconnect();            if(sb.toString().length()>0){                return sb.toString();            }            return String.valueOf(status);        }        return String.valueOf(status);    }}
0 0
原创粉丝点击