美文网首页
如何正确的处理支付回调

如何正确的处理支付回调

作者: 大风过岗 | 来源:发表于2020-12-16 17:21 被阅读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());
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:如何正确的处理支付回调

          本文链接:https://www.haomeiwen.com/subject/kxkogktx.html