| ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/CourseController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxPayController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-system/src/main/java/com/ruoyi/system/model/TCourse.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-system/src/main/java/com/ruoyi/system/model/TCourseOrder.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-system/src/main/java/com/ruoyi/system/query/CourseOrderListQuery.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-system/src/main/java/com/ruoyi/system/query/GetCourseListQuery.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-system/src/main/java/com/ruoyi/system/task/base/AbstractJob.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-system/src/main/java/com/ruoyi/system/task/base/TimeJobType.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ruoyi-system/src/main/java/com/ruoyi/system/task/jobs/OrderJob.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/CourseController.java
New file @@ -0,0 +1,186 @@ package com.ruoyi.web.controller.api; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.collect.ImmutableMap; import com.ruoyi.common.core.domain.BasePage; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.OrderNos; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.model.TAppUser; import com.ruoyi.system.model.TCourse; import com.ruoyi.system.model.TCourseOrder; import com.ruoyi.system.model.TEmploymentInfo; import com.ruoyi.system.query.CourseOrderListQuery; import com.ruoyi.system.query.GetCourseListQuery; import com.ruoyi.system.service.TAppUserService; import com.ruoyi.system.service.TCourseOrderService; import com.ruoyi.system.service.TCourseService; import com.ruoyi.system.service.TEmploymentInfoService; import com.ruoyi.system.task.base.QuartzManager; import com.ruoyi.system.task.base.TimeJobType; import com.ruoyi.system.task.jobs.OrderJob; import com.ruoyi.system.wxPay.model.WeixinPayProperties; import com.ruoyi.system.wxPay.model.WxPaymentRefundModel; import com.ruoyi.system.wxPay.utils.WxV3Pay; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Arrays; import java.util.Map; import java.util.Objects; @Slf4j @RestController @RequestMapping("/course") @Api(tags = "课程模块") public class CourseController { private final TCourseService courseService; private final TCourseOrderService courseOrderService; private final TokenService tokenService; private final WxV3Pay wxV3Pay; private final WeixinPayProperties weixinPayProperties; private final TAppUserService appUserService; public CourseController(TCourseService courseService, TCourseOrderService courseOrderService, TokenService tokenService, WxV3Pay wxV3Pay, WeixinPayProperties weixinPayProperties, TAppUserService appUserService) { this.courseService = courseService; this.courseOrderService = courseOrderService; this.tokenService = tokenService; this.wxV3Pay = wxV3Pay; this.weixinPayProperties = weixinPayProperties; this.appUserService = appUserService; } @PostMapping("/getCourseList") @ApiOperation(value = "课程模块--列表",response = TCourse.class) public R<Page<TCourse>> getCourseList(@RequestBody GetCourseListQuery query) { Page<TCourse> page = new Page<>(query.getPageNum(), query.getPageSize()); Page<TCourse> coursePage = courseService.page(page, Wrappers.<TCourse>lambdaQuery().eq(TCourse::getCourseType,query.getCourseType()).like(Objects.nonNull(query.getCourseTitle()), TCourse::getCourseTitle, query.getCourseTitle()).orderByDesc(TCourse::getCreateTime)); return R.ok(coursePage); } @PostMapping("/getCourseDetail/{id}") @ApiOperation(value = "课程模块--详情",response = TCourse.class) public R<TCourse> getCourseDetail(@PathVariable String id) { TCourse course = courseService.getById(id); long count = courseOrderService.count(Wrappers.lambdaQuery(TCourseOrder.class).eq(TCourseOrder::getCourseId, id).in(TCourseOrder::getPayStatus, Arrays.asList(1, 2, 5))); course.setSignUpNum((int) count); return R.ok(course); } @PostMapping("/getCourseOrderList") @ApiOperation(value = "课程模块--订单列表",response = TCourseOrder.class) public R<Page<TCourseOrder>> getCourseOrderList(@RequestBody CourseOrderListQuery query) { String userId = tokenService.getLoginUserApplet().getUserId(); Page<TCourseOrder> page = new Page<>(query.getPageNum(), query.getPageSize()); Page<TCourseOrder> courseOrderPage = courseOrderService.page(page, Wrappers.<TCourseOrder>lambdaQuery().eq(TCourseOrder::getAppUserId, userId).eq(Objects.nonNull(query.getPayStatus()),TCourseOrder::getPayStatus, query.getPayStatus()).orderByDesc(TCourseOrder::getCreateTime)); return R.ok(courseOrderPage); } @PostMapping("/saveOrder") @ApiOperation(value = "课程模块--报名") public R<Map<String, Object>> saveOrder(@RequestBody TCourseOrder courseOrder) { String userId = tokenService.getLoginUserApplet().getUserId(); TAppUser appUser = appUserService.getById(userId); TCourse course = courseService.getById(courseOrder.getCourseId()); long count = courseOrderService.count(Wrappers.lambdaQuery(TCourseOrder.class).eq(TCourseOrder::getCourseId, course.getId()).in(TCourseOrder::getPayStatus, Arrays.asList(1, 2, 5))); if(count>=course.getPeopleLimit()){ return R.fail("报名人数已满"); } courseOrder.setAppUserId(userId); courseOrder.setPayMoney(course.getCourseCost()); courseOrder.setPayStatus(1); courseOrder.setOrderNumber(OrderNos.getDid()); boolean save = courseOrderService.save(courseOrder); if (save) { Map<String, Object> result = wxV3Pay.jsApi(courseOrder.getOrderNumber(), course.getCourseCost().multiply(BigDecimal.valueOf(100)).longValue(), appUser.getOpenId(),"购买课程",""); return R.ok(result); } Map<String, ? extends Object> maps = new ImmutableMap.Builder<String, String>(). put("id", courseOrder.getId()) .build(); QuartzManager.addJob( OrderJob.class, (OrderJob.name+courseOrder.getId()).toUpperCase(), TimeJobType.CANCEL_ORDER, DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(15)), maps ); return R.fail("报名失败"); } @PostMapping("/payOrder") @ApiOperation(value = "课程模块--支付订单") public R<Map<String, Object>> payOrder(@RequestBody TCourseOrder courseOrder) { String userId = tokenService.getLoginUserApplet().getUserId(); TAppUser appUser = appUserService.getById(userId); TCourseOrder courseOrder1 = courseOrderService.getById(courseOrder.getId()); if(!userId.equals(courseOrder1.getAppUserId())){ return R.fail("无权限操作"); } courseOrder1.setOrderNumber(OrderNos.getDid()); courseOrderService.updateById(courseOrder1); Map<String, Object> result = wxV3Pay.jsApi(courseOrder1.getOrderNumber(), courseOrder1.getPayMoney().multiply(BigDecimal.valueOf(100)).longValue(), appUser.getOpenId(),"购买课程",""); return R.ok(result); } @PostMapping("/refundOrder") @ApiOperation(value = "课程模块--退款") public R<?> refundOrder(@RequestBody TCourseOrder courseOrder) { String userId = tokenService.getLoginUserApplet().getUserId(); TCourseOrder courseOrder1 = courseOrderService.getById(courseOrder.getId()); courseOrder1.setRefundReason(courseOrder.getRefundReason()); courseOrder1.setRefundReasonPictures(courseOrder.getRefundReasonPictures()); courseOrder1.setPayStatus(6); courseOrder1.setRequestRefundTime(LocalDateTime.now()); courseOrder1.setRefundMoney(courseOrder1.getPayMoney()); if(!userId.equals(courseOrder1.getAppUserId())){ return R.fail("无权限操作"); } if(courseOrder1.getPayStatus()!=2){ return R.fail("状态不允许退款"); } LocalDateTime payTime = courseOrder1.getPayTime(); if(payTime==null){ return R.fail("状态不允许退款"); } if(payTime.plusDays(2).isBefore(LocalDateTime.now())){ courseOrder1.setBankCardNumber(courseOrder.getBankCardNumber()); courseOrder1.setCardholderName(courseOrder.getCardholderName()); courseOrder1.setBankName(courseOrder.getBankName()); courseOrder1.setRefundStatus(1); courseOrderService.updateById(courseOrder1); }else { WxPaymentRefundModel refundModel = new WxPaymentRefundModel(); refundModel.setSub_mchid(weixinPayProperties.getMchId()); refundModel.setSp_appid(weixinPayProperties.getAppId()); refundModel.setTransaction_id(courseOrder1.getTransactionId()); refundModel.setOut_trade_no(courseOrder1.getOrderNumber()); refundModel.setOut_refund_no(OrderNos.getDid()); refundModel.setReason(courseOrder1.getRefundReason()); refundModel.setNotify_url(""); refundModel.setFunds_account("AVAILABLE"); refundModel.setAmount(new WxPaymentRefundModel.RefundAmount(courseOrder1.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue(), "CNY", courseOrder1.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue())); Map<String, Object> refund = wxV3Pay.refund(refundModel); } return R.ok(); } } ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxPayController.java
@@ -1,24 +1,35 @@ package com.ruoyi.web.controller.api; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.fasterxml.jackson.core.type.TypeReference; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.CodeGenerateUtils; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.model.TCourseOrder; import com.ruoyi.system.service.TCourseOrderService; import com.ruoyi.system.wxPay.enums.RefundEnum; import com.ruoyi.system.wxPay.enums.TradeStateEnum; import com.ruoyi.system.wxPay.model.WeixinPayProperties; import com.ruoyi.system.wxPay.utils.WxTimeUtils; import com.ruoyi.system.wxPay.utils.WxV3Pay; import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.formula.functions.T; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Objects; /** * 微信相关接口 @@ -36,35 +47,10 @@ @Autowired private WeixinPayProperties weixinPayProperties; @Autowired private TCourseOrderService courseOrderService; /** * 按实际修改 */ @ApiOperation("订单支付") @PostMapping("orderPay") public R<Map<String, Object>> orderPay(@RequestParam(value = "inspectionId") String inspectionId) { // TSysOtherConfig sysOtherConfig = sysOtherConfigService.getById(1); // if (Objects.isNull(sysOtherConfig.getAiPrice())) { // return R.fail("系统未配置AI支付价格"); // } // // String userId = tokenService.getLoginUserApplet().getUserId(); // TSysAppUser sysAppUser = sysAppUserService.getById(userId); // // 价格 // Long totalPrice = sysOtherConfig.getAiPrice().multiply(new BigDecimal(100)).longValue(); // // 生成订单号 // String orderNo = CodeGenerateUtils.generateOrderSn(); // // 查询用户信息 用户openid // String openId = sysAppUser.getOpenId(); // // 存储支付记录 // sysPayRecordService.saveData(orderNo, userId, sysOtherConfig.getAiPrice(), 1); // // 调用支付方法 // Map<String, Object> result = wxV3Pay.jsApi(orderNo, totalPrice, openId,"AI检测报告支付",""); // log.info("支付参数:{}", result); return R.ok(); } /** * 支付回调 @@ -94,20 +80,16 @@ String trade_state = jsonInfo.getString("trade_state"); String success_time = jsonInfo.getString("success_time"); // 查询订单 // TSysPayRecord sysPayRecord = sysPayRecordService.getOne(Wrappers.lambdaQuery(TSysPayRecord.class) // .eq(TSysPayRecord::getOrderNo, out_trade_no).last("LIMIT 1")); TCourseOrder order = courseOrderService.getOne(Wrappers.lambdaQuery(TCourseOrder.class) .eq(TCourseOrder::getOrderNumber, out_trade_no).last("LIMIT 1")); if (trade_state.equals(TradeStateEnum.SUCCESS.name())) { log.info("回调成功"); // 订单号查询订单 // sysPayRecord.setPayState(2); // sysPayRecord.setPayTime(WxTimeUtils.dateToLocalDateTime(WxTimeUtils.toRfc3339Date(success_time))); // sysPayRecord.setTransactionId(transaction_id); // sysPayRecordService.updateById(sysPayRecord); // // // 处理检测报告为可见 // TSysInspection sysInspection = sysInspectionService.getById(sysPayRecord.getInspectionId()); // sysInspection.setIsPay(1); // sysInspectionService.updateById(sysInspection); order.setPayStatus(2); order.setPayTime(WxTimeUtils.dateToLocalDateTime(WxTimeUtils.toRfc3339Date(success_time))); order.setTransactionId(transaction_id); courseOrderService.updateById(order); PrintWriter out = response.getWriter(); out.print("SUCCESS"); @@ -119,4 +101,54 @@ wxV3Pay.ack(false, e.getMessage()); } } /** * 退款回调 */ // @PostMapping("refund/notify") // @ApiOperation("退款回调") // public void refundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { // try { //// System.err.println("微信回调"); //// BufferedReader reader = request.getReader(); //// StringBuilder requestBody = new StringBuilder(); //// String line; //// while ((line = reader.readLine()) != null) { //// requestBody.append(line); //// } //// System.err.println("全部请求体" + requestBody); //// JSONObject jsonObject = JSONObject.parseObject(requestBody.toString()); //// JSONObject resource = jsonObject.getJSONObject("resource"); //// AesUtil aesUtil = new AesUtil(weixinPayProperties.getV3().getApiKey().getBytes(StandardCharsets.UTF_8)); //// String decryptedData = aesUtil.decryptToString(resource.getString("associated_data").getBytes(StandardCharsets.UTF_8), resource.getString("nonce").getBytes(StandardCharsets.UTF_8), resource.getString("ciphertext")) // } // } @PostMapping("refund/notify") public void refundNotify(HttpServletRequest request) throws IOException { try { Map<String, Object> params = wxV3Pay.verifyNotify(request, new TypeReference<Map<String, Object>>() { }); // 商户订单号 String out_trade_no = params.get("out_trade_no").toString(); // 商户退款单号 String out_refund_no = params.get("out_refund_no").toString(); // 退款状态 String tradeState = params.get("refund_status").toString(); // 微信支付订单号 String transaction_id = params.get("transaction_id").toString(); if (tradeState.equals(RefundEnum.SUCCESS.name())) { TCourseOrder order = courseOrderService.getOne(Wrappers.lambdaQuery(TCourseOrder.class) .eq(TCourseOrder::getRefundNumber, out_refund_no).last("LIMIT 1")); order.setPayStatus(3); order.setRefundStatus(2); order.setRefundTransactionId(transaction_id); courseOrderService.updateById(order); wxV3Pay.ack(); } }catch (Exception e){ wxV3Pay.ack(false, "不是成功的退款状态"); } } } ruoyi-system/src/main/java/com/ruoyi/system/model/TCourse.java
@@ -66,4 +66,8 @@ @TableField("status") private Integer status; @ApiModelProperty(value = "已经报名人数") @TableField(exist = false) private Integer signUpNum; } ruoyi-system/src/main/java/com/ruoyi/system/model/TCourseOrder.java
@@ -72,7 +72,7 @@ @TableField("id_card") private String idCard; @ApiModelProperty(value = "支付状态 1=待支付 2=已支付 3=已退款") @ApiModelProperty(value = "支付状态 1=待支付 2=已支付 3=已退款 4=已取消 5=已完成") @TableField("pay_status") private Integer payStatus; ruoyi-system/src/main/java/com/ruoyi/system/query/CourseOrderListQuery.java
New file @@ -0,0 +1,13 @@ package com.ruoyi.system.query; import com.ruoyi.common.core.domain.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("课程订单Query") public class CourseOrderListQuery extends BasePage { @ApiModelProperty("支付状态 1=待支付 2=已支付 3=已退款 4=已取消 5=已完成") private Integer payStatus; } ruoyi-system/src/main/java/com/ruoyi/system/query/GetCourseListQuery.java
New file @@ -0,0 +1,17 @@ package com.ruoyi.system.query; import com.ruoyi.common.core.domain.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("课程查询query") public class GetCourseListQuery extends BasePage { @ApiModelProperty("课程类型 1=社区大学课程 2=暑期青少年工艺培训班") private Integer courseType; @ApiModelProperty("课程名称") private String courseTitle; } ruoyi-system/src/main/java/com/ruoyi/system/task/base/AbstractJob.java
@@ -5,10 +5,7 @@ import com.ruoyi.system.model.TDeliberationVote; import com.ruoyi.system.model.TQuestionnaire; import com.ruoyi.system.model.TQuestionnaireStem; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.TCommunityActivityService; import com.ruoyi.system.service.TDeliberationVoteService; import com.ruoyi.system.service.TQuestionnaireService; import com.ruoyi.system.service.*; import com.ruoyi.system.task.utils.SpringContextsUtil; import org.quartz.Job; import org.quartz.JobExecutionContext; @@ -28,11 +25,14 @@ protected TCommunityActivityService communityActivityService; protected TQuestionnaireService questionnaireService; protected TCourseOrderService courseOrderService; public AbstractJob(){ this.sysUserService = SpringContextsUtil.getBean(ISysUserService.class); this.redisCache = SpringContextsUtil.getBean(RedisCache.class); this.deliberationVoteService = SpringContextsUtil.getBean(TDeliberationVoteService.class); this.questionnaireService = SpringContextsUtil.getBean(TQuestionnaireService.class); this.courseOrderService = SpringContextsUtil.getBean(TCourseOrderService.class); } ruoyi-system/src/main/java/com/ruoyi/system/task/base/TimeJobType.java
@@ -5,8 +5,7 @@ * @date 2025年2月17日 下午7:22:28 */ public enum TimeJobType { DELIBERATION_VOTE_PUSH("deliberation_vote_push","议事投票"), ACTIVITY_PUSH("activity_push","社区活动"), CANCEL_ORDER("cancel_order","取消订单"), QUESTIONNAIRE_PUSH("questionnaire_push","问卷调查"); private String type; private String desc; ruoyi-system/src/main/java/com/ruoyi/system/task/jobs/OrderJob.java
New file @@ -0,0 +1,33 @@ package com.ruoyi.system.task.jobs; import com.ruoyi.system.model.TCourseOrder; import com.ruoyi.system.task.base.AbstractJob; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * 订单定时任务 * @author Administrator * */ public class OrderJob extends AbstractJob { public static final String name = "cancel_order"; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap maps = context.getMergedJobDataMap(); String id = maps.getString("id"); try { TCourseOrder tCourseOrder = courseOrderService.getById(id); if(tCourseOrder.getPayStatus()==1){ tCourseOrder.setPayStatus(4); courseOrderService.updateById(tCourseOrder); } }catch(Exception e){ e.printStackTrace(); } } }