微信支付退款

作者:Jcode95
来源:CSDN
原文:https://blog.csdn.net/qq_34827263/article/details/82048943
版权声明:本文为博主原创文章,转载请附上博文链接!

maven文件

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

工具类:

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 getResult(String xml){
      Map map = new HashMap();
      try {
      org.dom4j.Document document = DocumentHelper.parseText(xml);
      org.dom4j.Element root = document.getRootElement();
      Iterator 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("”);
      }
      }

      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 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("");
      if (body.length() > 32) {
      body = body.substring(0, 32);
      }
      SortedMap 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("");
      SortedMap parameters = new TreeMap();
      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("");
      SortedMap parameters = new TreeMap();
      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 xmlToMap(String strXML) throws Exception {
      try {
      Map data = new HashMap();
      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 genPayRequest(String prepay_id) {
      SortedMap parameters = new TreeMap();
      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 params) {
      StringBuilder sb = new StringBuilder();
      Set es = params.entrySet();
      Iterator it = es.iterator();
      sb.append("\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("\n");
      }
      sb.append("");
      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里的属性为新设置的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.01";
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 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.01";
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 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)(totalFee100)));
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("");
String res = “”;
if (st >= 0) {
int en = result.indexOf("
");
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 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 map) {
      // 设置参数
      List formparams = new ArrayList();
      for (Map.Entry 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类型哦~~~

作者:Jcode95
来源:CSDN
原文:https://blog.csdn.net/qq_34827263/article/details/82048943
版权声明:本文为博主原创文章,转载请附上博文链接!

你可能感兴趣的:(微信支付捷成,微信支付,支付退款)