yupeng
2025-03-22 4ee8c6332c6f6fd7b78c6fd200fe32107f5cc37f
feat: 更新回调接口,完成回调方法添加解锁
2个文件已修改
220 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java
@@ -6,6 +6,7 @@
import com.alibaba.fastjson.TypeReference;
import com.ruoyi.common.constant.AmountConstant;
import com.ruoyi.common.enums.BillTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.TBillDto;
import com.ruoyi.system.model.TOrderBill;
@@ -13,9 +14,7 @@
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TOrderBillService;
import com.ruoyi.system.service.TPayOrderService;
import com.taxi591.bankapi.dto.CovertPayBackResult;
import com.taxi591.bankapi.dto.QueryBillRequest;
import com.taxi591.bankapi.dto.QueryBillResponse;
import com.taxi591.bankapi.dto.*;
import com.taxi591.bankapi.service.BankService;
import com.taxi591.bankapi.service.SignatureAndVerification;
import lombok.extern.slf4j.Slf4j;
@@ -28,9 +27,14 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -54,13 +58,188 @@
    @Autowired
    TPayOrderService payOrderService;
    public static String getRequestBody(HttpServletRequest request)
            throws IOException {
        /** 读取httpbody内容 */
        StringBuilder httpBody = new StringBuilder();
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(
                    request.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null) {
                httpBody.append(line);
            }
        } catch (IOException ex) {
            throw ex;
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
        return httpBody.toString();
    }
    @PostMapping(value = "payCallback")
    public @ResponseBody String payCallback(HttpServletRequest request){
        CovertPayBackResult result = bankService.covertPayCallBack(request, (billRequest) -> {
            tBillService.completePay(billRequest);
            return true;
    public void payCallback(HttpServletRequest servletRequest,HttpServletResponse servletResponse){
        String request = null;
        String responseJson = null;
        try {
            log.info("--------进入getRequest4Sale----------------------------------");
            // 接收报文
            String requestContent = getRequestBody(servletRequest).trim();
            String signatureString = requestContent.substring(0,
                    requestContent.indexOf("||"));
            log.info("-----ChargeBillController------------截取报文的signatureString:{}", signatureString);
            String requestBody = requestContent.substring(signatureString
                    .length() + 2);
            log.info("-----ChargeBillController------------截取报文的requestBody:{}", requestBody);
            //如果有双引号,则截取双引号内requestBody的内容
            Pattern p=Pattern.compile("\"");
            Matcher m=p.matcher(requestBody);
            while(m.find()){
                requestBody=requestBody.replace(m.group(), "");
                log.info("-----ChargeBillController------如果有双引号,则截取后的requestBody:{}", requestBody);
            }
            //requestBody是base64加密后的数据,需解析出来
            request = new String(
                    com.alibaba.fastjson.util.Base64.decodeFast(requestBody));
            log.info("-----ChargeBillController------------解析完成后的requestBody-------{}" + request);
            ChargeBillRequest chargeBillRequest = JSON.parseObject(request,
                    new TypeReference<ChargeBillRequest>() {
        });
        return result.getBack();
            boolean b = signatureAndVerification.read_cer_and_verify_sign(requestBody,
                    signatureString);
            if (!b){
                throw new ServiceException("验签失败");
            }
            /** 销账报文重发次数,通过resendTimes此字段识别销账报文是否为重发的,0表示首次、1表示重发一次,2表示重发2次,最多重发3次*/
            if(chargeBillRequest!=null && "0".equals(chargeBillRequest.getMessage().getInfo().getResendTimes())){
                ChargeBillResponse chargeBillResponse = new ChargeBillResponse(
                        chargeBillRequest);
                ChargeBillResponse.Message respMessage = chargeBillResponse
                        .getMessage();
                ChargeBillResponse.Message.Head respHead = chargeBillResponse
                        .getMessage().getHead();
                ChargeBillResponse.Message.Info respInfo = chargeBillResponse
                        .getMessage().getInfo();
                respHead.setTransFlag("02");
                respHead.setTimeStamp(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
                // respHead.setChannel("MBNK");
                respHead.setChannel(chargeBillRequest.getMessage().getHead()
                        .getChannel());
                // respHead.setTranCode("chargeBill");
                respHead.setTransCode(chargeBillRequest.getMessage().getHead()
                        .getTransCode());
                respHead.setTransSeqNum(chargeBillRequest.getMessage().getHead()
                        .getTransSeqNum());
                //测试销账返回报文中,本来是销账成功的报文,但是不要送0000成功码   (JF190510134746710555这个流水号是在Demo的returnCode设置成null的时候产生的,流水状态为6;)
                String epayCode = chargeBillRequest.getMessage().getInfo()
                        .getEpayCode();
                String traceNo = chargeBillRequest.getMessage().getInfo()
                        .getTraceNo();
                String numOpenMerchantOrder = chargeBillRequest.getMessage()
                        .getInfo().getNumOpenMerchantOrder();
                respInfo.setNumOpenMerchantOrder(numOpenMerchantOrder);
                respInfo.setEpayCode(epayCode);
                respInfo.setTraceNo(traceNo);
                try{
                    tBillService.completePay(chargeBillRequest);
                    respHead.setReturnCode("0000");
                    respHead.setReturnMessage("账单缴费成功");
                }catch (Exception e){
                    respHead.setReturnCode("1111");
                    respHead.setReturnMessage("账单处理失败");
                    log.error("支付第一次回调出现异常,{}",request,e);
                }
                //第一次处理失败,不退款
                respInfo.setRefundFlag("false");
                respMessage.setInfo(respInfo);
                respMessage.setHead(respHead);
                chargeBillResponse.setMessage(respMessage);
                responseJson = JSON.toJSONString(chargeBillResponse);
                //加签名
                String signatrue = signatureAndVerification
                        .signWhithsha1withrsa(responseJson);
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密前):" + responseJson);
                responseJson = signatrue + "||"
                        + new String(Base64.encodeBase64(responseJson.getBytes("utf-8")));
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密后):" + responseJson);
                servletResponse.setCharacterEncoding("utf-8");
                servletResponse.setContentType("text/plain");
                servletResponse.getWriter().write(responseJson);
            }else{
                //销账报文重发次数,通过resendTimes此字段识别销账报文是否为重发的,0表示首次、1表示重发一次,2表示重发2次,最多重发3次
                //商户端要注意销账重复通知的情况,要进行订单唯一性处理
                ChargeBillResponse chargeBillResponse = new ChargeBillResponse(
                        chargeBillRequest);
                ChargeBillResponse.Message respMessage = chargeBillResponse
                        .getMessage();
                ChargeBillResponse.Message.Head respHead = chargeBillResponse
                        .getMessage().getHead();
                ChargeBillResponse.Message.Info respInfo = chargeBillResponse
                        .getMessage().getInfo();
                respHead.setTransFlag("02");
                respHead.setTimeStamp(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
                // respHead.setChannel("MBNK");
                respHead.setChannel(chargeBillRequest.getMessage().getHead()
                        .getChannel());
                // respHead.setTranCode("chargeBill");
                respHead.setTransCode(chargeBillRequest.getMessage().getHead()
                        .getTransCode());
                respHead.setTransSeqNum(chargeBillRequest.getMessage().getHead()
                        .getTransSeqNum());
                try{
                    tBillService.completePay(chargeBillRequest);
                    respHead.setReturnCode("0000");
                    respHead.setReturnMessage("账单缴费成功");
                }catch (Exception e){
                    respHead.setReturnCode("1111");
                    respHead.setReturnMessage("账单处理失败");
                    log.error("支付第一次回调出现异常,{}",request,e);
                }
                // 再次推送未处理成功,则返回退款标志
                if (!"0000".equals(respHead.getReturnCode())) {
                    respInfo.setRefundFlag("true");
                }
                String epayCode = chargeBillRequest.getMessage().getInfo()
                        .getEpayCode();
                String traceNo = chargeBillRequest.getMessage().getInfo()
                        .getTraceNo();
                String numOpenMerchantOrder = chargeBillRequest.getMessage()
                        .getInfo().getNumOpenMerchantOrder();
                respInfo.setNumOpenMerchantOrder(numOpenMerchantOrder);
                respInfo.setEpayCode(epayCode);
                respInfo.setTraceNo(traceNo);
                respMessage.setInfo(respInfo);
                respMessage.setHead(respHead);
                chargeBillResponse.setMessage(respMessage);
                responseJson = JSON.toJSONString(chargeBillResponse);
                //加签名
                String signatrue = signatureAndVerification
                        .signWhithsha1withrsa(responseJson);
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密前):" + responseJson);
                responseJson = signatrue + "||"
                        + new String(Base64.encodeBase64(responseJson.getBytes("utf-8")));
                log.info("-----ChargeBillController------------responseJson打印结果是(responseJson加密后):" + responseJson);
                servletResponse.setCharacterEncoding("utf-8");
                servletResponse.setContentType("text/plain");
                servletResponse.getWriter().write(responseJson);
            }
        }catch (Exception e) {
            log.error("处理支付回调发生异常:返回内容:{}",request,e);
        }
    }
    @PostMapping(value = "queryBill")
@@ -99,8 +278,8 @@
                    .getInfo();
            //缴费账单子账单
            ArrayList<QueryBillResponse.Message.Info.Bill> respBills = new ArrayList<QueryBillResponse.Message.Info.Bill>();
            ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail> respDescDetail =
                    new ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail>();
//            ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail> respDescDetail =
//                    new ArrayList<QueryBillResponse.Message.Info.Bill.DescDetail>();
            QueryBillResponse.Message.Info.Bill respBill = respInfo.new Bill();
            //缴费子商户账单
//            ArrayList<QueryBillResponse.Message.Info.Bill.SplitSubMerInfo> splitSubMerInfos = new ArrayList<QueryBillResponse.Message.Info.Bill.SplitSubMerInfo>();
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java
@@ -124,6 +124,7 @@
        if (isok){
            try {
                TBill save = new TBill();
                save.setId(tBill.getId());
                TBill presist = getById(tBill.getId());
                //如果账单是已缴费状态,本方法不再进行更新账单
                if (presist.getPayFeesStatus().equals("3")){
@@ -323,6 +324,7 @@
        String uuid = UUID.fastUUID().toString();
        boolean lock = redisCache.trylockLoop(CacheConstants.COMPLETE_PAY_LOCK_KEY + orderNo, uuid, 60);
        if (lock){
            try {
            TPayOrder order = tPayOrderService.getById(orderNo);
            if (order==null){
                throw new ServiceException("订单不存在");
@@ -371,14 +373,17 @@
                saveFlow.setPreOutstand(bill.getPreOutstand());
                tFlowManagementService.save(saveFlow);
            });
            TBankFlow bankFlow = new TBankFlow();
            bankFlow.setPayType(1);
            bankFlow.setPayer(order.getUserId());
            bankFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime()));
            bankFlow.setBankSerialNumber(save.getPayNo());
            bankFlow.setFlowMoney(payAmount);
            bankFlow.setFlowStatus(1);
            tBankFlowService.save(bankFlow);
//                TBankFlow bankFlow = new TBankFlow();
//                bankFlow.setPayType(1);
//                bankFlow.setPayer(order.getUserId());
//                bankFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime()));
//                bankFlow.setBankSerialNumber(save.getPayNo());
//                bankFlow.setFlowMoney(payAmount);
//                bankFlow.setFlowStatus(1);
//                tBankFlowService.save(bankFlow);
            }finally {
                redisCache.unlock(CacheConstants.COMPLETE_PAY_LOCK_KEY + orderNo,uuid);
            }
        }