在pom.xml文件添加:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.47</version>
</dependency>

直接撸代码:

第一个文件代码:

public class GatewayNotifyController {
@Autowired
private MerchantTransCommonClient merchantTransCommonClient;
   @Autowired
private MerchantWebChatClient MerchantWebChatClient;
@Autowired
private MerchantAlipayClient merchantAlipayClient;
   @Autowired
   private AESUtil aESUtil;
@ApiOperation("微信退款结果回调")
@RequestMapping(value = "/wxRefund/notifRefundyUrl", produces = MediaType.APPLICATION_JSON_VALUE)
public void notifRefundyUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
    log.info("微信退款结果回调开始回调-------");
    SortedMap<String, Object> return_data = new TreeMap<String, Object>();
    try {

        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultxml = new String(outSteam.toByteArray(), "utf-8");
        log.info("微信退款结果回调内容:{}",resultxml);
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(resultxml);  // 转换成map
        outSteam.close();
        inStream.close();
        //判断返回状态码
        if(notifyMap.get("return_code")!=null&&notifyMap.get("return_code").equals("SUCCESS")){
            //表示通讯成功
            String appId=notifyMap.get("appid");//微信分配的公众账号ID
            String  mchId=notifyMap.get("mch_id");//微信支付分配的商户号
            //应用渠道参数 查询这个微信分配的商户号和公众账号id在数据库中的商户秘钥,注意:同一个分配的商户号和公众账号ID 无论支付方式是什么秘钥都是一样的  SUCCESS
           //这里面的代码是我自己的别用 主要是获取商户的秘钥开始 ---------begin
            HsyAppChannelParamsDto appChannelParamsDto=null;
            BaseResMessage<HsyAppChannelParamsDto> queryChannelByTransFlow = merchantTransCommonClient.queryChannelByChannelMerNoAndAppId(mchId,appId,PayChannelEnum.PAY_CHANNEL_WX.getIndex());
            log.info("queryChannelByTransFlow:{}",queryChannelByTransFlow);
            if(!ServiceConstants.RES_SUCCESS_CODE.equals(queryChannelByTransFlow.getCode())) {
                if(BaseTransExceptionEnum.MER_APP_PAY_CHANNEL_PARAMS_ERROR.getKey().equals(queryChannelByTransFlow.getCode())) {
                    log.info("appId:{},mch_id:{},channelCode:{},未查询到应用渠道参数",mchId,appId,PayChannelEnum.PAY_CHANNEL_WX.getIndex());
                    return_data.put("return_code", "FAIL");
                    return_data.put("return_msg", "OK");
                }else {
                     appChannelParamsDto= queryChannelByTransFlow.getData();
                    if(appChannelParamsDto==null||StringUtils.isEmpty(appChannelParamsDto.getSecretKey())){
                        log.info("appId:{},mch_id:{},channelCode:{},,查询到应用渠道参数秘钥为空",appId,mchId,PayChannelEnum.PAY_CHANNEL_WX.getIndex());
                        return_data.put("return_code", "FAIL");
                        return_data.put("return_msg", queryChannelByTransFlow.getMessage());
                    }
                }

                String respMsg= PayCommonUtil.getRequestXml(return_data);
                log.info("微信退款结果回调内容respMsg:{}",respMsg);
                sendResponse(response, respMsg);
                return;
            }
            appChannelParamsDto= queryChannelByTransFlow.getData();
            //返回成功商户秘钥为空的时候
            if(appChannelParamsDto==null||StringUtils.isEmpty(appChannelParamsDto.getSecretKey())){
                return_data.put("return_code", "FAIL");
                return_data.put("return_msg", "商户秘钥为空");
                String respMsg= PayCommonUtil.getRequestXml(return_data);
                log.info("微信退款结果回调内容respMsg:{}",respMsg);
                sendResponse(response, respMsg);
                return;
            }
            //获取要解析的数据
            String reqInfo=notifyMap.get("req_info");
            //---获取商户的秘钥结束 end    获取解密后的返回串,这个才是真正需要的数据
            log.info("微信退款结果退款解析数据前 appId:{}, mch_id:{}, SecretKey{}, reqInfo:{} ",appId,mchId,appChannelParamsDto.getSecretKey(),JSON.toJSONString(reqInfo));
            String decryptInfo = aESUtil.decryptData(reqInfo, appChannelParamsDto.getSecretKey());
            log.info("微信退款结果退款解析数据后  SecretKey:{}, decryptInfo解密后:{},",appChannelParamsDto.getSecretKey(),decryptInfo);
            //解析回来返回为空
            if(StringUtils.isEmpty(decryptInfo)){
                return_data.put("return_code", "FAIL");
                return_data.put("return_msg", "解密以后数据为空");
                String respMsg= PayCommonUtil.getRequestXml(return_data);
                log.info("微信退款结果回调内容respMsg:{}",respMsg);
                sendResponse(response, respMsg);
                return;
            }
            //将返回串转换成 Map
            Map<String, String> reqInfoMap = WXPayUtil.xmlToMap(decryptInfo);
            reqInfoMap.put("return_code",notifyMap.get("return_code"));
            reqInfoMap.put("return_msg",notifyMap.get("return_msg"));
            BaseResMessage<Object> dealTransOrderResult = MerchantWebChatClient.dealRefundNotifyOrderResult(reqInfoMap);
            if(!ServiceConstants.RES_SUCCESS_CODE.equals(dealTransOrderResult.getCode())) {
                if(BaseTransExceptionEnum.REFUND_RECORD_ALERDAY_SUCCESS.getKey().equals(dealTransOrderResult.getCode())) {
                    return_data.put("return_code", "SUCCESS");
                    return_data.put("return_msg", "OK");
                }else {
                    return_data.put("return_code", "FAIL");
                    return_data.put("return_msg", dealTransOrderResult.getMessage());

                }

            }else {
                return_data.put("return_code", "SUCCESS");
                return_data.put("return_msg", "OK");

            }
            String respMsg= PayCommonUtil.getRequestXml(return_data);
            log.info("结果通知返回微信内容respMsg:{}",respMsg);
            sendResponse(response, respMsg);
            return;
        }else{
            //表示通讯失败
            return_data.put("return_code", notifyMap.get("return_code"));
            return_data.put("return_msg", notifyMap.get("return_msg"));
            String respMsg= PayCommonUtil.getRequestXml(return_data);
            sendResponse(response, respMsg);
            return;
        }
    } catch (Exception e) {
        log.error("微信退款结果:"+e);
        return_data.put("return_code", "FAIL");
        return_data.put("return_msg", "系统异常");
        String respMsg= PayCommonUtil.getRequestXml(return_data);
        sendResponse(response, respMsg);
        return;
    }
 
/**
 * 发送服务应答报文
 *
 * @throws Exception
 * @throws IOException
 */
public void sendResponse(HttpServletResponse response, String respMsg) {
    // POST请求服务,发送报文
    OutputStream outputStream = null;
    try {
        byte[] bys = respMsg.getBytes("UTF-8");
        // 设置Http-headers信息
        response.setContentType("application/xml;charset=UTF-8");

        outputStream = response.getOutputStream();
        outputStream.write(bys);
        outputStream.flush();
    } catch (Exception e) {
        log.error("微信通知返回失败",e);
    } finally {
        if (null != outputStream) {
            try {
                outputStream.close();
            } catch (Exception e) {
                log.error("微信通知返回失败",e);
            }
        }
    }
}
}
}

第二个文件:

package com.haoshouyin.cloud.api.utils;

import com.github.wxpay.sdk.WXPayUtil;
import com.haoshouyin.cloud.common.utils.Base64Util;
import com.haoshouyin.cloud.common.utils.MD5Util;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Map;


@Slf4j
@Component
public class AESUtil {


    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "AES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";
    /**
     * 生成key
     */
    //微信支付API密钥设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
/*    private static String paySign = "d773533ef81d3b01f8933a5c0dcc8c71";

    //对商户key做md5,得到32位小写key*
    private static    SecretKeySpec key = new SecretKeySpec(MD5Util.MD5Encode(paySign, "UTF-8").toLowerCase().getBytes(), ALGORITHM);

    static {

    }*/

    /**
     * AES加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encryptData(String data, String merchKey) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        // 创建密码器
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");
        // 初始化
        SecretKeySpec key = new SecretKeySpec(MD5Util.MD5Encode(merchKey, "UTF-8").toLowerCase().getBytes(), ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return Base64Util.encode(cipher.doFinal(data.getBytes()));
    }

    /**
     * AES解密
     * <p>
     * (1)对加密串A做base64解码,得到加密串B
     * (2)用key*对加密串B做AES-256-ECB解密(PKCS7Padding)
     *
     * @param base64Data
     * @return
     * @throws Exception
     */
    public static String decryptData(String base64Data, String merchKey) throws Exception {

        try {
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");
            SecretKeySpec key = new SecretKeySpec(MD5Util.MD5Encode(merchKey, "UTF-8").toLowerCase().getBytes(), ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            return new String(cipher.doFinal(Base64Util.decode(base64Data)));
        } catch (Exception e) {
            log.error("AES解密出错:{}",e);
            e.printStackTrace();
        }
        return "";
    }

    public static void main(String[] args) throws Exception {
        // String reqInfo="XpYWVVDwnqZctk5n1u66B0a+fQQ2bDlISsgOLog67a4RuSRXAomNUjumCFeXMbo4u1Li2ZZTx8cLRZSM63PC5k3gmgxzlMFympZ/wVVnvqiypkWSAJwBZ4uoFe4ax7eHFksI5GKNeV/qe1Ev0mS0RqzBL+f7elTu61vWXAu7489A24UwGwFHHJFHRnjb7w/uSiaj+efpVqnJXjcqvGmPajWc6M8eYnT45FFAPZru2CBvoQYS1DSeb84w74uvYBOdX7mdQs3mdISPg7gANxPMfbLwZvlaAaP4B0V4MkisskgUuiJMlVqbIgMIxJn1vsvzBgzZ3HPcuCsP3EHIK4AKzCfb8uIrX3bmMo/YszJbTzMsfbd+PFZh1Uqzh3Y1aG3lm+oBqZciTAZVZjIRHf5EpavkUhGGWY2eqPoi2tbpuCHT1cFa6kTCDMSYgpd3IVChFiSOyYmKE61wtNwFLaCdNBbpcKTnQyWCl1YOUx7N62A57ahuk6ngYTxGfCJOHFL+HUrPwviaIPz1wolrnzasEroXzBRA7xPnKfiyvGsz1plaGX8XBLZVisiKzP87Yfq2DfJ85PLXuEOd5nXXMlRPqCgLslsoCEvb9QCPCNp7b3TtZc4u4fxuPU5+MWamnicpkdU5lYt9ZSBL/0wuCNN6lklEvZry3RAi1BY4TchIsIXKI5qY3pvsdnRBm/XNAxI9HleX2eE7z+HjwdMRZHjjn2GzlJ5gpSXag8fxJ8QrABiZpN6B7u/bcwr/J7Xh1r4sJHJqlBaJ1XDQAqibFbjbNfs+hxrdny3bvsq8fGaLj44xPfDtUUzlFGNACKZO/4u93oFyGI3RnTbW/hsEUqKHgoDcxRpkyeS0poH/7beNa2ZyMrU3Mxm2EY/Wm4iy3tx5Xxss5FuQ9/Qf/YLTY8HG0B1lJ/nCZaklRgBEywAjg3AFl/UpZWnvu2fEm3GdtuQ5hqG5D6miGtDUb936BpSFXfPcGPtTJ3YW8VMaod3Hv0o=";
        String xml = "<xml><return_code>SUCCESS</return_code><appid><![CDATA[wx7069606234e55acd]]></appid><mch_id><![CDATA[1504258471]]></mch_id><nonce_str><![CDATA[39874f40c95ac398ed839e07bfdd3ca3]]></nonce_str><req_info><![CDATA[XpYWVVDwnqZctk5n1u66B0a+fQQ2bDlISsgOLog67a4RuSRXAomNUjumCFeXMbo4u1Li2ZZTx8cLRZSM63PC5k3gmgxzlMFympZ/wVVnvqiypkWSAJwBZ4uoFe4ax7eHFksI5GKNeV/qe1Ev0mS0RqzBL+f7elTu61vWXAu7489A24UwGwFHHJFHRnjb7w/uSiaj+efpVqnJXjcqvGmPajWc6M8eYnT45FFAPZru2CBvoQYS1DSeb84w74uvYBOdX7mdQs3mdISPg7gANxPMfbLwZvlaAaP4B0V4MkisskgUuiJMlVqbIgMIxJn1vsvzBgzZ3HPcuCsP3EHIK4AKzCfb8uIrX3bmMo/YszJbTzMsfbd+PFZh1Uqzh3Y1aG3lm+oBqZciTAZVZjIRHf5EpavkUhGGWY2eqPoi2tbpuCHT1cFa6kTCDMSYgpd3IVChFiSOyYmKE61wtNwFLaCdNBbpcKTnQyWCl1YOUx7N62A57ahuk6ngYTxGfCJOHFL+HUrPwviaIPz1wolrnzasEroXzBRA7xPnKfiyvGsz1plaGX8XBLZVisiKzP87Yfq2DfJ85PLXuEOd5nXXMlRPqCgLslsoCEvb9QCPCNp7b3TtZc4u4fxuPU5+MWamnicpkdU5lYt9ZSBL/0wuCNN6lklEvZry3RAi1BY4TchIsIXKI5qY3pvsdnRBm/XNAxI9HleX2eE7z+HjwdMRZHjjn2GzlJ5gpSXag8fxJ8QrABiZpN6B7u/bcwr/J7Xh1r4sJHJqlBaJ1XDQAqibFbjbNfs+hxrdny3bvsq8fGaLj44xPfDtUUzlFGNACKZO/4u93oFyGI3RnTbW/hsEUqKHgoDcxRpkyeS0poH/7beNa2ZyMrU3Mxm2EY/Wm4iy3tx5Xxss5FuQ9/Qf/YLTY8HG0B1lJ/nCZaklRgBEywAjg3AFl/UpZWnvu2fEm3GdtuQ5hqG5D6miGtDUb936BpSFXfPcGPtTJ3YW8VMaod3Hv0o=]]></req_info></xml>";
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);  // 转换成map
        String reqInfo = notifyMap.get("req_info");
        String key = "d773533ef81d3b01f8933a5c0dcc8c71";
        System.out.println(AESUtil.decryptData(reqInfo, key));
    }
}

 

注意:

因为解密为PKCS7Padding
所以需要先下载jar包,根据版本下载也可以在下面的百度云盘链接下载;
JDK8 jar包下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
JDK7 jar包下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK6 jar包下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
下载后替换掉本地的包,提前把本地的包备份

D:\jdk1.8\jdk1.8.0_111\jre\lib\security

D:\jdk1.8\jre1.8.0_111\lib\security
local_policy.jar
US_export_policy.jar

,因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件,  从官方网站下载JCE无限制权限策略文件,注意自己JDK的版本别下错了。将local_policy.jar和US_export_policy.jar这两个文件替换%JRE_HOME%\lib\security和%JDK_HOME%\jre\lib\security下原来的文件,注意先备份原文件。

百度云盘:

链接: https://pan.baidu.com/s/1H90qANpIgzKAX2JjGzVzpA 提取码: bp9g 

里面提供了jdk6,jdk7,jdk8需要别的版本可以自己去下载

自己下载需要注册账户密码。