无关风月
2025-04-10 099ea14bba367fd86f0dde37d908f07cc04c3d39
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java
@@ -1,7 +1,24 @@
package com.ruoyi.web.controller.api;
import com.taxi591.bankapi.dto.CovertPayBackResult;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
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;
import com.ruoyi.system.model.TPayOrder;
import com.ruoyi.system.service.TBillService;
import com.ruoyi.system.service.TOrderBillService;
import com.ruoyi.system.service.TPayOrderService;
import com.taxi591.bankapi.dto.*;
import com.taxi591.bankapi.service.BankService;
import com.taxi591.bankapi.service.SignatureAndVerification;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -9,25 +26,380 @@
import org.springframework.web.bind.annotation.RestController;
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;
@RestController
@RequestMapping("open/bank")
@Slf4j
public class BankOutController {
    @Autowired
    BankService bankService;
    @Autowired
    TBillService tBillService;
    @PostMapping(value = "payCallback")
    public @ResponseBody String payCallback(HttpServletRequest request){
        CovertPayBackResult result = bankService.covertPayCallBack(request, (billRequest) -> {
    @Autowired
    SignatureAndVerification signatureAndVerification;
            return true;
        });
        return result.getBack();
    @Autowired
    TOrderBillService orderBillService;
    @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 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>() {
                    });
            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")
    public void bills(HttpServletRequest request, HttpServletResponse httpServletResponse){
        log.info("进入QueryBillController账单查询接口--------(金额规则为0的)-------");
        String responseJson = null;
        try {
            //接收报文request返回截取并返回requestBody和使用base64解析后的requestBody
            Map<String, String> requestMap = signatureAndVerification.requestBodyOfBase64(request);
            //使用base64解析完成后的requestBody
            String requestBodyOfDecoded = requestMap.get("requestBodyOfDecoded");
            //解析前的requestBody
            String requestBody = requestMap.get("requestBody");
            //获取缴费中心传送过来的签名
            String signatureString = requestMap.get("signatureString");
            // 验签
            boolean flag = signatureAndVerification.read_cer_and_verify_sign(requestBody,
                    signatureString);
            log.info("【QueryBill:getBill4DirectJoinMerch】缴费中心响应的报文验签结果为:{}" , flag);
            QueryBillRequest queryBillRequest = JSON.parseObject(requestBodyOfDecoded,
                    new TypeReference<QueryBillRequest>() {
                    });
            //交易编号
            String traceNo = queryBillRequest.getMessage().getInfo()
                    .getTraceNo();
            //返回给缴费中心的响应
            QueryBillResponse response = new QueryBillResponse(queryBillRequest);
            QueryBillResponse.Message respMessage = response.getMessage();
            QueryBillResponse.Message.Head respHead = response.getMessage()
                    .getHead();
            QueryBillResponse.Message.Info respInfo = response.getMessage()
                    .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>();
            QueryBillResponse.Message.Info.Bill respBill = respInfo.new Bill();
            //缴费子商户账单
//            ArrayList<QueryBillResponse.Message.Info.Bill.SplitSubMerInfo> splitSubMerInfos = new ArrayList<QueryBillResponse.Message.Info.Bill.SplitSubMerInfo>();
            //封装返回给缴费中心的响应
            String epayCode = queryBillRequest.getMessage().getInfo()
                    .getEpayCode();
            respInfo.setEpayCode(epayCode);
            String merchantId = queryBillRequest.getMessage().getInfo()
                    .getMerchantId();
            respInfo.setMerchantId(merchantId);
            respInfo.setTraceNo(traceNo);
            respInfo.setInput1(queryBillRequest.getMessage().getInfo()
                    .getInput1());
            respInfo.setInput2(queryBillRequest.getMessage().getInfo()
                    .getInput2());
            respInfo.setInput3(queryBillRequest.getMessage().getInfo()
                    .getInput3());
            respInfo.setInput4(queryBillRequest.getMessage().getInfo()
                    .getInput4());
            respInfo.setInput5(queryBillRequest.getMessage().getInfo()
                    .getInput5());
            String orderid= queryBillRequest.getMessage().getInfo().getInput1();
            if (StringUtils.isEmpty(orderid)){
                respHead.setReturnCode("0009");
                respHead.setReturnMessage("参数错误,input1订单号不能为空");
            }else{
                if (flag){
                    TPayOrder order = payOrderService.getById(orderid);
                    List<TOrderBill> orderBills = orderBillService.getByOrderNo(orderid);
                    List<TBillDto> bills = orderBills.stream().map(ob
                            -> tBillService.getDetailByBillId(ob.getBillId())).collect(Collectors.toList());
                    respBill.setBillNo(orderid);
                    List<String> types = bills.stream().map(bill -> BillTypeEnum.getByCode(Integer.parseInt(bill.getBillType())).getName()).distinct().collect(Collectors.toList());
//           封装详细账单信息
                    respBill.setBillName("缴费:"+CollectionUtil.join(types,","));
                    respBill.setOweAmt(BigDecimal.valueOf(order.getAmount()).divide(AmountConstant.b100,2, RoundingMode.HALF_DOWN).toPlainString());
                    respBills.add(respBill);
                    respInfo.setCustName(order.getUserName());
                    respInfo.setCustAddress("");
                    respInfo.setCacheMem("");
                    respInfo.setRemark("");
                    respInfo.setCallBackText("西藏国资委");
                    //respInfo.setCallBackUrl("https://abcsr.keepfx.cn/b/ejy/payResult/");
                    //使用base64加密信息
//                    respInfo.setCallBackUrl("aHR0cDp3d3cuYWJjaGluYS5jb20vY24v");
                    //金额规则字段
                    String amtRule = "0";
                    respInfo.setAmtRule(amtRule);
               /*QueryBillResponse.Message.Info.Bill.UnitDetail unitDetail = respBill.new UnitDetail(
                       "unitName", "6.66", "1");*/
                    //欠费金额
                    respBill.setFeeAmt("0.00");
//
//                    QueryBillResponse.Message.Info.Bill.DescDetail descDtail1 = respBill.new DescDetail(
//                            "缴费月份:", "2020年6月份");
//                    QueryBillResponse.Message.Info.Bill.DescDetail descDtail2 = respBill.new DescDetail(
//                            "供电局编号:", "4340152");
//                    QueryBillResponse.Message.Info.Bill.DescDetail descDtail3 = respBill.new DescDetail(
//                            "欠费金额:", "0.00元");
//                    QueryBillResponse.Message.Info.Bill.DescDetail descDtail4 = respBill.new DescDetail(
//                            "缴费月份:", "2020年6月份");
//                    QueryBillResponse.Message.Info.Bill.DescDetail descDtail5 = respBill.new DescDetail(
//                            "服务时间:", "每天0:30-23:30期间均可缴费");
//                    QueryBillResponse.Message.Info.Bill.DescDetail descDtail6 = respBill.new DescDetail(
//                            "温馨提示:", "北京电力电费代缴,咨询电话:95598 该用户为:预付费用户");
//                    respDescDetail.add(descDtail1);
//                    respDescDetail.add(descDtail2);
//                    respDescDetail.add(descDtail3);
//                    respDescDetail.add(descDtail4);
//                    respDescDetail.add(descDtail5);
//                    respDescDetail.add(descDtail6);
//                    respBill.setRcvMerchantId("103881104410001");
//             商户子商户详细信息
//                    QueryBillResponse.Message.Info.Bill.SplitSubMerInfo splitSubMerInfo1 =respBill.new SplitSubMerInfo("10388", "0.01");
//                    QueryBillResponse.Message.Info.Bill.SplitSubMerInfo splitSubMerInfo2 =respBill.new SplitSubMerInfo("1038819201", "0.02");
//                    splitSubMerInfos.add(splitSubMerInfo1);
//                    splitSubMerInfos.add(splitSubMerInfo2);
//                    respBill.setSplitSubMerInfos(splitSubMerInfos);
//                    respBill.setDescDetails(respDescDetail);
                    respInfo.setTotalBillCount(String.valueOf(respBills.size()));
                    respInfo.setBill(respBills);
                    // 有定制电子回单附言信息的,需添加自定义定制附言信息字段
                    respInfo.setMerchantRemark("");
                    respHead.setReturnCode("0000");
                    respHead.setReturnMessage("账单查询成功,返回成功标志");
                }else {
                    respHead.setReturnCode("0009");
                    respHead.setReturnMessage("缴费中心传送给商户的请求报文签名验签失败!");
                }
            }
            respHead.setTransFlag("02");
            respHead.setTimeStamp(DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"));
            respMessage.setInfo(respInfo);
            respMessage.setHead(respHead);
            response.setMessage(respMessage);
            responseJson = JSON.toJSONString(response);
            // 加签名
            String signatrue = signatureAndVerification
                    .signWhithsha1withrsa(responseJson);
            log.info("signatrue" + responseJson);
            log.info("responseJson打印结果是(responseJson加密前):" + responseJson);
            responseJson = signatrue + "||"
                    + new String(Base64.encodeBase64(responseJson.getBytes("utf-8")));
            log.info("responseJson打印结果是(responseJson加密后):{}", responseJson);
            httpServletResponse.setCharacterEncoding("utf-8");
            httpServletResponse.setContentType("text/plain");
            httpServletResponse.getWriter().write(responseJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}