用java实现微信支付,退款,部分退款服务端

由于公司业务需要,最近搞微信退款功能,今天抽空在此记录一下,以后用到也可以到这来看一眼。废话不多说,进入正题。

微信支付以及付款呢,先要有个证书,不清楚的,还要有证书,可以去微信平台看证书怎么下载 https://pay.weixin.qq.com, APP_ID,MCH_ID,API_KEY,当然这些你可以向你boss要,

下面就是我的代码了

maven文件

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.mobile</groupId>
            <artifactId>spring-mobile-device</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-search-orm</artifactId>
            <version>5.6.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.ansj</groupId>
            <artifactId>ansj_seg</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.ansj</groupId>
            <artifactId>ansj_lucene5_plug</artifactId>
            <version>5.1.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-web</artifactId>
            <version>2.0.4</version>
            <exclusions>
                <exclusion>
                    <groupId>net.sf.ehcache</groupId>
                    <artifactId>ehcache-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.3.2</version>
            <exclusions>
                <exclusion>
                    <groupId>net.sf.ehcache</groupId>
                    <artifactId>ehcache-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-email</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.12</version>
        </dependency>
        <dependency>
            <groupId>org.apache.oltu.oauth2</groupId>
            <artifactId>org.apache.oltu.oauth2.client</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.jxls</groupId>
            <artifactId>jxls</artifactId>
            <version>2.4.3</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jxls</groupId>
            <artifactId>jxls-poi</artifactId>
            <version>1.0.14</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
        </dependency>
        <dependency>
            <groupId>org.im4java</groupId>
            <artifactId>im4java</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.51</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>2.0.5</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.perf4j</groupId>
            <artifactId>perf4j</artifactId>
            <version>0.9.16</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
        <dependency>
            <groupId>com.googlecode.log4jdbc</groupId>
            <artifactId>log4jdbc</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.alipay</groupId>
            <artifactId>alipay-sdk</artifactId>
            <version>20171026141113</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.kaptcha</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>oracle</groupId>
            <artifactId>ojdbc</artifactId>
            <version>7</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.2.0</version>
        </dependency>
        
        <!-- getui -->
        <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-fastjson</artifactId>
            <version>1.0.0.1</version>
          </dependency>
        <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-sdk-http</artifactId>
            <version>4.0.1.17</version>
          </dependency>
          <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-sdk-template</artifactId>
            <version>4.0.0.16</version>
          </dependency>
          <dependency>
            <groupId>com.gexin.platform</groupId>
            <artifactId>gexin-rp-sdk-base</artifactId>
            <version>4.0.0.22</version>
          </dependency>
          <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>2.5.0</version>
        </dependency>
        
        <!-- 微信支付工具类需要的jar end-->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>
        <dependency>
          <groupId>com.alibaba</groupId>
              <artifactId>fastjson</artifactId>
              <version>1.2.32</version>
            </dependency>
            <!-- 微信支付工具类需要的jar start-->
        <dependency>
          <groupId>jdom</groupId>
          <artifactId>jdom</artifactId>
          <version>1.1</version>
        </dependency>
        <dependency>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpmime</artifactId>
          <version>4.5.3</version>
        </dependency>
        <!-- log start -->
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
        </dependency>
        <!-- 支付宝 -->
        <dependency>
          <groupId>commons-httpclient</groupId>
          <artifactId>commons-httpclient</artifactId>
          <version>3.1</version>
        </dependency>
    </dependencies>

工具类:

XMLUtil 类:

import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @Author: HONGLINCHEN
 * @Description: xml 工具类
 * @Date: 2018-8-23
 */
public class XMLUtil {
   /**
    * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 微信支付 解析xml xml转map  获取prepay_id
    * @param strxml
    * @throws JDOMException
    * @throws IOException
    */
   public static Map doXMLParse(String strxml) throws JDOMException, IOException {
      strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

      if(null == strxml || "".equals(strxml)) {
         return null;
      }
      
      Map m = new HashMap();
      
      InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
      SAXBuilder builder = new SAXBuilder();
      Document doc = builder.build(in);
      Element root = doc.getRootElement();
      List list = root.getChildren();
      Iterator it = list.iterator();
      while(it.hasNext()) {
         Element e = (Element) it.next();
         String k = e.getName();
         String v = "";
         List children = e.getChildren();
         if(children.isEmpty()) {
            v = e.getTextNormalize();
         } else {
            v = XMLUtil.getChildrenText(children);
         }
         
         m.put(k, v);
      }
      
      //关闭流
      in.close();
      
      return m;
   }
   /**
    * @Author: HONGLINCHEN
    * @Description: 微信支付 解析xml xml转map  获取prepay_id
    * @param xml
    * @Date: 2017-9-8 10:13
    */
   public static Map<String,Object> getResult(String xml){
      Map<String,Object> map = new HashMap<String, Object>();
      try {
         org.dom4j.Document document = DocumentHelper.parseText(xml);
         org.dom4j.Element root = document.getRootElement();
         Iterator<org.dom4j.Element> it = root.elementIterator();
         while (it.hasNext()) {
            org.dom4j.Element element = it.next();
            map.put(element.getName(), element.getTextTrim());
         }
      } catch (DocumentException e) {
         e.printStackTrace();
      }
      return map;
   }
   /**
    * 获取子结点的xml
    * @param children
    * @return String
    */
   public static String getChildrenText(List children) {
      StringBuffer sb = new StringBuffer();
      if(!children.isEmpty()) {
         Iterator it = children.iterator();
         while(it.hasNext()) {
            Element e = (Element) it.next();
            String name = e.getName();
            String value = e.getTextNormalize();
            List list = e.getChildren();
            sb.append("<" + name + ">");
            if(!list.isEmpty()) {
               sb.append(XMLUtil.getChildrenText(list));
            }
            sb.append(value);
            sb.append("</" + name + ">");
         }
      }
      
      return sb.toString();
   }
   
   /**
    * 获取xml编码字符集
    * @param strxml
    * @return
    * @throws IOException 
    * @throws JDOMException 
    */
   public static String getXMLEncoding(String strxml) throws JDOMException, IOException {
      InputStream in = String2Inputstream(strxml);
      SAXBuilder builder = new SAXBuilder();
      Document doc = builder.build(in);
      in.close();
      return (String)doc.getProperty("encoding");
   }
   public static InputStream String2Inputstream(String str) {
      return new ByteArrayInputStream(str.getBytes());
   }
   
}
 

WXPayUtil类:

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.util.*;

/**
 * @Author: HONGLINCHEN
 * @Description:微信支付
 * @Date: 2018-8-23
 */
public class WXPayUtil {
    public static String PostRequest(String url, String data) throws IOException {
        HttpClient client = new HttpClient();
        PostMethod post=new PostMethod(url);
        String result = "";
        post.addRequestHeader("Content-Type", "text/html; charset=utf-8");
        post.addRequestHeader("content", "text/html; charset=utf-8");
        post.setRequestBody(data);
        try {
            int status=client.executeMethod(post);
            result = post.getResponseBodyAsString();
            result = new String(result.getBytes(post.getResponseCharSet()), "utf-8");
        } catch (IOException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     */
    public static String createSign(SortedMap<String, String> packageParams, String AppKey) {
        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)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + AppKey);
        String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
        return sign;
    }
    /**
     * @Author: HONGLINCHEN
     * @Description:微信支付 统一下单
     * @param out_trade_no
     * @param body
     * @param detail
     * @param total_fee
     * @param ip_address
     * @Date:2018-8-23
     * @return:
     */
    public static String unifiedOrder(String out_trade_no, String body, String detail, int total_fee,String ip_address) {
        StringBuffer xml = new StringBuffer();
        String data = null;
        try{
            xml.append("</xml>");
            if (body.length() > 32) {
                body = body.substring(0, 32);
            }
            SortedMap<String, String> parameters = new TreeMap();
            parameters.put("appid", WXPayConstants.APP_ID);
            parameters.put("body", body);
            parameters.put("detail", detail);
            parameters.put("mch_id", WXPayConstants.MCH_ID);
            parameters.put("nonce_str", genNonceStr());
            parameters.put("notify_url", "http://www.aidongsports.com/wx");
            parameters.put("out_trade_no", out_trade_no);
            parameters.put("fee_type", "CNY");
            parameters.put("spbill_create_ip", ip_address);
            parameters.put("total_fee", String.valueOf(total_fee));
            parameters.put("trade_type", "APP");
            parameters.put("sign", createSign(parameters, WXPayConstants.API_KEY));
            data = PostRequest("https://api.mch.weixin.qq.com/pay/unifiedorder",SortedMaptoXml(parameters));
        }catch (Exception e){
            e.printStackTrace();
        }
        return data;
    }
    /**
     * @Author: HONGLINCHEN
     * @Description:微信退款
     * @param out_trade_no 商户订单号
     * @param transaction_id 微信订单号
     * @param total_fee 订单总金额
     * @Date: 2018-8-23
     * @return:
     */
    public static String wxPayRefund(String out_trade_no, String transaction_id,String total_fee) {
        StringBuffer xml = new StringBuffer();
        String data = null;
        try {
            String nonceStr = genNonceStr();//生成32位随机字符串
            xml.append("</xml>");
            SortedMap<String,String> parameters = new TreeMap<String,String>();
            parameters.put("appid", WXPayConstants.APP_ID);
            parameters.put("mch_id", WXPayConstants.MCH_ID);
            parameters.put("nonce_str", nonceStr);
            parameters.put("out_trade_no", out_trade_no);
            parameters.put("transaction_id", transaction_id);
            parameters.put("out_refund_no", nonceStr);
            parameters.put("fee_type", "CNY");
            parameters.put("total_fee", total_fee);
            parameters.put("refund_fee", total_fee);
            parameters.put("op_user_id", WXPayConstants.MCH_ID);
            parameters.put("sign", createSign(parameters, WXPayConstants.API_KEY));
            data =SortedMaptoXml(parameters);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
        return data;
    }
    
    /**
     * @Author: HONGLINCHEN
     * @Description:微信部分退款
     * @param out_trade_no 商户订单号
     * @param transaction_id 微信订单号
     * @param total_fee 订单总金额
     * @param refund_fee 退款金额
     * @Date: 2018-8-23
     * @return:
     */
    public static String wxPayRefund(String out_trade_no, String transaction_id,String total_fee,String refund_fee) {
        StringBuffer xml = new StringBuffer();
        String data = null;
        try {
            String nonceStr = genNonceStr();//生成32位随机字符串
            xml.append("</xml>");
            SortedMap<String,String> parameters = new TreeMap<String,String>();
            parameters.put("appid", WXPayConstants.APP_ID);
            parameters.put("mch_id", WXPayConstants.MCH_ID);
            parameters.put("nonce_str", nonceStr);
            parameters.put("out_trade_no", out_trade_no);
            parameters.put("transaction_id", transaction_id);
            parameters.put("out_refund_no", nonceStr);
            parameters.put("fee_type", "CNY");
            parameters.put("total_fee", total_fee);
            parameters.put("refund_fee", refund_fee);//部退款金额
            parameters.put("op_user_id", WXPayConstants.MCH_ID);
            parameters.put("sign", createSign(parameters, WXPayConstants.API_KEY));
            data =SortedMaptoXml(parameters);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
        return data;
    }
    
    
    /**
     * 证书使用
     * 微信退款
     */
    public static String wxPayBack(String url, String data) throws Exception {
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
//        FileInputStream instream = new FileInputStream(new File("F:\\wx\\apiclient_cert.p12"));
        
        InputStream inputStream = WXPayUtil.class.getClassLoader().getResourceAsStream("apiclient_cert.p12");
        //FileInputStream instream=(FileInputStream)inputStream;
        String result="";
        try {
            keyStore.load(inputStream, WXPayConstants.MCH_ID.toCharArray());
        } finally {
            inputStream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, WXPayConstants.MCH_ID.toCharArray())
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
            StringEntity entitys = new StringEntity(data);
            httppost.setEntity((HttpEntity) entitys);
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                HttpEntity entity = response.getEntity();

                if (entity != null) {
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
                    String text="";
                    String t="";
                    while ((text=bufferedReader.readLine()) != null) {
                        t+=text;
                    }
                    byte[] temp=t.getBytes("gbk");//这里写原编码方式
                    String newStr=new String(temp,"utf-8");//这里写转换后的编码方式
                    result=newStr;
                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        return result;
    }

    /**
     * XML格式字符串转换为Map
     * 微信支付 解析xml xml转map  获取prepay_id
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            } catch (Exception ex) {
                // do nothing
            }
            return data;
        } catch (Exception ex) {
            WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
            throw ex;
        }

    }

    /**
     * 获取随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public static String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }

    /**
     * 生成 MD5
     *
     * @param data 待处理数据
     * @return MD5结果
     */
    public static String MD5(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 生成 HMACSHA256
     * @param data 待处理数据
     * @param key 密钥
     * @return 加密结果
     * @throws Exception
     */
    public static String HMACSHA256(String data, String key) throws Exception {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString().toUpperCase();
    }

    /**
     * @Author: HONGLINCHEN
     * @Description:通过prepay_id 生成微信支付参数
     * @param prepay_id
     * @Date: 2018-8-23
     */
    public static  SortedMap<Object,Object> genPayRequest(String prepay_id) {
        SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
        parameters.put("appid", WXPayConstants.APP_ID);
        parameters.put("noncestr", genNonceStr());
        parameters.put("package", "Sign=WXPay");
        parameters.put("partnerid", WXPayConstants.MCH_ID);
        parameters.put("prepayid", prepay_id);
        parameters.put("timestamp",getCurrentTimestamp());
        parameters.put("sign", MD5.createSign("utf-8", parameters).toUpperCase());
        return parameters;
    }
    /**
     * @Author: HONGLINCHEN
     * @Description:请求值转换为xml格式 SortedMap转xml
     * @param params
     * @Date:2018-8-23
     */
    private static String SortedMaptoXml(SortedMap<String,String> params) {
        StringBuilder sb = new StringBuilder();
        Set es = params.entrySet();
        Iterator it = es.iterator();
        sb.append("<xml>\n");
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            sb.append("<"+k+">");
            sb.append(v);
            sb.append("</"+k+">\n");
        }
        sb.append("</xml>");
        return sb.toString();
    }
    /**
     * 日志
     * @return
     */
    public static Logger getLogger() {
        Logger logger = LoggerFactory.getLogger("wxpay java sdk");
        return logger;
    }

    /**
     * 生成32位随机数字
     */
    public static String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }
    /**
     * 获取当前时间戳,单位秒
     * @return
     */
    public static long getCurrentTimestamp() {
        return System.currentTimeMillis()/1000;
    }


    /**
     * 生成 uuid, 即用来标识一笔单,也用做 nonce_str
     * @return
     */
    public static String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }

}

WXPayConstants类:

/**
 * @Author: HONGLINCHEN
 * @Description:微信支付参数
 * @Date:2018-8-23
 */
public class WXPayConstants {

    //请同时修改  androidmanifest.xml里面 .PayActivityd里的属性<data android:scheme="wxb4ba3c02aa476ea1"/>为新设置的appid
//    public static final String APP_ID = "替换成自己的";
     public static final String APP_ID = "";
    //商户号
//    public static final String MCH_ID = "替换成自己的";
    public static final String MCH_ID = "";
    //API密钥,在商户平台设置
//    public static final  String API_KEY="替换成自己的";
    public static final  String API_KEY="";
    //商户号 微信小程序使用
    public static final String APPLET_MCHID = "替换成自己的";

    //appid 微信小程序使用
    public static final String APPLET_APPID = "替换成自己的";


}

WeiXinPayController类:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static net.shopxx.pay.utils.WXPayUtil.genPayRequest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.util.SortedMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: HONGLINCHEN
 * @Description:微信支付
 * @Date: 2018-8-23
 */

public class WeiXinPayController {

    private static final Logger logger = Logger.getLogger(WeiXinPayController.class);

    //@RequestMapping(value = "/weixinpay",method = {RequestMethod.GET})
    public String weixinpay(HttpServletRequest request, HttpServletResponse response, Model model){
        return "wxpay";
    }

    //@RequestMapping(value = "/wechatRefund",method = {RequestMethod.GET})
    public String wecharrefund(HttpServletRequest request, HttpServletResponse response, Model model){
        return "wechatrefund";
    }

    /**
     * @Author: HONGLINCHEN
     * @Description: 微信支付
     * @param number
     * @param money
     * @param request
     * @param response
     * @param model
     * @Date: 2018-8-23
     */
   // @RequestMapping(value = "/wxPay",method = {RequestMethod.GET,RequestMethod.POST})
    public String weixinpay(String number, double money, HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
        String ipAddress = request.getRemoteAddr();//得到来访者的IP地址
//      String ipAddress = RequestUtils.getClientIpAddress(request);
        String bodyStr = "参与活动", detailStr = "微信支付测试 1.0*1";
        String paySignXml = WXPayUtil.unifiedOrder(number, bodyStr, detailStr, (int)(money*100), ipAddress);
        System.err.println("加密以后的支付参数\n"+paySignXml);
        try {
            String prepay_id = WXPayUtil.xmlToMap(paySignXml).get("prepay_id").toString();
            if(prepay_id!=null&&!"".equals(prepay_id)){
                SortedMap<Object,Object> pay = genPayRequest(prepay_id);
                System.err.println("实际支付参数\n"+pay);
                response.getWriter().print(JSON.toJSON(pay));
            }else{
                model.addAttribute("result","请求支付参数错误!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * @Author: HONGLINCHEN
     * @Description: 微信取消订单
     * @param number
     * @param money
     * @param request
     * @param response
     * @param model
     * @Date:2018-8-23
     */
   // @RequestMapping(value = "/wxPayCancelOrder",method = {RequestMethod.GET,RequestMethod.POST})
    public String wxPayCancelOrder(String number, double money, HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
        String ipAddress = request.getRemoteAddr();//得到来访者的IP地址
       // String ipAddress = RequestUtils.getClientIpAddress(request);
        String bodyStr = "参与活动", detailStr = "微信支付测试 1.0*1";
        String paySignXml = WXPayUtil.unifiedOrder(number, bodyStr, detailStr, (int)(money*100), ipAddress);
        System.err.println("加密以后的支付参数\n"+paySignXml);
        try {
            String prepay_id = WXPayUtil.xmlToMap(paySignXml).get("prepay_id").toString();
            if(prepay_id!=null&&!"".equals(prepay_id)){
                SortedMap<Object,Object> pay = genPayRequest(prepay_id);
                System.err.println("实际支付参数\n"+pay);
                response.getWriter().print(JSON.toJSON(pay));
            }else{
                model.addAttribute("result","请求支付参数错误!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @Author: HONGLINCHEN  微信退款三种方式,随便哪一个都可以
     * @Description:微信退款   注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
     * @param merchantNumber 商户这边的订单号
     * @param wxTransactionNumber 微信那边的交易单号
     * @param totalFee 订单的金额
     * @Date: 2018-8-23
     */
   // @RequestMapping(value = "/wxPayRefundTwo", method = { RequestMethod.GET, RequestMethod.POST })
    public String qxwxsign(String merchantNumber,String wxTransactionNumber,double totalFee,HttpServletResponse response, HttpServletRequest request) throws IOException {
        String param = WXPayUtil.wxPayRefund(merchantNumber,wxTransactionNumber,String.valueOf((int)(totalFee*100)));
        System.err.println("param"+param);
        String result = "";
        String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        try {
            result = WXPayUtil.wxPayBack(url, param);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String tt = "2018072001201611180592735689";
        Pattern p = Pattern.compile("\\.*(\\w{" + tt.length() + "})\\.*");
        int st = result.indexOf("<refund_id>");
        String res = "";
        if (st >= 0) {
            int en = result.indexOf("</refund_id>");
            res = result.substring(st, en);
            Matcher m = p.matcher(res);
            if (m.find()) {
                res = m.group(1);
            }
            if (res.length() > 0) {
                result = "code:1,msg:退款成功";
            } else {
                result = "code:-1,msg:退款失败";
            }
            response.getWriter().print(JSON.toJSON(result));
        }
        return null;
    }

    /**
     * @Author: HONGLINCHEN
     * @Description:微信退款   注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
     * @param merchantNumber 商户这边的订单号
     * @param wxTransactionNumber 微信那边的交易单号
     * @param totalFee 订单的金额
     * @Date: 2018-8-23
     */
    //@RequestMapping(value = "/wxPayRefund", method = { RequestMethod.GET, RequestMethod.POST })
    public Object wxPayRefund(String merchantNumber,String wxTransactionNumber,double totalFee) {
        try{
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(new File("D:\\apiclient_cert.p12"));
            try {
                keyStore.load(instream, WXPayConstants.MCH_ID.toCharArray());
            }finally {
                instream.close();
            }
            // Trust own CA and all self-signed certs
  SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, WXPayConstants.MCH_ID.toCharArray()).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext, new String[] { "TLSv1" }, null,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf).build();
            // HttpGet httpget = new
            // HttpGet("https://api.mch.weixin.qq.com/secapi/pay/refund");
            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
            //微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
            String xml = WXPayUtil.wxPayRefund(merchantNumber,wxTransactionNumber,String.valueOf((int)(totalFee*100)));
            try {
                StringEntity se = new StringEntity(xml);
                httppost.setEntity(se);
                System.out.println("executing request" + httppost.getRequestLine());
                CloseableHttpResponse responseEntry = httpclient.execute(httppost);
                try {
                    HttpEntity entity = responseEntry.getEntity();
                    System.out.println(responseEntry.getStatusLine());
                    if (entity != null) {
                        System.out.println("Response content length: "+ entity.getContentLength());
                        SAXReader saxReader = new SAXReader();
                        Document document = saxReader.read(entity.getContent());
                        Element rootElt = document.getRootElement();
                        System.out.println("根节点:" + rootElt.getName());
                        System.out.println("==="+rootElt.elementText("result_code"));
                        System.out.println("==="+rootElt.elementText("return_msg"));
                        String resultCode = rootElt.elementText("result_code");
                        JSONObject result = new JSONObject();
                        Document documentXml = DocumentHelper.parseText(xml);
                        Element rootEltXml = documentXml.getRootElement();
                        if(resultCode.equals("SUCCESS")){
                            System.out.println("=================prepay_id===================="+ rootElt.elementText("prepay_id"));
                            System.out.println("=================sign===================="+ rootEltXml.elementText("sign"));
                            result.put("weixinPayUrl", rootElt.elementText("code_url"));
                            result.put("prepayId", rootElt.elementText("prepay_id"));
                            result.put("status","success");
                            result.put("msg","success");
                        }else{
                            result.put("status","false");
                            result.put("msg",rootElt.elementText("err_code_des"));
                        }
                        return result;
                    }
                    EntityUtils.consume(entity);
                }
                finally {
                    responseEntry.close();
                }
            }
            finally {
                httpclient.close();
            }
            return null;
        }catch(Exception e){
            e.printStackTrace();
            JSONObject result = new JSONObject();
            result.put("status","error");
            result.put("msg",e.getMessage());
            return result;
        }
    }


    /**
     * @Author: HONGLINCHEN
     * @Description:微信退款   注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
     * @param merchantNumber 商户这边的订单号
     * @param wxTransactionNumber 微信那边的交易单号
     * @param totalFee 订单的金额
     * @Date: 2018-8-23
     */
    //@RequestMapping(value = "/wxPayRefundone", method = { RequestMethod.GET, RequestMethod.POST })
    public Object wxPayRefundone(String merchantNumber,String wxTransactionNumber,double totalFee) {
        Object object = ClientCustomSSL.setUrl(merchantNumber,wxTransactionNumber,totalFee);
        return object;
    }
}

MD5Util类:

import java.security.MessageDigest;
public class MD5Util {
   private static String byteArrayToHexString(byte b[]) {
      StringBuffer resultSb = new StringBuffer();
      for (int i = 0; i < b.length; i++)
         resultSb.append(byteToHexString(b[i]));

      return resultSb.toString();
   }

   private static String byteToHexString(byte b) {
      int n = b;
      if (n < 0)
         n += 256;
      int d1 = n / 16;
      int d2 = n % 16;
      return hexDigits[d1] + hexDigits[d2];
   }

   public static String MD5Encode(String origin, String charsetname) {
      String resultString = null;
      try {
         resultString = new String(origin);
         MessageDigest md = MessageDigest.getInstance("MD5");
         if (charsetname == null || "".equals(charsetname))
            resultString = byteArrayToHexString(md.digest(resultString
                  .getBytes()));
         else
            resultString = byteArrayToHexString(md.digest(resultString
                  .getBytes(charsetname)));
      } catch (Exception exception) {
      }
      return resultString;
   }

   private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
         "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

}

MD5类:

import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
/**
 * @Author: HONGLINCHEN
 * @Description: MD5 工具类
 * @Date: 2018-8-23 
 */
public class MD5 {
   public final static String getMessageDigest(byte[] buffer) {
      char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
      try {
         MessageDigest mdTemp = MessageDigest.getInstance("MD5");
         mdTemp.update(buffer);
         byte[] md = mdTemp.digest();
         int j = md.length;
         char str[] = new char[j * 2];
         int k = 0;
         for (int i = 0; i < j; i++) {
            byte byte0 = md[i];
            str[k++] = hexDigits[byte0 >>> 4 & 0xf];
            str[k++] = hexDigits[byte0 & 0xf];
         }
         return new String(str);
      } catch (Exception e) {
         return null;
      }
   }
   private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();  
        for (int i = 0; i < b.length; i++)  
            resultSb.append(byteToHexString(b[i]));  
  
        return resultSb.toString();  
    }  
  
    private static String byteToHexString(byte b) {  
        int n = b;  
        if (n < 0)  
            n += 256;  
        int d1 = n / 16;  
        int d2 = n % 16;  
        return hexDigits[d1] + hexDigits[d2];  
    }  
  
    public static String MD5Encode(String origin, String charsetname) {  
        String resultString = null;
        try {  
            resultString = new String(origin);  
            MessageDigest md = MessageDigest.getInstance("MD5");  
            if (charsetname == null || "".equals(charsetname))  
                resultString = byteArrayToHexString(md.digest(resultString  
                        .getBytes()));  
            else  
                resultString = byteArrayToHexString(md.digest(resultString  
                        .getBytes(charsetname)));  
        } catch (Exception exception) {  
        }  
        return resultString;  
    }  
  
    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",  
        "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    /**
     * @Author: HONGLINCHEN
     * @Description:支付参数生成签名
     * @param characterEncoding
     * @param parameters
     * @Date: 2018-8-23
     */
    public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){  

        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while(it.hasNext()) {  
            Map.Entry entry = (Map.Entry)it.next();  
            String k = (String)entry.getKey();  
            Object v = entry.getValue();  
            if(null != v && !"".equals(v)&& !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");  
            }
        }  
        sb.append("key=" + WXPayConstants.API_KEY);
        String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;  
    }

}

HttpUtil类:

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * @Author: HONGLINCHEN
 * @Description: Http工具类,发送Http请求, Get请求请将参数放在url中 Post请求请将参数放在Map中
 * @Date: 2018-8-23
 */
public class HttpUtil {
    private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);
    private static final CloseableHttpClient httpclient = HttpClients.createDefault();
    private static final String userAgent = "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.87 Safari/537.36";

    /**
     * 发送HttpGet请求
     *
     * @param url
     *            请求地址
     * @return 返回字符串
     */
    public static String sendGet(String url) {
        String result = null;
        CloseableHttpResponse response = null;
        try {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("User-Agent", userAgent);
            response = httpclient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            log.error("处理失败 {}" + e);
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return result;
    }

    /**
     * 发送HttpPost请求,参数为map
     *
     * @param url
     *            请求地址
     * @param map
     *            请求参数
     * @return 返回字符串
     */
    public static String sendPost(String url, Map<String, String> map) {
        // 设置参数
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
        }
        // 编码
        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
        // 取得HttpPost对象
        HttpPost httpPost = new HttpPost(url);
        // 防止被当成攻击添加的
        httpPost.setHeader("User-Agent", userAgent);
        // 参数放入Entity
        httpPost.setEntity(formEntity);
        CloseableHttpResponse response = null;
        String result = null;
        try {
            // 执行post请求
            response = httpclient.execute(httpPost);
            // 得到entity
            HttpEntity entity = response.getEntity();
            // 得到字符串
            result = EntityUtils.toString(entity);
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return result;
    }

    /**
     * 发送HttpPost请求,参数为文件,适用于微信上传素材
     *
     * @param url
     *            请求地址
     * @param file
     *            上传的文件
     * @return 返回字符串
     * @throws IOException
     * @throws ClientProtocolException
     */
    public static String sendPost(String url, File file) {
        String result = null;
        HttpPost httpPost = new HttpPost(url);
        // 防止被当成攻击添加的
        httpPost.setHeader("User-Agent", userAgent);
        MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
        multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        multipartEntity.addPart("media", new FileBody(file));
        httpPost.setEntity(multipartEntity.build());
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity);
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            // 关闭CloseableHttpResponse
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return result;

    }

    /**
     * 发送HttpPost请求,参数为json字符串
     *
     * @param url
     * @param jsonStr
     * @return
     */
    public static String sendPost(String url, String jsonStr) {
        String result = null;
        // 字符串编码
        StringEntity entity = new StringEntity(jsonStr, Consts.UTF_8);
        // 设置content-type
        entity.setContentType("application/json");
        HttpPost httpPost = new HttpPost(url);
        // 防止被当成攻击添加的
        httpPost.setHeader("User-Agent", userAgent);
        httpPost.setEntity(entity);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            result = EntityUtils.toString(httpEntity);
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            // 关闭CloseableHttpResponse
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return result;
    }

    /**
     * 发送不带参数的HttpPost请求
     *
     * @param url
     * @return
     */
    public static String sendPost(String url) {
        String result = null;
        // 得到一个HttpPost对象
        HttpPost httpPost = new HttpPost(url);
        // 防止被当成攻击添加的
        httpPost.setHeader("User-Agent", userAgent);
        CloseableHttpResponse response = null;
        try {
            // 执行HttpPost请求,并得到一个CloseableHttpResponse
            response = httpclient.execute(httpPost);
            // 从CloseableHttpResponse中拿到HttpEntity
            HttpEntity entity = response.getEntity();
            // 将HttpEntity转换为字符串
            result = EntityUtils.toString(entity);
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            // 关闭CloseableHttpResponse
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return result;
    }
}

ClientCustomSSL类:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
/**
 * @Author: HONGLINCHEN
 * @Description: 微信退款
 * @Date: 2018-8-23
 */
public class ClientCustomSSL {
    /**
     * @Author: HONGLINCHEN
     * @Description:微信退款方法封装   注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
     * @param merchantNumber 商户这边的订单号
     * @param wxTransactionNumber 微信那边的交易单号
     * @param totalFee 订单的金额
     * @Date: 2018-8-23
     */
    public static Object setUrl(String merchantNumber,String wxTransactionNumber,double totalFee) {
        try{
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            FileInputStream instream = new FileInputStream(new File("F:\\wx\\apiclient_cert.p12"));
            try {
                keyStore.load(instream, WXPayConstants.MCH_ID.toCharArray());
            }finally {
                instream.close();
            }
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, WXPayConstants.MCH_ID.toCharArray()).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext, new String[] { "TLSv1" }, null,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf).build();
            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
            String xml = WXPayUtil.wxPayRefund(merchantNumber,wxTransactionNumber,String.valueOf((int)(totalFee*100)));
 
            try {
                StringEntity se = new StringEntity(xml);
                httppost.setEntity(se);
                System.out.println("executing request" + httppost.getRequestLine());
                CloseableHttpResponse responseEntry = httpclient.execute(httppost);
                try {
                    HttpEntity entity = responseEntry.getEntity();
                    System.out.println(responseEntry.getStatusLine());
                    if (entity != null) {
                        System.out.println("Response content length: "
                                + entity.getContentLength());
                        SAXReader saxReader = new SAXReader();
                        Document document = saxReader.read(entity.getContent());
                        Element rootElt = document.getRootElement();
                        System.out.println("根节点:" + rootElt.getName());
                        System.out.println("==="+rootElt.elementText("result_code"));
                        System.out.println("==="+rootElt.elementText("return_msg"));
                        String resultCode = rootElt.elementText("result_code");
                        JSONObject result = new JSONObject();
 
                        Document documentXml = DocumentHelper.parseText(xml);
                        Element rootEltXml = documentXml.getRootElement();
                        if(resultCode.equals("SUCCESS")){
                            System.out.println("=================prepay_id===================="+ rootElt.elementText("prepay_id"));
                            System.out.println("=================sign===================="+ rootEltXml.elementText("sign"));
                            result.put("weixinPayUrl", rootElt.elementText("code_url"));
                            result.put("prepayId", rootElt.elementText("prepay_id"));
                            result.put("status","success");
                            result.put("msg","success");
                        }else{
                            result.put("status","false");
                            result.put("msg",rootElt.elementText("err_code_des"));
                        }
                        return result;
                    }
                    EntityUtils.consume(entity);
                }
                finally {
                    responseEntry.close();
                }
            }
            finally {
                httpclient.close();
            }
            return null;
        }catch(Exception e){
            e.printStackTrace();
            JSONObject result = new JSONObject();
            result.put("status","error");
            result.put("msg",e.getMessage());
            return result;
        }
    }
    
    
    
  public static void main(String[] args) {
      Object setUrl = setUrl("", "XXXXXX", 0.03d);
      System.out.println(setUrl);
      
  }
}
以上就是微信支付以及退款的代码了,喜欢的小伙伴可以试着用一下,再次提醒一下,微信支付的金额单位是分,所以金额要*100并且要是int类型,如果你的是double类型,*100之后记得转为int类型哦~~~

猜你喜欢

转载自blog.csdn.net/qq_34827263/article/details/82048943
今日推荐