微信支付回调通用工具类

1.demo

package com.util;

import cn.hutool.core.util.StrUtil;
import com.lib.util.MD5Util;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiFunction;

public class WxPayUtil {
     
    private final static Logger logger = LoggerFactory.getLogger(WxPayUtil.class);

    /**
     * 微信支付回调通用模板
     * BiFunction: 参数一:支付金额 参数二:订单号 参数三: 返回信息
     */
    public static String payCallback(HttpServletRequest request, HttpServletResponse response, BiFunction<Double, String, String> function) throws Exception {
     
        response.setContentType("text/html;charset=UTF-8");

        ServletInputStream inputStream = request.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader bufferReader = new BufferedReader(inputStreamReader);
        String line = null;
        String result = "";
        while ((line = bufferReader.readLine()) != null) {
     
            result += line;
        }
        logger.info("微信支付回调返回:" + result);
        Document doc = DocumentHelper.parseText(result);
        Element et = doc.getRootElement();
        List<Element> elementList = et.elements();
        HashMap<String, String> params = new HashMap<String, String>();
        for (Element e : elementList) {
     
            params.put(e.getName(), e.getTextTrim());
        }
        String return_code = params.get("return_code");
        String appid = params.get("appid");
        String appidConfig = WechatConfig.appid;
        String signWxpay = signWxpay(params);
        boolean isReturnCode = "SUCCESS".equals(return_code) && appid.equals(appidConfig);
        if (!isReturnCode) {
     
            logger.info("return_code is fail");
            return responseFailedWxpay("return_code is fail");
        }
        String sign = params.get("sign");
        boolean isSign = StrUtil.isNotBlank(sign) && sign.equals(signWxpay);
        if (!isSign) {
     
            logger.warn("签名校验有误");
            return responseFailedWxpay("签名校验有误");
        }
        String result_code = params.get("result_code");
        boolean isResultCode = "SUCCESS".equals(result_code);
        if (!isResultCode) {
     
            logger.info("result_code is fail");
            return responseFailedWxpay("result_code is fail");
        }
        String transaction_id = params.get("transaction_id");
        String out_trade_no = params.get("out_trade_no");
        double cash_fee = Double.parseDouble(params.get("cash_fee")) / 100.0f;
        logger.info("transaction_id:" + transaction_id + ",out_trade_no:" + out_trade_no + "," + cash_fee);

        // 处理业务
        String apply = function.apply(cash_fee, out_trade_no);

        return apply;
    }

    /**
     * 微信支付通知参数签名
     *
     * @param params
     * @return String
     */
    public static String signWxpay(HashMap<String, String> params) {
     
        Object[] keys = params.keySet().toArray();
        Arrays.sort(keys);
        String k, v;
        String str = "";

        for (int i = 0; i < keys.length; i++) {
     
            k = (String) keys[i];
            if (k.equals("sign")) {
     
                continue;
            }
            if (params.get(k) == null) {
     
                continue;
            }
            v = (String) params.get(k);
            if (v.equals("0") || v.equals("")) {
     
                continue;
            }
            str += k + "=" + v + "&";
        }
        String appSecret = WechatConfig.key;
        str += "key=" + appSecret;
        String md5Str = MD5Util.MD5(str).toUpperCase();
        return md5Str;
    }

    public static String responseFailedWxpay(String msg) {
     
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("xml");
        root.addElement("return_code").addText("FAIL");
        root.addElement("return_msg").addText(msg + "");
        String result = doc.asXML();
        System.out.println(result);
        return result;
    }

    public static String responseSuccessWxpay() {
     
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("xml");
        root.addElement("return_code").addText("SUCCESS");
        root.addElement("return_msg").addText("OK");
        String result = doc.asXML();
        return result;
    }
}
    /**
     * 微信支付回调
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public synchronized String buyCardNotifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
     
        try {
     
            String s = WxPayUtil.payCallback(request, response, (payMoney, orderId) -> {
     
                // 查询待支付订单状态
                QueryWrapper<OrderMembership> orderMembershipQueryWrapper = new QueryWrapper<>();
                orderMembershipQueryWrapper.lambda().eq(OrderMembership::getDeflag, Dictionary.DEFLAG_BY_NOT_DELETE)
                        .eq(OrderMembership::getStatus, Dictionary.ORDER_COURSE_STATUS_BY_WAIT_PAY)
                        .eq(OrderMembership::getOrderSn, orderId);
                orderMembershipQueryWrapper.last("LIMIT 1");
                OrderMembership orderMembership = orderMembershipService.getOne(orderMembershipQueryWrapper);
                if (orderMembership == null) {
     
                    return WxPayUtil.responseSuccessWxpay();
                }

                // 需对非开发环境做金额校验
                boolean isErrorPayMoney = !"dev".equals(env) && orderMembership.getPayedMoney() != payMoney;
                if (isErrorPayMoney) {
     
                    return WxPayUtil.responseFailedWxpay("cash_fee Error");
                }

                try {
     
                    homePageService.buyCardNotifyUrl(orderMembership);
                } catch (Exception e) {
     
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    e.printStackTrace();
                    return WxPayUtil.responseFailedWxpay("Internal Error");
                }
                return WxPayUtil.responseSuccessWxpay();
            });

            return s;
        } catch (Exception e) {
     
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return WxPayUtil.responseFailedWxpay("Internal Error");
        }
    }

2.微信支付回调postman测试数据

<?xml version="1.0" encoding="utf-8"?>
<xml>
  <appid><![CDATA[appid]]></appid>
  <bank_type><![CDATA[CMB_CREDIT]]></bank_type>
  <cash_fee><![CDATA[1]]></cash_fee>
  <fee_type><![CDATA[CNY]]></fee_type>
  <is_subscribe><![CDATA[N]]></is_subscribe>
  <mch_id><![CDATA[mch_id]]></mch_id>
  <nonce_str><![CDATA[8cfa9ff035f9409dae4806f677891a31]]></nonce_str>
  <openid><![CDATA[openid]]></openid>
  <out_trade_no><![CDATA[out_trade_no]]></out_trade_no>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <sign><![CDATA[2C3F3B207FBA0A21A819424A82A25058]]></sign>
  <time_end><![CDATA[20200806200255]]></time_end>
  <total_fee>1</total_fee>
  <trade_type><![CDATA[JSAPI]]></trade_type>
  <transaction_id><![CDATA[4200000713202008064770449128]]></transaction_id>
</xml>

3.文章参考链接
a.https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html

你可能感兴趣的:(工具类,java)