mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-02 10:36:57 +00:00
perf 消息通知功能调试和流水记录
This commit is contained in:
16
README.md
16
README.md
@@ -15,10 +15,11 @@
|
||||
> DaxPay是一套基于Bootx-Platform脚手架构建的开源支付网关系统,已经对接支付宝、微信支付相关的接口,以及扩展了钱包支付、储值卡支付、现金支付等新的支付方式。
|
||||
> 可以独立部署,提供接口供业务系统进行调用,不对原有系统产生影响
|
||||
|
||||
> 当前处于功能开发阶段,部分功能可能会有调整,`V2.1.0`时将作为正式生产可用版本进行发布,之后会保证系统版本非大版本升级时,API接口和数据接口向前兼容
|
||||
|
||||
## 🧭 特色功能
|
||||
- 封装各类支付通道的接口为统一的接口,方便业务系统进行调用,简化对接多种支付方式的复杂度
|
||||
- 已对接`微信支付`相关的接口,目前已经支持`V2`版本的接口,后续版本将支持`V3`版本的接口
|
||||
- 已对接`支付宝`相关的接口,目前已经支持`V2`版本的接口,后续版本将支持`V3`版本的接口
|
||||
- 已对接`微信支付`和`支付宝`相关的接口,目前已经支持`V2`版本的接口,后续版本将支持`V3`版本的接口
|
||||
- 支持组合支付,满足用户系统需要多种方式同时进行支付的场景。
|
||||
- 提供`HTTP`方式接口调用能力,和`Java`版本的`SDK`,方便业务系统进行对接
|
||||
- 接口请求和响应数据支持启用签名机制,可根据实际需要进行开关,保证交易安全可靠
|
||||
@@ -162,17 +163,10 @@ public class SimplePayOrderTest {
|
||||
|
||||
### 2.0.X版本:
|
||||
- [ ] 对账比对功能实现
|
||||
- [ ] 支持转账操作
|
||||
- [ ] 支持转账、分账操作
|
||||
- [ ] 云闪付支付支持
|
||||
- [ ] 微信增加V3版本接口支持
|
||||
- [ ] 支付宝增加V3版本接口支持
|
||||
- [x] 钱包功能完善
|
||||
- [x] 储值卡功能完善
|
||||
- [x] 现金支付功能完善
|
||||
- [ ] 支付流水记录功能
|
||||
- [ ] 支付宝和微信增加V3版本接口支持
|
||||
- [ ] 消息通知支持消息中间件模式
|
||||
- [ ] 增加验签调试等功能的页面
|
||||
- [ ] 支付宝进行关闭时,支持通过撤销模式进行订单关闭
|
||||
|
||||
### 2.1.X版本:
|
||||
- [ ] 增加账户金额表
|
||||
|
@@ -1,6 +1,17 @@
|
||||
# CHANGELOG
|
||||
## [v2.0.1]
|
||||
- 增加支付、退款时客户通知功能,支持多次重发
|
||||
- 增加客户通知任务记录功能
|
||||
- 支持钱包支付、流水记录、各类操作等功能
|
||||
- 支持储值卡支付、流水记录、各类操作等功能
|
||||
- 支持现金支付和流水记录功能
|
||||
- 增加支付宝流水记录功能
|
||||
- 增加微信流水记录功能
|
||||
- 变更:废弃调用接口时的`version`字段,调用时不再进行传输,SDK中同步进行删除
|
||||
- 优化:订单支持关闭时间记录
|
||||
- 优化:增加退款订单扩展记录
|
||||
- fix: 同步支付通道订单不能正确生成
|
||||
|
||||
## [v2.0.0]
|
||||
- 支持支付宝支付:扫码支付、付款码支付、PC支付、H5支付
|
||||
- 支持微信支付:扫码支付、WAP支付、公众号支付
|
||||
|
@@ -4,6 +4,10 @@
|
||||
- [x] 钱包支付, 钱包流水
|
||||
- [x] 储值卡支付, 储值卡流水
|
||||
- [ ] 支付回调通知和退款回调通知功能
|
||||
- [x] 回调任务发起
|
||||
- [ ] 回调调用记录
|
||||
- [x] SDK接收对象编写
|
||||
- [ ] Demo模块接收回调演示
|
||||
- [x] 通道配置启用停用配置生效
|
||||
- [x] 支付对账的序列化生成器有问题,待platform更新
|
||||
|
||||
|
@@ -0,0 +1,59 @@
|
||||
package cn.bootx.platform.daxpay.demo.controller;
|
||||
|
||||
import cn.bootx.platform.common.core.annotation.IgnoreAuth;
|
||||
import cn.bootx.platform.daxpay.sdk.model.notice.PayNoticeModel;
|
||||
import cn.bootx.platform.daxpay.sdk.model.notice.RefundNoticeModel;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/24
|
||||
*/
|
||||
@Slf4j
|
||||
@IgnoreAuth
|
||||
@Tag(name = "回调测试")
|
||||
@RestController
|
||||
@RequestMapping("/demo/callback")
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeReceiveController {
|
||||
|
||||
@Operation(summary = "支付消息(map接收)")
|
||||
@PostMapping("/pay")
|
||||
public String pay(@RequestBody Map<String,Object> map){
|
||||
log.info("接收到支付回调消息: {}",map);
|
||||
return "SUCCESS";
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "支付消息(对象接收)")
|
||||
@PostMapping("/payObject")
|
||||
public String pay(@RequestBody PayNoticeModel model){
|
||||
log.info("接收到支付回调消息: {}",model);
|
||||
return "SUCCESS";
|
||||
}
|
||||
|
||||
@Operation(summary = "退款消息")
|
||||
@PostMapping("/refund")
|
||||
public String refund(@RequestBody Map<String,Object> map) {
|
||||
log.info("接收到退款回调消息: {}",map);
|
||||
return "SUCCESS";
|
||||
}
|
||||
|
||||
@Operation(summary = "退款消息()")
|
||||
@PostMapping("/refundObject")
|
||||
public String refund(@RequestBody RefundNoticeModel map) {
|
||||
log.info("接收到退款回调消息: {}",map);
|
||||
return "SUCCESS";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.bootx.platform.daxpay.sdk.model.notice;
|
||||
|
||||
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.sdk.code.PayWayEnum;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 支付通道信息
|
||||
* @author xxm
|
||||
* @since 2024/1/7
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class PayChannelModel {
|
||||
/**
|
||||
* 支付通道编码
|
||||
* @see PayChannelEnum#getCode()
|
||||
*/
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 支付方式编码
|
||||
* @see PayWayEnum
|
||||
*/
|
||||
private String way;
|
||||
|
||||
/** 支付金额 */
|
||||
private Integer amount;
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package cn.bootx.platform.daxpay.sdk.model.notice;
|
||||
|
||||
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.sdk.code.PayStatusEnum;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 支付异步通知类
|
||||
* @author xxm
|
||||
* @since 2024/1/7
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class PayNoticeModel {
|
||||
|
||||
/** 支付ID */
|
||||
private Long paymentId;
|
||||
|
||||
/** 业务号 */
|
||||
private String businessNo;
|
||||
|
||||
/** 是否是异步支付 */
|
||||
private boolean asyncPay;
|
||||
|
||||
/**
|
||||
* 异步支付通道
|
||||
* @see PayChannelEnum
|
||||
*/
|
||||
private String asyncChannel;
|
||||
|
||||
/** 支付金额 */
|
||||
private Integer amount;
|
||||
|
||||
/** 支付通道信息 */
|
||||
private List<PayChannelModel> payChannels;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/** 支付创建时间 */
|
||||
private Long createTime;
|
||||
|
||||
/** 支付成功时间 */
|
||||
private Long payTime;
|
||||
|
||||
/** 支付关闭时间 */
|
||||
private Long closeTime;
|
||||
|
||||
/** 商户扩展参数,回调时会原样返回 */
|
||||
private String attach;
|
||||
|
||||
/** 签名 */
|
||||
private String sign;
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package cn.bootx.platform.daxpay.sdk.model.notice;
|
||||
|
||||
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 退款通道信息
|
||||
* @author xxm
|
||||
* @since 2024/2/22
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class RefundChannelModel {
|
||||
|
||||
/**
|
||||
* 通道编码
|
||||
* @see PayChannelEnum#getCode()
|
||||
*/
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 退款金额
|
||||
*/
|
||||
private Integer amount;
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
package cn.bootx.platform.daxpay.sdk.model.notice;
|
||||
|
||||
import cn.bootx.platform.daxpay.sdk.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.sdk.code.RefundStatusEnum;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 退款通知消息
|
||||
* @author xxm
|
||||
* @since 2024/2/22
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class RefundNoticeModel {
|
||||
|
||||
/** 退款ID */
|
||||
private Long refundId;
|
||||
|
||||
/** 退款号 */
|
||||
private String refundNo;
|
||||
|
||||
/** 是否含有异步通道 */
|
||||
private boolean asyncPay;
|
||||
|
||||
/**
|
||||
* 异步通道
|
||||
* @see PayChannelEnum
|
||||
*/
|
||||
private String asyncChannel;
|
||||
|
||||
/** 退款金额 */
|
||||
private Integer amount;
|
||||
|
||||
/** 退款通道信息 */
|
||||
private List<RefundChannelModel> refundChannels;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
* @see RefundStatusEnum
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/** 退款成功时间 */
|
||||
private Long refundTime;
|
||||
|
||||
/** 退款创建时间 */
|
||||
private Long createTime;
|
||||
|
||||
/** 商户扩展参数,回调时会原样返回 */
|
||||
private String attach;
|
||||
|
||||
/** 签名 */
|
||||
private String sign;
|
||||
}
|
@@ -67,7 +67,6 @@ public class DaxPayKit {
|
||||
}
|
||||
String body = execute.body();
|
||||
|
||||
|
||||
log.debug("响应参数:{}", body);
|
||||
return request.toModel(body);
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ import cn.bootx.platform.daxpay.sdk.net.DaxPayConfig;
|
||||
import cn.bootx.platform.daxpay.sdk.net.DaxPayKit;
|
||||
import cn.bootx.platform.daxpay.sdk.param.pay.SimplePayParam;
|
||||
import cn.bootx.platform.daxpay.sdk.response.DaxPayResult;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -27,6 +28,9 @@ public class SimplePayOrderTest {
|
||||
DaxPayKit.initConfig(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步通道测试
|
||||
*/
|
||||
@Test
|
||||
public void simplePay() {
|
||||
// 简单支付参数
|
||||
@@ -44,4 +48,24 @@ public class SimplePayOrderTest {
|
||||
PayOrderModel data = execute.getData();
|
||||
System.out.println(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步通道+回调测试
|
||||
*/
|
||||
@Test
|
||||
public void simplePayCallback() {
|
||||
SimplePayParam param = new SimplePayParam();
|
||||
param.setBusinessNo("P"+ RandomUtil.randomNumbers(5));
|
||||
param.setAmount(12);
|
||||
param.setTitle("测试接口支付");
|
||||
param.setChannel(PayChannelEnum.CASH.getCode());
|
||||
param.setPayWay(PayWayEnum.NORMAL.getCode());
|
||||
param.setClientIp("127.0.0.1");
|
||||
param.setNotifyUrl("http://127.0.0.1:9000/demo/callback/pay");
|
||||
param.setNotifyUrl("http://127.0.0.1:9000/demo/callback/payObject");
|
||||
DaxPayResult<PayOrderModel> execute = DaxPayKit.execute(param);
|
||||
System.out.println(execute);
|
||||
PayOrderModel data = execute.getData();
|
||||
System.out.println(data);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,64 @@
|
||||
package cn.bootx.platform.daxpay.admin.controller.task;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.PageResult;
|
||||
import cn.bootx.platform.common.core.rest.Res;
|
||||
import cn.bootx.platform.common.core.rest.ResResult;
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.service.ClientNoticeTaskService;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeRecordDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeTaskDto;
|
||||
import cn.bootx.platform.daxpay.service.param.record.ClientNoticeRecordQuery;
|
||||
import cn.bootx.platform.daxpay.service.param.record.ClientNoticeTaskQuery;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 客户通知任务
|
||||
* @author xxm
|
||||
* @since 2024/2/24
|
||||
*/
|
||||
@Tag(name = "客户系统通知任务")
|
||||
@RestController
|
||||
@RequestMapping("/task/notice")
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeTaskController {
|
||||
private final ClientNoticeTaskService clientNoticeTaskService;
|
||||
|
||||
|
||||
@Operation(summary = "重新发送消息通知")
|
||||
@PostMapping("/resetSend")
|
||||
public ResResult<Void> resetSend(Long taskId){
|
||||
clientNoticeTaskService.sendData(taskId);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "分页查询")
|
||||
@GetMapping("/page")
|
||||
public ResResult<PageResult<ClientNoticeTaskDto>> page(PageParam pageParam, ClientNoticeTaskQuery query){
|
||||
return Res.ok(clientNoticeTaskService.taskPage(pageParam, query));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询单条")
|
||||
@GetMapping("/findById")
|
||||
public ResResult<ClientNoticeTaskDto> findById(Long id){
|
||||
return Res.ok(clientNoticeTaskService.findTaskById(id));
|
||||
}
|
||||
@Operation(summary = "分页查询")
|
||||
@GetMapping("/record/page")
|
||||
public ResResult<PageResult<ClientNoticeRecordDto>> recordPage(PageParam pageParam, ClientNoticeRecordQuery query){
|
||||
return Res.ok(clientNoticeTaskService.recordPage(pageParam, query));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询单条")
|
||||
@GetMapping("/record/findById")
|
||||
public ResResult<ClientNoticeRecordDto> findRecordById(Long id){
|
||||
return Res.ok(clientNoticeTaskService.findRecordById(id));
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package cn.bootx.platform.daxpay.service.code;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 消息通知发送类型
|
||||
* @author xxm
|
||||
* @since 2024/2/25
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ClientNoticeSendTypeEnum {
|
||||
/** 自动发送 */
|
||||
AUTO("auto", "自动发送"),
|
||||
/** 手动发送 */
|
||||
MANUAL("manual", "手动发送");
|
||||
|
||||
private final String type;
|
||||
private final String name;
|
||||
|
||||
}
|
@@ -1,10 +1,14 @@
|
||||
package cn.bootx.platform.daxpay.service.common.context;
|
||||
|
||||
import cn.bootx.platform.daxpay.code.PayWayEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 异步支付信息
|
||||
@@ -13,7 +17,7 @@ import java.time.LocalDateTime;
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AsyncPayLocal {
|
||||
public class PayLocal {
|
||||
|
||||
/**
|
||||
* 异步支付方式
|
||||
@@ -36,4 +40,13 @@ public class AsyncPayLocal {
|
||||
/** 订单失效时间, */
|
||||
private LocalDateTime expiredTime;
|
||||
|
||||
/** 支付订单 */
|
||||
private PayOrder payOrder;
|
||||
|
||||
/** 支付订单扩展 */
|
||||
private PayOrderExtra payOrderExtra;
|
||||
|
||||
/** 通道支付订单 */
|
||||
private List<PayChannelOrder> payChannelOrders;
|
||||
|
||||
}
|
@@ -18,8 +18,8 @@ public class PaymentContext {
|
||||
/** 平台全局配置 */
|
||||
private final PlatformLocal platformInfo = new PlatformLocal();
|
||||
|
||||
/** 异步支付相关信息 */
|
||||
private final AsyncPayLocal asyncPayInfo = new AsyncPayLocal();
|
||||
/** 支付相关信息 */
|
||||
private final PayLocal payInfo = new PayLocal();
|
||||
|
||||
/** 退款相关信息 */
|
||||
private final RefundLocal refundInfo = new RefundLocal();
|
||||
|
@@ -6,7 +6,7 @@ import cn.bootx.platform.daxpay.param.channel.AliPayParam;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.service.code.AliPayCode;
|
||||
import cn.bootx.platform.daxpay.service.code.AliPayWay;
|
||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.NoticeLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig;
|
||||
@@ -66,7 +66,7 @@ public class AliPayService {
|
||||
Integer amount = payChannelParam.getAmount();
|
||||
String payBody = null;
|
||||
// 异步线程存储
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
// wap支付
|
||||
if (Objects.equals(payChannelParam.getWay(), PayWayEnum.WAP.getCode())) {
|
||||
payBody = this.wapPay(amount, payOrder, alipayConfig);
|
||||
@@ -207,7 +207,7 @@ public class AliPayService {
|
||||
* 付款码支付
|
||||
*/
|
||||
public void barCode(int amount, PayOrder payOrder, AliPayParam aliPayParam, AliPayConfig alipayConfig) {
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
|
||||
AlipayTradePayModel model = new AlipayTradePayModel();
|
||||
model.setSubject(payOrder.getTitle());
|
||||
|
@@ -10,7 +10,7 @@ import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.SyncResult;
|
||||
import cn.bootx.platform.daxpay.service.code.WeChatPayCode;
|
||||
import cn.bootx.platform.daxpay.service.code.WeChatPayWay;
|
||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
@@ -79,7 +79,7 @@ public class WeChatPayService {
|
||||
|
||||
Integer amount = payChannelParam.getAmount();
|
||||
String totalFee = String.valueOf(amount);
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();;
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();;
|
||||
String payBody = null;
|
||||
PayWayEnum payWayEnum = PayWayEnum.findByCode(payChannelParam.getWay());
|
||||
|
||||
@@ -173,7 +173,7 @@ public class WeChatPayService {
|
||||
* 付款码支付
|
||||
*/
|
||||
private void barCode(String amount, PayOrder payment, String authCode, WeChatPayConfig weChatPayConfig) {
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
|
||||
Map<String, String> params = MicroPayModel.builder()
|
||||
.appid(weChatPayConfig.getWxAppId())
|
||||
|
@@ -5,7 +5,7 @@ import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.PayResult;
|
||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.NoticeLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
@@ -37,7 +37,7 @@ public class PayBuilder {
|
||||
public PayOrder buildPayOrder(PayParam payParam) {
|
||||
// 订单超时时间
|
||||
LocalDateTime expiredTime = PaymentContextLocal.get()
|
||||
.getAsyncPayInfo()
|
||||
.getPayInfo()
|
||||
.getExpiredTime();
|
||||
// 计算总价
|
||||
int sumAmount = payParam.getPayChannels().stream()
|
||||
@@ -118,7 +118,7 @@ public class PayBuilder {
|
||||
paymentResult.setStatus(payOrder.getStatus());
|
||||
|
||||
// 设置异步支付参数
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();;
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();;
|
||||
if (StrUtil.isNotBlank(asyncPayInfo.getPayBody())) {
|
||||
paymentResult.setPayBody(asyncPayInfo.getPayBody());
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import cn.bootx.platform.common.core.util.ResultConvertUtil;
|
||||
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
@@ -54,7 +54,7 @@ public class PayChannelOrderService {
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void switchAsyncPayChannel(PayOrder payOrder, PayChannelParam payChannelParam){
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
// 是否支付完成
|
||||
PayStatusEnum payStatus = asyncPayInfo.isPayComplete() ? PayStatusEnum.SUCCESS : PayStatusEnum.PROGRESS;
|
||||
// 判断新发起的
|
||||
|
@@ -1,18 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.notice.dao;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.entity.ClientNoticeTask;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeTaskManager extends BaseManager<ClientNoticeTaskMapper, ClientNoticeTask> {
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.notice.entity;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 消息通知任务记录表
|
||||
* @author xxm
|
||||
* @since 2024/2/20
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ClientNoticeRecord extends MpCreateEntity {
|
||||
}
|
@@ -3,8 +3,10 @@ package cn.bootx.platform.daxpay.service.core.payment.notice.service;
|
||||
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.bootx.platform.common.core.util.CollUtil;
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.common.jackson.util.JacksonUtil;
|
||||
import cn.bootx.platform.common.redis.RedisClient;
|
||||
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeSendTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderExtraManager;
|
||||
@@ -12,24 +14,23 @@ import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundChannelOrderManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderExtraManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.dao.ClientNoticeTaskManager;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.entity.ClientNoticeTask;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.result.PayChannelResult;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.result.PayNoticeResult;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.result.RefundChannelResult;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.result.RefundNoticeResult;
|
||||
import cn.bootx.platform.daxpay.service.core.system.config.entity.PlatformConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.system.config.service.PlatformConfigService;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.dao.ClientNoticeTaskManager;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeRecord;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeTask;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.service.ClientNoticeRecordService;
|
||||
import cn.bootx.platform.daxpay.util.PaySignUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.ContentType;
|
||||
import cn.hutool.http.HttpException;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -43,7 +44,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 消息通知任务服务
|
||||
* 总共会发起15次通知,通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h
|
||||
* 如果失败总共会重新发起15次通知,通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h
|
||||
* @author xxm
|
||||
* @since 2024/2/20
|
||||
*/
|
||||
@@ -56,14 +57,14 @@ public class ClientNoticeService {
|
||||
|
||||
private final PayChannelOrderManager payChannelOrderManager;
|
||||
|
||||
private final RefundOrderExtraManager refundOrderExtraManager;
|
||||
|
||||
private final RefundChannelOrderManager refundChannelOrderManager;
|
||||
|
||||
private final PlatformConfigService configService;
|
||||
|
||||
private final ClientNoticeTaskManager taskManager;
|
||||
|
||||
private final ClientNoticeRecordService recordService;
|
||||
|
||||
private final RedisClient redisClient;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
@@ -129,12 +130,8 @@ public class ClientNoticeService {
|
||||
log.error("注册支付消息通知任务失败,数据错误,订单ID:{}",order.getId());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
// 同时触发一次通知, 如果成功发送, 任务结束
|
||||
this.sendData(task, LocalDateTime.now());
|
||||
} catch (HttpException e) {
|
||||
this.failHandler(task, LocalDateTime.now());
|
||||
}
|
||||
// 同时触发一次通知, 如果成功发送, 任务结束
|
||||
this.sendData(task, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +167,8 @@ public class ClientNoticeService {
|
||||
}
|
||||
return new ClientNoticeTask()
|
||||
.setUrl(orderExtra.getNotifyUrl())
|
||||
.setContent(JSONUtil.toJsonStr(payNoticeResult))
|
||||
// 时间序列化进行了重写
|
||||
.setContent(JacksonUtil.toJson(payNoticeResult))
|
||||
.setType(ClientNoticeTypeEnum.PAY.getType())
|
||||
.setSendCount(0)
|
||||
.setOrderId(order.getId());
|
||||
@@ -209,14 +207,11 @@ public class ClientNoticeService {
|
||||
taskManager.save(task);
|
||||
} catch (Exception e) {
|
||||
log.error("注册退款消息通知任务失败,数据错误,订单ID:{}",order.getId());
|
||||
log.error("错误内容",e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
// 同时触发一次通知, 如果成功发送, 任务结束
|
||||
this.sendData(task, LocalDateTime.now());
|
||||
} catch (HttpException e) {
|
||||
this.failHandler(task, LocalDateTime.now());
|
||||
}
|
||||
// 同时触发一次通知, 如果成功发送, 任务结束
|
||||
this.sendData(task, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,7 +247,8 @@ public class ClientNoticeService {
|
||||
}
|
||||
return new ClientNoticeTask()
|
||||
.setUrl(orderExtra.getNotifyUrl())
|
||||
.setContent(JSONUtil.toJsonStr(payNoticeResult))
|
||||
// 时间序列化进行了重写
|
||||
.setContent(JacksonUtil.toJson(payNoticeResult))
|
||||
.setType(ClientNoticeTypeEnum.PAY.getType())
|
||||
.setSendCount(0)
|
||||
.setOrderId(order.getId());
|
||||
@@ -269,9 +265,9 @@ public class ClientNoticeService {
|
||||
// 发起一个异步任务,
|
||||
for (String taskId : taskIds) {
|
||||
this.run(Long.valueOf(taskId));
|
||||
// 删除Redis中任务
|
||||
redisClient.zremByMembers(KEY,taskId);
|
||||
}
|
||||
// 删除Redis中任务
|
||||
redisClient.zremRangeByScore(KEY, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,16 +281,19 @@ public class ClientNoticeService {
|
||||
throw new RepetitiveOperationException("支付同步处理中,请勿重复操作");
|
||||
}
|
||||
// 查询任务, 进行发送
|
||||
ClientNoticeTask task = taskManager.findById(taskId).orElse(null);
|
||||
ClientNoticeTask task = null;
|
||||
try {
|
||||
task = taskManager.findById(taskId).orElse(null);
|
||||
// 不存在任务直接跳过
|
||||
if (Objects.isNull(task)) {
|
||||
return;
|
||||
}
|
||||
// 已经发送成功则不进行发送
|
||||
if (task.isSuccess()){
|
||||
return;
|
||||
}
|
||||
// 执行发送逻辑
|
||||
this.sendData(task, now);
|
||||
} catch (HttpException e) {
|
||||
//noinspection DataFlowIssue
|
||||
this.failHandler(task, now);
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
@@ -304,17 +303,37 @@ public class ClientNoticeService {
|
||||
* 发送通知数据, 如果失败, 注册下次重发的任务
|
||||
*/
|
||||
private void sendData(ClientNoticeTask task, LocalDateTime now){
|
||||
HttpResponse execute = HttpUtil.createPost(task.getUrl())
|
||||
.body(task.getContent(), ContentType.JSON.getValue())
|
||||
.timeout(5000)
|
||||
.execute();
|
||||
String body = execute.body();
|
||||
// 创建记录
|
||||
ClientNoticeRecord record = new ClientNoticeRecord()
|
||||
.setTaskId(task.getId())
|
||||
.setType(ClientNoticeSendTypeEnum.AUTO.getType())
|
||||
.setReqCount(task.getSendCount()+1);
|
||||
String body = null;
|
||||
try {
|
||||
HttpResponse execute = HttpUtil.createPost(task.getUrl())
|
||||
.body(task.getContent(), ContentType.JSON.getValue())
|
||||
.timeout(5000)
|
||||
.execute();
|
||||
body = execute.body();
|
||||
} catch (Exception e) {
|
||||
log.error("发送通知失败,数据错误,任务ID:{}",task.getOrderId());
|
||||
log.error("错误内容",e);
|
||||
record.setErrorMsg(e.getMessage());
|
||||
}
|
||||
// 如果响应值等于SUCCESS, 说明发送成功, 进行成功处理
|
||||
if (Objects.equals(body, "SUCCESS")){
|
||||
this.successHandler(task);
|
||||
record.setSuccess(true);
|
||||
} else {
|
||||
this.failHandler(task,now);
|
||||
// 如果响应地址不为空, 将错误响应写到记录中
|
||||
if (Objects.nonNull(body)){
|
||||
// 预防返回值过长, 只保留100位
|
||||
record.setErrorMsg(StrUtil.sub(body,0,100));
|
||||
}
|
||||
}
|
||||
// 保存请求记录
|
||||
recordService.save(record);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -331,8 +350,13 @@ public class ClientNoticeService {
|
||||
* 失败处理, 首先发送次数+1, 然后注册后推指定时间的重试任务
|
||||
*/
|
||||
private void failHandler(ClientNoticeTask task, LocalDateTime now){
|
||||
// 为空不进行处理
|
||||
if (Objects.isNull(task)){
|
||||
return;
|
||||
}
|
||||
|
||||
// 次数+1
|
||||
task.setSendCount(task.getSendCount() + 1);
|
||||
task.setSendCount(task.getSendCount() + 1).setLatestTime(now);
|
||||
// 判断发送次数是否未超过15次, 注册任务到redis中
|
||||
if (task.getSendCount() < 16){
|
||||
// 根据当前次数和时间计算出毫秒值, 然后写入到Redis中
|
||||
|
@@ -17,6 +17,7 @@ import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService;
|
||||
import cn.bootx.platform.daxpay.service.func.AbsPayStrategy;
|
||||
import cn.bootx.platform.daxpay.util.PayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -27,6 +28,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.bootx.platform.daxpay.code.PayStatusEnum.*;
|
||||
|
||||
@@ -71,7 +73,7 @@ public class PayAssistService {
|
||||
if (PayUtil.isNotSync(payParam.getPayChannels())){
|
||||
return;
|
||||
}
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
|
||||
// 支付订单是非为空
|
||||
if (Objects.nonNull(order)){
|
||||
@@ -100,18 +102,18 @@ public class PayAssistService {
|
||||
// 首先读取请求参数
|
||||
noticeInfo.setNotifyUrl(payParam.getNotifyUrl());
|
||||
// 读取接口配置
|
||||
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
|
||||
if (StrUtil.isBlank(noticeInfo.getNotifyUrl())){
|
||||
noticeInfo.setNotifyUrl(apiInfo.getNoticeUrl());
|
||||
}
|
||||
// 读取平台配置
|
||||
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
|
||||
if (StrUtil.isBlank(noticeInfo.getNotifyUrl())){
|
||||
noticeInfo.setNotifyUrl(platform.getNotifyUrl());
|
||||
}
|
||||
}
|
||||
// 同步回调
|
||||
noticeInfo.setNotifyUrl(payParam.getReturnUrl());
|
||||
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
|
||||
noticeInfo.setNotifyUrl(platform.getNotifyUrl());
|
||||
noticeInfo.setReturnUrl(payParam.getReturnUrl());
|
||||
if (StrUtil.isBlank(noticeInfo.getReturnUrl())){
|
||||
noticeInfo.setReturnUrl(platform.getNotifyUrl());
|
||||
}
|
||||
// 退出回调地址
|
||||
noticeInfo.setQuitUrl(payParam.getQuitUrl());
|
||||
@@ -141,16 +143,31 @@ public class PayAssistService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付订单/附加表/支付通道表并保存,返回支付订单
|
||||
* 创建支付订单并保存, 返回支付订单
|
||||
*/
|
||||
public PayOrder createPayOrder(PayParam payParam) {
|
||||
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
|
||||
// 构建支付订单并保存
|
||||
PayOrder payOrder = PayBuilder.buildPayOrder(payParam);
|
||||
payOrderService.save(payOrder);
|
||||
PayOrder order = PayBuilder.buildPayOrder(payParam);
|
||||
payOrderService.save(order);
|
||||
// 构建支付订单扩展表并保存
|
||||
PayOrderExtra payOrderExtra = PayBuilder.buildPayOrderExtra(payParam, payOrder.getId());
|
||||
PayOrderExtra payOrderExtra = PayBuilder.buildPayOrderExtra(payParam, order.getId());
|
||||
payOrderExtraManager.save(payOrderExtra);
|
||||
return payOrder;
|
||||
payInfo.setPayOrder(order).setPayOrderExtra(payOrderExtra);
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并保存通道支付订单
|
||||
*/
|
||||
public void createPayChannelOrder(List<AbsPayStrategy> payStrategies) {
|
||||
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
|
||||
List<PayChannelOrder> channelOrders = payStrategies.stream()
|
||||
.map(AbsPayStrategy::getChannelOrder)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
payChannelOrderManager.saveAll(channelOrders);
|
||||
payInfo.setPayChannelOrders(channelOrders);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,8 +182,7 @@ public class PayAssistService {
|
||||
PayOrderExtra payOrderExtra = payOrderExtraManager.findById(paymentId)
|
||||
.orElseThrow(() -> new DataNotExistException("支付订单不存在"));
|
||||
|
||||
NoticeLocal noticeInfo = PaymentContextLocal.get()
|
||||
.getNoticeInfo();
|
||||
NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo();
|
||||
String notifyUrl = noticeInfo.getNotifyUrl();
|
||||
String returnUrl = noticeInfo.getReturnUrl();
|
||||
|
||||
|
@@ -6,11 +6,10 @@ import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayParam;
|
||||
import cn.bootx.platform.daxpay.param.pay.SimplePayParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.PayResult;
|
||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.builder.PayBuilder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
|
||||
@@ -33,7 +32,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.bootx.platform.daxpay.code.PayStatusEnum.*;
|
||||
|
||||
@@ -144,31 +142,27 @@ public class PayService {
|
||||
private void firstPayHandler(PayParam payParam, PayOrder payOrder) {
|
||||
|
||||
// 1.获取支付方式,通过工厂生成对应的策略组
|
||||
List<AbsPayStrategy> payStrategyList = PayStrategyFactory.createAsyncLast(payParam.getPayChannels());
|
||||
if (CollectionUtil.isEmpty(payStrategyList)) {
|
||||
List<AbsPayStrategy> strategies = PayStrategyFactory.createAsyncLast(payParam.getPayChannels());
|
||||
if (CollectionUtil.isEmpty(strategies)) {
|
||||
throw new PayUnsupportedMethodException();
|
||||
}
|
||||
|
||||
// 2.初始化支付的参数
|
||||
for (AbsPayStrategy paymentStrategy : payStrategyList) {
|
||||
paymentStrategy.initPayParam(payOrder, payParam);
|
||||
for (AbsPayStrategy strategy : strategies) {
|
||||
strategy.initPayParam(payOrder, payParam);
|
||||
}
|
||||
|
||||
// 3.1 执行支付前处理动作
|
||||
payStrategyList.forEach(AbsPayStrategy::doBeforePayHandler);
|
||||
strategies.forEach(AbsPayStrategy::doBeforePayHandler);
|
||||
// 3.2 执行通道支付单的生成动作
|
||||
payStrategyList.forEach(AbsPayStrategy::generateChannelOrder);
|
||||
strategies.forEach(AbsPayStrategy::generateChannelOrder);
|
||||
|
||||
// 4.1 支付操作
|
||||
payStrategyList.forEach(AbsPayStrategy::doPayHandler);
|
||||
strategies.forEach(AbsPayStrategy::doPayHandler);
|
||||
// 4.2 支付调用成功操作, 进行扣款、创建记录类类似的操作
|
||||
payStrategyList.forEach(AbsPayStrategy::doSuccessHandler);
|
||||
// 4.3 获取通道支付订单进行保存, 异步支付通道的订单单独处理
|
||||
List<PayChannelOrder> channelOrders = payStrategyList.stream()
|
||||
.map(AbsPayStrategy::getChannelOrder)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
payChannelOrderManager.saveAll(channelOrders);
|
||||
strategies.forEach(AbsPayStrategy::doSuccessHandler);
|
||||
// 4.3 保存通道支付订单
|
||||
payAssistService.createPayChannelOrder(strategies);
|
||||
|
||||
// 5.1 如果没有异步支付, 直接进行订单完成处理
|
||||
if (PayUtil.isNotSync(payParam.getPayChannels())) {
|
||||
@@ -178,7 +172,7 @@ public class PayService {
|
||||
payOrderService.updateById(payOrder);
|
||||
}
|
||||
// 5.2 如果异步支付完成, 进行订单完成处理, 同时发送回调消息
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
if (asyncPayInfo.isPayComplete()) {
|
||||
payOrder.setGatewayOrderNo(asyncPayInfo.getGatewayOrderNo())
|
||||
.setStatus(SUCCESS.getCode())
|
||||
@@ -188,9 +182,9 @@ public class PayService {
|
||||
|
||||
// 如果支付完成 发送通知
|
||||
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())){
|
||||
clientNoticeService.registerPayNotice(payOrder, null, channelOrders);
|
||||
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
|
||||
clientNoticeService.registerPayNotice(payOrder, payInfo.getPayOrderExtra(), payInfo.getPayChannelOrders());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +216,7 @@ public class PayService {
|
||||
payStrategyList.forEach(AbsPayStrategy::doSuccessHandler);
|
||||
|
||||
// 6.1 如果异步支付完成, 进行订单完成处理
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
if (asyncPayInfo.isPayComplete()) {
|
||||
payOrder.setGatewayOrderNo(asyncPayInfo.getGatewayOrderNo())
|
||||
.setStatus(SUCCESS.getCode())
|
||||
|
@@ -5,7 +5,7 @@ import cn.bootx.platform.daxpay.exception.pay.PayAmountAbnormalException;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.param.channel.AliPayParam;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfigService;
|
||||
@@ -93,7 +93,7 @@ public class AliPayStrategy extends AbsPayStrategy {
|
||||
*/
|
||||
@Override
|
||||
public void doSuccessHandler() {
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
|
||||
// 支付完成, 保存记录
|
||||
if (asyncPayInfo.isPayComplete()) {
|
||||
|
@@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.service.core.payment.pay.strategy;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayAmountAbnormalException;
|
||||
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
|
||||
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayConfigService;
|
||||
@@ -92,7 +92,7 @@ public class WeChatPayStrategy extends AbsPayStrategy {
|
||||
public void doSuccessHandler() {
|
||||
channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
|
||||
this.getOrder().setAsyncChannel(this.getChannel().getCode());
|
||||
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
|
||||
// 是否支付完成, 保存流水记录
|
||||
if (asyncPayInfo.isPayComplete()){
|
||||
weChatPayRecordService.pay(this.getOrder(), this.getChannelOrder());
|
||||
|
@@ -0,0 +1,23 @@
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.convert;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeRecord;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeTask;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeRecordDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeTaskDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/23
|
||||
*/
|
||||
@Mapper
|
||||
public interface ClientNoticeConvert {
|
||||
ClientNoticeConvert CONVERT = Mappers.getMapper(ClientNoticeConvert.class);
|
||||
|
||||
ClientNoticeRecordDto convert(ClientNoticeRecord in);
|
||||
|
||||
ClientNoticeTaskDto convert(ClientNoticeTask in);
|
||||
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.dao;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeRecord;
|
||||
import cn.bootx.platform.daxpay.service.param.record.ClientNoticeRecordQuery;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/23
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeRecordManager extends BaseManager<ClientNoticeRecordMapper, ClientNoticeRecord> {
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public Page<ClientNoticeRecord> page(PageParam pageParam, ClientNoticeRecordQuery query){
|
||||
QueryWrapper<ClientNoticeRecord> generator = QueryGenerator.generator(query);
|
||||
Page<ClientNoticeRecord> mpPage = MpUtil.getMpPage(pageParam, ClientNoticeRecord.class);
|
||||
|
||||
return this.page(mpPage, generator);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.dao;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeRecord;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/23
|
||||
*/
|
||||
@Mapper
|
||||
public interface ClientNoticeRecordMapper extends BaseMapper<ClientNoticeRecord> {
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.dao;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeTask;
|
||||
import cn.bootx.platform.daxpay.service.param.record.ClientNoticeTaskQuery;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeTaskManager extends BaseManager<ClientNoticeTaskMapper, ClientNoticeTask> {
|
||||
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public Page<ClientNoticeTask> page(PageParam pageParam, ClientNoticeTaskQuery query){
|
||||
QueryWrapper<ClientNoticeTask> generator = QueryGenerator.generator(query);
|
||||
Page<ClientNoticeTask> mpPage = MpUtil.getMpPage(pageParam, ClientNoticeTask.class);
|
||||
|
||||
return this.page(mpPage, generator);
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.notice.dao;
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.dao;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.entity.ClientNoticeTask;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeTask;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
@@ -0,0 +1,57 @@
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeSendTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.convert.ClientNoticeConvert;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeRecordDto;
|
||||
import cn.bootx.table.modify.annotation.DbColumn;
|
||||
import cn.bootx.table.modify.annotation.DbTable;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 消息通知任务记录表
|
||||
* @author xxm
|
||||
* @since 2024/2/20
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@DbTable(comment = "消息通知任务记录")
|
||||
@TableName("pay_client_notice_record")
|
||||
public class ClientNoticeRecord extends MpCreateEntity implements EntityBaseFunction<ClientNoticeRecordDto> {
|
||||
|
||||
/** 任务ID */
|
||||
@DbColumn(comment = "任务ID")
|
||||
private Long taskId;
|
||||
|
||||
/** 请求次数 */
|
||||
@DbColumn(comment = "请求次数")
|
||||
private Integer reqCount;
|
||||
|
||||
/** 发送是否成功 */
|
||||
@DbColumn(comment = "发送是否成功")
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* 发送类型, 自动发送, 手动发送
|
||||
* @see ClientNoticeSendTypeEnum
|
||||
*/
|
||||
@DbColumn(comment = "发送类型")
|
||||
private String type;
|
||||
|
||||
/** 错误信息 */
|
||||
@DbColumn(comment = "错误信息")
|
||||
private String errorMsg;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
@Override
|
||||
public ClientNoticeRecordDto toDto() {
|
||||
return ClientNoticeConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -1,7 +1,10 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.notice.entity;
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.entity;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.convert.ClientNoticeConvert;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeTaskDto;
|
||||
import cn.bootx.table.modify.annotation.DbColumn;
|
||||
import cn.bootx.table.modify.annotation.DbTable;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -9,6 +12,8 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 消息通知任务
|
||||
* @author xxm
|
||||
@@ -18,18 +23,18 @@ import lombok.experimental.Accessors;
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@DbTable(comment = "消息通知任务")
|
||||
@TableName("tb_client_notice_task")
|
||||
public class ClientNoticeTask extends MpCreateEntity {
|
||||
@TableName("pay_client_notice_task")
|
||||
public class ClientNoticeTask extends MpBaseEntity implements EntityBaseFunction<ClientNoticeTaskDto> {
|
||||
|
||||
/** 本地订单ID */
|
||||
@DbColumn(comment = "本地订单ID")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 回调类型
|
||||
* 消息类型
|
||||
* @see ClientNoticeTypeEnum
|
||||
*/
|
||||
@DbColumn(comment = "回调类型")
|
||||
@DbColumn(comment = "消息类型")
|
||||
private String type;
|
||||
|
||||
/** 消息内容 */
|
||||
@@ -47,4 +52,16 @@ public class ClientNoticeTask extends MpCreateEntity {
|
||||
/** 发送地址 */
|
||||
@DbColumn(comment = "发送地址")
|
||||
private String url;
|
||||
|
||||
/** 最后发送时间 */
|
||||
@DbColumn(comment = "最后发送时间")
|
||||
private LocalDateTime latestTime;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
@Override
|
||||
public ClientNoticeTaskDto toDto() {
|
||||
return ClientNoticeConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.service;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.dao.ClientNoticeRecordManager;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeRecord;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 消息通知发送记录
|
||||
* @author xxm
|
||||
* @since 2024/2/23
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeRecordService {
|
||||
private final ClientNoticeRecordManager recordManager;
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
|
||||
public void save(ClientNoticeRecord record){
|
||||
recordManager.save(record);
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package cn.bootx.platform.daxpay.service.core.task.notice.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.rest.PageResult;
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeRecord;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.entity.ClientNoticeTask;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.dao.ClientNoticeRecordManager;
|
||||
import cn.bootx.platform.daxpay.service.core.task.notice.dao.ClientNoticeTaskManager;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeRecordDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.record.notice.ClientNoticeTaskDto;
|
||||
import cn.bootx.platform.daxpay.service.param.record.ClientNoticeRecordQuery;
|
||||
import cn.bootx.platform.daxpay.service.param.record.ClientNoticeTaskQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 通知任务查询类
|
||||
* @author xxm
|
||||
* @since 2024/2/23
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeTaskService {
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final ClientNoticeTaskManager taskManager;
|
||||
|
||||
private final ClientNoticeRecordManager recordManager;
|
||||
|
||||
|
||||
/**
|
||||
* 手动触发消息发送
|
||||
*/
|
||||
public void sendData(Long taskId){
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务分页查询
|
||||
*/
|
||||
public PageResult<ClientNoticeTaskDto> taskPage(PageParam pageParam, ClientNoticeTaskQuery query){
|
||||
return MpUtil.convert2DtoPageResult(taskManager.page(pageParam, query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务详情
|
||||
*/
|
||||
public ClientNoticeTaskDto findTaskById(Long id){
|
||||
return taskManager.findById(id).map(ClientNoticeTask::toDto).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录分页
|
||||
*/
|
||||
public PageResult<ClientNoticeRecordDto> recordPage(PageParam pageParam, ClientNoticeRecordQuery query){
|
||||
return MpUtil.convert2DtoPageResult(recordManager.page(pageParam, query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录详情
|
||||
*/
|
||||
public ClientNoticeRecordDto findRecordById(Long id){
|
||||
return recordManager.findById(id).map(ClientNoticeRecord::toDto).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package cn.bootx.platform.daxpay.service.dto.record.notice;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.dto.BaseDto;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeSendTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 消息通知记录
|
||||
* @author xxm
|
||||
* @since 2024/2/23
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "消息通知记录")
|
||||
public class ClientNoticeRecordDto extends BaseDto {
|
||||
|
||||
/** 任务ID */
|
||||
@Schema(description = "任务ID")
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 发送类型, 自动发送, 手动发送
|
||||
* @see ClientNoticeSendTypeEnum
|
||||
*/
|
||||
@Schema(description = "发送类型")
|
||||
private String type;
|
||||
|
||||
/** 请求次数 */
|
||||
@Schema(description = "请求次数")
|
||||
private Integer reqCount;
|
||||
|
||||
/** 发送是否成功 */
|
||||
@Schema(description = "发送是否成功")
|
||||
private boolean success;
|
||||
|
||||
/** 错误信息 */
|
||||
@Schema(description = "错误信息")
|
||||
private String errorMsg;
|
||||
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package cn.bootx.platform.daxpay.service.dto.record.notice;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.dto.BaseDto;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 消息通知任务
|
||||
* @author xxm
|
||||
* @since 2024/2/23
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "消息通知任务")
|
||||
public class ClientNoticeTaskDto extends BaseDto {
|
||||
|
||||
/** 本地订单ID */
|
||||
@Schema(description = "本地订单ID")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 回调类型
|
||||
* @see ClientNoticeTypeEnum
|
||||
*/
|
||||
@Schema(description = "回调类型")
|
||||
private String type;
|
||||
|
||||
/** 消息内容 */
|
||||
@Schema(description = "消息内容")
|
||||
private String content;
|
||||
|
||||
/** 是否发送成功 */
|
||||
@Schema(description = "是否发送成功")
|
||||
private boolean success;
|
||||
|
||||
/** 发送次数 */
|
||||
@Schema(description = "发送次数")
|
||||
private Integer sendCount;
|
||||
|
||||
/** 发送地址 */
|
||||
@Schema(description = "发送地址")
|
||||
private String url;
|
||||
|
||||
/** 最后发送时间 */
|
||||
@Schema(description = "最后发送时间")
|
||||
private LocalDateTime latestTime;
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package cn.bootx.platform.daxpay.service.param.record;
|
||||
|
||||
import cn.bootx.platform.common.core.annotation.QueryParam;
|
||||
import cn.bootx.platform.common.core.rest.param.QueryOrder;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 客户通知记录查询
|
||||
* @author xxm
|
||||
* @since 2024/2/24
|
||||
*/
|
||||
@QueryParam
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "客户通知记录查询")
|
||||
public class ClientNoticeRecordQuery extends QueryOrder {
|
||||
|
||||
/** 任务ID */
|
||||
@Schema(description ="任务ID")
|
||||
private Long taskId;
|
||||
|
||||
/** 请求次数 */
|
||||
@Schema(description ="请求次数")
|
||||
private Integer reqCount;
|
||||
|
||||
/** 发送是否成功 */
|
||||
@Schema(description ="发送是否成功")
|
||||
private Boolean success;
|
||||
|
||||
/** 错误信息 */
|
||||
@Schema(description ="错误信息")
|
||||
private String errorMsg;
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package cn.bootx.platform.daxpay.service.param.record;
|
||||
|
||||
import cn.bootx.platform.common.core.annotation.QueryParam;
|
||||
import cn.bootx.platform.common.core.rest.param.QueryOrder;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 发送通知任务查询
|
||||
* @author xxm
|
||||
* @since 2024/2/24
|
||||
*/
|
||||
@QueryParam
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "发送通知任务查询")
|
||||
public class ClientNoticeTaskQuery extends QueryOrder {
|
||||
|
||||
/** 本地订单ID */
|
||||
@Schema(description ="本地订单ID")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 通知类型
|
||||
* @see ClientNoticeTypeEnum
|
||||
*/
|
||||
@Schema(description ="通知类型")
|
||||
private String type;
|
||||
|
||||
/** 消息内容 */
|
||||
@Schema(description ="消息内容")
|
||||
private String content;
|
||||
|
||||
/** 是否发送成功 */
|
||||
@Schema(description ="是否发送成功")
|
||||
private Boolean success;
|
||||
|
||||
/** 发送次数 */
|
||||
@Schema(description ="发送次数")
|
||||
private Integer sendCount;
|
||||
|
||||
/** 发送地址 */
|
||||
@Schema(description ="发送地址")
|
||||
private String url;
|
||||
}
|
@@ -10,7 +10,7 @@ import org.springframework.stereotype.Component;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 消息通知任务
|
||||
* 发送消息通知任务
|
||||
* @author xxm
|
||||
* @since 2024/2/22
|
||||
*/
|
||||
@@ -19,7 +19,7 @@ import java.time.LocalDateTime;
|
||||
@DisallowConcurrentExecution
|
||||
@PersistJobDataAfterExecution
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeTask implements Job {
|
||||
public class ClientNoticeSendTask implements Job {
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
@@ -33,7 +33,7 @@ public class PayReconcileTaskService {
|
||||
reconcileService.downAndSave(reconcileOrder);
|
||||
|
||||
// 3. 执行账单比对, 生成差异单
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user