package com.ruoyi.web.controller.api; 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; import org.springframework.web.bind.annotation.ResponseBody; 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; @Autowired SignatureAndVerification signatureAndVerification; @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() { }); 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 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() { }); //交易编号 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 respBills = new ArrayList(); // ArrayList respDescDetail = // new ArrayList(); QueryBillResponse.Message.Info.Bill respBill = respInfo.new Bill(); //缴费子商户账单 // ArrayList splitSubMerInfos = new ArrayList(); //封装返回给缴费中心的响应 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 orderBills = orderBillService.getByOrderNo(orderid); List bills = orderBills.stream().map(ob -> tBillService.getDetailByBillId(ob.getBillId())).collect(Collectors.toList()); respBill.setBillNo(orderid); List 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(); } } }