如何正确的处理支付回调

2020-12-16  本文已影响0人  大风过岗

下面以处理微信支付的回调为例

完整代码


import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Author: chihaojie
 * @Date: 2020/12/7 16:26
 * @Version 1.0
 * @Note
 */
@Service
public class WXCallbackServiceImpl implements WXCallbackService {


    private static final String CLASS_NAME = WXCallbackServiceImpl.class.getName();

    private static final Logger infoLogger = BatteryCabinetLoggerFactory.getServerInfoLogger(WXCallbackServiceImpl.class);
    private static final Logger errorLogger = BatteryCabinetLoggerFactory.getServerErrorLogger(WXCallbackServiceImpl.class);

    private static final Object concurrentNotifyLock = new Object();

    private static final String   resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";


    @Autowired
    private RentOrderMapper rentOrderMapper;


    @Transactional
    @Override
    public void wxPaySuccessNotify(HttpServletRequest request, HttpServletResponse response) throws BatteryException {
        final String methodName = "wxPaySuccessNotify";
        Date now = new Date();
        PrintWriter out = null;
        String respWX = resXml;
        String orderNum = null;
        SortedMap<String, String> callbackParam = null;
        try{
            out = response.getWriter();
            callbackParam = getWechatCallbackSortedMap(request);
            infoLogger.info("[微信回调的内容为: {}]",JSONObject.toJSONString(callbackParam));
            String result_code = callbackParam.get("result_code");
             orderNum = callbackParam.get("out_trade_no");
            String orderType = callbackParam.get("attach");
            BigDecimal totalFee = new BigDecimal(callbackParam.get("total_fee"));

            //校验签名
            if (!WXPayUtil.isSignatureValid(callbackParam, WXPayConfig.KEY)) {
                errorLogger.error("微信回调异常发生-回调签名错误: [ className: {},methodName: {},methodParam: {},]",CLASS_NAME,methodName,new String[]{JSONObject.toJSONString(callbackParam)});
            }
            synchronized (concurrentNotifyLock){
                //在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
                //校验订单状态
                RentOrderEntity rentOrder = rentOrderMapper.selectOrderByOrderNum(orderNum);
                if(!ObjectUtils.isEmpty(rentOrder) ){
                    Boolean isEqual = rentOrder.getPayMoney().compareTo(totalFee) == 0;
                    //校验 支付状态 和订单金额
                    if( !SystemConstant.PAY_STATUS_NOTPAY.equals(rentOrder.getIsPayed())  && isEqual){
                       //执行相关的业务逻辑处理
                       //......修改订单支付状态
                      //....... 其他业务逻辑处理
                    }
                }else errorLogger.error("微信回调异常发生-回调订单中错误: 订单不存在, 回调参数为:{}",callbackParam);
                out.println(respWX);
                out.flush();
                out.close();
            }
        }catch (Exception e){
            errorLogger.error("微信回调异常发生: [ className: {},methodName: {},callbackParam: {},orderNum: {}, ex: {}]",CLASS_NAME,methodName,JSONObject.toJSONString(callbackParam),orderNum, ExceptionUtils.formatExceptionStack(e));
            respWX = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[处理失败]]></return_msg>" + "</xml> ";
            out.println(respWX);
            out.flush();
            out.close();
        }
    }


    private SortedMap<String, String> getWechatCallbackSortedMap(HttpServletRequest request) throws BatteryException {
        final String methodName = "getWechatCallbackSortedMap";
        try{
            //读取参数
            StringBuffer sb = new StringBuffer();
            InputStream inputStream = request.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            String s;
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
            //解析xml成map;
            Map<String, String> xmlToMap = WXPayUtil.xmlToMap(sb.toString());
            if (null == xmlToMap) {
                throw new BatteryException(ErrorCodeEnum.ERROR_CODE_WECHAT_PAY_CALLBACK_EXCEPTION);
            }
            //过滤空 设置 TreeMap
            SortedMap<String, String> callbackParam = new TreeMap<>();
            Iterator it = xmlToMap.keySet().iterator();
            while (it.hasNext()) {
                String parameter = (String) it.next();
                String parameterValue = xmlToMap.get(parameter);
                String v = "";
                if (null != parameterValue) {
                    v = parameterValue.trim();
                }
                callbackParam.put(parameter, v);
            }
            return callbackParam;
        }catch (Exception e){
            errorLogger.error("微信回调异常发生: [ className: {},methodName: {},methodParam: {},orderNum: {}, ex: {}]",CLASS_NAME,methodName,new String[]{"nothing"}, ExceptionUtils.formatExceptionStack(e));
            throw new BatteryException(e.getCause());
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读