微信退款

来源:互联网 发布:淘宝买手店 编辑:程序博客网 时间:2024/06/02 23:21

需要用到的工具类 PayCommonUtil

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 com.thinkgem.jeesite.common.config.Global;import java.text.DecimalFormat;import java.util.*;/** * 微信支付 * Created by yuhaiming on 2016/11/18 0018. */public class WeChatUtil {    /**     * 基本常量设置     */    /**     * 统一下单请求路径     */    public static String UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";    /**     * 退款请求     */    public static String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";    /**     * APPID     */    public static String APP_ID = Global.getConfig("wechat.appid");    public static String APP_SECRET = Global.getConfig("wechat.appsecret");    /**     * 微信支付商户号     */    public static String MCH_ID = Global.getConfig("wechat.mch_id");    /**     * 密匙     */    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://tonyyule.ngrok.wendal.cn/app/home/paySeccess";    /**     * 生成微信签名     *     * @param order_id    订单ID     * @param body        描述     * @param order_price 价格     * @return     */    public static String GetWeChatXML(String order_id, String body, double order_price,String openid) {        String currTime = PayCommonUtil.getCurrTime();        String strTime = currTime.substring(8, currTime.length());        String strRandom = PayCommonUtil.buildRandom(4) + "";        //随机字符串        String nonce_str = strTime + strRandom;//UUID.randomUUID().toString();        // 获取发起电脑 ip        String spbill_create_ip = WeChatUtil.CREATE_IP;        //交易类型        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", 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;    }    /**     * 微信退款初始化数据     * @param out_trade_no     * @param total_fee     * @param refund_fee     * @return     */    public static String RefundInit(String out_trade_no,Double total_fee,Double refund_fee){        String refundid = UUID.randomUUID().toString();        refundid = refundid.substring(0, 32);        String currTime = PayCommonUtil.getCurrTime();        String strTime = currTime.substring(8, currTime.length());        String strRandom = PayCommonUtil.buildRandom(4) + "";        //随机字符串        String nonce_str = strTime + strRandom;        //价格转换        DecimalFormat df = new DecimalFormat("#######.##");        total_fee = total_fee * 100;        total_fee = Math.ceil(total_fee);        String total_price = df.format(total_fee);        refund_fee = refund_fee * 100;        refund_fee = Math.ceil(refund_fee);        String refund_price = df.format(refund_fee);        /*-----  1.生成预支付订单需要的的package数据-----*/        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();        packageParams.put("appid", APP_ID);        packageParams.put("mch_id", MCH_ID);        packageParams.put("nonce_str", nonce_str);        packageParams.put("op_user_id", MCH_ID);//操作员帐号, 默认为商户号        packageParams.put("out_trade_no", out_trade_no);        packageParams.put("out_refund_no", refundid);        packageParams.put("total_fee", total_price);        packageParams.put("refund_fee", refund_price);        /*----2.根据package生成签名sign---- */        String sign = PayCommonUtil.createSign("UTF-8", packageParams, API_KEY);        packageParams.put("sign", sign);         /*----3.拼装需要提交到微信的数据xml---- */        String xml = PayCommonUtil.getRequestXml(packageParams);        return xml;    }    /**     *     * 查询订单初始化数据     * @param out_trade_no     * @return     */    public static String OrderQuery(String out_trade_no){        String currTime = PayCommonUtil.getCurrTime();        String strTime = currTime.substring(8, currTime.length());        String strRandom = PayCommonUtil.buildRandom(4) + "";        //随机字符串        String nonce_str = strTime + strRandom;        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();        packageParams.put("appid", APP_ID);        packageParams.put("mch_id", MCH_ID);        packageParams.put("out_trade_no", out_trade_no);        packageParams.put("nonce_str", nonce_str);        /*----2.根据package生成签名sign---- */        String sign = PayCommonUtil.createSign("UTF-8", packageParams, API_KEY);        packageParams.put("sign", sign);         /*----3.拼装需要提交到微信的数据xml---- */        String xml = PayCommonUtil.getRequestXml(packageParams);        return xml;    }}


  /**     * 微信退款     * @param out_trade_no     * @param total_fee     * @param refund_fee     * @return     */    public static Map<String, String> wxRefund(String out_trade_no,Double total_fee,Double refund_fee) {        //证书文件路径        String path = Global.getProjectPath() + "/pp.p12";        Map<String, String> result = new HashMap<String, String>();        //初始化数据        String data = WeChatUtil.RefundInit(out_trade_no,total_fee,refund_fee);        try {             /*----4.读取证书文件,这一段是直接从微信支付平台提供的demo中copy的,所以一般不需要修改---- */            KeyStore keyStore = KeyStore.getInstance("PKCS12");            FileInputStream instream = new FileInputStream(new File(path));            try {                //证书密码(初始是商户 ID)                keyStore.load(instream, WeChatUtil.MCH_ID.toCharArray());            } finally {                instream.close();            }            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, WeChatUtil.MCH_ID.toCharArray()).build();            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);            CloseableHttpClient httpclient = HttpClients.custom() .setSSLSocketFactory(sslsf) .build();            HttpPost httpost = new HttpPost(WeChatUtil.REFUND_URL);            httpost.addHeader("Connection", "keep-alive");            httpost.addHeader("Accept", "*/*");            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");            httpost.addHeader("Host", "api.mch.weixin.qq.com");            httpost.addHeader("X-Requested-With", "XMLHttpRequest");            httpost.addHeader("Cache-Control", "max-age=0");            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");            httpost.setEntity(new StringEntity(data, "UTF-8"));            CloseableHttpResponse response = httpclient.execute(httpost);            HttpEntity entity = response.getEntity();            String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");            EntityUtils.consume(entity);            result = XMLUtil.doXMLParse(jsonStr);        } catch (Exception e) {            result.put("returncode", "error");            result.put("returninfo", "退款失败");        }        return result;    }





0 0