教育训练处考试制证系统后端
heheng
2025-01-23 f8b251573040d2762507909a02f274a6cf4d751c
特种作业非煤缴费版本优化
已修改12个文件
已添加5个文件
633 ■■■■■ 文件已修改
exam-system/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/controller/NonCoalPayController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalCateRep.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalPayOrder.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/dto/rep/NonCoalStuRep.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/mapper/NonCoalPayMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/service/NonCoalPayStudentService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/service/impl/CoalPayServiceImpl.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/service/impl/NonCoalPayStudentServiceImpl.java 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/pay/utils/PayUtils.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/resources/mapper/pay/NonCoalPayMapper.xml 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/test/java/TextPay.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-dev.yml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-pro.yml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/RedissonConfig.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/RandomUtil.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisLock.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
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));
    }
}
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;
}
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;
}
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;
}
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);
    /**
     * 修改【请填写功能名称】
     *
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);
    /**
     * 新增【请填写功能名称】
     *
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
     */
@@ -137,6 +137,7 @@
    /**
     * 修改缴费信息
     *
     * @param coalPayDto
     * @return
     */
@@ -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,7 +249,7 @@
        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){
@@ -259,7 +260,7 @@
            }
            ResultVo resultVo = PayUtils.sendApiPost(payReqData);
            ResultVo resultVo = payUtils.sendApiPost(payReqData);
            if (resultVo.getRespcode().equals("BUS0000")){
                payStudent.setId(studentId);
                payStudent.setOrderId(resultVo.getRespdata().getOrderNo());
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;
    }
    /**
     * 查询【请填写功能名称】
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,12 +45,25 @@
/**
 * 缴费相关接口
 */
@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";
@@ -54,18 +72,18 @@
        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("appid", appId);
        param.put("reqdata",reqData);
        param.put("mac",mac);
        httpPost.setEntity(assemblyFormEntity(param,"utf-8"));
        HttpClient httpClient = getHttpClient(testUrl);
        HttpClient httpClient = getHttpClient(orderUrl);
        HttpResultVo execute = httpClient.execute(httpPost, getResponseHandler());
        String stringContent = execute.getStringContent();
        ResultVo resultVo = JSONObject.parseObject(stringContent, ResultVo.class);
@@ -117,10 +135,12 @@
                }
                @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);
@@ -210,7 +230,7 @@
    //缴费结果通知
    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();
@@ -224,9 +244,9 @@
        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("appid", appId);
        params.put("reqdata",req);
        params.put("mac",mac);
@@ -234,28 +254,26 @@
    }
    //缴费结果确认查询
    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);
        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("appid", appId);
        param.put("reqdata",reqdata);
        param.put("mac",mac);
        HttpPost httppost = new HttpPost(testUrl);
        HttpPost httppost = new HttpPost(payNotifyUrl);
        httppost.setEntity(assemblyFormEntity(param,"utf-8"));
        HttpClient httpClient = getHttpClient(testUrl);
        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);
        log.info("请求结果为:" + resultVo);
        if (resultVo.getRespcode().equals("BUS0000")){
            return "success";
        }
@@ -263,7 +281,7 @@
    }
    //缴费结果查询
    public static JSONObject query(String orderNo) throws IOException {
    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";
@@ -272,19 +290,19 @@
        JSONObject jsonObject = new JSONObject();
        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("appid", appId);
        param.put("reqdata",reqdata);
        param.put("mac",mac);
        HttpPost httppost = new HttpPost(testUrl);
        HttpPost httppost = new HttpPost(payQueryUrl);
        httppost.setEntity(assemblyFormEntity(param,"utf-8"));
        HttpClient httpClient = getHttpClient(testUrl);
        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;
    }
}
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
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")
@@ -31,7 +26,7 @@
       PayReqData.Feedata feedatas = new PayReqData.Feedata();
       payReqData.setDesc("安全技术考试考务费_煤矿安全作业-001504");
       payReqData.setOrderNo(RandomUtil.generateOrderNumber());
        payReqData.setOrderNo(RandomUtil.generateOrderNumber(1L, "CO"));
       payReqData.setMoney(BigDecimal.valueOf(103));
       payReqData.setAmount(1);
       payReqData.setPayerName("测试");
@@ -57,19 +52,15 @@
   }
   @Test
    public void text001(){
       try {
//           String s = PayUtils.affirmPost("10000001");
           JSONObject query = PayUtils.query("1000001");
       } catch (IOException e) {
           throw new RuntimeException(e);
//       try {
////           String s = PayUtils.affirmPost("10000001");
//           //JSONObject query = PayUtils.query("1000001");
//       } catch (IOException e) {
//           throw new RuntimeException(e);
//       }
       }
   }
}
ruoyi-admin/src/main/resources/application-dev.yml
@@ -130,3 +130,10 @@
    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
ruoyi-admin/src/main/resources/application-pro.yml
@@ -129,3 +129,10 @@
    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
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);
    }
}
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;
    }
}
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();
    }
}