From f8b251573040d2762507909a02f274a6cf4d751c Mon Sep 17 00:00:00 2001 From: heheng <heheng@123456> Date: 星期四, 23 一月 2025 14:40:27 +0800 Subject: [PATCH] 特种作业非煤缴费版本优化 --- exam-system/src/main/java/com/gkhy/exam/pay/service/impl/CoalPayServiceImpl.java | 61 +- exam-system/src/main/java/com/gkhy/exam/pay/utils/PayUtils.java | 120 +++-- ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisLock.java | 98 ++++ exam-system/src/main/java/com/gkhy/exam/pay/controller/NonCoalPayController.java | 14 exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalPayOrder.java | 20 ruoyi-common/src/main/java/com/ruoyi/common/config/RedissonConfig.java | 29 + exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalCateRep.java | 68 +++ exam-system/src/main/resources/mapper/pay/NonCoalPayMapper.xml | 69 +++ ruoyi-admin/src/main/resources/application-pro.yml | 237 +++++----- exam-system/src/main/java/com/gkhy/exam/pay/service/NonCoalPayStudentService.java | 2 ruoyi-common/src/main/java/com/ruoyi/common/utils/RandomUtil.java | 10 exam-system/pom.xml | 6 exam-system/src/test/java/TextPay.java | 77 +-- exam-system/src/main/java/com/gkhy/exam/pay/service/impl/NonCoalPayStudentServiceImpl.java | 148 ++++++ exam-system/src/main/java/com/gkhy/exam/pay/mapper/NonCoalPayMapper.java | 3 exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalStuRep.java | 46 ++ ruoyi-admin/src/main/resources/application-dev.yml | 237 +++++----- 17 files changed, 880 insertions(+), 365 deletions(-) diff --git a/exam-system/pom.xml b/exam-system/pom.xml index 6a85092..505b850 100644 --- a/exam-system/pom.xml +++ b/exam-system/pom.xml @@ -31,6 +31,12 @@ <artifactId>qiniu-java-sdk</artifactId> <version>[7.2.0, 7.2.99]</version> </dependency> + <dependency> + <groupId>org.redisson</groupId> + <artifactId>redisson</artifactId> + <version>3.18.0</version> + <scope>compile</scope> + </dependency> </dependencies> diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/controller/NonCoalPayController.java b/exam-system/src/main/java/com/gkhy/exam/pay/controller/NonCoalPayController.java index 86139f4..8d11c9a 100644 --- a/exam-system/src/main/java/com/gkhy/exam/pay/controller/NonCoalPayController.java +++ b/exam-system/src/main/java/com/gkhy/exam/pay/controller/NonCoalPayController.java @@ -147,7 +147,7 @@ */ @PostMapping("/editNonCoalStu") @ApiOperation(value = "修改非煤缴费学员") - public AjaxResult editNonCoalStu(@RequestBody NonCoalPayStudent nonCoalPayStudent) { + public AjaxResult editNonCoalStu(@Validated @RequestBody NonCoalPayStudent nonCoalPayStudent) { return toAjax(nonCoalPayStudentService.updateNonCoalPayStudent(nonCoalPayStudent)); } @@ -194,4 +194,16 @@ } + @PostMapping("/sendOrder") + @ApiOperation(value = "生成财政订单") + @Anonymous + @RepeatSubmit + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", dataTypeClass = Long.class, value = "个人缴费学员数据id,团队缴费数据id", required = true), + @ApiImplicitParam(name = "payType", dataTypeClass = String.class, value = "1个人2是团队", required = true), + }) + public AjaxResult sendOrder(@RequestParam("id") Long id, @RequestParam("payType") String payType) { + return success(nonCoalPayStudentService.sendOrder(id, payType)); + } + } diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalCateRep.java b/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalCateRep.java new file mode 100644 index 0000000..c5810ce --- /dev/null +++ b/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalCateRep.java @@ -0,0 +1,68 @@ +package com.gkhy.exam.pay.dto.rep; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class NonCoalCateRep { + /** + * $column.columnComment + */ + private Long id; + + /** + * $column.columnComment + */ + @ApiModelProperty("非煤管理id") + private Long nonCoalPayId; + + /** + * 类别id + */ + + @ApiModelProperty("类别id") + private Long categoryId; + + @ApiModelProperty("类别名称") + private String subjectName; + + /** + * 类别1理论2实操 + */ + @ApiModelProperty("类别类型id") + private Long categoryType; + + @ApiModelProperty("缴费金额") + private BigDecimal categoryAmount; + + + @ApiModelProperty("业务编码") + private String businessCode; + + /** + * 单位编码 + */ + @ApiModelProperty("单位编码") + private String companyCode; + + /** + * 开票人 + */ + @ApiModelProperty("开票人") + private String drawer; + + /** + * 复核人 + */ + @ApiModelProperty("复核人") + private String reviewer; + + /** + * 开票单位社会信用代码 + */ + @ApiModelProperty("开票单位社会信用代码") + private String invoicingCompanyCode; + +} diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalPayOrder.java b/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalPayOrder.java new file mode 100644 index 0000000..17b35dd --- /dev/null +++ b/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalPayOrder.java @@ -0,0 +1,20 @@ +package com.gkhy.exam.pay.dto.rep; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +@Data +public class NonCoalPayOrder { + + private Long id; + private String batchName; + private BigDecimal amount; + private Long payPersonType; + private String payCompanyName; + private String payCompanyCard; + + private List<NonCoalStuRep> nonCoalStuList; + private List<NonCoalCateRep> nonCoalPayCategoryList; +} diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalStuRep.java b/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalStuRep.java new file mode 100644 index 0000000..b42ba0d --- /dev/null +++ b/exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalStuRep.java @@ -0,0 +1,46 @@ +package com.gkhy.exam.pay.dto.rep; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class NonCoalStuRep { + + private Long id; + + /** + * 姓名 + */ + @ApiModelProperty("姓名") + private String studentName; + + /** + * 身份证号 + */ + @ApiModelProperty("身份证号") + private String idCard; + + /** + * 电话 + */ + + @ApiModelProperty("电话") + private String phone; + + /** + * 0男 1女 2未知 + */ + + @ApiModelProperty("性别 0男1女2未知") + private Long sex; + + /** + * 是否缴款0否1是 + */ + @ApiModelProperty("是否缴款0否1是") + private Long payStatus; + + + @ApiModelProperty("财政订单编号") + private String orderId; +} diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/mapper/NonCoalPayMapper.java b/exam-system/src/main/java/com/gkhy/exam/pay/mapper/NonCoalPayMapper.java index 8da20c7..fab9763 100644 --- a/exam-system/src/main/java/com/gkhy/exam/pay/mapper/NonCoalPayMapper.java +++ b/exam-system/src/main/java/com/gkhy/exam/pay/mapper/NonCoalPayMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.gkhy.exam.pay.dto.rep.NonCoalPayDetailH5RepDto; import com.gkhy.exam.pay.dto.rep.NonCoalPayDetailRepDto; +import com.gkhy.exam.pay.dto.rep.NonCoalPayOrder; import com.gkhy.exam.pay.dto.rep.NonCoalPayPageRepDto; import com.gkhy.exam.pay.entity.NonCoalPay; import org.apache.ibatis.annotations.Param; @@ -59,6 +60,8 @@ */ public int insertNonCoalPay(NonCoalPay nonCoalPay); + List<NonCoalPayOrder> selectNonCoalPayOrderByParam(@Param("dataId") Long dataId, @Param("payType") Long payType); + /** * 修改【请填写功能名称】 * diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/service/NonCoalPayStudentService.java b/exam-system/src/main/java/com/gkhy/exam/pay/service/NonCoalPayStudentService.java index 05ff00c..5c2ee94 100644 --- a/exam-system/src/main/java/com/gkhy/exam/pay/service/NonCoalPayStudentService.java +++ b/exam-system/src/main/java/com/gkhy/exam/pay/service/NonCoalPayStudentService.java @@ -31,6 +31,8 @@ */ public List<NonCoalPayStudent> selectNonCoalPayStudentList(NonCoalPayStudent nonCoalPayStudent); + public String sendOrder(Long dataId, String payType); + /** * 新增【请填写功能名称】 * diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/CoalPayServiceImpl.java b/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/CoalPayServiceImpl.java index 4043ca1..4271919 100644 --- a/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/CoalPayServiceImpl.java +++ b/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/CoalPayServiceImpl.java @@ -23,7 +23,6 @@ import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.mapper.SysDeptMapper; -import org.aspectj.lang.reflect.UnlockSignature; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.BeanUtils; @@ -37,7 +36,6 @@ import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; import java.util.stream.Collectors; @Service @@ -58,11 +56,13 @@ @Autowired private RedissonClient redissonClient; - + @Autowired + private PayUtils payUtils; /** * 缴费管理列表 + * * @param coalPay * @return */ @@ -72,7 +72,7 @@ List<CoalPay> coalPays = coalPayMapper.selectCoalPayList(coalPay); for (CoalPay pay : coalPays) { CoalPayRepDto coalPayRepDto = new CoalPayRepDto(); - BeanUtils.copyProperties(pay,coalPayRepDto); + BeanUtils.copyProperties(pay, coalPayRepDto); //部门数据 SysDept sysDept = sysDeptMapper.selectDeptById(pay.getDeptId()); coalPayRepDto.setDeptName(sysDept.getDeptName()); @@ -98,7 +98,7 @@ //基本数据 CoalPay coalPay = coalPayMapper.selectById(id); - BeanUtils.copyProperties(coalPay,coalPayRepDto); + BeanUtils.copyProperties(coalPay, coalPayRepDto); //考点名称 SysDept sysDept = sysDeptMapper.selectDeptById(coalPay.getDeptId()); coalPayRepDto.setDeptName(sysDept.getDeptName()); @@ -120,12 +120,12 @@ @Override public int insertCoalPay(CoalPayDto coalPayDto) { CoalPay coalPay = new CoalPay(); - BeanUtils.copyProperties(coalPayDto,coalPay); + BeanUtils.copyProperties(coalPayDto, coalPay); coalPay.setCreateBy(SecurityUtils.getUsername()); coalPay.setCreateTime(new Date()); int insert = coalPayMapper.insertBath(coalPay); - if (CollectionUtils.isEmpty(coalPayDto.getCoalPayCategoryies())){ - throw new BusinessException(this.getClass(),ResultConstants.BUSINESS_ERROR,"工种类别不能为空"); + if (CollectionUtils.isEmpty(coalPayDto.getCoalPayCategoryies())) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "工种类别不能为空"); } List<CoalPayCategory> coalPayCategories = coalPayDto.getCoalPayCategoryies(); for (CoalPayCategory coalPayCategory : coalPayCategories) { @@ -137,18 +137,19 @@ /** * 修改缴费信息 + * * @param coalPayDto * @return */ @Override public int updateCoalPay(CoalPayDto coalPayDto) { CoalPay coalPay = new CoalPay(); - BeanUtils.copyProperties(coalPayDto,coalPay); + BeanUtils.copyProperties(coalPayDto, coalPay); coalPay.setUpdateBy(SecurityUtils.getUsername()); coalPay.setUpdateTime(new Date()); int i = coalPayMapper.updateCoalPayById(coalPay); int update = coalPayCategoryMapper.deleteByCoalPayId(coalPayDto.getId()); - if (update>0){ + if (update > 0) { List<CoalPayCategory> coalPayCategories = coalPayDto.getCoalPayCategoryies(); for (CoalPayCategory coalPayCategory : coalPayCategories) { coalPayCategory.setCoalPayId(coalPay.getId()); @@ -161,13 +162,13 @@ @Override public AjaxResult deleteCoalPayByIds(Long[] ids) { for (Long id : ids) { - List<CoalPayStudent> coalPayStudents = coalPayStudentService.selectByCoalPayIdAndPayStatus(id,1); - if (!CollectionUtils.isEmpty(coalPayStudents)){ - throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR,"已有学员完成缴费,请勿删除"); + List<CoalPayStudent> coalPayStudents = coalPayStudentService.selectByCoalPayIdAndPayStatus(id, 1); + if (!CollectionUtils.isEmpty(coalPayStudents)) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "已有学员完成缴费,请勿删除"); } } int i = coalPayMapper.updateByIds(ids); - if (i>0){ + if (i > 0) { return AjaxResult.success(); } return AjaxResult.error(); @@ -175,7 +176,7 @@ //个人查询缴费 @Override - public List<CoalPayStudentRep> selectCoalPay(String idcard,String phone) { + public List<CoalPayStudentRep> selectCoalPay(String idcard, String phone) { CoalPayStudentReq coalPayStudentReq = new CoalPayStudentReq(); coalPayStudentReq.setIdCard(idcard); coalPayStudentReq.setPhone(phone); @@ -194,7 +195,7 @@ //查询对应批次以及批次包含工种类别 CoalPay coalPay = coalPayMapper.selectById(payStudent.getCoalPayId()); CoalPayRepDto coalPayRepDto = new CoalPayRepDto(); - BeanUtils.copyProperties(coalPay,coalPayRepDto); + BeanUtils.copyProperties(coalPay, coalPayRepDto); //考点名称 SysDept sysDept = sysDeptMapper.selectDeptById(coalPay.getDeptId()); coalPayRepDto.setDeptName(sysDept.getDeptName()); @@ -210,8 +211,8 @@ @Override public int updateCoalPayType(CoalPayTypeReq coalPayTypeReq) { CoalPay byId = coalPayMapper.selectById(coalPayTypeReq.getCoalPayId()); - if (coalPayTypeReq.getPayPersonType() != null && byId.getPayPersonType() == 2){ - throw new BusinessException(this.getClass(),ResultConstants.BUSINESS_ERROR,"已为团体缴费,不可更改"); + if (coalPayTypeReq.getPayPersonType() != null && byId.getPayPersonType() == 2) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "已为团体缴费,不可更改"); } return coalPayMapper.updateByPayId(coalPayTypeReq); } @@ -224,7 +225,7 @@ CoalTicket coalTicket = coalCategoryMapper.selectCoalTicket(); PayReqData payReqData = new PayReqData(); - payReqData.setOrderNo(RandomUtil.generateOrderNumber()); + payReqData.setOrderNo(RandomUtil.generateOrderNumber(coalPayId, "CO")); payReqData.setMoney(coalPay.getAmount()); payReqData.setAmount(1); payReqData.setPayerName(coalPayStudent.getName()); @@ -248,34 +249,34 @@ CoalPayStudent payStudent = new CoalPayStudent(); - RLock lock = redissonClient.getLock("SWSPKMAS_PAY_PERSON"); + RLock lock = redissonClient.getLock("SWSPKMAS_PAY_PERSON_" + coalPayId); try { lock.lock(10, TimeUnit.SECONDS); - if (coalPayStudent.getGovPayStatus()!=0){ - throw new BusinessException(this.getClass(),ResultConstants.BUSINESS_ERROR,"请勿重复发起支付"); + if (coalPayStudent.getGovPayStatus() != 0) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "请勿重复发起支付"); } - if (StringUtils.isEmpty(coalPayStudent.getPayCode())){ + if (StringUtils.isEmpty(coalPayStudent.getPayCode())) { } - ResultVo resultVo = PayUtils.sendApiPost(payReqData); - if (resultVo.getRespcode().equals("BUS0000")){ + ResultVo resultVo = payUtils.sendApiPost(payReqData); + if (resultVo.getRespcode().equals("BUS0000")) { payStudent.setId(studentId); payStudent.setOrderId(resultVo.getRespdata().getOrderNo()); payStudent.setGovPayStatus(1); payStudent.setPayCode(resultVo.getRespdata().getBillNo()); coalPayStudentService.updateByCoalPayStudent(payStudent); return resultVo.getRespdata().getBillNo(); - }else { - throw new BusinessException(this.getClass(),ResultConstants.BUSINESS_ERROR,"发起支付失败,请稍后重试"); + } else { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "发起支付失败,请稍后重试"); } - }catch (BusinessException e){ - throw new BusinessException(this.getClass(),ResultConstants.BUSINESS_ERROR,"请稍后重试"); + } catch (BusinessException e) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "请稍后重试"); } catch (IOException e) { throw new RuntimeException(e); } finally { - if(lock.isLocked()){ + if (lock.isLocked()) { lock.unlock(); } } diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/NonCoalPayStudentServiceImpl.java b/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/NonCoalPayStudentServiceImpl.java index 3b78a96..21dda14 100644 --- a/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/NonCoalPayStudentServiceImpl.java +++ b/exam-system/src/main/java/com/gkhy/exam/pay/service/impl/NonCoalPayStudentServiceImpl.java @@ -4,23 +4,34 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gkhy.exam.institutionalaccess.enums.StudentSex; +import com.gkhy.exam.pay.dto.rep.NonCoalCateRep; +import com.gkhy.exam.pay.dto.rep.NonCoalPayOrder; +import com.gkhy.exam.pay.dto.rep.NonCoalStuRep; import com.gkhy.exam.pay.dto.req.NonCoalPayStuImport; import com.gkhy.exam.pay.dto.req.NonCoalPayStudentReqDto; import com.gkhy.exam.pay.entity.NonCoalPay; import com.gkhy.exam.pay.entity.NonCoalPayStudent; +import com.gkhy.exam.pay.entity.PayReqData; import com.gkhy.exam.pay.mapper.NonCoalPayMapper; import com.gkhy.exam.pay.mapper.NonCoalPayStudentMapper; import com.gkhy.exam.pay.service.NonCoalPayStudentService; +import com.gkhy.exam.pay.utils.PayUtils; +import com.gkhy.exam.pay.utils.ResultVo; +import com.ruoyi.common.constant.ResultConstants; +import com.ruoyi.common.exception.BusinessException; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.RandomUtil; +import com.ruoyi.common.utils.RedisLock; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -31,11 +42,138 @@ * @date 2025-01-16 */ @Service +@Slf4j public class NonCoalPayStudentServiceImpl extends ServiceImpl<NonCoalPayStudentMapper, NonCoalPayStudent> implements NonCoalPayStudentService { @Resource private NonCoalPayStudentMapper nonCoalPayStudentMapper; @Resource private NonCoalPayMapper nonCoalPayMapper; + @Resource + private PayUtils payUtils; + @Autowired + private RedisLock redisLock; + + private static final String NON_COAL_PAY_STUDENT_LOCK = "NON_COAL_PAY_STUDENT_LOCK_"; + + + @Override + public String sendOrder(Long dataId, String payType) { + + String lockKey = NON_COAL_PAY_STUDENT_LOCK + dataId + "_PAY_TYPE_" + payType; + + + Boolean b = redisLock.tryLock(lockKey, 10, 20, TimeUnit.SECONDS); + if (b) { + String orderNo = RandomUtil.generateOrderNumber(dataId, "NC"); + List<NonCoalPayOrder> nonCoalPayOrders = nonCoalPayMapper.selectNonCoalPayOrderByParam(dataId, Long.valueOf(payType)); + if (StringUtils.isEmpty(nonCoalPayOrders)) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "未找到相关缴费信息"); + } + NonCoalPayOrder nonCoalPayOrder = nonCoalPayOrders.get(0); + + List<NonCoalStuRep> nonCoalStuList = nonCoalPayOrder.getNonCoalStuList(); + + if (StringUtils.isEmpty(nonCoalStuList)) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "未找到需要缴费的学员"); + } + NonCoalStuRep nonCoalStuRep = nonCoalStuList.get(0); + if (nonCoalStuRep.getPayStatus() == 1) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "已缴费请勿重复缴费"); + } + List<NonCoalCateRep> nonCoalPayCategoryList = nonCoalPayOrder.getNonCoalPayCategoryList(); + + if (StringUtils.isEmpty(nonCoalPayCategoryList)) { + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "缴费信息缺失"); + } + // 业务处理 + //查询主信息 查询是否是团队 + PayReqData payReqData = dealData(nonCoalPayOrder, orderNo, payType); + + try { + ResultVo resultVo = payUtils.sendApiPost(payReqData); + log.info("调用接口返回结果:" + resultVo); + if (resultVo.getRespcode().equals("BUS0000")) { + String orderId = resultVo.getRespdata().getOrderId(); + String billNo = resultVo.getRespdata().getBillNo(); + if (StringUtils.isNotEmpty(orderId)) { + // 更新订单 + if ("1".equals(payType)) { + baseMapper.update(null, Wrappers.<NonCoalPayStudent>lambdaUpdate() + .set(NonCoalPayStudent::getOrderId, orderId) + .set(NonCoalPayStudent::getOrderNo, orderNo) + .set(NonCoalPayStudent::getPayCode, billNo) + .eq(NonCoalPayStudent::getId, dataId).eq(NonCoalPayStudent::getDelFlag, 0) + .eq(NonCoalPayStudent::getPayType, payType).eq(NonCoalPayStudent::getPayStatus, 0)); + } else { + //团体缴费 + baseMapper.update(null, Wrappers.<NonCoalPayStudent>lambdaUpdate() + .set(NonCoalPayStudent::getOrderId, orderId) + .set(NonCoalPayStudent::getOrderNo, orderNo) + .set(NonCoalPayStudent::getPayCode, billNo) + .eq(NonCoalPayStudent::getNonCoalPayId, dataId).eq(NonCoalPayStudent::getDelFlag, 0) + .eq(NonCoalPayStudent::getPayType, payType).eq(NonCoalPayStudent::getPayStatus, 0)); + } + } + return orderId; + } else { + log.error("生成订单失败:" + resultVo.getRespmsg() + ",请稍后重试,错误编码:" + resultVo.getRespcode() + "参数如下:" + payReqData); + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, "发起支付失败,请稍后重试"); + } + + } catch (Exception e) { + log.error("发起支付调用接口失败:" + e); + throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR, e.getMessage()); + } finally { + redisLock.unlock(lockKey); + } + } + + + return null; + } + + private PayReqData dealData(NonCoalPayOrder nonCoalPayOrder, String orderNo, String payType) { + List<NonCoalStuRep> nonCoalStuList = nonCoalPayOrder.getNonCoalStuList(); + List<NonCoalCateRep> nonCoalPayCategoryList = nonCoalPayOrder.getNonCoalPayCategoryList(); + PayReqData payReqData = new PayReqData(); + payReqData.setOrderNo(orderNo); + payReqData.setPayerType(Integer.valueOf(payType)); + payReqData.setMoney(nonCoalPayOrder.getAmount().multiply(BigDecimal.valueOf(nonCoalStuList.size()))); + payReqData.setAmount(nonCoalStuList.size()); + + payReqData.setDesc(nonCoalPayOrder.getBatchName()); + + NonCoalCateRep nonCoalCateRep1 = nonCoalPayCategoryList.get(0); + payReqData.setHandlingPerson(nonCoalCateRep1.getDrawer()); + payReqData.setChecker(nonCoalCateRep1.getReviewer()); + payReqData.setEnterCode(nonCoalCateRep1.getCompanyCode()); + payReqData.setInvoiceSocialCode(nonCoalCateRep1.getInvoicingCompanyCode()); + + List<PayReqData.Feedata> feedatas1 = new ArrayList<>(); + for (NonCoalCateRep nonCoalCateRep : nonCoalPayCategoryList) { + PayReqData.Feedata feedatas = new PayReqData.Feedata(); + feedatas.setAmount(nonCoalStuList.size()); + feedatas.setBusCode(nonCoalCateRep.getBusinessCode()); + feedatas.setPrice(nonCoalCateRep.getCategoryAmount()); + feedatas1.add(feedatas); + } + payReqData.setFeeDatas(feedatas1); + if ("1".equals(payType)) { + //个人缴费 + NonCoalStuRep nonCoalStuRep = nonCoalStuList.get(0); + payReqData.setPayerName(nonCoalStuRep.getStudentName()); + payReqData.setCertNo(nonCoalStuRep.getIdCard()); + } else { + //团体缴费 + payReqData.setPayerName(nonCoalPayOrder.getPayCompanyName()); + payReqData.setCertNo(nonCoalPayOrder.getPayCompanyCard()); + //todo 待确认 + payReqData.setInvoiceSocialCode(nonCoalPayOrder.getPayCompanyCard()); + payReqData.setEnterCode(nonCoalPayOrder.getPayCompanyCard()); + } + return payReqData; + + } /** * 查询【请填写功能名称】 @@ -212,7 +350,7 @@ stu1.setName(stu.getName()); stu1.setIdCard(stu.getIdCard()); stu1.setPhone(stu.getPhone()); - + // stu1.setOrderNo(RandomUtil.generateOrderNumber()); stu1.setSex(StudentSex.BOY.getStatus().equals(stu.getSex().trim()) ? 0L : 1L); nonCoalPayStudentMapper.insertNonCoalPayStudent(stu1); diff --git a/exam-system/src/main/java/com/gkhy/exam/pay/utils/PayUtils.java b/exam-system/src/main/java/com/gkhy/exam/pay/utils/PayUtils.java index 135fade..0c23d46 100644 --- a/exam-system/src/main/java/com/gkhy/exam/pay/utils/PayUtils.java +++ b/exam-system/src/main/java/com/gkhy/exam/pay/utils/PayUtils.java @@ -2,8 +2,12 @@ import com.alibaba.fastjson2.JSONObject; import com.gkhy.exam.pay.entity.PayReqData; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; -import org.apache.http.*; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpResponseException; @@ -25,8 +29,9 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; -import javax.annotation.Resource; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; @@ -40,32 +45,45 @@ /** * 缴费相关接口 */ +@Component +@Slf4j public class PayUtils { - private final static String appid="ED76A5F1703540BE977D34780B371FEB"; +// private final static String appid = "ED76A5F1703540BE977D34780B371FEB"; + @Value("${finance.orderUrl}") + private String orderUrl; - public static ResultVo sendApiPost(PayReqData payReqData) throws IOException { + @Value("${finance.payNotifyUrl}") + private String payNotifyUrl; + + @Value("${finance.payQueryUrl}") + private String payQueryUrl; + + @Value("${finance.apiId}") + private String appId; + + public ResultVo sendApiPost(PayReqData payReqData) throws IOException { //正式 - String proUrl="http://finpt.xjcz.gov.cn/fs-service/fs-pay/invoice.do"; + String proUrl = "http://finpt.xjcz.gov.cn/fs-service/fs-pay/invoice.do"; //测试 - String testUrl= "http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/invoice.do"; + String testUrl = "http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/invoice.do"; Map<String, String> param = new HashMap<>(); - HttpPost httpPost = new HttpPost(testUrl); + HttpPost httpPost = new HttpPost(orderUrl); //请求参数转为json格式base64编码 String reqData = Base64.getEncoder().encodeToString(JSONObject.toJSONString(payReqData).getBytes()); - String mac = appid+"||"+reqData; + String mac = appId + "||" + reqData; mac = DigestUtils.md5Hex(mac.getBytes()); - param.put("appid",appid); - param.put("reqdata",reqData); - param.put("mac",mac); + param.put("appid", appId); + param.put("reqdata", reqData); + param.put("mac", mac); - httpPost.setEntity(assemblyFormEntity(param,"utf-8")); - HttpClient httpClient = getHttpClient(testUrl); + httpPost.setEntity(assemblyFormEntity(param, "utf-8")); + HttpClient httpClient = getHttpClient(orderUrl); HttpResultVo execute = httpClient.execute(httpPost, getResponseHandler()); String stringContent = execute.getStringContent(); ResultVo resultVo = JSONObject.parseObject(stringContent, ResultVo.class); @@ -117,13 +135,15 @@ } @Override - public void checkClientTrusted(X509Certificate[] xcs, String str) {} + public void checkClientTrusted(X509Certificate[] xcs, String str) { + } @Override - public void checkServerTrusted(X509Certificate[] xcs, String str) {} + public void checkServerTrusted(X509Certificate[] xcs, String str) { + } }; SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS); - ctx.init(null, new TrustManager[] {trustManager}, null); + ctx.init(null, new TrustManager[]{trustManager}, null); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE); // 创建Registry @@ -210,81 +230,79 @@ //缴费结果通知 - public static Map<String,String> receive(JSONObject jsonObject) throws IOException { + public Map<String, String> receive(JSONObject jsonObject) throws IOException { Map<String, String> params = new HashMap<>(); JSONObject reqdata = new JSONObject(); - Map<String,String> result = (Map<String, String>) jsonObject.get("reqdata"); + Map<String, String> result = (Map<String, String>) jsonObject.get("reqdata"); String orderNo = result.get("orderNo"); //确认是否成功 - String notarize= affirmPost(orderNo); - reqdata.put("orderNo",orderNo); - reqdata.put("status",notarize); + String notarize = affirmPost(orderNo); + reqdata.put("orderNo", orderNo); + reqdata.put("status", notarize); String req = Base64.getEncoder().encodeToString(reqdata.toJSONString().getBytes()); - String mac = appid+"||"+req; + String mac = appId + "||" + req; mac = DigestUtils.md5Hex(mac.getBytes()); - params.put("appid",appid); - params.put("reqdata",req); - params.put("mac",mac); + params.put("appid", appId); + params.put("reqdata", req); + params.put("mac", mac); return params; } //缴费结果确认查询 - public static String affirmPost(String orderNo) throws IOException { - String porUrl="http://finpt.xjcz.gov.cn/fs-service/fs-pay/notifyConfirm.do"; - String testUrl="http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/notifyConfirm.do"; + public String affirmPost(String orderNo) throws IOException { HashMap<String, String> param = new HashMap<>(); JSONObject jsonObject = new JSONObject(); - jsonObject.put("orderNo",orderNo); + jsonObject.put("orderNo", orderNo); String reqdata = Base64.getEncoder().encodeToString(jsonObject.toJSONString().getBytes()); - String mac = appid+"||"+reqdata; - mac=DigestUtils.md5Hex(mac.getBytes()); - param.put("appid",appid); - param.put("reqdata",reqdata); - param.put("mac",mac); + String mac = appId + "||" + reqdata; + mac = DigestUtils.md5Hex(mac.getBytes()); + param.put("appid", appId); + param.put("reqdata", reqdata); + param.put("mac", mac); - HttpPost httppost = new HttpPost(testUrl); - httppost.setEntity(assemblyFormEntity(param,"utf-8")); - HttpClient httpClient = getHttpClient(testUrl); + HttpPost httppost = new HttpPost(payNotifyUrl); + httppost.setEntity(assemblyFormEntity(param, "utf-8")); + HttpClient httpClient = getHttpClient(payNotifyUrl); HttpResultVo execute = httpClient.execute(httppost, getResponseHandler()); String stringContent = execute.getStringContent(); ResultVo resultVo = JSONObject.parseObject(stringContent, ResultVo.class); - System.out.printf("请求结果为:"+resultVo); - if (resultVo.getRespcode().equals("BUS0000")){ + log.info("请求结果为:" + resultVo); + if (resultVo.getRespcode().equals("BUS0000")) { return "success"; } return "fail"; } //缴费结果查询 - public static JSONObject query(String orderNo) throws IOException { - String proUrl="http://finpt.xjcz.gov.cn/fs-service/fs-pay/query.do"; - String testUrl="http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/query.do"; + public JSONObject query(String orderNo) throws IOException { + String proUrl = "http://finpt.xjcz.gov.cn/fs-service/fs-pay/query.do"; + String testUrl = "http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/query.do"; HashMap<String, String> param = new HashMap<>(); JSONObject jsonObject = new JSONObject(); - jsonObject.put("orderNo",orderNo); + jsonObject.put("orderNo", orderNo); String reqdata = Base64.getEncoder().encodeToString(jsonObject.toJSONString().getBytes()); - String mac = appid+"||"+reqdata; + String mac = appId + "||" + reqdata; mac = DigestUtils.md5Hex(mac.getBytes()); - param.put("appid",appid); - param.put("reqdata",reqdata); - param.put("mac",mac); + param.put("appid", appId); + param.put("reqdata", reqdata); + param.put("mac", mac); - HttpPost httppost = new HttpPost(testUrl); - httppost.setEntity(assemblyFormEntity(param,"utf-8")); - HttpClient httpClient = getHttpClient(testUrl); + HttpPost httppost = new HttpPost(payQueryUrl); + httppost.setEntity(assemblyFormEntity(param, "utf-8")); + HttpClient httpClient = getHttpClient(payQueryUrl); HttpResultVo execute = httpClient.execute(httppost, getResponseHandler()); String stringContent = execute.getStringContent(); JSONObject result = JSONObject.parseObject(stringContent); - System.out.printf("请求结果json为:"+result); + log.info("请求结果json为:" + result); return result; } } diff --git a/exam-system/src/main/resources/mapper/pay/NonCoalPayMapper.xml b/exam-system/src/main/resources/mapper/pay/NonCoalPayMapper.xml index b273dae..352ec81 100644 --- a/exam-system/src/main/resources/mapper/pay/NonCoalPayMapper.xml +++ b/exam-system/src/main/resources/mapper/pay/NonCoalPayMapper.xml @@ -202,6 +202,75 @@ </select> + <resultMap type="com.gkhy.exam.pay.dto.rep.NonCoalPayOrder" id="getNonCoalPayResultOrder"> + <result property="id" column="id"/> + <result property="batchName" column="batch_name"/> + <result property="amount" column="amount"/> + <result property="payPersonType" column="pay_person_type"/> + <result property="payCompanyName" column="pay_company_name"/> + <result property="payCompanyCard" column="pay_company_card"/> + <collection property="nonCoalPayCategoryList" javaType="java.util.List" + resultMap="nonCoalPayCategoryListOrder"/> + <collection property="nonCoalStuList" javaType="java.util.List" + resultMap="nonCoalPayStuListOrder"/> + </resultMap> + <resultMap id="nonCoalPayCategoryListOrder" type="com.gkhy.exam.pay.dto.rep.NonCoalCateRep"> + <result property="id" column="non_category_id"/> + <result property="businessCode" column="business_code"/> + <result property="companyCode" column="company_code"/> + <result property="invoicingCompanyCode" column="invoicing_company_code"/> + <result property="drawer" column="drawer"/> + <result property="reviewer" column="reviewer"/> + <result property="categoryId" column="category_id"/> + <result property="subjectName" column="subject_name"/> + <result property="categoryType" column="category_type"/> + <result property="categoryAmount" column="category_amount"/> + </resultMap> + + <resultMap id="nonCoalPayStuListOrder" type="com.gkhy.exam.pay.dto.rep.NonCoalStuRep"> + <result property="id" column="non_coal_student_id"/> + <result property="phone" column="phone"/> + <result property="idCard" column="id_card"/> + <result property="studentName" column="student_name"/> + <result property="payStatus" column="pay_status"/> + <result property="orderId" column="order_id"/> + </resultMap> + + + <select id="selectNonCoalPayOrderByParam" resultMap="getNonCoalPayResultOrder"> + select a.id, + a.batch_name, + a.pay_type, + a.amount, + a.pay_person_type, + a.pay_company_name, + a.pay_company_card, + b.id as non_category_id, + b.category_id, + c.subject_name, + c.category_type, + c.business_code, + c.company_code, + c.drawer, + c.reviewer, + c.invoicing_company_code, + b.category_amount, + t.id as non_coal_student_id, + t.phone, + t.id_card, + t.name as student_name, + t.pay_status, + t.order_id + from non_coal_pay a + inner join non_coal_pay_student t on t.non_coal_pay_id = a.id and t.del_flag = 0 and t.pay_status = 0 + inner join non_coal_pay_category b on a.id = b.non_coal_pay_id and b.del_flag = 0 + left join non_coal_category c on b.category_id = c.id and c.del_flag = 0 + where a.del_flag = 0 + <if test="payType != null and payType == 2 ">and a.id = #{dataId} and t.pay_type = #{payType}</if> + <if test="payType != null and payType == 1 ">and t.id = #{dataId} and t.pay_type = #{payType}</if> + + </select> + <insert id="insertNonCoalPay" parameterType="NonCoalPay" useGeneratedKeys="true" keyProperty="id"> insert into non_coal_pay diff --git a/exam-system/src/test/java/TextPay.java b/exam-system/src/test/java/TextPay.java index f3b89da..3d46294 100644 --- a/exam-system/src/test/java/TextPay.java +++ b/exam-system/src/test/java/TextPay.java @@ -1,21 +1,16 @@ -import com.alibaba.fastjson2.JSONObject; import com.gkhy.exam.pay.entity.PayReqData; import com.gkhy.exam.pay.utils.PayUtils; import com.gkhy.exam.pay.utils.ResultVo; -import com.google.gson.JsonObject; import com.ruoyi.common.utils.RandomUtil; -import com.ruoyi.common.utils.uuid.UUID; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; -import java.util.Map; @SpringBootTest(classes = TextPay.class) @ActiveProfiles("dev") @@ -23,53 +18,49 @@ public class TextPay { - @Test - public void paytext() throws IOException { + @Test + public void paytext() throws IOException { - PayReqData payReqData = new PayReqData(); - PayReqData.Feedata feedatas = new PayReqData.Feedata(); + PayReqData payReqData = new PayReqData(); + PayReqData.Feedata feedatas = new PayReqData.Feedata(); - payReqData.setDesc("安全技术考试考务费_煤矿安全作业-001504"); - payReqData.setOrderNo(RandomUtil.generateOrderNumber()); - payReqData.setMoney(BigDecimal.valueOf(103)); - payReqData.setAmount(1); - payReqData.setPayerName("测试"); - payReqData.setCertNo("411381199801093991"); - payReqData.setPayerType(1); - payReqData.setInvoiceSocialCode("11650000MB1957293J"); - payReqData.setHandlingPerson("张三"); - payReqData.setChecker("李四"); - payReqData.setEnterCode("680534083"); + payReqData.setDesc("安全技术考试考务费_煤矿安全作业-001504"); + payReqData.setOrderNo(RandomUtil.generateOrderNumber(1L, "CO")); + payReqData.setMoney(BigDecimal.valueOf(103)); + payReqData.setAmount(1); + payReqData.setPayerName("测试"); + payReqData.setCertNo("411381199801093991"); + payReqData.setPayerType(1); + payReqData.setInvoiceSocialCode("11650000MB1957293J"); + payReqData.setHandlingPerson("张三"); + payReqData.setChecker("李四"); + payReqData.setEnterCode("680534083"); - List<PayReqData.Feedata> feedatas1 = new ArrayList<>(); - feedatas.setAmount(1); - feedatas.setBusCode("DZ001504"); - feedatas.setPrice(BigDecimal.valueOf(103)); - feedatas1.add(feedatas); - payReqData.setFeeDatas(feedatas1); + List<PayReqData.Feedata> feedatas1 = new ArrayList<>(); + feedatas.setAmount(1); + feedatas.setBusCode("DZ001504"); + feedatas.setPrice(BigDecimal.valueOf(103)); + feedatas1.add(feedatas); + payReqData.setFeeDatas(feedatas1); - PayUtils payUtils = new PayUtils(); - ResultVo resultVo = payUtils.sendApiPost(payReqData); - System.out.printf("请求结果:"+resultVo); + PayUtils payUtils = new PayUtils(); + ResultVo resultVo = payUtils.sendApiPost(payReqData); + System.out.printf("请求结果:" + resultVo); - } + } - - @Test - public void text001(){ - try { -// String s = PayUtils.affirmPost("10000001"); - JSONObject query = PayUtils.query("1000001"); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - - + @Test + public void text001() { +// try { +//// String s = PayUtils.affirmPost("10000001"); +// //JSONObject query = PayUtils.query("1000001"); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } + } } diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 3098c60..a687cfe 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -1,132 +1,139 @@ # 开发环境配置 server: - # 服务器的HTTP端口,默认为8080 - port: 8085 - servlet: - # 应用的访问路径 - context-path: /api - tomcat: - # tomcat的URI编码 - uri-encoding: UTF-8 - # 连接数满后的排队数,默认为100 - accept-count: 1000 - threads: - # tomcat最大线程数,默认为200 - max: 800 - # Tomcat启动初始化的线程数,默认值10 - min-spare: 100 + # 服务器的HTTP端口,默认为8080 + port: 8085 + servlet: + # 应用的访问路径 + context-path: /api + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # 连接数满后的排队数,默认为100 + accept-count: 1000 + threads: + # tomcat最大线程数,默认为200 + max: 800 + # Tomcat启动初始化的线程数,默认值10 + min-spare: 100 # 数据源配置 spring: - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driverClassName: com.mysql.cj.jdbc.Driver - druid: - # 主库数据源 - master: - url: jdbc:mysql://192.168.2.16:7006/swspkmas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true - username: root - password: 2farwL3yPXfbH2AP - # 从库数据源 - slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 - # 最大连接池数量 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置连接超时时间 - connectTimeout: 30000 - # 配置网络超时时间 - socketTimeout: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - webStatFilter: - enabled: true - statViewServlet: - enabled: true - # 设置白名单,不填则允许所有访问 - allow: - url-pattern: /druid/* - # 控制台管理用户名和密码 - login-username: ruoyi - login-password: 123456 - filter: - stat: - enabled: true - # 慢SQL记录 - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://192.168.2.16:7006/swspkmas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true + username: root + password: 2farwL3yPXfbH2AP + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置连接超时时间 + connectTimeout: 30000 + # 配置网络超时时间 + socketTimeout: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 配置一个连接在池中最大生存的时间,单位是毫秒 + maxEvictableIdleTimeMillis: 900000 + # 配置检测连接是否有效 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + webStatFilter: + enabled: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true - # redis 配置 - redis: - # 地址 - host: 192.168.2.16 - # 端口,默认为6379 - port: 6379 - # 数据库索引 - database: 5 - # 密码 -# password: wioowr23923sd3*& - # 连接超时时间 - timeout: 10s - lettuce: - pool: - # 连接池中的最小空闲连接 - min-idle: 0 - # 连接池中的最大空闲连接 - max-idle: 8 - # 连接池的最大数据库连接数 - max-active: 8 - # #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1ms + # redis 配置 + redis: + # 地址 + host: 192.168.2.16 + # 端口,默认为6379 + port: 6379 + # 数据库索引 + database: 5 + # 密码 + # password: wioowr23923sd3*& + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms tripartite: - restSever: https://inspurtestcx.saws.org.cn/sjjh - appKey: hj92qe - appPwd: dxep6j + restSever: https://inspurtestcx.saws.org.cn/sjjh + appKey: hj92qe + appPwd: dxep6j #windous测试 file: - path: - #基础路径 - dcPath: upload - urlRootPath: /uploadfile/ - module: - #用户模块 - accountPath: /account/ + path: + #基础路径 + dcPath: upload + urlRootPath: /uploadfile/ + module: + #用户模块 + accountPath: /account/ #线程池配置 threadPool: - corePoolSize: 20 - maxPoolSize: 20 - queueCapacity: 10000 - scheduling: - #控制线程是否执行 true:执行;false:不执行 - enabled: true + corePoolSize: 20 + maxPoolSize: 20 + queueCapacity: 10000 + scheduling: + #控制线程是否执行 true:执行;false:不执行 + enabled: true # 七牛云相关信息 safecheckqiniuymes: - accesskey: 5YprpjY0BJiyjII2VqlHed7UhBEvvkPZicbwd8Kl - secretkey: m3gGQNQ9cLmVBBZwPXZ5-Wzr0duzyAPPmJUx4_ay - templateid: 1844221365930962944 \ No newline at end of file + accesskey: 5YprpjY0BJiyjII2VqlHed7UhBEvvkPZicbwd8Kl + secretkey: m3gGQNQ9cLmVBBZwPXZ5-Wzr0duzyAPPmJUx4_ay + templateid: 1844221365930962944 + +#财政接口地址及api +finance: + apiId: ED76A5F1703540BE977D34780B371FEB + orderUrl: http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/invoice.do + payNotifyUrl: http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/notifyConfirm.do + payQueryUrl: http://finpt.xjcz.gov.cn/fs-service/fs-pay/query.do diff --git a/ruoyi-admin/src/main/resources/application-pro.yml b/ruoyi-admin/src/main/resources/application-pro.yml index cb188b5..20fc39e 100644 --- a/ruoyi-admin/src/main/resources/application-pro.yml +++ b/ruoyi-admin/src/main/resources/application-pro.yml @@ -1,131 +1,138 @@ # 开发环境配置 server: - # 服务器的HTTP端口,默认为8080 - port: 8085 - servlet: - # 应用的访问路径 - context-path: /api - tomcat: - # tomcat的URI编码 - uri-encoding: UTF-8 - # 连接数满后的排队数,默认为100 - accept-count: 1000 - threads: - # tomcat最大线程数,默认为200 - max: 800 - # Tomcat启动初始化的线程数,默认值10 - min-spare: 100 + # 服务器的HTTP端口,默认为8080 + port: 8085 + servlet: + # 应用的访问路径 + context-path: /api + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # 连接数满后的排队数,默认为100 + accept-count: 1000 + threads: + # tomcat最大线程数,默认为200 + max: 800 + # Tomcat启动初始化的线程数,默认值10 + min-spare: 100 # 数据源配置 spring: - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driverClassName: com.mysql.cj.jdbc.Driver - druid: - # 主库数据源 - master: - url: jdbc:mysql://127.0.0.1:7006/swspkmas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true - username: root - password: 2farwL3yPXfbH2AP - # 从库数据源 - slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 - # 最大连接池数量 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置连接超时时间 - connectTimeout: 30000 - # 配置网络超时时间 - socketTimeout: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - webStatFilter: - enabled: true - statViewServlet: - enabled: true - # 设置白名单,不填则允许所有访问 - allow: - url-pattern: /druid/* - # 控制台管理用户名和密码 - login-username: ruoyi - login-password: 123456 - filter: - stat: - enabled: true - # 慢SQL记录 - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://127.0.0.1:7006/swspkmas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true + username: root + password: 2farwL3yPXfbH2AP + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置连接超时时间 + connectTimeout: 30000 + # 配置网络超时时间 + socketTimeout: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 配置一个连接在池中最大生存的时间,单位是毫秒 + maxEvictableIdleTimeMillis: 900000 + # 配置检测连接是否有效 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + webStatFilter: + enabled: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true - # redis 配置 - redis: - # 地址 - host: 127.0.0.1 - # 端口,默认为6379 - port: 6379 - # 数据库索引 - database: 5 - # 密码 - password: akj78avauba789a - # 连接超时时间 - timeout: 10s - lettuce: - pool: - # 连接池中的最小空闲连接 - min-idle: 0 - # 连接池中的最大空闲连接 - max-idle: 8 - # 连接池的最大数据库连接数 - max-active: 8 - # #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1ms + # redis 配置 + redis: + # 地址 + host: 127.0.0.1 + # 端口,默认为6379 + port: 6379 + # 数据库索引 + database: 5 + # 密码 + password: akj78avauba789a + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms tripartite: - restSever: https://inspurtestcx.saws.org.cn/sjjh - appKey: hj92qe - appPwd: dxep6j + restSever: https://inspurtestcx.saws.org.cn/sjjh + appKey: hj92qe + appPwd: dxep6j #windous测试 file: - path: - #基础路径 - dcPath: upload - urlRootPath: /uploadfile/ - module: - #用户模块 - accountPath: /account/ + path: + #基础路径 + dcPath: upload + urlRootPath: /uploadfile/ + module: + #用户模块 + accountPath: /account/ #线程池配置 threadPool: - corePoolSize: 20 - maxPoolSize: 20 - queueCapacity: 10000 - scheduling: - #控制线程是否执行 true:执行;false:不执行 - enabled: true + corePoolSize: 20 + maxPoolSize: 20 + queueCapacity: 10000 + scheduling: + #控制线程是否执行 true:执行;false:不执行 + enabled: true # 七牛云相关信息 safecheckqiniuymes: - accesskey: 5YprpjY0BJiyjII2VqlHed7UhBEvvkPZicbwd8Kl - secretkey: m3gGQNQ9cLmVBBZwPXZ5-Wzr0duzyAPPmJUx4_ay - templateid: 1844221365930962944 \ No newline at end of file + accesskey: 5YprpjY0BJiyjII2VqlHed7UhBEvvkPZicbwd8Kl + secretkey: m3gGQNQ9cLmVBBZwPXZ5-Wzr0duzyAPPmJUx4_ay + templateid: 1844221365930962944 + + +finance: + apiId: ED76A5F1703540BE977D34780B371FEB + orderUrl: http://finpt.xjcz.gov.cn/fs-service/fs-pay/invoice.do + payNotifyUrl: http://finpt.xjcz.gov.cn/fs-service/fs-pay/notifyConfirm.do + payQueryUrl: http://finpt.xjcz.gov.cn/fs-service-test/fs-pay/query.do \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RedissonConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RedissonConfig.java new file mode 100644 index 0000000..a2ba522 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RedissonConfig.java @@ -0,0 +1,29 @@ +package com.ruoyi.common.config; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RedissonConfig { + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private String port; + +// @Value("${spring.redis.password}") +// private String password; + + @Bean(destroyMethod = "shutdown") + @ConditionalOnMissingBean(RedissonClient.class) + public RedissonClient redissonClient() { + Config config = new Config(); + config.useSingleServer().setAddress("redis://" + host + ":" + port); // 更多.set + return Redisson.create(config); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/RandomUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RandomUtil.java index 89ed10b..80a68c2 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/RandomUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RandomUtil.java @@ -35,20 +35,20 @@ public static void main(String[] args) { String s = generateRandomString(26); System.out.println(s); - System.out.println(generateOrderNumber()); + System.out.println(generateOrderNumber(10L, "NC")); } + private static final Random RANDOM = new Random(); private static final AtomicInteger SEQUENCE = new AtomicInteger(0); private static final int MAX_SEQUENCE = 99999;// 5位数的序列号 private static final String ORDER_PER = "SN"; - public static synchronized String generateOrderNumber() { + public static String generateOrderNumber(Long dataId, String orderType) { String datePart = new SimpleDateFormat("yyyyMMddhhmm").format(new Date()); - int sequencePart = SEQUENCE.getAndIncrement() % MAX_SEQUENCE; - String sequenceStr = String.format("%05d", sequencePart); // 保证序列号是5位数,不足的前面补0 + int randomPart = RANDOM.nextInt(90000) + 10000; // 生成5位随机数 - return ORDER_PER + datePart + sequenceStr; + return ORDER_PER + datePart + String.format("%05d", randomPart) + dataId; } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisLock.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisLock.java new file mode 100644 index 0000000..e7d24b8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisLock.java @@ -0,0 +1,98 @@ +package com.ruoyi.common.utils; + +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.concurrent.TimeUnit; + +@Component +public class RedisLock { + @Autowired + private RedissonClient redissonClient; + + /** + * 获取锁 + * + * @param lockKey 锁实例key + * @return 锁信息 + */ + public RLock getRLock(String lockKey) { + return redissonClient.getLock(lockKey); + } + + /** + * 加锁 + * + * @param lockKey 锁实例key + * @return 锁信息 + */ + public RLock lock(String lockKey) { + RLock lock = getRLock(lockKey); + lock.lock(); + return lock; + } + + /** + * 加锁 + * + * @param lockKey 锁实例key + * @param leaseTime 上锁后自动释放锁时间 + * @return true=成功;false=失败 + */ + public Boolean tryLock(String lockKey, long leaseTime) { + return tryLock(lockKey, 0, leaseTime, TimeUnit.SECONDS); + } + + /** + * 加锁 + * + * @param lockKey 锁实例key + * @param leaseTime 上锁后自动释放锁时间 + * @param unit 时间颗粒度 + * @return true=加锁成功;false=加锁失败 + */ + public Boolean tryLock(String lockKey, long leaseTime, TimeUnit unit) { + return tryLock(lockKey, 0, leaseTime, unit); + } + + /** + * 加锁 + * + * @param lockKey 锁实例key + * @param waitTime 最多等待时间 + * @param leaseTime 上锁后自动释放锁时间 + * @param unit 时间颗粒度 + * @return true=加锁成功;false=加锁失败 + */ + public Boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) { + RLock rLock = getRLock(lockKey); + boolean tryLock = false; + try { + tryLock = rLock.tryLock(waitTime, leaseTime, unit); + } catch (InterruptedException e) { + return false; + } + return tryLock; + } + + /** + * 释放锁 + * + * @param lockKey 锁实例key + */ + public void unlock(String lockKey) { + RLock lock = getRLock(lockKey); + lock.unlock(); + } + + /** + * 释放锁 + * + * @param lock 锁信息 + */ + public void unlock(RLock lock) { + lock.unlock(); + } +} -- Gitblit v1.9.2