微信公众号支付后申请退款代码

package net.dunotech.mercury.mtzx.Test;

import net.dunotech.mercury.mtzx.logger.MyLogger;
import net.dunotech.mercury.mtzx.logger.MyLoggerFactory;
import net.dunotech.mercury.mtzx.utils.WXPayXmlUtil;
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.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.net.ssl.SSLContext;
import javax.xml.parsers.DocumentBuilder;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author MTZX on 19/11/11 0011
 */
public class Test2 {

    private static MyLogger logger = MyLoggerFactory.getMyLogger(Test.class);

    public Map<String, String> refund(int refundFee) {
        Map<String, Object> signMap = new HashMap<>(10);
        String mchId = "【MCHID】";
        signMap.put("appid", "【APPID】");
        signMap.put("mch_id", mchId);
        signMap.put("nonce_str", "32随机数");
        // 以下transaction_id和out_trade_no二选一
        //signMap.put("transaction_id", "支付成功时微信返回的transaction_id");
        signMap.put("out_trade_no", "支付时自己这边生成的订单号");
        signMap.put("out_refund_no", "32随机数");
        signMap.put("refund_fee", "需要退款的金额,单位:分");
        signMap.put("total_fee", "订单支付时的总金额,单位:分");
        signMap.put("notify_url", "退款回调地址,退成成功微信支付会请求这个地址");
        // 对数据进行签名
        signMap.put("sign", dataSign("【APIKEY】", signMap));
        String xml = WXPayXmlUtil.mapToXml(signMap);
        if (isEmpty(xml)) {
            logger.error("生成的申请退款信息错误");
            return new HashMap<>(0);
        }
        logger.info("加载证书开始=========================================》》》》》");
        StringBuilder sb2 = new StringBuilder();
        FileInputStream instream = null;
        try {
            // 指定读取证书格式为PKCS12
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            // 读取本机存放的PKCS12证书文件
            instream = new FileInputStream(new File("/projects/microcourse/cert/apiclient_cert.p12"));
            // 指定PKCS12的密码(商户ID)
            keyStore.load(instream, mchId.toCharArray());
            // ssl双向验证发送http请求报文
            SSLContext sslcontext = null;
            sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
            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");
            StringEntity se = new StringEntity(xml, "UTF-8");
            httppost.setEntity(se);
            CloseableHttpResponse responseEntry = null;
            String xmlStr2 = null;
            responseEntry = httpclient.execute(httppost);
            HttpEntity httpEntity = responseEntry.getEntity();
            if (httpEntity != null) {
                BufferedReader bufferedReader = null;
                bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent(),
                        StandardCharsets.UTF_8));
                while ((xmlStr2 = bufferedReader.readLine()) != null) {
                    sb2.append(xmlStr2);
                }
            }
        } catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException | KeyManagementException e) {
            logger.error("异常", e);
            return new HashMap<>(0);
        } finally {
            try {
                Objects.requireNonNull(instream).close();
            } catch (IOException e) {
                logger.error("异常", e);
            }
        }

        Map<String, String> map;
        try {
            logger.info("返回请求结果=" + sb2.toString());
            map = xmlToMap(sb2.toString());
        } catch (Exception e) {
            logger.error("异常", e);
            return new HashMap<>(0);
        }
        if (map == null || map.size() == 0) {
            logger.error("错误:生成的申请退款信息错误");
            return new HashMap<>(0);
        }
        logger.info("申请退款接口返回的结果集======>" + map);
        if ("SUCCESS".equalsIgnoreCase(map.get("return_code")) && "SUCCESS".equalsIgnoreCase(map.get("result_code"))) {
            logger.info("****************退款申请成功!**********************");
            return map;
        } else {
            logger.error("*****************退款申请失败!*********************");
            return map;
        }
    }

    /**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<>();
            DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes(StandardCharsets.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) {
                logger.error("异常 ", ex);
            }
            return data;
        } catch (Exception ex) {
            logger.error("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(),
                    strXML);
            throw ex;
        }

    }

    private String dataSign(String key, Map signMap) {
        String appid = objectToString(signMap.get("appid"));
        String mchId = objectToString(signMap.get("mch_id"));
        String nonceStr = objectToString(signMap.get("nonce_str"));
        String notifyUrl = objectToString(signMap.get("notify_url"));
        String outRefundNo = objectToString(signMap.get("out_refund_no"));
        String outTradeNo = objectToString(signMap.get("out_trade_no"));
        String refundFee = objectToString(signMap.get("refund_fee"));
        //String subMchId = objectToString(signMap.get("sub_mch_id"));
        String totalFee = objectToString(signMap.get("total_fee"));
        String transactionId = objectToString(signMap.get("transaction_id"));
        StringBuilder stringBuilder = new StringBuilder();
        if (isNotEmpty(appid)) {
            stringBuilder.append("appid=").append(appid);
        }
        if (isNotEmpty(mchId)) {
            stringBuilder.append("&mch_id=").append(mchId);
        }
        if (isNotEmpty(nonceStr)) {
            stringBuilder.append("&nonce_str=").append(nonceStr);
        }
        if (isNotEmpty(notifyUrl)) {
            stringBuilder.append("&notify_url=").append(notifyUrl);
        }
        if (isNotEmpty(outRefundNo)) {
            stringBuilder.append("&out_refund_no=").append(outRefundNo);
        }
        if (isNotEmpty(outTradeNo)) {
            stringBuilder.append("&out_trade_no=").append(outTradeNo);
        }
        if (isNotEmpty(refundFee)) {
            stringBuilder.append("&refund_fee=").append(refundFee);
        }
        if (isNotEmpty(totalFee)) {
            stringBuilder.append("&total_fee=").append(totalFee);
        }
        if (isNotEmpty(transactionId)) {
            stringBuilder.append("&transaction_id=").append(transactionId);
        }
        stringBuilder.append("&key=").append(key);
        try {
            return MD5(stringBuilder.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String MD5(String data) throws Exception {
        java.security.MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
        }
        return sb.toString().toUpperCase();
    }

    public static String objectToString(Object object) {
        if (object == null) {
            return null;
        }
        return String.valueOf(object);
    }

    public static boolean isEmpty(String string) {
        return string == null || string.replaceAll(" ", "").trim().length() == 0;
    }

    public static boolean isNotEmpty(String string) {
        return !isEmpty(string);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值