diff --git a/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java b/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java index feceec6a..f4aaa2e2 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java @@ -14,8 +14,6 @@ import org.springframework.scheduling.annotation.EnableScheduling; */ @SpringBootApplication @MapperScan("com.cdzy.payment.mapper") -//引入Spring Task -@EnableScheduling public class EbikePaymentApplication { public static void main(String[] args) { SpringApplication.run(EbikePaymentApplication.class, args); diff --git a/ebike-payment/src/main/java/com/cdzy/payment/config/ScheduledTaskConfig.java b/ebike-payment/src/main/java/com/cdzy/payment/config/ScheduledTaskConfig.java new file mode 100644 index 00000000..59eed4d1 --- /dev/null +++ b/ebike-payment/src/main/java/com/cdzy/payment/config/ScheduledTaskConfig.java @@ -0,0 +1,48 @@ +package com.cdzy.payment.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +/** + * 作业调度配置 + * + * @author dingchao + * @date 2025/5/2 + * @modified by: + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "task-scheduler-pool") +public class ScheduledTaskConfig { + /** + * 线程池大小 + */ + private int poolSize; + /** + * 线程名称前缀 + */ + private String threadNamePrefix; + /** + * 等待任务在关闭时完成 + */ + private boolean waitForTasksToCompleteOnShutdown; + /** + * 等待终止的秒数 + */ + private int awaitTerminationSeconds; + + + @Bean + public ThreadPoolTaskScheduler threadPoolTaskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setPoolSize(poolSize); + taskScheduler.setThreadNamePrefix(threadNamePrefix); + taskScheduler.setWaitForTasksToCompleteOnShutdown(waitForTasksToCompleteOnShutdown); + taskScheduler.setAwaitTerminationSeconds(awaitTerminationSeconds); + taskScheduler.initialize(); + return taskScheduler; + } +} diff --git a/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java b/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java index e6d0ea68..c071b9c4 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java @@ -7,7 +7,6 @@ import com.wechat.pay.java.core.util.PemUtil; import com.wechat.pay.java.service.payments.jsapi.JsapiService; import com.wechat.pay.java.service.refund.RefundService; import lombok.Data; -import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,7 +20,6 @@ import java.security.PrivateKey; * @date 2025/4/24 * @modified by: */ -@Slf4j @Data @Configuration @ConfigurationProperties(prefix = "payment.wx-pay") diff --git a/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPayNotifyController.java b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPayNotifyController.java new file mode 100644 index 00000000..86117fae --- /dev/null +++ b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPayNotifyController.java @@ -0,0 +1,75 @@ +package com.cdzy.payment.controller; + +import com.alibaba.fastjson2.JSONObject; +import com.cdzy.payment.model.dto.HandleNotifyResult; +import com.cdzy.payment.service.WxPayService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 微信支付通知回调接口 + *
通知接口不能鉴权 + * + * @author dingchao + * @date 2025/5/6 + * @modified by: + */ +@RestController +@RequestMapping("/wxPayment/notify") +public class EbikeWxPayNotifyController { + + @Resource + private WxPayService wxPayService; + + /** + * 支付回调通知 + * + * @param request 支付回调请求 + * @param response 支付回调响应 + * @return 支付回调响应 + */ + @PostMapping("/pay") + public String payNotify(HttpServletRequest request, HttpServletResponse response) { + HandleNotifyResult r = wxPayService.handlePayNotify(request); + if(!r.isSuccess()) { + response.setStatus(500); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", "SYSTEM_ERROR"); + jsonObject.put("message", r.getMessage()); + return jsonObject.toJSONString(); + } + response.setStatus(200); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", "SUCCESS"); + jsonObject.put("message", "OK"); + return jsonObject.toJSONString(); + } + + /** + * 退款回调通知 + * + * @param request 退款回调请求 + * @param response 退款回调响应 + * @return 退款回调响应 + */ + @PostMapping("/refund") + public String refundNotify(HttpServletRequest request, HttpServletResponse response) { + HandleNotifyResult r = wxPayService.handleRefundNotify(request); + if(!r.isSuccess()) { + response.setStatus(500); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", "SYSTEM_ERROR"); + jsonObject.put("message", r.getMessage()); + return jsonObject.toJSONString(); + } + response.setStatus(200); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("code", "SUCCESS"); + jsonObject.put("message", "OK"); + return jsonObject.toJSONString(); + } +} diff --git a/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java index cd9dd9ed..39b2f200 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java @@ -17,9 +17,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - /** * 用户订单微信支付 控制层。 * @@ -106,55 +103,4 @@ public class EbikeWxPaymentController { return r == null?JsonResult.failed(String.format("退款单号{%s}查询退款失败", outRefundNo)):JsonResult.success(r); } - - - // ================通知回调接口=============== - // TODO 通知接口不能鉴权 - /** - * 支付回调通知 - * - * @param request 支付回调请求 - * @param response 支付回调响应 - * @return 支付回调响应 - */ - @PostMapping("/pay/notify") - public String payNotify(HttpServletRequest request, HttpServletResponse response) { - HandleNotifyResult r = wxPayService.handlePayNotify(request); - if(!r.isSuccess()) { - response.setStatus(500); - JSONObject jsonObject = new JSONObject(); - jsonObject.put("code", "SYSTEM_ERROR"); - jsonObject.put("message", r.getMessage()); - return jsonObject.toJSONString(); - } - response.setStatus(200); - JSONObject jsonObject = new JSONObject(); - jsonObject.put("code", "SUCCESS"); - jsonObject.put("message", "OK"); - return jsonObject.toJSONString(); - } - - /** - * 退款回调通知 - * - * @param request 退款回调请求 - * @param response 退款回调响应 - * @return 退款回调响应 - */ - @PostMapping("/refund/notify") - public String refundNotify(HttpServletRequest request, HttpServletResponse response) { - HandleNotifyResult r = wxPayService.handleRefundNotify(request); - if(!r.isSuccess()) { - response.setStatus(500); - JSONObject jsonObject = new JSONObject(); - jsonObject.put("code", "SYSTEM_ERROR"); - jsonObject.put("message", r.getMessage()); - return jsonObject.toJSONString(); - } - response.setStatus(200); - JSONObject jsonObject = new JSONObject(); - jsonObject.put("code", "SUCCESS"); - jsonObject.put("message", "OK"); - return jsonObject.toJSONString(); - } } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/task/ScheduledTaskManager.java b/ebike-payment/src/main/java/com/cdzy/payment/task/ScheduledTaskManager.java new file mode 100644 index 00000000..3fa11b05 --- /dev/null +++ b/ebike-payment/src/main/java/com/cdzy/payment/task/ScheduledTaskManager.java @@ -0,0 +1,69 @@ +package com.cdzy.payment.task; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.stereotype.Component; + +/** + * 定时作业调度器。 + * + * @author dingchao + * @date 2025/5/2 + * @modified by: + */ +@Slf4j +@Component +public class ScheduledTaskManager { + // 每隔30秒执行1次 + private final static String CRON_EXPRESSION = "0/30 * * * *?"; + + // @Scheduled任务线程默认串行执行,需要考虑并发问题 + @Resource + private ThreadPoolTaskScheduler threadPoolTaskScheduler; + @Resource + private WsPayTask wxPayTask; + + @PostConstruct + public void init() { + // 启动定时任务 + // 1. 每隔30秒执行1次,查询创建未超过5分钟,并且未支付的订单 + threadPoolTaskScheduler.schedule(new Runnable() { + @Override + public void run() { + try { + wxPayTask.checkOrderStatus(); + }catch (Exception e) { + log.error("checkOrderStatus 执行异常", e); + } + } + }, new CronTrigger(CRON_EXPRESSION)); + + // 2. 每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单 + threadPoolTaskScheduler.schedule(new Runnable() { + @Override + public void run() { + try { + wxPayTask.closeOrder(); + } catch (Exception e) { + log.error("closeOrder 执行异常", e); + } + } + }, new CronTrigger(CRON_EXPRESSION)); + + // 3. 每隔30秒执行1次,查询创建未超过5分钟,并且未成功的退款单 + threadPoolTaskScheduler.schedule(new Runnable() { + @Override + public void run() { + try { + wxPayTask.checkRefundStatus(); + } catch (Exception e) { + log.error("checkRefundStatus 执行异常", e); + } + } + }, new CronTrigger(CRON_EXPRESSION)); + } + +} diff --git a/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java b/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java index 05d3391c..3a0e0dc2 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java @@ -8,11 +8,9 @@ import com.cdzy.payment.service.EbikeRefundService; import com.cdzy.payment.service.WxPayService; import com.wechat.pay.java.service.payments.model.Transaction; import com.wechat.pay.java.service.refund.model.Refund; -import com.wechat.pay.java.service.refund.model.Status; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import java.util.List; @@ -24,7 +22,7 @@ import java.util.List; * @modified by: */ @Slf4j -@Component +@Service public class WsPayTask { @Resource @@ -36,11 +34,10 @@ public class WsPayTask { @Resource private EbikeRefundService ebikeRefundService; - // TODO @Scheduled任务线程默认串行执行,需要考虑并发问题 + /** - * 每隔30秒执行1次,查询创建未超过5分钟,并且未支付的订单 + * 查询创建未超过5分钟,并且未支付的订单 */ - @Scheduled(cron = "0/30 * * * * ?") public void checkOrderStatus() throws Exception { log.info("checkOrderStatus 执行......"); // 1. 查询未支付的订单 @@ -57,9 +54,8 @@ public class WsPayTask { } /** - * 每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单 + * 查询创建超过5分钟,并且未支付的订单 */ - @Scheduled(cron = "0/30 * * * * ?") public void closeOrder() throws Exception { log.info("closeOrder 执行......"); // 1. 查询未支付的超时订单 @@ -80,9 +76,8 @@ public class WsPayTask { } /** - * 每隔30秒执行1次,查询创建未超过5分钟,并且未成功的退款单 + * 查询创建未超过5分钟,并且未成功的退款单 */ - @Scheduled(cron = "0/30 * * * * ?") public void checkRefundStatus() throws Exception { log.info("checkRefundStatus 执行......"); diff --git a/ebike-payment/src/main/resources/application-dev.yml b/ebike-payment/src/main/resources/application-dev.yml index 5d484368..d50448d7 100644 --- a/ebike-payment/src/main/resources/application-dev.yml +++ b/ebike-payment/src/main/resources/application-dev.yml @@ -41,3 +41,8 @@ payment: pay-notify_url: http://192.168.2.156:10017/wxPayment/pay-notify refund-notify_url: http://192.168.2.156:10017/wxPayment/refund-notify expire-minutes: 5 +task-scheduler-pool: + poolSize: 100 + threadNamePrefix: task-scheduled- + waitForTasksToCompleteOnShutdown: true + awaitTerminationSeconds: 30 \ No newline at end of file