微信退款

准备:①下载证书:微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->证书下载   必须是管理员账户才能下载

如果加入了微信退款回调函数:②一定要需要替换本地的两个jar包,local_policy.jar、US_export_policy.jar,具体路径为jdk1.7\jre\lib\security。

替换的包下载地址:

jdk1.7:  下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

jdk1.8:下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

jdk1.6:下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

 

接着附上mvc层代码:

import net.sf.json.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.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.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
 * @Description:微信退款   注意::微信金额的单位是分 所以这里要X100 转成int是因为 退款的时候不能有小数点
 * @param merchantNumber 商户这边的订单号
 * @param wxTransactionNumber 微信那边的交易单号
 * @param totalFee 订单的金额 单位分
 */
@RequestMapping(value = "wxPayRefund", produces = {"application/json;charset=UTF-8"}, method = RequestMethod.POST)
@ResponseBody
public Object wxPayRefund(String merchantNumber,String wxTransactionNumber,double totalFee) {
    try{
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        String weixin_docx = ConfigureUtil.getProperty("weixin_docx");//微信文档apiclient_cert.p12路径
        FileInputStream instream = new FileInputStream(new File(weixin_docx));
        try {
            keyStore.load(instream, ConfigureUtil.getProperty("weixin_mch_id").toCharArray());
        }finally {
            instream.close();
        }
        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, ConfigureUtil.getProperty("weixin_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)));
        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("result_code==="+rootElt.elementText("result_code")+",return_msg=="+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;
    }
}

 

工具类WXPayUtil.java

package com.hb.common.util.pay;

import com.hb.common.util.ConfigureUtil;
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 javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.*;

public class WXPayUtil {
    /**
     * 证书使用
     * 微信退款
     */
    public static String wxPayBack(String url, String data) throws Exception {
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File("D:\\apiclient_cert.p12"));
        String result="";
        try {
            keyStore.load(instream, ConfigureUtil.getProperty("weixin_mch_id").toCharArray());//添加商户号
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, ConfigureUtil.getProperty("weixin_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;
    }

    /**
     * @Description:微信退款
     * @param out_trade_no
     * @param total_fee
     * @Date: 2017-9-11 14:35
     * @return:
     */
    public static String wxPayRefund(String out_trade_no, String transaction_id,String total_fee) {
        StringBuffer xml = new StringBuffer();
        String data = null;
        String callbackUrl = ConfigureUtil.getProperty("aiwen.ip") + "/service/weixinBack/wxRegisterNotify";//回调函数
        try {
            String nonceStr = PayCommonUtil.CreateNoncestr();
            System.out.println("nonceStr====="+nonceStr);
            xml.append("</xml>");
            SortedMap<String,String> parameters = new TreeMap<String,String>();
            parameters.put("appid", ConfigureUtil.getProperty("weixin_appid"));
            parameters.put("mch_id",ConfigureUtil.getProperty("weixin_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("refund_fee_type", "CNY");
            parameters.put("total_fee", total_fee);
            parameters.put("refund_fee", total_fee);
            parameters.put("notify_url",callbackUrl);
            parameters.put("op_user_id", ConfigureUtil.getProperty("weixin_mch_id"));
            parameters.put("sign", createSign(parameters,ConfigureUtil.getProperty("weixin_key")));
            data = SortedMaptoXml(parameters);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return null;
        }
        return data;
    }

    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;
    }
    /**
     * @Description:请求值转换为xml格式 SortedMap转xml
     * @param params
     * @Date:
     */
    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();
    }
}

 

工具类PayCommonUtil.java

package com.hb.common.util.pay;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import com.alibaba.fastjson.JSONObject;
import com.hb.common.util.ConfigureUtil;

public class PayCommonUtil {
    public static String CreateNoncestr(int length) {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String res = "";
        for (int i = 0; i < length; i++) {
            Random rd = new Random();
            res += chars.indexOf(rd.nextInt(chars.length() - 1));
        }
        return res;
    }

    public static String CreateNoncestr() {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String res = "";
        for (int i = 0; i < 16; i++) {
            Random rd = new Random();
            res += chars.charAt(rd.nextInt(chars.length() - 1));
        }
        return res;
    }
    /**
     * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     * @return boolean
     */
    public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams) {
        String key = ConfigureUtil.getProperty("weixin_key");
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            if(!"sign".equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key="+key);
        //算出摘要
        String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();
        String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();

        //System.out.println(tenpaySign + "/n" + mysign);
        return tenpaySign.equals(mysign);
    }
    /**
     * @Description:sign签名
     * @param characterEncoding 编码格式
     * @param parameters 请求参数
     * @return
     */
    public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
        String key = ConfigureUtil.getProperty("weixin_key");
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();
        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="+key);
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }
    /**
     * @Description:将请求参数转换为xml格式的string
     * @param parameters  请求参数
     * @return
     */
    public static String getRequestXml(SortedMap<Object,Object> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            //sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
           /*if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)) {
                sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
            }else if("mch_id".equalsIgnoreCase(k)){
               sb.append("<"+k+">1492021772</"+k+">");
           }else {
                sb.append("<"+k+">"+v+"</"+k+">");
            }*/
           if("trade_type".equalsIgnoreCase(k)){
               sb.append("<"+k+">"+v+"</"+k+">");
           }else {
               sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
           }
        }
        sb.append("</xml>");
        return sb.toString();
    }
    /**
     * @Description:返回给微信的参数
     * @param return_code 返回编码
     * @param return_msg  返回信息
     * @return
     */
    public static String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code
                + "]]></return_code><return_msg><![CDATA[" + return_msg
                + "]]></return_msg></xml>";
    }


    /**
     * 发送https请求
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return 返回微信服务器响应的信息
     */
    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            //conn.setSSLSocketFactory(ssf);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            return buffer.toString();
        } catch (ConnectException ce) {
//          log.error("连接超时:{}", ce);
        } catch (Exception e) {
//          log.error("https请求异常:{}", e);
        }
        return null;
    }
    /**
     * 发送https请求
     *
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param ‘outputStr’ 提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            //conn.setSSLSocketFactory(ssf);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setConnectTimeout(3000);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);
            //conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            // 当outputStr不为null时向输出流写数据
            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
//                    log.error("连接超时:{}", ce);
        } catch (Exception e) {
            System.out.println(e);
//                    log.error("https请求异常:{}", e);
        }
        return jsonObject;
    }
    public static String urlEncodeUTF8(String source){
        String result = source;
        try {
            result = java.net.URLEncoder.encode(source,"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }
}

微信回调地址下一页

AESDecodeUtil.java 工具类 (解密 对回调函数的req_info进行解密) 
package com.hb.common.util.pay;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.hb.common.util.ConfigureUtil;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.security.NoSuchAlgorithmException;
import java.util.*;

public class AESDecodeUtil {
    public static final String ALGORITHM = "AES/ECB/PKCS7Padding";
    public static String decode(String reqInfo) throws Exception{
        try {
            String key = ConfigureUtil.getProperty("weixin_key");//key的内容
            //String key = "02a86cb980b1237eaa77fb86adf64657";
            byte[] decodeBase64 = Base64.decodeBase64(reqInfo);
            String md5Key =encryption(key);
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            SecretKey keySpec = new SecretKeySpec(md5Key.getBytes(), "AES"); //生成加密解密需要的Key
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            byte[] decoded = cipher.doFinal(decodeBase64);
            String  result = new String(decoded, "UTF-8");
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String encryption(String plainText) {
        String re_md5 = new String();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(plainText.getBytes());
            byte b[] = md.digest();
            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }

            re_md5 = buf.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return re_md5;
    }
    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;
    }
    public static SortedMap<Object,Object> sortedMap( Map<String, String> m){
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        Iterator<String> it = m.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = m.get(parameter);
            String v = "";
            if(null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }
        return packageParams;
    }
    public static void main(String[] args) {
        AESDecodeUtil test = new AESDecodeUtil();
        String A = "cbRfjwOKrLQCOjAU0v1Ac6cDJQhK6349ngVplZHLe010obV59BJ75z05eUzG+Um3Zk9WxNO6jtk60bBDkMLmf4dZk41wSbyx/GiNNcRp3g0GdUMjGjhlyJgMAKiLbmVwcPEQnOoikcCbwGd0VmOdWcTk67kDlE4ssYW6pgBXp5bSBVotuar2Wxi0z20HGgsz7dcIVELP9+JfGwuiVV9xkhO8sPbEO4SIO2qhkRQ0QzbDYgn9gU1Iprzv6wGxFh+Bm/lJWuiBGwhFCT2fq1xEF1nDPEyW3LOWq4daCegXpvTXoXLZp9Xp6zcdxiDCsLgj8yj+q7ZNmVNt1vTUR94ZQAI1UAtCqK+1dI89DZdbifU7o0fVm/9WQqjcOIo4WemUJU7WfCsyHXBVvx8lZezoQc5ZGZOqTEZJCVKV6OF5iqvlNnZJ1byPg7BfHZnmbIjdETFMIOkq3oPicshnNlVZ9g08DvesDZzG/KJzI8NBMFfXNMjSJyuemsZ/0jFJRtKDOWoCQetWox+mORa5BPrMwvibTLkPZL0okvnyrJgFwGtE4BFTdnN/+cfuUISXMTbeZv6UjRJwD9y8B+wi4wTSUC1QXjlZEkV+RgBNnJD/n13NWUK1nlrwev/RHLsgjoMSYnF0mYec8g1BCyW0POcp4iEDaRVMrjQnACyyeMncSxA+KawdoFEOqMuAITv3B0Q9iZOTpI7yqnpquWiphXMuKovJgLp4vnPqerMMthTeaQ/rfVVO/U6Z4K/heTZKT2Y0y7kQP2GS+r/N5Qvu+J0sihJ8opoZ0AJ7ktwGrzcmkIq/DCCtAfgdAT8x3rtSXA4f8pb7WqFssdGRqgzMZR1jlcz3LD5+Du+BWK5QmyCeynywd9b6s7oYdyU0aI75LrT5EBOtEHAMGi2rmwb1X2wlEd3g4gCr2l1EEA4dUTdhsqynG0w64VHWJkvJgTOdmzMPWYksLu463qcy6dN44WuNBG0aw7uEQQIUXeRhDEwCBQVmzXNLzwQ6wHv6O9j7yvkvZll3SuGw7bbsfdSdAfQkJkLCj/MHuEKUauiV0mQS/2M=";
      try {
          String B = test.decode(A);
          System.out.println(B);
          System.out.println("======================================");
          Map<String, String> m =  doXMLParse(B);
          System.out.println(m);
          System.out.println(m.get("refund_recv_accout"));
          System.out.println("======================================");
          SortedMap<Object,Object> packageParams = sortedMap(m);
          System.out.println(packageParams);

      }catch (Exception e){
          e.printStackTrace();
      }
    }
}

 

回调函数返回接口方法  

/**
 * 微信app支付回调通知
 */
@RequestMapping(value = "/wxRegisterNotify")
@ResponseBody
public String wxRegisterNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=UTF-8");
    response.setHeader("Access-Control-Allow-Origin", "*");
    String result="";//返回给微信的处理结果
    String inputLine;
    String notityXml = "";
    //微信给返回的东西
    try {
        while ((inputLine = request.getReader().readLine()) != null) {
            notityXml += inputLine;
        }
        request.getReader().close();
    } catch (Exception e) {
        e.printStackTrace();
        result = setXml("FAIL","xml获取失败");
        System.out.println("退款失败,错误信息:" + "xml获取失败");
        return result;
    }
    if (isEmpty(notityXml)) {
        result = setXml("FAIL","xml为空");
        System.out.println("退款失败,错误信息:" + "xml为空");
        return result;
    }
    Map<String, String> m = XMLUtil.doXMLParse(notityXml);
    //过滤空 设置 TreeMap
    SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
    Iterator<String> it = m.keySet().iterator();
    while (it.hasNext()) {
        String parameter = (String) it.next();
        String parameterValue = m.get(parameter);
        String v = "";
        if(null != parameterValue) {
            v = parameterValue.trim();
        }
        packageParams.put(parameter, v);
    }
    //判断签名是否正确
    if(PayCommonUtil.isTenpaySign("UTF-8", packageParams)) {//验证签名得注意
        if("SUCCESS".equals((String)packageParams.get("return_code"))) {
            String req_info = (String)packageParams.get("req_info"); //加密信息
            String rel = AESDecodeUtil.decode(req_info);//处理加密信息
            Map<String, String> relSutSuccess = XMLUtil.doXMLParse(rel);//解析xml
            if("SUCCESS".equals(relSutSuccess.get("refund_status"))){//退款成功
                System.out.println("微信退款订单开始处理");
                // 这里是支付成功
                //执行自己的业务逻辑
                String mch_id = (String)relSutSuccess.get("settlement_refund_fee"); //退款金额=申请退款金额-非充值代金券退款金额
                String openid = (String)relSutSuccess.get("refund_fee");  //申请退款金额
                String out_trade_no = (String)relSutSuccess.get("out_trade_no"); //商户订单号
                String total_fee = (String)relSutSuccess.get("total_fee");//金额
                String transaction_id = (String)relSutSuccess.get("transaction_id"); //微信支付订单号
                String  time_end = (String)relSutSuccess.get("success_time");//退款成功时间
                String  refund_id = (String)relSutSuccess.get("refund_id");//微信退款单号
                String  out_refund_no = (String)relSutSuccess.get("out_refund_no");//商户退款单号



            }else if("CHANGE".equals(relSutSuccess.get("refund_status"))){
                String out_trade_no = (String)relSutSuccess.get("out_trade_no"); //商户订单号
                System.out.println("退款异常:===返回订单号:"+out_trade_no);
                result = setXml("FAIL","报文为空");
            }else {
                String out_trade_no = (String)relSutSuccess.get("out_trade_no"); //商户订单号
                System.out.println("退款关闭:===返回订单号:"+out_trade_no);
                result = setXml("FAIL","报文为空");
            }
        }else {
            System.out.println("支付失败,错误信息:" + packageParams.get("return_msg"));
            result = setXml("FAIL","报文为空");
        }
    }else {
        result = setXml("FAIL","通知签名验证失败");
        System.out.println("通知签名验证失败");
    }
    return result;
}
//通过xml 发给微信消息
public static String setXml(String return_code, String return_msg) {
    SortedMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("return_code", return_code);
    parameters.put("return_msg", return_msg);
    return "<xml><return_code><![CDATA[" + return_code + "]]>" +
            "</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
}
public String orderIDget(){
    SimpleDateFormat sd = new SimpleDateFormat("yyMMddHHmmss");
    String date = sd.format(new Date());
    StringBuffer sb = new StringBuffer();
    sb.append(date);
    String num = getRandomString(4);
    sb.append(num);
    return sb.toString();
}
//随机数
public static String getRandomString(int length) { // length表示生成字符串的长度
    String base = "0123456789";
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < length; i++) {
        int number = random.nextInt(base.length());
        sb.append(base.charAt(number));
    }
    return sb.toString();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值