微信公众号支付

首先感谢这位大佬的博客提供的帮助,按步骤做下来基本没什么问题.(https://blog.csdn.net/javaYouCome/article/details/79473743)

说一说我在对接过程中遇到的坑吧。

1、获取到预下单prepay_id之后,把5个参数放进map里面,还要额外给前端一个sign,获取调用接口的权限。生成paySign,然后给前端调用支付接口,一直出现签名错误,搞了大半天,终于解决了,主要是检查参数。

 1)、生成签名时的timeStamp,S大写,前台访问接口时小写,毫秒数需要除以1000,把获取到的13位毫秒数变成10位。

 2)、如果参数确实没问题那就要用很玄乎了的解决办法了, 重置API秘钥,可能多重置几次就好了,在公众平台重置之后记得还需要在商户平台->账户中心->API安全中设置一下秘钥。

2、调用申请退款接口,一直提示证书密码错误,简直要崩溃,最后发现是在网上找的读取证书的方法有问题,改了一下就成功了,最后会把代码贴出来,供大家参考。还有个小细节,申请退款接口是可以直接在本地IDE里面调用退款接口的,能打断点简直太爽了有木有,这也是解决后尝试才发现的,一遍一遍往服务器上放太浪费时间。

3、付款成功后的回调处理,退款成功后一直收不到回调,最后发现调用申请退款接口时忘了传notify_url参数了... 然后就是解密了, 需要替换掉sdk里面的两个jar包, 这个网上都有的,然后具体的解密代码最后也会贴出来,是用的网上大佬写好的,很感谢大家无私的分享,我贴出来也只是想帮助更多的人,如有不妥,还请联系我删除。

微信支付后台代码:

package com.zxf.service.impl;

import com.zxf.common.utils.RedisUtil;
import com.zxf.common.utils.WXPayConstants;
import com.zxf.common.utils.WxUtil;
import com.zxf.domain.OrderInfo;
import com.zxf.service.IWxService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Service
public class WxServiceImpl implements IWxService {

    @Resource
    private RedisUtil redisUtil;

    @Override
    public Map wxPay(String code, OrderInfo orderInfo,String url) throws Exception {
        String jsonStr = WxUtil.getOpenid(code);
        String openId = WxUtil.getJson(jsonStr,"openid");
        //获取access_token
        String accessToken = WxUtil.getJson(jsonStr,"access_token");
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>微信accessToken:"+accessToken);

        System.out.println(">>>>>>>>>>>>>>>>>openid:"+openId);
        System.out.println(">>>>>>>>>>>>>>>>>orderInfo:"+orderInfo);

        Map data = new HashMap<>();

        data.put("appid",WxUtil.APPID);
        //商品描述
        data.put("body","订单");
//        data.put("body","zhenxiufang");
        //商户号
        data.put("mch_id",WxUtil.MCH_ID);
        //随机字符串
        data.put("nonce_str",WxUtil.generateNonceStr());
        //订单号
        data.put("out_trade_no",orderInfo.getOrderNo());

        BigDecimal branch = new BigDecimal("100");
        BigDecimal orderAmountTotal = orderInfo.getOrderAmountTotal();

        String total_fee = orderAmountTotal.multiply(branch).toString();

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>total_fee:"+total_fee.substring(0,total_fee.indexOf(".")));

        //付款金额(单位:分,且不能含小数)
        data.put("total_fee",total_fee.substring(0,total_fee.indexOf(".")));
        //支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
        data.put("spbill_create_ip",WxUtil.SPBILL_CREATE_IP);
        //回调地址
        data.put("notify_url",WxUtil.NOTIFY_URL);
        //交易类型:公众号支付
        data.put("trade_type",WxUtil.TRADE_TYPE);

        data.put("openid",openId);

        //获取签名
        String sign = WxUtil.generateSignature(data,WxUtil.APPSECET, WXPayConstants.SignType.MD5);
        data.put("sign",sign);

        String xmlParam = WxUtil.mapToXml(data);

        System.out.println(">>>>>>>>>>>>>>>>>xmlParam:"+xmlParam);

        //调用统一下单接口
        String xmlResult = WxUtil.httpsRequest(WxUtil.PLACE_ORDER_URL,"POST",xmlParam);

        System.out.println(">>>>>>>>>>>>>>>>>xmlResult:"+xmlResult);

        System.out.println(xmlResult);
        //xml解析成map
        Map resultMap = WxUtil.xmlToMap(xmlResult);

        //给前台请求,需要的参数
        Map responseMap = new HashMap<>();
        responseMap.put("appId",WxUtil.APPID);

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>currentTimeMillis:"+System.currentTimeMillis()/1000);

        responseMap.put("timeStamp",System.currentTimeMillis()/1000+"");
        responseMap.put("nonceStr",WxUtil.generateNonceStr());
        responseMap.put("package","prepay_id="+resultMap.get("prepay_id"));
        responseMap.put("signType","MD5");

        //获取签名
        String paySign = WxUtil.generateSignature(responseMap,WxUtil.APPSECET, WXPayConstants.SignType.MD5);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>paySign:"+paySign);
        responseMap.put("paySign",paySign);

        String testResponseXml = WxUtil.mapToXml(responseMap);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>testResponseXml:"+testResponseXml);


        Object ticket = redisUtil.get("ticket");
        if (ticket==null){
            //根据access_token获取jsapi_ticket,有效期7200s
            String jsapiTicketStr = WxUtil.getJsapiTicket(accessToken);
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>jsapiTicketStr:"+jsapiTicketStr);
            ticket = WxUtil.getJson(jsapiTicketStr,"ticket");
            redisUtil.set("ticket",ticket,7200);
        }

        //config接口注入权限验证需要的签名
        String signature = WxUtil.getJsSdkSign(WxUtil.generateNonceStr(),ticket.toString(),System.currentTimeMillis()+"",url);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>前台js接口注入需要的签名signature:"+signature);

        responseMap.put("signature",signature);

        return responseMap;
    }

}

微信申请退款代码:

public void wxRefund(OrderInfo orderInfo) throws Exception {
        BigDecimal branch = new BigDecimal("100");
        Map data = new HashMap<>();
        data.put("appid", WxUtil.APPID);
        //商户号
        data.put("mch_id", WxUtil.MCH_ID);
        //随机字符串
        data.put("nonce_str", WxUtil.generateNonceStr());
        //订单编号
        data.put("out_trade_no", orderInfo.getOrderNo());
        //退款编号
        data.put("out_refund_no", WxUtil.generateNonceStr());

        BigDecimal orderAmountTotal = orderInfo.getOrderAmountTotal();
        String total_fee = orderAmountTotal.multiply(branch).toString();

        //订单金额(单位:分,不能有小数点)
        data.put("total_fee", total_fee.substring(0,total_fee.indexOf(".")));
        //退款金额(分)
        data.put("refund_fee", total_fee.substring(0,total_fee.indexOf(".")));

        //微信退款回调
        data.put("notify_url", WxUtil.NOTIFY_URL);

        //获取签名
        String sign = WxUtil.generateSignature(data,WxUtil.APPSECET, WXPayConstants.SignType.MD5);
        data.put("sign",sign);
        String xmlParam = WxUtil.mapToXml(data);
//        String xmlResult = WxUtil.postData(xmlParam,WxUtil.MCH_ID,WxUtil.REFUND_URL,WxUtil.APICLIENT_CERT);
        String xmlResult = WxUtil.doRefund(WxUtil.REFUND_URL,xmlParam);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>微信申请退款接口返回xmlResult:"+xmlResult);

    }

微信申请退款读取证书和发请求代码:

/**
     * 退款认证
     * @param url 微信退款路径
     * @param data 字符串xml参数
     * @return
     * @throws Exception
     */
    public static String doRefund(String url,String data) throws Exception {
        /**
         * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
         */
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
//        File certfile = ResourceUtils.getFile("classpath:wx_certificate"+ SF_FILE_SEPARATOR + APICLIENT_CERT);
        File certfile = new File(APICLIENT_CERT);
        FileInputStream instream = new FileInputStream(certfile);
        try {
            keyStore.load(instream, MCH_ID.toCharArray());
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, MCH_ID.toCharArray())
                .build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        try {
            HttpPost httpost = new HttpPost(url);
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

微信申请退款回调处理代码:

/**
 * 微信退款回调
 * @param request
 */
@RequestMapping("/wxRefundNotifyUrl")
public void wxRefundNotifyUrl(HttpServletRequest request){
    System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>进入微信退款回调");
    InputStream inStream = null;
    try {
        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");
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>微信退款回调resultByteXml:"+resultxml);
        Map refundMap = WxUtil.xmlToMap(resultxml);

        if (refundMap.get("return_code").equals("SUCCESS")) {
            //解码,先base64解码, 然后AES解码
            String aesXml = AESUtil.decryptData(refundMap.get("req_info"));
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>微信退款回调解密后的串,应该是aesXml:" + aesXml);
            Map aesMap = WxUtil.xmlToMap(aesXml);
            //订单号
            String out_trade_no = aesMap.get("out_trade_no");
            //金额
            BigDecimal total_fee = new BigDecimal(aesMap.get("total_fee")).divide(new BigDecimal(100));
            OrderInfo orderInfo = orderInfoService.selectOne(new EntityWrapper().eq("order_no", out_trade_no));
            //验证订单是否存在,付款金额,状态是否为退款中
            if (orderInfo != null && orderInfo.getOrderAmountTotal().compareTo(total_fee) == 0 && orderInfo.getOrderStatus().equals(9)) {
                orderInfo.setOrderStatus(6);
                orderInfoService.updateById(orderInfo);
                //传输退款销货单
                tService.refundSalesOrder(orderInfo, TUtil.WX_PAY, TUtil.WX_ACCOUNT_ID);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

微信退款AES解密工具类:

package com.zxf.common.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

public class AESUtil {
    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "AES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";
    /**
     * 生成key
     */
    private static final String key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//此处为测试key,正式环境请替换成商户密钥
    private static SecretKeySpec secretKey = new SecretKeySpec(MD5Util.MD5Encode(key, "UTF-8").toLowerCase().getBytes(), ALGORITHM);

    /**
     * AES加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encryptData(String data) throws Exception {
        /**
         * 这个地方调用BouncyCastleProvider
         *让java支持PKCS7Padding
         */
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        // 创建密码器
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        // 初始化
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return Base64Util.encode(cipher.doFinal(data.getBytes()));
    }

    /**
     * AES解密
     *
     * @param base64Data
     * @return
     * @throws Exception
     */
    public static String decryptData(String base64Data) throws Exception {
        /**
         * 这个地方调用BouncyCastleProvider
         *让java支持PKCS7Padding
         */
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        // 创建密码器
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return new String(cipher.doFinal(Base64Util.decode(base64Data)));
    }

   /* public static void main(String[] args) throws Exception {
        //String A 为测试字符串,是微信返回过来的退款通知字符串
        String A = "oSWxqqMF5lk2EF+gdrdt5wPrOru854za5XjHq5cUXs74zF9+jlxGOo7DHQIuntolVF3kQAruoMoNK5lLRsCulgG2hAT+6sNen8f/f3drMxfsTFOj3aBTKkIHs2p3AVJA4fXpGRCpejq3JJplSQnnSwFljzcxvqe7rU3y/H0KpFyBuYUSEf+msbkHEnHnIHQi4p9JDlLPWoKHramM7R65Qd13GdUU41scNybWCkwl+q/cY2Nv6KUt490JXTbTEgZNE6ArJKGg9woRMUdJEimTnv2OSY16yjo8dlIiozEoHcoQsvSFuMA5DHfHmtk5gbn8y6FVLHbt8XmmOIkfl/CVCXGQ+fGJmazxmqpTLBnAxXogFX2c2h8ZFqrWHW0wWZNSqpRX8HnMBw4V5hUMCiN9ASP3AzkpbtxdkDaeJYagVFgpB7oXxNUlQMy7pCqWCqbhoeLlZtzACx3qNqf57cQLn06T8wrYddf3f78oIYceVWMBses6wcJW2uTUdci4hYOQn5G+iVGLRzMuI8xwQSeBtdrWBor842tEsg4/wgFRxiEgjN+Jl+pCbwULjzt870OwC/UKD9mM3bhyay1jxeKNfkqgks0TH9eZXT1mR6IBfIUipgk9nTrGLFQwt4AAAf7/KoW7A3d1eYGY1vo/QkinixiZsxOJhzw95X6wiiARPa8oe0180lCuhLtIrNRlxyVMbbwA8GQVuCCE6w+/yKIF+el+Gcf7Gm2ljQzV7PEwiomW/DsBqUb5mwGfI52NLRa70kJ8vgaXeMN1xhwWYLzg02muvGGwS2P4kgGO0Sg0L5ycpN7Vp421+HnAPdcW6y/pQi03BKAR6fZT5JQYAIoNN4K8K6ZbgfZiuG32q0q4bwVWrg4jBlyPmj8JwHtbikbAgoJ9sUwWYi7P+Btk1ZHCPLW90p+1mIL8eVpneOaon3mSW0R4JDiIJK8oYLD/1n4NTKRTg9c6OMdSHnK8BUnodw==";
        String B = AESUtil.decryptData(A);
        System.out.println(B);
    }*/

}

微信退款Base64解密工具类:

package com.zxf.common.utils;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

/**
 * Base64工具类
 */
public class Base64Util {

    private static final char S_BASE64CHAR[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
            'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
            'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
    private static final byte S_DECODETABLE[];

    static {
        S_DECODETABLE = new byte[128];
        for (int i = 0; i < S_DECODETABLE.length; i++)
            S_DECODETABLE[i] = 127;

        for (int i = 0; i < S_BASE64CHAR.length; i++)
            S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i;

    }

    /**
     *
     * @param ibuf
     * @param obuf
     * @param wp
     * @return
     */
    private static int decode0(char ibuf[], byte obuf[], int wp) {
        int outlen = 3;
        if (ibuf[3] == '=')
            outlen = 2;
        if (ibuf[2] == '=')
            outlen = 1;
        int b0 = S_DECODETABLE[ibuf[0]];
        int b1 = S_DECODETABLE[ibuf[1]];
        int b2 = S_DECODETABLE[ibuf[2]];
        int b3 = S_DECODETABLE[ibuf[3]];
        switch (outlen) {
            case 1: // '\001'
                obuf[wp] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);
                return 1;

            case 2: // '\002'
                obuf[wp++] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);
                obuf[wp] = (byte) (b1 << 4 & 240 | b2 >> 2 & 15);
                return 2;

            case 3: // '\003'
                obuf[wp++] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);
                obuf[wp++] = (byte) (b1 << 4 & 240 | b2 >> 2 & 15);
                obuf[wp] = (byte) (b2 << 6 & 192 | b3 & 63);
                return 3;
        }
        throw new RuntimeException("Internal error");
    }

    /**
     *
     * @param data
     * @param off
     * @param len
     * @return
     */
    public static byte[] decode(char data[], int off, int len) {
        char ibuf[] = new char[4];
        int ibufcount = 0;
        byte obuf[] = new byte[(len / 4) * 3 + 3];
        int obufcount = 0;
        for (int i = off; i < off + len; i++) {
            char ch = data[i];
            if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))
                continue;
            ibuf[ibufcount++] = ch;
            if (ibufcount == ibuf.length) {
                ibufcount = 0;
                obufcount += decode0(ibuf, obuf, obufcount);
            }
        }

        if (obufcount == obuf.length) {
            return obuf;
        }
        else {
            byte ret[] = new byte[obufcount];
            System.arraycopy(obuf, 0, ret, 0, obufcount);
            return ret;
        }
    }

    /**
     *
     * @param data
     * @return
     */
    public static byte[] decode(String data) {
        char ibuf[] = new char[4];
        int ibufcount = 0;
        byte obuf[] = new byte[(data.length() / 4) * 3 + 3];
        int obufcount = 0;
        for (int i = 0; i < data.length(); i++) {
            char ch = data.charAt(i);
            if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))
                continue;
            ibuf[ibufcount++] = ch;
            if (ibufcount == ibuf.length) {
                ibufcount = 0;
                obufcount += decode0(ibuf, obuf, obufcount);
            }
        }

        if (obufcount == obuf.length) {
            return obuf;
        }
        else {
            byte ret[] = new byte[obufcount];
            System.arraycopy(obuf, 0, ret, 0, obufcount);
            return ret;
        }
    }

    /**
     *
     * @param data
     * @param off
     * @param len
     * @param ostream
     * @throws IOException
     */
    public static void decode(char data[], int off, int len, OutputStream ostream) throws IOException {
        char ibuf[] = new char[4];
        int ibufcount = 0;
        byte obuf[] = new byte[3];
        for (int i = off; i < off + len; i++) {
            char ch = data[i];
            if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))
                continue;
            ibuf[ibufcount++] = ch;
            if (ibufcount == ibuf.length) {
                ibufcount = 0;
                int obufcount = decode0(ibuf, obuf, 0);
                ostream.write(obuf, 0, obufcount);
            }
        }

    }

    /**
     *
     * @param data
     * @param ostream
     * @throws IOException
     */
    public static void decode(String data, OutputStream ostream) throws IOException {
        char ibuf[] = new char[4];
        int ibufcount = 0;
        byte obuf[] = new byte[3];
        for (int i = 0; i < data.length(); i++) {
            char ch = data.charAt(i);
            if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))
                continue;
            ibuf[ibufcount++] = ch;
            if (ibufcount == ibuf.length) {
                ibufcount = 0;
                int obufcount = decode0(ibuf, obuf, 0);
                ostream.write(obuf, 0, obufcount);
            }
        }

    }

    /**
     *
     * @param data
     * @return
     */
    public static String encode(byte data[]) {
        return encode(data, 0, data.length);
    }

    /**
     *
     * @param data
     * @param off
     * @param len
     * @return
     */
    public static String encode(byte data[], int off, int len) {
        if (len <= 0)
            return "";
        char out[] = new char[(len / 3) * 4 + 4];
        int rindex = off;
        int windex = 0;
        int rest;
        for (rest = len - off; rest >= 3; rest -= 3) {
            int i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);
            out[windex++] = S_BASE64CHAR[i >> 18];
            out[windex++] = S_BASE64CHAR[i >> 12 & 63];
            out[windex++] = S_BASE64CHAR[i >> 6 & 63];
            out[windex++] = S_BASE64CHAR[i & 63];
            rindex += 3;
        }

        if (rest == 1) {
            int i = data[rindex] & 255;
            out[windex++] = S_BASE64CHAR[i >> 2];
            out[windex++] = S_BASE64CHAR[i << 4 & 63];
            out[windex++] = '=';
            out[windex++] = '=';
        }
        else if (rest == 2) {
            int i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);
            out[windex++] = S_BASE64CHAR[i >> 10];
            out[windex++] = S_BASE64CHAR[i >> 4 & 63];
            out[windex++] = S_BASE64CHAR[i << 2 & 63];
            out[windex++] = '=';
        }
        return new String(out, 0, windex);
    }

    /**
     *
     * @param data
     * @param off
     * @param len
     * @param ostream
     * @throws IOException
     */
    public static void encode(byte data[], int off, int len, OutputStream ostream) throws IOException {
        if (len <= 0)
            return;
        byte out[] = new byte[4];
        int rindex = off;
        int rest;
        for (rest = len - off; rest >= 3; rest -= 3) {
            int i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);
            out[0] = (byte) S_BASE64CHAR[i >> 18];
            out[1] = (byte) S_BASE64CHAR[i >> 12 & 63];
            out[2] = (byte) S_BASE64CHAR[i >> 6 & 63];
            out[3] = (byte) S_BASE64CHAR[i & 63];
            ostream.write(out, 0, 4);
            rindex += 3;
        }

        if (rest == 1) {
            int i = data[rindex] & 255;
            out[0] = (byte) S_BASE64CHAR[i >> 2];
            out[1] = (byte) S_BASE64CHAR[i << 4 & 63];
            out[2] = 61;
            out[3] = 61;
            ostream.write(out, 0, 4);
        }
        else if (rest == 2) {
            int i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);
            out[0] = (byte) S_BASE64CHAR[i >> 10];
            out[1] = (byte) S_BASE64CHAR[i >> 4 & 63];
            out[2] = (byte) S_BASE64CHAR[i << 2 & 63];
            out[3] = 61;
            ostream.write(out, 0, 4);
        }
    }

    /**
     *
     * @param data
     * @param off
     * @param len
     * @param writer
     * @throws IOException
     */
    public static void encode(byte data[], int off, int len, Writer writer) throws IOException {
        if (len <= 0)
            return;
        char out[] = new char[4];
        int rindex = off;
        int rest = len - off;
        int output = 0;
        do {
            if (rest < 3)
                break;
            int i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);
            out[0] = S_BASE64CHAR[i >> 18];
            out[1] = S_BASE64CHAR[i >> 12 & 63];
            out[2] = S_BASE64CHAR[i >> 6 & 63];
            out[3] = S_BASE64CHAR[i & 63];
            writer.write(out, 0, 4);
            rindex += 3;
            rest -= 3;
            if ((output += 4) % 76 == 0)
                writer.write("\n");
        }
        while (true);
        if (rest == 1) {
            int i = data[rindex] & 255;
            out[0] = S_BASE64CHAR[i >> 2];
            out[1] = S_BASE64CHAR[i << 4 & 63];
            out[2] = '=';
            out[3] = '=';
            writer.write(out, 0, 4);
        }
        else if (rest == 2) {
            int i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);
            out[0] = S_BASE64CHAR[i >> 10];
            out[1] = S_BASE64CHAR[i >> 4 & 63];
            out[2] = S_BASE64CHAR[i << 2 & 63];
            out[3] = '=';
            writer.write(out, 0, 4);
        }
    }

}

微信退款MD5解密工具类:

package com.zxf.common.utils;

import java.security.MessageDigest;

public class MD5Util {
    public final static String MD5(String s) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        try {
            byte[] btInput = s.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.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) {
            e.printStackTrace();
            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" };

    /*public static void main(String[] asd) {
        String con = "hello kitty";
        String str = MD5Encode(con, "UTF-8");
        System.out.println(str.toUpperCase());
    }*/
}

你可能感兴趣的:(第三方支付相关,微信支付,微信退款,微信退款回调)