From f708174b00e73a501dca4eb5ffb23520b4be3f67 Mon Sep 17 00:00:00 2001 From: mitao <2763622819@qq.com> Date: 星期三, 26 三月 2025 15:45:24 +0800 Subject: [PATCH] Merge branch 'dev' of http://120.76.84.145:10101/gitblit/r/java/xizang into dev --- ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentMailUtil.java | 12 - ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java | 10 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java | 201 +++++++++++++++++++++++++++++++- ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java | 113 +++++++++--------- ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java | 6 5 files changed, 264 insertions(+), 78 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java index 56ef4cd..b45ecd7 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/BankOutController.java +++ b/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; - }); - return result.getBack(); + 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") @@ -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>(); diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java index 01e7e68..6d0ea4a 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java @@ -1,6 +1,7 @@ package com.ruoyi.common.utils; import com.ruoyi.common.core.domain.model.LoginUserApplet; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -13,6 +14,7 @@ * * @author ruoyi */ +@Slf4j public class SecurityUtils { /** @@ -69,8 +71,10 @@ } catch (Exception e) { - throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED); + log.error("获取用户信息发生异常",e); +// throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED); } + return ""; } /** * 获取用户账户小程序 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentMailUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentMailUtil.java index 64d39bb..617c714 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentMailUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/TencentMailUtil.java @@ -14,13 +14,11 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import java.util.*; import java.util.concurrent.CompletableFuture; @Component @@ -149,9 +147,9 @@ tempFilePath.add(Paths.get(filePath)); FileDataSource source = new FileDataSource(filePath); messageBodyPart.setDataHandler(new DataHandler(source)); - String filenameEncode = MimeUtility.encodeText(fileName, "UTF-8", "base64"); - // String encodedFileName = Base64.getEncoder().encodeToString(fileName.getBytes(StandardCharsets.UTF_8)); - // String filenameEncode = MimeUtility.encodeText(encodedFileName); + // String filenameEncode = MimeUtility.encodeText(fileName, "UTF-8", "base64"); + String encodedFileName = Base64.getEncoder().encodeToString(fileName.getBytes(StandardCharsets.UTF_8)); + String filenameEncode = MimeUtility.encodeText(encodedFileName); messageBodyPart.setFileName(filenameEncode); messageBodyPart.setHeader("Content-Transfer-Encoding", "base64"); messageBodyPart.setHeader("Content-Disposition", "attachment"); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java index 94a394a..a18f96b 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/FlowListenerService.java @@ -301,7 +301,6 @@ } List<TContractRentType> contractRentTypes = contractRentTypeService.list(); TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null); - // 生成第一笔账单 // 第一次应缴费日期 LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0); @@ -455,7 +454,7 @@ if (dayOfMonth == 1) { money = money.add(contract.getMonthRent()); } else { - long allDays = ChronoUnit.DAYS.between(contract.getStartPayTime(), contract.getStartPayTime().with(TemporalAdjusters.lastDayOfMonth())) + 1; + long allDays = ChronoUnit.DAYS.between(rentBill.getStartTime(), rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth())) ; money =money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays))); } // 后续 @@ -463,15 +462,16 @@ rentBill.setPayableFeesMoney(money); rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney()); }else{ - LocalDateTime localDateTime = rentBill.getStartTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()); +// LocalDateTime localDateTime = rentBill.getStartTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()); + LocalDateTime localDateTime = rentBill.getStartTime().with(TemporalAdjusters.lastDayOfMonth()).plusDays(1); while (true){ if (localDateTime.isBefore(rentBill.getEndTime())){ + localDateTime = localDateTime.plusMonths(1); money = money.add(contract.getMonthRent()); }else{ - money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(ChronoUnit.DAYS.between(rentBill.getEndTime(),localDateTime.with(TemporalAdjusters.firstDayOfMonth()))+1))); + money = money.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(ChronoUnit.DAYS.between(rentBill.getEndTime(),localDateTime.with(TemporalAdjusters.firstDayOfMonth()))))); break; } - localDateTime = localDateTime.plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()); } rentBill.setPayableFeesMoney(money); rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney()); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java index 05bbd56..57597b2 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBillServiceImpl.java @@ -144,6 +144,7 @@ if (isok){ try { TBill save = new TBill(); + save.setId(tBill.getId()); TBill presist = getById(tBill.getId()); //如果账单是已缴费状态,本方法不再进行更新账单 if (presist.getPayFeesStatus().equals("3")){ @@ -343,62 +344,66 @@ String uuid = UUID.fastUUID().toString(); boolean lock = redisCache.trylockLoop(CacheConstants.COMPLETE_PAY_LOCK_KEY + orderNo, uuid, 60); if (lock){ - TPayOrder order = tPayOrderService.getById(orderNo); - if (order==null){ - throw new ServiceException("订单不存在"); - } - if (StringUtils.isNotEmpty(order.getPayNo())){ - log.info("订单号已处理:{}",orderNo); - return; - } - /** - * 更新订单状态 - */ - TPayOrder save = new TPayOrder(); - save.setId(order.getId()); - save.setStatus(1); - save.setPayNo(billRequest.getMessage().getInfo().getTraceNo()); - save.setPayType(billRequest.getMessage().getHead().getChannel()); try { - save.setPayTime(DateUtils.parseDate(billRequest.getMessage().getHead().getTimeStamp(),"yyyyMMddHHmmssSSS")); - } catch (ParseException e) { - throw new ServiceException("日期格式化错误"); + TPayOrder order = tPayOrderService.getById(orderNo); + if (order==null){ + throw new ServiceException("订单不存在"); + } + if (StringUtils.isNotEmpty(order.getPayNo())){ + log.info("订单号已处理:{}",orderNo); + return; + } + /** + * 更新订单状态 + */ + TPayOrder save = new TPayOrder(); + save.setId(order.getId()); + save.setStatus(1); + save.setPayNo(billRequest.getMessage().getInfo().getTraceNo()); + save.setPayType(billRequest.getMessage().getHead().getChannel()); + try { + save.setPayTime(DateUtils.parseDate(billRequest.getMessage().getHead().getTimeStamp(),"yyyyMMddHHmmssSSS")); + } catch (ParseException e) { + throw new ServiceException("日期格式化错误"); + } + save.setCallbackTime(new Date()); + BigDecimal payAmount = new BigDecimal(billRequest.getMessage().getInfo().getPayBillAmt()); + save.setActPayAmount(payAmount + .multiply(AmountConstant.b100).longValue()); + save.setStatus(1); + save.setPayInfo(billRequest.getMessage().toString()); + tPayOrderService.updateById(save); + /** + * 更新账单状态 + */ + List<TOrderBill> orderBills = orderBillService.getByOrderNo(order.getId()); + List<TBill> bills = orderBills.stream().map(ob -> getById(ob.getBillId())).collect(Collectors.toList()); + lockAndUpdateByAmountBatch(bills,payAmount,(bill)->{ + TFlowManagement saveFlow = new TFlowManagement(); + saveFlow.setPayType(1); + saveFlow.setPayer(order.getUserId()); + saveFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime())); + saveFlow.setSysSerialNumber(OrderNos.getDid(30)); + saveFlow.setBankSerialNumber(save.getPayNo()); + saveFlow.setFlowType(2); + saveFlow.setPaymentBillId(bill.getId()); + saveFlow.setDeductionMoney(bill.getDeductionMoney()); + saveFlow.setFlowMoney(payAmount); + saveFlow.setRemainingMoney(bill.getOutstandingMoney()); + 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); + }finally { + redisCache.unlock(CacheConstants.COMPLETE_PAY_LOCK_KEY + orderNo,uuid); } - save.setCallbackTime(new Date()); - BigDecimal payAmount = new BigDecimal(billRequest.getMessage().getInfo().getPayBillAmt()); - save.setActPayAmount(payAmount - .multiply(AmountConstant.b100).longValue()); - save.setStatus(1); - save.setPayInfo(billRequest.getMessage().toString()); - tPayOrderService.updateById(save); - /** - * 更新账单状态 - */ - List<TOrderBill> orderBills = orderBillService.getByOrderNo(order.getId()); - List<TBill> bills = orderBills.stream().map(ob -> getById(ob.getBillId())).collect(Collectors.toList()); - lockAndUpdateByAmountBatch(bills,payAmount,(bill)->{ - TFlowManagement saveFlow = new TFlowManagement(); - saveFlow.setPayType(1); - saveFlow.setPayer(order.getUserId()); - saveFlow.setPayTime(DateUtils.dateToLocalDateTime(save.getPayTime())); - saveFlow.setSysSerialNumber(OrderNos.getDid(30)); - saveFlow.setBankSerialNumber(save.getPayNo()); - saveFlow.setFlowType(2); - saveFlow.setPaymentBillId(bill.getId()); - saveFlow.setDeductionMoney(bill.getDeductionMoney()); - saveFlow.setFlowMoney(payAmount); - saveFlow.setRemainingMoney(bill.getOutstandingMoney()); - 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); } -- Gitblit v1.7.1