springboot对接微信支付

公共配置类

import lombok.Data;
import springboot.util.TestProperties;

@Data
public class PayConfig {
    //appId(与你商户号绑定的小程序或公众号的appid)
    private String appID= "wxzf.appID";
    
    //小程序秘钥
    private String aPPSECRET="wxzf.aPPSECRET";

    //商户号
    private String mchID="wxzf.mchID";

    //支付秘钥
    private String Key="wxzf.Key";

}

支付签名工具

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;

/**
 * 生成签名
 */
public class SignUtil {
    //指定为MD5加密方式
    public static String generateSignature(Map<String, String> data, String key) throws Exception {
        return generateSignature(data, key, "MD5");
    }

    //自选加密方式加密方式
    public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = (String[])keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        String[] var6 = keyArray;
        int var7 = keyArray.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            String k = var6[var8];
            if (!k.equals("sign") && ((String)data.get(k)).trim().length() > 0) {
                sb.append(k).append("=").append(((String)data.get(k)).trim()).append("&");
            }
        }

        sb.append("key=").append(key);
        if ("MD5".equals(signType)) {
            return MD5(sb.toString()).toUpperCase();
        } else if ("HMACSHA256".equals(signType)) {
            return HMACSHA256(sb.toString(), key);
        } else {
            throw new Exception(String.format("Invalid sign_type: %s", signType));
        }
    }


    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();
        byte[] var4 = array;
        int var5 = array.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            byte item = var4[var6];
            sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
        }

        return sb.toString().toUpperCase();
    }


    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();
        byte[] var6 = array;
        int var7 = array.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            byte item = var6[var8];
            sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
        }

        return sb.toString().toUpperCase();
    }
}

支付签名验证工具

import springboot.wexPayApi.dto.PayConfig;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;

/**
 * 验证签名
 */
public class Verification {
    public static boolean isPayResultNotifySignatureValid(Map<String, String> reqData) throws Exception {
        String signTypeInData = (String)reqData.get("sign_type");
         String signType;
        if (signTypeInData == null) {
            signType = "MD5";
        } else {
            signTypeInData = signTypeInData.trim();
            if (signTypeInData.length() == 0) {
                signType =  "MD5";
            } else if ("MD5".equals(signTypeInData)) {
                signType =  "MD5";
            } else {
                if (!"HMAC-SHA256".equals(signTypeInData)) {
                    throw new Exception(String.format("Unsupported sign_type: %s", signTypeInData));
                }

                signType = "HMACSHA256";
            }
        }
        PayConfig config=new PayConfig();

        return isSignatureValid(reqData, config.getKey(), signType);
    }

    public static boolean isSignatureValid(Map<String, String> data, String key, String signType) throws Exception {
        if (!data.containsKey("sign")) {
            return false;
        } else {
            String sign = (String)data.get("sign");
            return generateSignature(data, key, signType).equals(sign);
        }
    }


    public static String generateSignature(Map<String, String> data, String key, String signType) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = (String[])keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        String[] var6 = keyArray;
        int var7 = keyArray.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            String k = var6[var8];
            if (!k.equals("sign") && ((String)data.get(k)).trim().length() > 0) {
                sb.append(k).append("=").append(((String)data.get(k)).trim()).append("&");
            }
        }

        sb.append("key=").append(key);
        if ("MD5".equals(signType)) {
            return MD5(sb.toString()).toUpperCase();
        } else if ("HMACSHA256".equals(signType)) {
            return HMACSHA256(sb.toString(), key);
        } else {
            throw new Exception(String.format("Invalid sign_type: %s", signType));
        }
    }

    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();
        byte[] var6 = array;
        int var7 = array.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            byte item = var6[var8];
            sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
        }

        return sb.toString().toUpperCase();
    }

    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();
        byte[] var4 = array;
        int var5 = array.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            byte item = var4[var6];
            sb.append(Integer.toHexString(item & 255 | 256).substring(1, 3));
        }

        return sb.toString().toUpperCase();
    }
}

普通请求发送工具post,get请求

import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;

/**
 * 发送请求(post,get请求)
 */
public class HttpKit {
    private static String CHARSET = "UTF-8";
    private static final SSLSocketFactory sslSocketFactory = initSSLSocketFactory();
    private static final TrustAnyHostnameVerifier trustAnyHostnameVerifier = new HttpKit().new TrustAnyHostnameVerifier();

//    public static final OkHttp3Delegate delegate = new OkHttp3Delegate();

    private HttpKit() {
    }

    private static SSLSocketFactory initSSLSocketFactory() {
        try {
            TrustManager[] e = new TrustManager[]{new HttpKit().new TrustAnyTrustManager()};
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init((KeyManager[])null, e, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception var2) {
            throw new RuntimeException(var2);
        }
    }


    private static HttpURLConnection getHttpConnection(String url, String method, Map<String, String> headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException{
        URL _url = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)_url.openConnection();
        if(conn instanceof HttpsURLConnection) {
            ((HttpsURLConnection)conn).setSSLSocketFactory(sslSocketFactory);
            ((HttpsURLConnection)conn).setHostnameVerifier(trustAnyHostnameVerifier);
        }

        conn.setRequestMethod(method);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setConnectTimeout(19000);
        conn.setReadTimeout(19000);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("AuthUser-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
        if(headers != null && !headers.isEmpty()) {
            Iterator i$ = headers.entrySet().iterator();

            while(i$.hasNext()) {
                Map.Entry entry = (Map.Entry)i$.next();
                conn.setRequestProperty((String)entry.getKey(), (String)entry.getValue());
            }
        }

        return conn;
    }

    public static String get(String url, Map<String, String> queryParas, Map<String, String> headers) {
        HttpURLConnection conn = null;
        String e;
        try {
            conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "GET", headers);
            conn.connect();
            e = readResponseString(conn);
        } catch (Exception var8) {
            throw new RuntimeException(var8);
        } finally {
            if(conn != null) {
                conn.disconnect();
            }
        }
        return e;
    }

    public static String get(String url, Map<String, String> queryParas) {
        return get(url, queryParas, (Map)null);
    }

    public static String get(String url) {
        return get(url, (Map)null, (Map)null);
    }

    public static String post(String url, Map<String, String> queryParas, String data, Map<String, String> headers) {
        HttpURLConnection conn = null;

        String var6;
        try {
            conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "POST", headers);
            conn.connect();
            OutputStream e = conn.getOutputStream();
            e.write(data.getBytes(CHARSET));
            e.flush();
            e.close();
            var6 = readResponseString(conn);
        } catch (Exception var10) {
            throw new RuntimeException(var10);
        } finally {
            if(conn != null) {
                conn.disconnect();
            }
        }
        return var6;
    }

    public static String post(String url, Map<String, String> queryParas, String data) {
        return post(url, queryParas, data, (Map)null);
    }

    public static String post(String url, String data, Map<String, String> headers) {
        return post(url, (Map)null, data, headers);
    }

    public static String post(String url, String data) {
        return post(url, (Map)null, data, (Map)null);
    }

    private static String readResponseString(HttpURLConnection conn) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;

        try {
            inputStream = conn.getInputStream();
            BufferedReader e = new BufferedReader(new InputStreamReader(inputStream, CHARSET));
            String line = null;

            while((line = e.readLine()) != null) {
                sb.append(line).append("\n");
            }

            String var5 = sb.toString();
            return var5;
        } catch (Exception var14) {
            throw new RuntimeException(var14);
        } finally {
            if(inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException var13) {
                }
            }

        }
    }

    private static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
        if(queryParas != null && !queryParas.isEmpty()) {
            StringBuilder sb = new StringBuilder(url);
            boolean isFirst;
            if(url.indexOf("?") == -1) {
                isFirst = true;
                sb.append("?");
            } else {
                isFirst = false;
            }

            String key;
            String value;
            for(Iterator i$ = queryParas.entrySet().iterator() ; i$.hasNext(); sb.append(key).append("=").append(value)) {
                Map.Entry entry = (Map.Entry)i$.next();
                if(isFirst) {
                    isFirst = false;
                } else {
                    sb.append("&");
                }

                key = (String)entry.getKey();
                value = (String)entry.getValue();
                if(value!=null && !"".equals(value)) {
                    try {
                        value = URLEncoder.encode(value, CHARSET);
                    } catch (UnsupportedEncodingException var9) {
                        throw new RuntimeException(var9);
                    }
                }
            }

            return sb.toString();
        } else {
            return url;
        }
    }

    public static String readData(HttpServletRequest request) {
        BufferedReader br = null;

        try {
            StringBuilder e = new StringBuilder();
            br = request.getReader();
            String line = null;

            while((line = br.readLine()) != null) {
                e.append(line).append("\n");
            }

            line = e.toString();
            return line;
        } catch (IOException var12) {
            throw new RuntimeException(var12);
        } finally {
            if(br != null) {
                try {
                    br.close();
                } catch (IOException var11) {
                }
            }

        }
    }

    /** @deprecated */
    @Deprecated
    public static String readIncommingRequestData(HttpServletRequest request) {
        return readData(request);
    }


    private class TrustAnyTrustManager implements X509TrustManager {
        private TrustAnyTrustManager() {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException{
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }
    }

    private class TrustAnyHostnameVerifier implements HostnameVerifier {
        private TrustAnyHostnameVerifier() {
        }

        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
}

携带证书请求与处理Xml格式


import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
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.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.springframework.core.io.ClassPathResource;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import springboot.util.TestProperties;

import javax.net.ssl.SSLContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

/**
 * 发送HTTPS的post的请求携带证书请求
 * xml转map,map转xml
 *
 */
public class HttpsPost {
    /**
     * 微信下单,map to xml
     * @param params 参数
     * @return String
     */
    public static String toXml(Map<String, String> params) {
        StringBuilder xml = new StringBuilder();
        xml.append("<xml>");
        //遍历map获取key与value
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String key   = entry.getKey();
            String value = entry.getValue();
            // 略过空值
            if (isEmpty(value)){ continue;}
            xml.append("<").append(key).append(">");
            xml.append(entry.getValue());
            xml.append("</").append(key).append(">");
        }
        xml.append("</xml>");
        return xml.toString();
    }

    /**
     * 检测字符串是否为空(null,"","null")
     *
     * @param s
     * @return 为空则返回true,不否则返回false
     */
    public static boolean isEmpty(String s) {
        return s == null || "".equals(s) || "null".equals(s);
    }

    /**
     * String转map
     * @param str_json
     * @return
     */
    public static Map<String, String> json2map(String str_json) {
        Map<String, String> res = null;
        try {
            Gson gson = new Gson();
            res = gson.fromJson(str_json, new TypeToken<Map<String, String>>() {
            }.getType());
        } catch (JsonSyntaxException e) {
        }
        return res;
    }

    /**
     * 带证书httpPost请求
     * @param url   接口地址
     * @param param 参数
     * @return
     * @throws Exception
     */
    public static String sendRedEnvelope(String url, String param) throws Exception {
        //PKCS12的密码
        String PKCS12 = TestProperties.getvalue("wxzf.mchID");
        //证书地址 apiclient_cert.p12
        String fileRoute = TestProperties.getvalue("wxzf.certPath");
        //指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        //读取本机存放的PKCS12证书文件
//        FileInputStream instream = new FileInputStream(new File(fileRoute));
        InputStream instream = new ClassPathResource(fileRoute).getInputStream();
        try {
            //指定PKCS12的密码
            keyStore.load(instream, PKCS12.toCharArray());
        } finally {
            instream.close();
        }
        //指定TLS版本
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, PKCS12.toCharArray())
                .build();
        //设置httpclient的SSLSocketFactory
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        StringBuffer stringBuffer = new StringBuffer();
        try {
            HttpPost httpPost = new HttpPost(url);
            InputStream is = new ByteArrayInputStream(param.getBytes("UTF-8"));
            //InputStreamEntity严格是对内容和长度相匹配的。用法和BasicHttpEntity类似
            InputStreamEntity inputStreamEntity = new InputStreamEntity(is, is.available());
            httpPost.setEntity(inputStreamEntity);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        entity.getContent(), "UTF-8"));
                String inputLine;
                while ((inputLine = reader.readLine()) != null) {
                    stringBuffer.append(inputLine);
                }
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        String str=stringBuffer.toString();

        return str;
    }

    /**
     * XML格式字符串转换为Map
     *
     * @param xml XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String xml) {
        try {
            Map<String, String> data = new HashMap<>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(xml.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());
                }
            }
            stream.close();
            return data;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

Jsapi支付



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import springboot.util.startuputil.IpUtil;
import springboot.wexPayApi.controller.HDController;
import springboot.wexPayApi.dto.PayConfig;
import springboot.wexPayApi.util.HttpKit;
import springboot.wexPayApi.util.HttpsPost;
import springboot.wexPayApi.util.SignUtil;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Jsapi支付接口
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
 * 作者:王文斌
 */
@Component
public class JsapiPayUtil {

    private static Logger logger = LoggerFactory.getLogger(HDController.class);//可注释


    /**
     * 微信支付接口
     *
     * @param money  金额
     * @param openid 用户openid
     * @return
     * @throws Exception
     */
    public  Object genWxProgramPayChannel(String money, String orderNumber, String openid, String body) throws Exception {
        //orderNumber号 订单
        PayConfig config = new PayConfig();
        Map<String, String> reqParams = new HashMap<>();
        //微信分配的小程序ID
        reqParams.put("appid", config.getAppID());
        //微信支付分配的商户号
        reqParams.put("mch_id", config.getMchID());
        //随机字符串
        reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
        //签名类型
        reqParams.put("sign_type", "MD5");
        //充值订单 商品描述
        reqParams.put("body", body);
        //商户订单号
        reqParams.put("out_trade_no", orderNumber);
        //订单总金额,单位为分
        reqParams.put("total_fee", money);
        //终端IP
        reqParams.put("spbill_create_ip", IpUtil.getRequestIp());
        //通知地址http://www.bskuqi.cn/
        reqParams.put("notify_url", "https://bskuqi.cn/yldh/web/api/yys/JSAPI/notify/");
        //交易类型
        reqParams.put("trade_type", "JSAPI");
        //用户标识
        reqParams.put("openid", openid);

        //签名
        String sign = SignUtil.generateSignature(reqParams, config.getKey());
//        request.getSession().setAttribute(orderNumber,sign);
        reqParams.put("sign", sign);
        /*
            调用支付定义下单API,返回预付单信息 prepay_id
         */
        String xmlResult = HttpKit.post("https://api.mch.weixin.qq.com/pay/unifiedorder", HttpsPost.toXml(reqParams));
        logger.info("---" + xmlResult);
        Map<String, String> result = HttpsPost.xmlToMap(xmlResult);

        System.out.println("money========================================"+money);

        String prepay_id = result.get("prepay_id");

        /*
            小程序调起支付数据签名
         */
        Map<String, String> packageParams = new HashMap<String, String>();
        packageParams.put("appId", config.getAppID());
        packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
        packageParams.put("nonceStr", System.currentTimeMillis() + "");
        packageParams.put("package", "prepay_id=" + prepay_id);
        packageParams.put("signType", "MD5");
        String packageSign = SignUtil.generateSignature(packageParams, config.getKey());
        packageParams.put("paySign", packageSign);
        return packageParams;
    }

    /**
     * jsapi退款方法
     * @param outTradeNo 退款订单号(支付时产生的订单号)
     * @param total_fee  总金额(及退款金额)
     * @return
     * @throws Exception MD5Util签名异常
     */
    public boolean refund(String outTradeNo, String total_fee) throws Exception {
        PayConfig config = new PayConfig();

        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String hehe = dateFormat.format(now);
        String out_refund_no = hehe + "wxrefund";

        int allFee = (int) (Double.parseDouble(total_fee))*100;

        Map<String, String> reqParams = new HashMap<>();
        reqParams.put("appid",config.getAppID());
        reqParams.put("mch_id", config.getMchID());
        reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
        reqParams.put("out_trade_no", outTradeNo);
        reqParams.put("total_fee",String.valueOf(allFee));
        reqParams.put("refund_fee",String.valueOf(allFee));
        reqParams.put("out_refund_no",out_refund_no);

        //签名
        String sign = SignUtil.generateSignature(reqParams, config.getKey());
        reqParams.put("sign", sign);

        System.out.println(HttpsPost.toXml(reqParams));

        String xmlResult = HttpsPost.sendRedEnvelope("https://api.mch.weixin.qq.com/secapi/pay/refund", HttpsPost.toXml(reqParams));
        logger.info("---" + xmlResult);
        Map<String, String> result = HttpsPost.xmlToMap(xmlResult);

        if(xmlResult.contains("大于可退金额")){
            return false;
        }else {
            return true;
        }
    }


    /**
     * 退回剩余金额
     * @param outTradeNo (支付时产生的订单号)
     * @param all_fee 总金额
     * @param over_fee 退回金额
     * @return
     * @throws Exception
     */
    public boolean overrefund(String outTradeNo, String all_fee,String over_fee) throws Exception {
        PayConfig config = new PayConfig();

        System.err.println("进入微信退款申请");
        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");//可以方便地修改日期格式
        String hehe = dateFormat.format(now);
        int allFee = (int) (Double.parseDouble(all_fee))*100; //需要*100
        int overFee = (int) (Double.parseDouble(over_fee))*100; //需要*100

        String out_refund_no = hehe + "wxrefund";
        Map<String, String> reqParams = new HashMap<>();
        reqParams.put("appid",config.getAppID());
        reqParams.put("mch_id", config.getMchID());
        reqParams.put("nonce_str", System.currentTimeMillis() / 1000 + "");
        reqParams.put("out_trade_no", outTradeNo);
        reqParams.put("total_fee",String.valueOf(allFee));
        reqParams.put("refund_fee",String.valueOf(overFee));
        reqParams.put("out_refund_no",out_refund_no);

        //签名
        String sign = SignUtil.generateSignature(reqParams, config.getKey());
        reqParams.put("sign", sign);

        System.out.println(HttpsPost.toXml(reqParams));

        String xmlResult = HttpsPost.sendRedEnvelope("https://api.mch.weixin.qq.com/secapi/pay/refund", HttpsPost.toXml(reqParams));
        logger.info("---" + xmlResult);
        Map<String, String> result = HttpsPost.xmlToMap(xmlResult);

        if(xmlResult.contains("大于可退金额")){
            return false;
        }else {
            return true;
        }
    }


}

回调

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springboot.common.api.ApiResult;
import springboot.common.constant.CommonConstant;
import springboot.wexPayApi.SelectAndCloseUtil;
import springboot.wexPayApi.dto.PayConfig;
import springboot.wexPayApi.util.HttpsPost;
import springboot.wexPayApi.util.Verification;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;

/**
 * 回调
 * @Author ttaurus
 * @Date Create in 2020/1/21 11:24
 */
@RestController
@Api(value = CommonConstant.WEB_API_PREFIX + "pay", description = "微信支付")
@RequestMapping(CommonConstant.WEB_API_PREFIX + "/pay")
@Slf4j
public class HDController {
    //可注释
    private static Logger logger = LoggerFactory.getLogger(HDController.class);
    

    @Autowired
    private SelectAndCloseUtil selectAndCloseUtil;


    @PostMapping(value = "/JSAPI/notify/") //回调函数
    @ApiOperation(value = "添加微信支付回调", notes = "添加微信支付回调", response = ApiResult.class)
    public String payJSAPI(HttpServletRequest request) {
        InputStream is = null;
        String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
        try {
            is = request.getInputStream();
            // 将InputStream转换成String
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            xmlBack = notify(request, sb.toString());  //调用通知方法
            System.out.println("返回的信息如下:\n" + sb.toString());
            System.out.println("已成功支付且回复到微信服务器!");
        } catch (Exception e) {
            logger.error("微信手机支付回调通知失败:", e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("已成功支付且回复到微信服务器!");
        return xmlBack;
    }
    

    public String notify(HttpServletRequest request, String notifyStr) {
        String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
        try {
            // 转换成map,判断是否是你本商户的支付订单
            Map<String, String> resultMap = HttpsPost.xmlToMap(notifyStr);
            if (Verification.isPayResultNotifySignatureValid(resultMap)) {
                //状态
                String returnCode = resultMap.get("return_code");
                String transactionId = resultMap.get("transaction_id");
                System.out.println(transactionId);
                if ("SUCCESS".equals(returnCode)) {
                    String outTradeNo = resultMap.get("out_trade_no");

                    //这个if判断是判断该订单是否支付成功,如果支付成功的话就关闭,
                    //都返回Ok就行了不用多此一举做判断了
                    if (selectAndCloseUtil.genSupply(outTradeNo)) {
                        selectAndCloseUtil.CloseSupply(outTradeNo);
                    }
                    
                    //这里写支付完成后的逻辑,你需要更改订单状态之类的东西
                    
                    xmlBack = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

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

    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值