feat 接口订单和定时任务调整

This commit is contained in:
DaxPay
2024-05-17 18:03:52 +08:00
parent 9699661a1f
commit 4c6262be05
27 changed files with 486 additions and 188 deletions

View File

@@ -0,0 +1,40 @@
package cn.daxpay.single.admin.controller.record;
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.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
import cn.daxpay.single.service.dto.record.flow.TradeFlowRecordDto;
import cn.daxpay.single.service.param.record.TradeFlowRecordQuery;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 交易流水记录控制器
* @author xxm
* @since 2024/5/17
*/
@Tag(name = "交易流水记录控制器")
@RestController
@RequestMapping("/record/flow")
@RequiredArgsConstructor
public class TradeFlowRecordController {
private final TradeFlowRecordService service;
@Operation(summary = "分页查询")
@GetMapping("/page")
public ResResult<PageResult<TradeFlowRecordDto>> page(PageParam pageParam, TradeFlowRecordQuery query) {
return Res.ok(service.page(pageParam, query));
}
@Operation(summary = "查询单条")
@GetMapping("/findById")
public ResResult<TradeFlowRecordDto> findById(Long id) {
return Res.ok(service.findById(id));
}
}

View File

@@ -6,28 +6,37 @@ package cn.daxpay.single.code;
* @since 2024/2/25
*/
public interface PaymentApiCode {
/** 支付 */
String PAY = "pay";
/** 退款 */
String REFUND = "refund";
/** 关闭订单 */
String CLOSE = "close";
/** 分账 */
String ALLOCATION = "allocation";
/** 分账完结 */
String ALLOCATION_FINISH = "allocationFinish";
/** 支付同步 */
String SYNC_PAY = "syncPay";
/** 退款同步 */
String SYNC_REFUND = "syncRefund";
/** 查询支付订单 */
String QUERY_PAY_ORDER = "queryPayOrder";
/** 查询退款订单 */
String QUERY_REFUND_ORDER = "queryRefundOrder";
/** 查询分账订单 */
String QUERY_ALLOCATION_ORDER = "queryAllocationOrder";
/** 获取微信授权链接 */
String GET_WX_AUTH_URL = "getWxAuthUrl";
/** 获取微信AccessToken */
String GET_WX_ACCESS_TOKEN = "getWxAccessToken";
/** 添加分账方接口 */
String ALLOCATION_RECEIVER_ADD = "allocationReceiverAdd";
/** 删除分账方 */
String ALLOCATION_RECEIVER_REMOVE = "allocationReceiverRemove";
/** 查询分账方 */
String ALLOCATION_RECEIVER_QUERY = "allocationReceiverQuery";

View File

@@ -22,7 +22,7 @@ import java.util.Objects;
@RestController
@RequestMapping("/gateway/notice")
@RequiredArgsConstructor
public class PayGatewayNoticeController {
public class PayNoticeReceiverController {
@Operation(summary = "支付宝消息通知")
@PostMapping("/alipay")
@@ -35,4 +35,5 @@ public class PayGatewayNoticeController {
public Map<String, Objects> wechatPayNotice() {
return new HashMap<>();
}
}

View File

@@ -0,0 +1,79 @@
package cn.daxpay.single.gateway.controller;
import cn.daxpay.single.code.PaymentApiCode;
import cn.daxpay.single.param.payment.allocation.AllocationFinishParam;
import cn.daxpay.single.param.payment.allocation.AllocationStartParam;
import cn.daxpay.single.result.DaxResult;
import cn.daxpay.single.result.allocation.AllocationResult;
import cn.daxpay.single.service.annotation.PaymentApi;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationReceiverService;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationService;
import cn.daxpay.single.service.param.allocation.group.AllocationReceiverParam;
import cn.daxpay.single.util.DaxRes;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
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;
/**
* 分账控制器
* @author xxm
* @since 2024/5/17
*/
@Tag(name = "分账控制器")
@RestController
@RequestMapping("/unipay/allocation")
@RequiredArgsConstructor
public class UniAllocationController {
private final AllocationService allocationService;
private final AllocationReceiverService receiverService;
@PaymentApi(PaymentApiCode.ALLOCATION)
@Operation(summary = "触发分账接口")
@PostMapping("/open")
public DaxResult<AllocationResult> open(@RequestBody AllocationStartParam param){
return DaxRes.ok(allocationService.allocation(param));
}
@PaymentApi(PaymentApiCode.ALLOCATION_FINISH)
@Operation(summary = "分账完结接口")
@PostMapping("/finish")
public DaxResult<Void> finish(@RequestBody AllocationFinishParam param){
allocationService.finish(param);
return DaxRes.ok();
}
@PaymentApi(PaymentApiCode.ALLOCATION_RECEIVER_QUERY)
@Operation(summary = "分账接收方查询接口")
@PostMapping("/allocationReceiverQuery")
public DaxResult<Void> allocationReceiverQuery(@RequestBody AllocationReceiverParam param){
return DaxRes.ok();
}
@PaymentApi(PaymentApiCode.ALLOCATION_RECEIVER_ADD)
@Operation(summary = "添加分账接收方接口")
@PostMapping("/allocationReceiverAdd")
public DaxResult<Void> allocationReceiverAdd(@RequestBody AllocationReceiverParam param){
return DaxRes.ok();
}
@PaymentApi(PaymentApiCode.ALLOCATION_RECEIVER_REMOVE)
@Operation(summary = "删除分账接收方接口")
@PostMapping("/allocationReceiverRemove")
public DaxResult<Void> allocationReceiverRemove(@RequestBody AllocationReceiverParam param){
return DaxRes.ok();
}
@PaymentApi(PaymentApiCode.ALLOCATION_RECEIVER_QUERY)
@Operation(summary = "查询分账接收方接口")
@PostMapping("/allocationReceiverRemoveByGateway")
public DaxResult<Void> allocationReceiverRemoveByGateway(@RequestBody AllocationReceiverParam param){
return DaxRes.ok();
}
}

View File

@@ -2,21 +2,17 @@ package cn.daxpay.single.gateway.controller;
import cn.bootx.platform.common.core.annotation.IgnoreAuth;
import cn.daxpay.single.code.PaymentApiCode;
import cn.daxpay.single.param.payment.allocation.AllocationFinishParam;
import cn.daxpay.single.param.payment.allocation.AllocationStartParam;
import cn.daxpay.single.param.payment.pay.PayCloseParam;
import cn.daxpay.single.param.payment.pay.PayParam;
import cn.daxpay.single.param.payment.pay.PaySyncParam;
import cn.daxpay.single.param.payment.refund.RefundParam;
import cn.daxpay.single.param.payment.refund.RefundSyncParam;
import cn.daxpay.single.result.DaxResult;
import cn.daxpay.single.result.allocation.AllocationResult;
import cn.daxpay.single.result.pay.PayCloseResult;
import cn.daxpay.single.result.pay.PayResult;
import cn.daxpay.single.result.pay.RefundResult;
import cn.daxpay.single.result.pay.SyncResult;
import cn.daxpay.single.service.annotation.PaymentApi;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationService;
import cn.daxpay.single.service.core.payment.close.service.PayCloseService;
import cn.daxpay.single.service.core.payment.pay.service.PayService;
import cn.daxpay.single.service.core.payment.refund.service.RefundService;
@@ -47,7 +43,6 @@ public class UniPayController {
private final PaySyncService paySyncService;
private final PayCloseService payCloseService;
private final RefundSyncService refundSyncService;
private final AllocationService allocationService;
@PaymentApi(PaymentApiCode.PAY)
@@ -85,21 +80,4 @@ public class UniPayController {
return DaxRes.ok(refundSyncService.sync(param));
}
@PaymentApi(PaymentApiCode.ALLOCATION)
@Operation(summary = "开启分账接口")
@PostMapping("/allocation")
public DaxResult<AllocationResult> allocation(@RequestBody AllocationStartParam param){
return DaxRes.ok(allocationService.allocation(param));
}
@PaymentApi(PaymentApiCode.ALLOCATION_FINISH)
@Operation(summary = "分账完结接口")
@PostMapping("/allocationFinish")
public DaxResult<Void> allocationFinish(@RequestBody AllocationFinishParam param){
allocationService.finish(param);
return DaxRes.ok();
}
}

View File

@@ -0,0 +1,34 @@
package cn.daxpay.single.gateway.controller;
import cn.daxpay.single.code.PaymentApiCode;
import cn.daxpay.single.param.payment.pay.PayParam;
import cn.daxpay.single.result.DaxResult;
import cn.daxpay.single.service.annotation.PaymentApi;
import cn.daxpay.single.util.DaxRes;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
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;
/**
* 对账相关接口
* @author xxm
* @since 2024/5/17
*/
@Tag(name = "对账接口处理器")
@RestController
@RequestMapping("/unipay/reconcile")
@RequiredArgsConstructor
public class UniReconcileController {
@PaymentApi(PaymentApiCode.PAY)
@Operation(summary = "下载指定日期的资金流水")
@PostMapping("/pay")
public DaxResult<?> down(@RequestBody PayParam payParam){
return DaxRes.ok();
}
}

View File

@@ -99,4 +99,13 @@ public class PayOrderManager extends BaseManager<PayOrderMapper, PayOrder> {
return baseMapper.getTalAmount(generator);
}
/**
* 查询当前超时的未支付订单
*/
public List<PayOrder> queryExpiredOrder() {
return lambdaQuery()
.eq(PayOrder::getStatus, PayStatusEnum.REFUNDING.getCode())
.lt(PayOrder::getExpiredTime, LocalDateTime.now())
.list();
}
}

View File

@@ -92,6 +92,7 @@ public class PayOrderQueryService {
return PayOrderConvert.CONVERT.convertResult(payOrder);
}
/**
* 查询支付总金额
*/

View File

@@ -11,6 +11,7 @@ import cn.daxpay.single.service.core.order.pay.entity.PayOrderExtra;
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
import cn.daxpay.single.service.core.payment.pay.factory.PayStrategyFactory;
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
import cn.daxpay.single.service.func.AbsPayStrategy;
import cn.daxpay.single.util.PayUtil;
import cn.hutool.extra.spring.SpringUtil;
@@ -45,6 +46,8 @@ public class PayService {
private final PayOrderExtraManager payOrderExtraManager;
private final TradeFlowRecordService tradeFlowRecordService;
private final LockTemplate lockTemplate;
/**
@@ -129,8 +132,9 @@ public class PayService {
payOrder.setErrorCode(null);
payOrder.setErrorMsg(null);
payOrderService.updateById(payOrder);
// 如果支付完成 发送通知
// 如果支付完成 发送通知, 记录流水
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())){
tradeFlowRecordService.savePay(payOrder);
clientNoticeService.registerPayNotice(payOrder, payInfo.getPayOrderExtra());
}
return payAssistService.buildResult(payOrder);
@@ -181,8 +185,9 @@ public class PayService {
payOrder.setErrorMsg(null);
payOrder.setErrorCode(null);
payOrderService.updateById(payOrder);
// 如果支付完成 发送通知
// 如果支付完成 发送通知, 记录流水
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())){
tradeFlowRecordService.savePay(payOrder);
clientNoticeService.registerPayNotice(payOrder, payOrderExtra);
}
return payAssistService.buildResult(payOrder);

View File

@@ -19,6 +19,7 @@ import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
import cn.daxpay.single.service.core.order.refund.entity.RefundOrderExtra;
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
import cn.daxpay.single.service.core.payment.refund.factory.RefundStrategyFactory;
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
import cn.daxpay.single.service.func.AbsRefundStrategy;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
@@ -54,6 +55,8 @@ public class RefundService {
private final PayOrderQueryService payOrderQueryService;
private final TradeFlowRecordService tradeFlowRecordService;
private final RefundOrderExtraManager refundOrderExtraManager;
private final LockTemplate lockTemplate;
@@ -199,16 +202,23 @@ public class RefundService {
*/
@Transactional(rollbackFor = Exception.class)
public void successHandler(RefundOrder refundOrder, PayOrder payOrder) {
RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo();
RefundLocal refundInfo = PaymentContextLocal.get()
.getRefundInfo();
// 剩余可退款余额
int refundableBalance = payOrder.getRefundableBalance();
// 设置支付订单状态
// 退款状态为退款中
if (refundInfo.getStatus() == RefundStatusEnum.PROGRESS) {
payOrder.setStatus(PayStatusEnum.REFUNDING.getCode());
} else if (refundableBalance == 0) {
payOrder.setStatus(PayStatusEnum.REFUNDED.getCode());
} else {
payOrder.setStatus(PayStatusEnum.PARTIAL_REFUND.getCode());
}
// 退款状态为成功
else {
if (refundableBalance == 0) {
payOrder.setStatus(PayStatusEnum.REFUNDED.getCode());
} else {
payOrder.setStatus(PayStatusEnum.PARTIAL_REFUND.getCode());
}
// 记录流水
tradeFlowRecordService.saveRefund(refundOrder);
}
payOrderService.updateById(payOrder);

View File

@@ -10,6 +10,7 @@ import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
import cn.daxpay.single.service.core.payment.repair.factory.PayRepairStrategyFactory;
import cn.daxpay.single.service.core.payment.repair.result.PayRepairResult;
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
import cn.daxpay.single.service.core.record.repair.entity.PayRepairRecord;
import cn.daxpay.single.service.core.record.repair.service.PayRepairRecordService;
import cn.daxpay.single.service.func.AbsPayRepairStrategy;
@@ -41,6 +42,7 @@ public class PayRepairService {
private final PayRepairRecordService recordService;
private final LockTemplate lockTemplate;
private final TradeFlowRecordService tradeFlowRecordService;
/**
* 修复支付单
@@ -117,6 +119,7 @@ public class PayRepairService {
order.setStatus(PayStatusEnum.SUCCESS.getCode())
.setPayTime(payTime)
.setCloseTime(null);
tradeFlowRecordService.savePay(order);
payOrderService.updateById(order);
}

View File

@@ -13,6 +13,7 @@ import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
import cn.daxpay.single.service.core.payment.repair.result.RefundRepairResult;
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
import cn.daxpay.single.service.core.record.repair.entity.PayRepairRecord;
import cn.daxpay.single.service.core.record.repair.service.PayRepairRecordService;
import cn.daxpay.single.util.OrderNoGenerateUtil;
@@ -49,6 +50,7 @@ public class RefundRepairService {
private final PayRepairRecordService recordService;
private final LockTemplate lockTemplate;
private final TradeFlowRecordService tradeFlowRecordService;
/**
* 修复退款单
@@ -113,11 +115,13 @@ public class RefundRepairService {
.setFinishTime(repairInfo.getFinishTime());
payOrder.setStatus(afterPayRefundStatus.getCode());
// 更新订单和退款相关订单
payOrderService.updateById(payOrder);
refundOrderManager.updateById(refundOrder);
// 记录流水
tradeFlowRecordService.saveRefund(refundOrder);
// 发送通知
List<String> list = Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode(), RefundStatusEnum.FAIL.getCode());
if (list.contains(refundOrder.getStatus())){

View File

@@ -1,6 +1,9 @@
package cn.daxpay.single.service.core.record.flow.convert;
import cn.daxpay.single.service.core.record.flow.entity.TradeFlowRecord;
import cn.daxpay.single.service.dto.record.flow.TradeFlowRecordDto;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
*
@@ -9,4 +12,7 @@ import org.mapstruct.Mapper;
*/
@Mapper
public interface TradeFlowRecordConvert {
TradeFlowRecordConvert CONVERT = Mappers.getMapper(TradeFlowRecordConvert.class);
TradeFlowRecordDto convert(TradeFlowRecord entity);
}

View File

@@ -1,7 +1,13 @@
package cn.daxpay.single.service.core.record.flow.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.daxpay.single.service.core.record.flow.entity.TradeFlowRecord;
import cn.daxpay.single.service.param.record.TradeFlowRecordQuery;
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;
@@ -15,4 +21,13 @@ import org.springframework.stereotype.Repository;
@Repository
@RequiredArgsConstructor
public class TradeFlowRecordManager extends BaseManager<TradeFlowRecordMapper, TradeFlowRecord> {
/**
* 分页
*/
public Page<TradeFlowRecord> page(PageParam pageParam, TradeFlowRecordQuery param){
Page<TradeFlowRecord> mpPage = MpUtil.getMpPage(pageParam, TradeFlowRecord.class);
QueryWrapper<TradeFlowRecord> generator = QueryGenerator.generator(param);
return page(mpPage, generator);
}
}

View File

@@ -1,16 +1,17 @@
package cn.daxpay.single.service.core.record.flow.entity;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.daxpay.single.code.PayChannelEnum;
import cn.daxpay.single.service.code.TradeFlowRecordTypeEnum;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.daxpay.single.service.core.record.flow.convert.TradeFlowRecordConvert;
import cn.daxpay.single.service.dto.record.flow.TradeFlowRecordDto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 资金流水记录
* @author xxm
@@ -20,8 +21,9 @@ import java.time.LocalDateTime;
@Data
@Accessors(chain = true)
@Schema(title = "资金流水记录")
public class TradeFlowRecord extends MpCreateEntity {
/** 支付订单标题 */
public class TradeFlowRecord extends MpCreateEntity implements EntityBaseFunction<TradeFlowRecordDto> {
/** 订单标题 */
@DbColumn(comment = "标题")
private String title;
@@ -55,7 +57,8 @@ public class TradeFlowRecord extends MpCreateEntity {
@DbColumn(comment = "三方系统交易号")
private String outTradeNo;
/** 网关完成时间 */
@DbColumn(comment = "网关完成时间")
private LocalDateTime finishTime;
@Override
public TradeFlowRecordDto toDto() {
return TradeFlowRecordConvert.CONVERT.convert(this);
}
}

View File

@@ -1,5 +1,16 @@
package cn.daxpay.single.service.core.record.flow.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.daxpay.single.service.code.TradeFlowRecordTypeEnum;
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
import cn.daxpay.single.service.core.record.flow.dao.TradeFlowRecordManager;
import cn.daxpay.single.service.core.record.flow.entity.TradeFlowRecord;
import cn.daxpay.single.service.dto.record.flow.TradeFlowRecordDto;
import cn.daxpay.single.service.param.record.TradeFlowRecordQuery;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -13,4 +24,53 @@ import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class TradeFlowRecordService {
private final TradeFlowRecordManager tradeFlowRecordManager;
/**
* 分页
*/
public PageResult<TradeFlowRecordDto> page(PageParam pageParam, TradeFlowRecordQuery query){
return MpUtil.convert2DtoPageResult(tradeFlowRecordManager.page(pageParam, query));
}
/**
* 查询详情
*/
public TradeFlowRecordDto findById(Long id){
return tradeFlowRecordManager.findById(id).map(TradeFlowRecord::toDto)
.orElseThrow(()->new DataNotExistException("交易流水记录不存在"));
}
/**
* 支付记账
*/
public void savePay(PayOrder payOrder){
TradeFlowRecord tradeFlowRecord = new TradeFlowRecord()
.setTradeNo(payOrder.getOrderNo())
.setBizTradeNo(payOrder.getBizOrderNo())
.setOutTradeNo(payOrder.getOutOrderNo())
.setChannel(payOrder.getChannel())
.setTitle(payOrder.getTitle())
.setType(TradeFlowRecordTypeEnum.PAY.getCode())
.setAmount(payOrder.getAmount());
tradeFlowRecordManager.save(tradeFlowRecord);
}
/**
* 退款记账
*/
public void saveRefund(RefundOrder refundOrder){
TradeFlowRecord tradeFlowRecord = new TradeFlowRecord()
.setTradeNo(refundOrder.getRefundNo())
.setBizTradeNo(refundOrder.getBizRefundNo())
.setOutTradeNo(refundOrder.getOutRefundNo())
.setChannel(refundOrder.getChannel())
.setTitle(refundOrder.getTitle())
.setType(TradeFlowRecordTypeEnum.PAY.getCode())
.setAmount(refundOrder.getAmount());
tradeFlowRecordManager.save(tradeFlowRecord);
}
}

View File

@@ -0,0 +1,53 @@
package cn.daxpay.single.service.dto.record.flow;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.daxpay.single.code.PayChannelEnum;
import cn.daxpay.single.service.code.TradeFlowRecordTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 资金流水记录
* @author xxm
* @since 2024/5/17
*/
@Data
@Accessors(chain = true)
@Schema(title = "资金流水记录")
public class TradeFlowRecordDto {
/** 订单标题 */
@DbColumn(comment = "标题")
private String title;
/** 金额 */
@DbColumn(comment = "金额")
private Integer amount;
/**
* 业务类型
* @see TradeFlowRecordTypeEnum
*/
@DbColumn(comment = "业务类型")
private String type;
/**
* 支付通道
* @see PayChannelEnum
*/
@DbColumn(comment = "支付通道")
private String channel;
/** 本地交易号 */
@DbColumn(comment = "本地订单号")
private String tradeNo;
/** 商户交易号 */
@DbColumn(comment = "商户交易号")
private String bizTradeNo;
/** 三方系统交易号 */
@DbColumn(comment = "三方系统交易号")
private String outTradeNo;
}

View File

@@ -0,0 +1,18 @@
package cn.daxpay.single.service.param.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 流水记录查询类
* @author xxm
* @since 2024/5/17
*/
@Data
@Accessors(chain = true)
@Schema(title = "流水记录查询类")
public class TradeFlowRecordQuery {
}

View File

@@ -0,0 +1,45 @@
package cn.daxpay.single.service.task;
import cn.daxpay.single.service.core.order.pay.dao.PayOrderManager;
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
import cn.daxpay.single.service.core.payment.sync.service.PaySyncService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.stereotype.Component;
import java.util.List;
/**
*
* @author xxm
* @since 2024/5/17
*/
@Slf4j
@Component
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
@RequiredArgsConstructor
public class PayExpiredByDbTimeTask implements Job {
private final PaySyncService paySyncService;
private final PayOrderManager payOrderManager;
@Override
public void execute(JobExecutionContext context) {
// 从数据库查询获取超时的任务对象
List<PayOrder> payOrders = payOrderManager.queryExpiredOrder();
for (PayOrder order : payOrders) {
try {
// 设置补偿来源为定时任务
paySyncService.syncPayOrder(order);
} catch (Exception e) {
log.error("超时取消任务 异常", e);
}
}
}
}

View File

@@ -9,21 +9,25 @@ import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Service;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Set;
/**
* 支付超时处理
* 支付超时处理(手动注册)
* @author xxm
* @since 2024/1/2
*/
@Slf4j
@Service
@Component
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
@RequiredArgsConstructor
public class PayExpiredTimeTask implements Job {
private final PayExpiredTimeRepository repository;

View File

@@ -1,6 +1,7 @@
package cn.daxpay.single.service.task;
import cn.daxpay.single.service.task.service.ReconcileTaskService;
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileOrder;
import cn.daxpay.single.service.core.payment.reconcile.service.ReconcileService;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.Getter;
@@ -24,7 +25,7 @@ import java.util.Objects;
@PersistJobDataAfterExecution
@RequiredArgsConstructor
public class ReconcileTask implements Job {
private final ReconcileTaskService reconcileTaskService;
private final ReconcileService reconcileService;
/**
* 任务参数, 格式
@@ -37,7 +38,7 @@ public class ReconcileTask implements Job {
* 任务实现
*/
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
public void execute(JobExecutionContext context) {
if (StrUtil.isBlank(parameter)){
log.warn("传输参数为空");
return;
@@ -50,9 +51,26 @@ public class ReconcileTask implements Job {
} else {
date = date.minusDays(1);
}
reconcileTaskService.reconcileTask(date,bean.channel);
this.reconcileTask(date,bean.channel);
}
/**
* 执行任务
*/
public void reconcileTask(LocalDate date, String channel){
// 1. 查询需要定时对账的通道, 创建出来对账订单
ReconcileOrder reconcileOrder = reconcileService.create(date, channel);
// 2. 执行对账任务, 下载对账单并解析, 分别存储为原始数据和通用对账数据
reconcileService.downAndSave(reconcileOrder);
// 3. 执行账单明细比对, 生成差异单
reconcileService.compare(reconcileOrder);
}
/**
* 接收参数
*/

View File

@@ -1,11 +1,15 @@
package cn.daxpay.single.service.task;
import cn.daxpay.single.service.task.service.RefundSyncTaskService;
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
import cn.daxpay.single.service.core.payment.sync.service.RefundSyncService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 退款定时同步任务 一分钟一次, 查询退款中的订单进行同步
* @author xxm
@@ -18,10 +22,22 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class RefundSyncTask implements Job {
private final RefundSyncTaskService refundSyncTaskService;
private final RefundSyncService refundSyncService;
private final RefundOrderManager refundOrderManager;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
refundSyncTaskService.syncTask();
// 查询退款中的退款订单
List<RefundOrder> list = refundOrderManager.findAllByProgress();
for (RefundOrder refundOrder : list) {
try {
// 调用同步方法
refundSyncService.syncRefundOrder(refundOrder);
} catch (Exception e) {
log.warn("退款执行同步失败, ID: {}",refundOrder.getId());
log.warn("退款执行同步失败",e);
}
}
}
}

View File

@@ -1,37 +0,0 @@
package cn.daxpay.single.service.task.service;
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileOrder;
import cn.daxpay.single.service.core.payment.reconcile.service.ReconcileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
/**
* 支付对账定时任务服务类
* @author xxm
* @since 2024/1/20
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ReconcileTaskService {
private final ReconcileService reconcileService;
/**
* 执行任务
*/
public void reconcileTask(LocalDate date, String channel){
// 1. 查询需要定时对账的通道, 创建出来对账订单
ReconcileOrder reconcileOrder = reconcileService.create(date, channel);
// 2. 执行对账任务, 下载对账单并解析, 分别存储为原始数据和通用对账数据
reconcileService.downAndSave(reconcileOrder);
// 3. 执行账单明细比对, 生成差异单
reconcileService.compare(reconcileOrder);
}
}

View File

@@ -1,42 +0,0 @@
package cn.daxpay.single.service.task.service;
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
import cn.daxpay.single.service.core.payment.sync.service.RefundSyncService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 定时
* @author xxm
* @since 2024/3/12
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class RefundSyncTaskService {
private final RefundSyncService refundSyncService;
private final RefundOrderManager refundOrderManager;
/**
* 同步任务
*/
public void syncTask(){
// 查询退款中的退款订单
List<RefundOrder> list = refundOrderManager.findAllByProgress();
for (RefundOrder refundOrder : list) {
try {
// 调用同步方法
refundSyncService.syncRefundOrder(refundOrder);
} catch (Exception e) {
log.warn("退款执行同步失败, ID: {}",refundOrder.getId());
log.warn("退款执行同步失败",e);
}
}
}
}