feat 通知消息功能编写, 退款相关类去除pay前缀

This commit is contained in:
bootx
2024-02-22 01:24:22 +08:00
parent 3ef655aa3e
commit 84d1c2f451
69 changed files with 675 additions and 471 deletions

View File

@@ -18,8 +18,8 @@ public class ApiInfoLocal {
/** 是否开启通知 */
private boolean notice;
/** 只有异步支付才进行通知 */
private boolean onlyAsyncNotice;
/** 回调地址 */
private String noticeUrl;
/** 请求参数是否签名 */
private boolean reqSign;

View File

@@ -12,10 +12,19 @@ import lombok.experimental.Accessors;
@Accessors(chain = true)
public class NoticeLocal {
/** 异步回调地址 */
/**
* 异步回调地址
* 如果系统关闭回调, 则通知地址为空
* 如果传输参数中不进行回调为true, 则通知地址为空
* 如果传输参数地址为空, 读取接口配置回调地址
* 如果接口配置为空, 读取系统平台配置的回调地址
*/
private String notifyUrl;
/** 同步回调地址 */
/**
* 同步回调地址, 这个一定会触发, 只有支付会触发且无法关闭
* 如果参数中不传输, 会自动读取系统平台配置的回调地址
*/
private String returnUrl;
/** 退出回调地址 */

View File

@@ -28,6 +28,9 @@ public class PlatformLocal {
/** 支付通知地址 */
private String notifyUrl;
/** 支付同步跳转地址 */
private String returnUrl;
/** 订单支付超时(分钟) */
private Integer orderTimeout;
}

View File

@@ -14,20 +14,12 @@ import java.time.LocalDateTime;
@Accessors(chain = true)
public class RequestLocal {
/** 接口信息 */
/** 客户端ip */
private String clientIp;
/** 商户扩展参数,回调时会原样返回 */
private String attach;
/** 签名 */
private String sign;
/** API版本号 */
private String version;
/** 请求时间,时间戳转时间 */
private LocalDateTime reqTime;

View File

@@ -9,8 +9,8 @@ import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliPayRecordMana
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord;
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.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
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.dto.channel.alipay.AliPayRecordDto;
import cn.bootx.platform.daxpay.service.param.channel.alipay.AliPayRecordQuery;
import lombok.RequiredArgsConstructor;
@@ -45,7 +45,7 @@ public class AliPayRecordService {
/**
* 退款
*/
public void refund(PayRefundOrder order, PayRefundChannelOrder channelOrder){
public void refund(RefundOrder order, RefundChannelOrder channelOrder){
AliPayRecord aliPayRecord = new AliPayRecord()
.setType(AliPayRecordTypeEnum.PAY.getCode())
.setTitle(order.getTitle())

View File

@@ -5,7 +5,7 @@ import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.service.code.AliPayCode;
import cn.bootx.platform.daxpay.service.common.context.RefundLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.response.AlipayTradeRefundResponse;
@@ -29,7 +29,7 @@ public class AliPayRefundService {
/**
* 退款, 调用支付宝退款
*/
public void refund(PayRefundOrder refundOrder, int amount) {
public void refund(RefundOrder refundOrder, int amount) {
RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo();
AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
refundModel.setOutTradeNo(String.valueOf(refundOrder.getPaymentId()));

View File

@@ -5,7 +5,7 @@ import cn.bootx.platform.daxpay.code.RefundSyncStatusEnum;
import cn.bootx.platform.daxpay.code.PaySyncStatusEnum;
import cn.bootx.platform.daxpay.service.code.AliPayCode;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncResult;
import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult;
import cn.hutool.json.JSONUtil;
@@ -96,7 +96,7 @@ public class AliPaySyncService {
* 退款同步查询
* 注意: 支付宝退款没有网关订单号, 网关订单号是支付单的
*/
public RefundGatewaySyncResult syncRefundStatus(PayRefundOrder refundOrder) {
public RefundGatewaySyncResult syncRefundStatus(RefundOrder refundOrder) {
RefundGatewaySyncResult syncResult = new RefundGatewaySyncResult().setSyncStatus(RefundSyncStatusEnum.FAIL);
try {
AlipayTradeFastpayRefundQueryModel queryModel = new AlipayTradeFastpayRefundQueryModel();

View File

@@ -7,7 +7,7 @@ import cn.bootx.platform.daxpay.service.code.CashRecordTypeEnum;
import cn.bootx.platform.daxpay.service.core.channel.cash.dao.CashRecordManager;
import cn.bootx.platform.daxpay.service.core.channel.cash.entity.CashRecord;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.dto.channel.cash.CashRecordDto;
import cn.bootx.platform.daxpay.service.param.channel.cash.CashRecordQuery;
import lombok.RequiredArgsConstructor;
@@ -41,7 +41,7 @@ public class CashRecordService {
/**
* 退款保存
*/
public void refund(PayRefundChannelOrder channelOrder, String title){
public void refund(RefundChannelOrder channelOrder, String title){
CashRecord record = new CashRecord()
.setTitle(title)
.setType(CashRecordTypeEnum.REFUND.getCode())

View File

@@ -8,7 +8,7 @@ import cn.bootx.platform.daxpay.service.core.channel.voucher.dao.VoucherRecordMa
import cn.bootx.platform.daxpay.service.core.channel.voucher.entity.Voucher;
import cn.bootx.platform.daxpay.service.core.channel.voucher.entity.VoucherRecord;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.dto.channel.voucher.VoucherRecordDto;
import cn.bootx.platform.daxpay.service.param.channel.voucher.VoucherRecordQuery;
import lombok.RequiredArgsConstructor;
@@ -59,7 +59,7 @@ public class VoucherRecordService {
/**
* 退款保存
*/
public void refund(PayRefundChannelOrder channelOrder, String title, Voucher voucher){
public void refund(RefundChannelOrder channelOrder, String title, Voucher voucher){
VoucherRecord voucherRecord = new VoucherRecord()
.setTitle(title)
.setType(VoucherRecordTypeEnum.REFUND.getCode())

View File

@@ -9,7 +9,7 @@ import cn.bootx.platform.daxpay.service.core.channel.wallet.dao.WalletRecordMana
import cn.bootx.platform.daxpay.service.core.channel.wallet.entity.Wallet;
import cn.bootx.platform.daxpay.service.core.channel.wallet.entity.WalletRecord;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.dto.channel.wallet.WalletRecordDto;
import cn.bootx.platform.daxpay.service.param.channel.wallet.WalletRecordQuery;
import cn.hutool.core.util.StrUtil;
@@ -88,7 +88,7 @@ public class WalletRecordService {
/**
* 退款保存
*/
public void refund(PayRefundChannelOrder channelOrder, String title, Wallet wallet){
public void refund(RefundChannelOrder channelOrder, String title, Wallet wallet){
WalletRecord walletRecord = new WalletRecord()
.setTitle(title)
.setType(WalletRecordTypeEnum.REFUND.getCode())

View File

@@ -9,8 +9,8 @@ import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WeChatPayRecordM
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayRecord;
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.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
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.dto.channel.wechat.WeChatPayRecordDto;
import cn.bootx.platform.daxpay.service.param.channel.wechat.WeChatPayRecordQuery;
import lombok.RequiredArgsConstructor;
@@ -44,7 +44,7 @@ public class WeChatPayRecordService {
/**
* 退款
*/
public void refund(PayRefundOrder order, PayRefundChannelOrder channelOrder){
public void refund(RefundOrder order, RefundChannelOrder channelOrder){
WeChatPayRecord weChatPayRecord = new WeChatPayRecord()
.setType(AliPayRecordTypeEnum.PAY.getCode())
.setTitle(order.getTitle())

View File

@@ -6,7 +6,7 @@ import cn.bootx.platform.daxpay.code.PaySyncStatusEnum;
import cn.bootx.platform.daxpay.service.code.WeChatPayCode;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncResult;
import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult;
import cn.hutool.core.date.DatePattern;
@@ -102,7 +102,7 @@ public class WeChatPaySyncService {
/**
* 退款信息查询
*/
public RefundGatewaySyncResult syncRefundStatus(PayRefundOrder refundOrder, WeChatPayConfig weChatPayConfig){
public RefundGatewaySyncResult syncRefundStatus(RefundOrder refundOrder, WeChatPayConfig weChatPayConfig){
RefundGatewaySyncResult syncResult = new RefundGatewaySyncResult();
Map<String, String> params = RefundQueryModel.builder()
.appid(weChatPayConfig.getWxAppId())

View File

@@ -8,7 +8,7 @@ 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.dao.PayChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.ijpay.core.enums.SignType;
@@ -39,7 +39,7 @@ public class WechatRefundService {
* 退款方法
* 微信需要同时传输订单金额或退款金额
*/
public void refund(PayRefundOrder refundOrder, int amount, PayChannelOrder orderChannel, WeChatPayConfig weChatPayConfig) {
public void refund(RefundOrder refundOrder, int amount, PayChannelOrder orderChannel, WeChatPayConfig weChatPayConfig) {
String refundFee = String.valueOf(amount);
String totalFee = String.valueOf(orderChannel.getAmount());
// 设置退款信息

View File

@@ -1,105 +0,0 @@
package cn.bootx.platform.daxpay.service.core.notice.service;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
import cn.bootx.platform.daxpay.service.common.context.ApiInfoLocal;
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.notice.result.PayChannelResult;
import cn.bootx.platform.daxpay.service.core.notice.result.PayNoticeResult;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderExtraManager;
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.PayOrderQueryService;
import cn.bootx.platform.daxpay.util.PaySignUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 支付相关消息通知
* @author xxm
* @since 2024/1/7
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class PayNoticeService {
private final PayOrderQueryService payOrderQueryService;
private final PayOrderExtraManager payOrderExtraManager;
private final PayChannelOrderManager payChannelOrderManager;
/**
* 发送支付完成回调通知
*/
public void sendPayCallbackNotice(Long paymentId){
try {
// 获取通知地址和内容相关的信息
ApiInfoLocal apiInfo = PaymentContextLocal.get().getApiInfo();
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
// 首先判断接口是开启了通知回调功能
if (apiInfo.isNotice()){
PayOrder payOrder = payOrderQueryService.findById(paymentId).orElseThrow(DataNotExistException::new);
// 判断是否是同步支付, 并且配置不进行消息通知
if (!payOrder.isAsyncPay() && apiInfo.isOnlyAsyncNotice()){
return;
}
// 判断客户端发送的请求是否需要发送回调通知
PayOrderExtra payOrderExtra = payOrderExtraManager.findById(paymentId).orElseThrow(DataNotExistException::new);
if (payOrderExtra.isNotNotify()){
return;
}
List<PayChannelResult> orderChannels = payChannelOrderManager.findAllByPaymentId(paymentId).stream()
.map(o->new PayChannelResult().setChannel(o.getChannel()).setWay(o.getPayWay()).setAmount(o.getAmount()))
.collect(Collectors.toList());
// 组装内容
PayNoticeResult payNoticeResult = new PayNoticeResult()
.setPaymentId(payOrder.getId())
.setAsyncPay(payOrder.isAsyncPay())
.setBusinessNo(payOrder.getBusinessNo())
.setAmount(payOrder.getAmount())
.setPayTime(payOrder.getPayTime())
.setCreateTime(payOrder.getCreateTime())
.setStatus(payOrder.getStatus())
.setAttach(payOrderExtra.getAttach())
.setPayChannels(orderChannels);
// 是否需要签名
if (apiInfo.isNoticeSign()){
// 签名
if (Objects.equals(platform.getSignType(), PaySignTypeEnum.MD5.getCode())){
payNoticeResult.setSign(PaySignUtil.md5Sign(payNoticeResult,platform.getSignSecret()));
} else {
payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,platform.getSignSecret()));
}
}
// 地址
String notifyUrl = payOrderExtra.getNotifyUrl();
if (StrUtil.isBlank(notifyUrl)){
throw new DataNotExistException("通知地址为空");
}
// 发送请求数据
HttpResponse execute = HttpUtil.createPost(notifyUrl)
.body(JSONUtil.toJsonStr(payNoticeResult), ContentType.JSON.getValue())
.timeout(10000)
.execute();
log.info(execute.body());
}
} catch (Exception e) {
log.error("发送失败",e);
// 记录错误信息, 同时配置下次通知的时间
}
}
}

View File

@@ -74,13 +74,11 @@ public class PayBuilder {
PayOrderExtra payOrderExtra = new PayOrderExtra()
.setClientIp(payParam.getClientIp())
.setDescription(payParam.getDescription())
.setNotNotify(payParam.isNotNotify())
.setNotifyUrl(noticeInfo.getNotifyUrl())
.setReturnUrl(noticeInfo.getReturnUrl())
.setReqSign(payParam.getSign())
.setReqSignType(platform.getSignType())
.setAttach(payParam.getAttach())
.setApiVersion(payParam.getVersion())
.setReqTime(payParam.getReqTime());
payOrderExtra.setId(paymentId);
return payOrderExtra;

View File

@@ -32,29 +32,22 @@ public class PayOrderExtra extends MpBaseEntity implements EntityBaseFunction<Pa
@DbColumn(comment = "描述")
private String description;
/** 支付终端ip */
@DbColumn(comment = "支付终端ip")
private String clientIp;
/** 同步跳转地址, 以最后一次为准 */
@DbColumn(comment = "同步跳转地址")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String returnUrl;
/** 是否需要异步通知,以最后一次为准 */
@DbColumn(comment = "是否不需要异步通知")
private boolean notNotify;
@DbColumn(comment = "回调通知时是否需要进行签名")
private boolean noticeSign;
/** 异步通知地址 */
@DbColumn(comment = "异步通知地址,以最后一次为准")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String notifyUrl;
/** 同步调转地址 */
@DbColumn(comment = "同步调转地址,以最后一次为准")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String returnUrl;
@DbColumn(comment = "是否需要通知客户系统")
private boolean notice;
@DbColumn(comment = "回调通知时是否需要进行签名")
private boolean noticeSign;
/** 商户扩展参数,回调时会原样返回 */
@DbColumn(comment = "商户扩展参数")
private String attach;
/** 请求签名类型 */
@DbColumn(comment = "签名类型")
@@ -68,14 +61,20 @@ public class PayOrderExtra extends MpBaseEntity implements EntityBaseFunction<Pa
@DbColumn(comment = "商户扩展参数")
private String attach;
/** API版本号 */
@DbColumn(comment = "API版本号")
private String apiVersion;
/** 请求时间,时间戳转时间, 以最后一次为准 */
@DbColumn(comment = "请求时间,传输时间戳,以最后一次为准")
private LocalDateTime reqTime;
/** 支付终端ip */
@DbColumn(comment = "支付终端ip")
private String clientIp;
/** 请求链路ID */
@DbColumn(comment = "请求链路ID")
private String reqId;
/** 错误码 */
@DbColumn(comment = "错误码")
private String errorCode;

View File

@@ -10,7 +10,7 @@ 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;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
@@ -94,7 +94,7 @@ public class PayChannelOrderService {
/**
* 更新异步支付通道退款余额和状态
*/
public void updateAsyncPayRefund(PayChannelOrder payChannelOrder, PayRefundChannelOrder refundChannelOrder){
public void updateAsyncPayRefund(PayChannelOrder payChannelOrder, RefundChannelOrder refundChannelOrder){
// 支付通道订单状态
if (Objects.equals(refundChannelOrder.getStatus(), RefundStatusEnum.SUCCESS.getCode())){
// 如果可退金额为0说明已经全部退款

View File

@@ -1,23 +0,0 @@
package cn.bootx.platform.daxpay.service.core.order.refund.convert;
import cn.bootx.platform.daxpay.result.order.RefundOrderResult;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.dto.order.refund.PayRefundOrderDto;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* @author xxm
* @since 2022/3/2
*/
@Mapper
public interface PayRefundOrderConvert {
PayRefundOrderConvert CONVERT = Mappers.getMapper(PayRefundOrderConvert.class);
PayRefundOrderDto convert(PayRefundOrder in);
RefundOrderResult convertResult(PayRefundOrder in);
}

View File

@@ -1,7 +1,7 @@
package cn.bootx.platform.daxpay.service.core.order.refund.convert;
import cn.bootx.platform.daxpay.result.order.RefundChannelOrderResult;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@@ -16,8 +16,8 @@ public interface RefundOrderChannelConvert {
RefundOrderChannelConvert CONVERT = Mappers.getMapper(RefundOrderChannelConvert.class);
RefundChannelOrderDto convert(PayRefundChannelOrder in);
RefundChannelOrderDto convert(RefundChannelOrder in);
RefundChannelOrderResult convertResult(PayRefundChannelOrder in);
RefundChannelOrderResult convertResult(RefundChannelOrder in);
}

View File

@@ -0,0 +1,23 @@
package cn.bootx.platform.daxpay.service.core.order.refund.convert;
import cn.bootx.platform.daxpay.result.order.RefundOrderResult;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundOrderDto;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* @author xxm
* @since 2022/3/2
*/
@Mapper
public interface RefundOrderConvert {
RefundOrderConvert CONVERT = Mappers.getMapper(RefundOrderConvert.class);
RefundOrderDto convert(RefundOrder in);
RefundOrderResult convertResult(RefundOrder in);
}

View File

@@ -1,7 +1,7 @@
package cn.bootx.platform.daxpay.service.core.order.refund.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
@@ -17,22 +17,22 @@ import java.util.Optional;
@Slf4j
@Repository
@RequiredArgsConstructor
public class PayRefundChannelOrderManager extends BaseManager<PayRefundChannelOrderMapper, PayRefundChannelOrder> {
public class RefundChannelOrderManager extends BaseManager<RefundChannelOrderMapper, RefundChannelOrder> {
/**
* 根据退款单ID查找
*/
public List<PayRefundChannelOrder> findAllByRefundId(Long paymentId){
return findAllByField(PayRefundChannelOrder::getRefundId,paymentId);
public List<RefundChannelOrder> findAllByRefundId(Long paymentId){
return findAllByField(RefundChannelOrder::getRefundId,paymentId);
}
/**
* 根据退款单ID和退款通道查询
*/
public Optional<PayRefundChannelOrder> findByRefundIdAndChannel(Long refundId, String channel) {
public Optional<RefundChannelOrder> findByRefundIdAndChannel(Long refundId, String channel) {
return lambdaQuery()
.eq(PayRefundChannelOrder::getRefundId,refundId)
.eq(PayRefundChannelOrder::getChannel,channel)
.eq(RefundChannelOrder::getRefundId,refundId)
.eq(RefundChannelOrder::getChannel,channel)
.oneOpt();
}
}

View File

@@ -1,6 +1,6 @@
package cn.bootx.platform.daxpay.service.core.order.refund.dao;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Mapper;
* @since 2024/1/17
*/
@Mapper
public interface PayRefundChannelOrderMapper extends BaseMapper<PayRefundChannelOrder> {
public interface RefundChannelOrderMapper extends BaseMapper<RefundChannelOrder> {
}

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.order.refund.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrderExtra;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/2/22
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class RefundOrderExtraManager extends BaseManager<RefundOrderExtraMapper, RefundOrderExtra> {
}

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.service.core.order.refund.dao;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrderExtra;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/2/22
*/
@Mapper
public interface RefundOrderExtraMapper extends BaseMapper<RefundOrderExtra> {
}

View File

@@ -4,8 +4,8 @@ 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.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.param.order.PayRefundOrderQuery;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.bootx.platform.daxpay.service.param.order.RefundOrderQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
@@ -22,28 +22,28 @@ import java.util.Optional;
@Slf4j
@Repository
@RequiredArgsConstructor
public class PayRefundOrderManager extends BaseManager<PayRefundOrderMapper, PayRefundOrder> {
public class RefundOrderManager extends BaseManager<RefundOrderMapper, RefundOrder> {
/**
* 分页
*/
public Page<PayRefundOrder> page(PageParam pageParam, PayRefundOrderQuery query) {
Page<PayRefundOrder> mpPage = MpUtil.getMpPage(pageParam, PayRefundOrder.class);
QueryWrapper<PayRefundOrder> generator = QueryGenerator.generator(query);
public Page<RefundOrder> page(PageParam pageParam, RefundOrderQuery query) {
Page<RefundOrder> mpPage = MpUtil.getMpPage(pageParam, RefundOrder.class);
QueryWrapper<RefundOrder> generator = QueryGenerator.generator(query);
return page(mpPage,generator);
}
/**
* 根据退款号查询
*/
public Optional<PayRefundOrder> findByRefundNo(String refundNo) {
return findByField(PayRefundOrder::getRefundNo, refundNo);
public Optional<RefundOrder> findByRefundNo(String refundNo) {
return findByField(RefundOrder::getRefundNo, refundNo);
}
/**
* 查询支付号是否重复
*/
public boolean existsByRefundNo(String refundNo){
return this.existedByField(PayRefundOrder::getRefundNo,refundNo);
return this.existedByField(RefundOrder::getRefundNo,refundNo);
}
}

View File

@@ -1,6 +1,6 @@
package cn.bootx.platform.daxpay.service.core.order.refund.dao;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@@ -9,6 +9,6 @@ import org.apache.ibatis.annotations.Mapper;
* @since 2022/3/2
*/
@Mapper
public interface PayRefundOrderMapper extends BaseMapper<PayRefundOrder> {
public interface RefundOrderMapper extends BaseMapper<RefundOrder> {
}

View File

@@ -26,7 +26,7 @@ import java.time.LocalDateTime;
@DbTable(comment = "支付退款通道订单")
@Accessors(chain = true)
@TableName("pay_refund_channel_order")
public class PayRefundChannelOrder extends MpCreateEntity implements EntityBaseFunction<RefundChannelOrderDto> {
public class RefundChannelOrder extends MpCreateEntity implements EntityBaseFunction<RefundChannelOrderDto> {
@DbColumn(comment = "关联退款id")
private Long refundId;

View File

@@ -4,8 +4,8 @@ import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
import cn.bootx.platform.daxpay.service.core.order.refund.convert.PayRefundOrderConvert;
import cn.bootx.platform.daxpay.service.dto.order.refund.PayRefundOrderDto;
import cn.bootx.platform.daxpay.service.core.order.refund.convert.RefundOrderConvert;
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundOrderDto;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
@@ -29,7 +29,7 @@ import java.time.LocalDateTime;
@Accessors(chain = true)
@DbTable(comment = "退款订单")
@TableName(value = "pay_refund_order", autoResultMap = true)
public class PayRefundOrder extends MpBaseEntity implements EntityBaseFunction<PayRefundOrderDto> {
public class RefundOrder extends MpBaseEntity implements EntityBaseFunction<RefundOrderDto> {
/** 关联支付id */
@DbColumn(comment = "关联支付id")
@@ -77,14 +77,6 @@ public class PayRefundOrder extends MpBaseEntity implements EntityBaseFunction<P
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Integer refundableBalance;
/** 请求链路ID */
@DbColumn(comment = "请求链路ID")
private String reqId;
/** 退款终端ip */
@DbColumn(comment = "退款终端ip")
private String clientIp;
/** 退款原因 */
@DbColumn(comment = "退款原因")
private String reason;
@@ -109,8 +101,8 @@ public class PayRefundOrder extends MpBaseEntity implements EntityBaseFunction<P
private String errorMsg;
@Override
public PayRefundOrderDto toDto() {
return PayRefundOrderConvert.CONVERT.convert(this);
public RefundOrderDto toDto() {
return RefundOrderConvert.CONVERT.convert(this);
}
}

View File

@@ -0,0 +1,60 @@
package cn.bootx.platform.daxpay.service.core.order.refund.entity;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 退款订单扩展信息
* @author xxm
* @since 2024/2/21
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("pay_refund_order_extra")
@DbTable(comment = "退款订单扩展信息")
public class RefundOrderExtra extends MpBaseEntity {
/** 回调通知时是否需要进行签名 */
@DbColumn(comment = "回调通知时是否需要进行签名")
private boolean noticeSign;
/** 异步通知地址 */
@DbColumn(comment = "异步通知地址")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String notifyUrl;
/** 商户扩展参数,回调时会原样返回 */
@DbColumn(comment = "商户扩展参数")
private String attach;
/** 请求签名类型 */
@DbColumn(comment = "请求签名值")
private String reqSignType;
/** 请求签名值 */
@DbColumn(comment = "请求签名值")
private String reqSign;
/** 请求链路ID */
@DbColumn(comment = "请求链路ID")
private String reqId;
/** 请求时间,时间戳转时间 */
@DbColumn(comment = "请求时间,传输时间戳")
private LocalDateTime reqTime;
/** 终端ip */
@DbColumn(comment = "支付终端ip")
private String clientIp;
}

View File

@@ -8,15 +8,15 @@ import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.bootx.platform.daxpay.param.pay.QueryRefundParam;
import cn.bootx.platform.daxpay.result.order.RefundChannelOrderResult;
import cn.bootx.platform.daxpay.result.order.RefundOrderResult;
import cn.bootx.platform.daxpay.service.core.order.refund.convert.PayRefundOrderConvert;
import cn.bootx.platform.daxpay.service.core.order.refund.convert.RefundOrderConvert;
import cn.bootx.platform.daxpay.service.core.order.refund.convert.RefundOrderChannelConvert;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.dto.order.refund.PayRefundOrderDto;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderManager;
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.dto.order.refund.RefundOrderDto;
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto;
import cn.bootx.platform.daxpay.service.param.order.PayRefundOrderQuery;
import cn.bootx.platform.daxpay.service.param.order.RefundOrderQuery;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
@@ -36,24 +36,24 @@ import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class PayRefundOrderQueryService {
public class RefundOrderQueryService {
private final PayRefundOrderManager refundOrderManager;
private final PayRefundChannelOrderManager refundOrderChannelManager;
private final RefundOrderManager refundOrderManager;
private final RefundChannelOrderManager refundOrderChannelManager;
/**
* 分页查询
*/
public PageResult<PayRefundOrderDto> page(PageParam pageParam, PayRefundOrderQuery query) {
Page<PayRefundOrder> page = refundOrderManager.page(pageParam, query);
public PageResult<RefundOrderDto> page(PageParam pageParam, RefundOrderQuery query) {
Page<RefundOrder> page = refundOrderManager.page(pageParam, query);
return MpUtil.convert2DtoPageResult(page);
}
/**
* 根据id查询
*/
public PayRefundOrderDto findById(Long id) {
return refundOrderManager.findById(id).map(PayRefundOrder::toDto)
public RefundOrderDto findById(Long id) {
return refundOrderManager.findById(id).map(RefundOrder::toDto)
.orElseThrow(() -> new DataNotExistException("退款订单不存在"));
}
@@ -61,7 +61,7 @@ public class PayRefundOrderQueryService {
* 通道退款订单列表查询
*/
public List<RefundChannelOrderDto> listByChannel(Long refundId){
List<PayRefundChannelOrder> refundOrderChannels = refundOrderChannelManager.findAllByRefundId(refundId);
List<RefundChannelOrder> refundOrderChannels = refundOrderChannelManager.findAllByRefundId(refundId);
return refundOrderChannels.stream()
.map(RefundOrderChannelConvert.CONVERT::convert)
.collect(Collectors.toList());
@@ -72,7 +72,7 @@ public class PayRefundOrderQueryService {
*/
public RefundChannelOrderDto findChannelById(Long id) {
return refundOrderChannelManager.findById(id)
.map(PayRefundChannelOrder::toDto)
.map(RefundChannelOrder::toDto)
.orElseThrow(() -> new DataNotExistException("通道退款订单不存在"));
}
@@ -86,7 +86,7 @@ public class PayRefundOrderQueryService {
}
// 查询退款单
PayRefundOrder refundOrder = null;
RefundOrder refundOrder = null;
if (Objects.nonNull(param.getRefundId())){
refundOrder = refundOrderManager.findById(param.getRefundId())
.orElseThrow(() -> new DataNotExistException("未查询到支付订单"));
@@ -96,12 +96,12 @@ public class PayRefundOrderQueryService {
.orElseThrow(() -> new DataNotExistException("未查询到支付订单"));
}
// 查询退款明细
List<PayRefundChannelOrder> refundOrderChannels = refundOrderChannelManager.findAllByRefundId(refundOrder.getId());
List<RefundChannelOrder> refundOrderChannels = refundOrderChannelManager.findAllByRefundId(refundOrder.getId());
List<RefundChannelOrderResult> channels = refundOrderChannels.stream()
.map(RefundOrderChannelConvert.CONVERT::convertResult)
.collect(Collectors.toList());
RefundOrderResult refundOrderResult = PayRefundOrderConvert.CONVERT.convertResult(refundOrder);
RefundOrderResult refundOrderResult = RefundOrderConvert.CONVERT.convertResult(refundOrder);
refundOrderResult.setRefundId(refundOrder.getId());
refundOrderResult.setChannels(channels);
return refundOrderResult;

View File

@@ -5,8 +5,8 @@ import cn.bootx.platform.daxpay.service.code.PayCallbackStatusEnum;
import cn.bootx.platform.daxpay.service.code.RefundRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.context.CallbackLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.bootx.platform.daxpay.service.core.payment.repair.result.RefundRepairResult;
import cn.bootx.platform.daxpay.service.core.payment.repair.service.RefundRepairService;
import com.baomidou.lock.LockInfo;
@@ -18,15 +18,15 @@ import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* 支付退款回调
* 退款回调
* @author xxm
* @since 2024/1/24
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class PayRefundCallbackService {
private final PayRefundOrderManager refundOrderManager;
public class RefundCallbackService {
private final RefundOrderManager refundOrderManager;
private final RefundRepairService reflectionService;
@@ -47,7 +47,7 @@ public class PayRefundCallbackService {
}
try {
// 获取退款单
PayRefundOrder refundOrder = refundOrderManager.findById(callbackInfo.getOrderId()).orElse(null);
RefundOrder refundOrder = refundOrderManager.findById(callbackInfo.getOrderId()).orElse(null);
// 退款单不存在,记录回调记录
if (Objects.isNull(refundOrder)) {
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.NOT_FOUND).setMsg("退款单不存在,记录回调记录");

View File

@@ -52,9 +52,7 @@ public class PaymentAssistService {
private void initRequest(PaymentCommonParam paymentCommonParam){
RequestLocal request = PaymentContextLocal.get().getRequestInfo();
request.setClientIp(paymentCommonParam.getClientIp())
// .setAttach(paymentCommonParam.getAttach())
.setSign(paymentCommonParam.getSign())
.setVersion(paymentCommonParam.getVersion())
.setReqTime(paymentCommonParam.getReqTime())
.setReqId(MDC.get(CommonCode.TRACE_ID));
}

View File

@@ -1,4 +1,4 @@
package cn.bootx.platform.daxpay.service.core.notice.result;
package cn.bootx.platform.daxpay.service.core.payment.notice.result;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayWayEnum;

View File

@@ -1,4 +1,4 @@
package cn.bootx.platform.daxpay.service.core.notice.result;
package cn.bootx.platform.daxpay.service.core.payment.notice.result;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;

View File

@@ -0,0 +1,26 @@
package cn.bootx.platform.daxpay.service.core.payment.notice.result;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 退款通道信息
* @author xxm
* @since 2024/2/22
*/
@Data
@Accessors(chain = true)
@Schema(title = "退款通道信息")
public class RefundChannelResult {
/**
* @see PayChannelEnum#getCode()
*/
@Schema(description = "支付通道编码")
private String channel;
@Schema(description = "退款金额")
private Integer amount;
}

View File

@@ -0,0 +1,61 @@
package cn.bootx.platform.daxpay.service.core.payment.notice.result;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
/**
*
* @author xxm
* @since 2024/2/22
*/
@Data
@Accessors(chain = true)
@Schema(title = "退款通知消息")
public class RefundNoticeResult {
@Schema(description = "退款ID")
private Long refundId;
@Schema(description = "退款号")
private String refundNo;
@Schema(description = "是否含有异步通道")
private boolean asyncPay;
/**
* @see PayChannelEnum#ASYNC_TYPE_CODE
*/
@Schema(description = "异步支付通道")
private String asyncChannel;
@Schema(description = "退款金额")
private Integer amount;
@Schema(description = "退款通道信息")
private List<RefundChannelResult> refundChannels;
/**
* @see RefundStatusEnum
*/
@Schema(description = "退款状态")
private String status;
@Schema(description = "退款成功时间")
private LocalDateTime refundTime;
@Schema(description = "退款创建时间")
private LocalDateTime createTime;
@Schema(description = "商户扩展参数,回调时会原样返回")
private String attach;
@Schema(description = "签名")
private String sign;
}

View File

@@ -6,22 +6,30 @@ import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.common.redis.RedisClient;
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum;
import cn.bootx.platform.daxpay.service.core.notice.result.PayChannelResult;
import cn.bootx.platform.daxpay.service.core.notice.result.PayNoticeResult;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderExtraManager;
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.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;
@@ -44,9 +52,13 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class ClientNoticeService {
private final PayOrderExtraManager orderExtraManager;
private final PayOrderExtraManager payOrderExtraManager;
private final PayChannelOrderManager channelOrderManager;
private final PayChannelOrderManager payChannelOrderManager;
private final RefundOrderExtraManager refundOrderExtraManager;
private final RefundChannelOrderManager refundChannelOrderManager;
private final PlatformConfigService configService;
@@ -61,30 +73,30 @@ public class ClientNoticeService {
private static final Map<Integer,Integer> DELAY_TIME = new HashMap<>();
/*
* key: 当前通知次数, value 下次通知的时间间隔
* 初始化延迟时间表, 总共会发起16次通知吗, 总计 24h4m
* 通知频率为0s/15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h
*/
static {
DELAY_TIME.put(1, 0);
DELAY_TIME.put(1, 15 * 1000);
DELAY_TIME.put(2, 15 * 1000);
DELAY_TIME.put(3, 15 * 1000);
DELAY_TIME.put(4, 30 * 1000);
DELAY_TIME.put(5, 3 * 60 * 1000);
DELAY_TIME.put(6, 10 * 60 * 1000);
DELAY_TIME.put(7, 20 * 60 * 1000);
DELAY_TIME.put(3, 30 * 1000);
DELAY_TIME.put(4, 3 * 60 * 1000);
DELAY_TIME.put(5, 10 * 60 * 1000);
DELAY_TIME.put(6, 20 * 60 * 1000);
DELAY_TIME.put(7, 30 * 60 * 1000);
DELAY_TIME.put(8, 30 * 60 * 1000);
DELAY_TIME.put(9, 30 * 60 * 1000);
DELAY_TIME.put(10, 30 * 60 * 1000);
DELAY_TIME.put(11, 60 * 60 * 1000);
DELAY_TIME.put(10, 60 * 60 * 1000);
DELAY_TIME.put(11, 3 * 60 * 60 * 1000);
DELAY_TIME.put(12, 3 * 60 * 60 * 1000);
DELAY_TIME.put(13, 3 * 60 * 60 * 1000);
DELAY_TIME.put(14, 3 * 60 * 60 * 1000);
DELAY_TIME.put(14, 6 * 60 * 60 * 1000);
DELAY_TIME.put(15, 6 * 60 * 60 * 1000);
DELAY_TIME.put(16, 6 * 60 * 60 * 1000);
}
/**
* 注册支付消息通知任务, 失败重试3次, 间隔一秒
* 注册支付消息通知任务
* @param order 支付订单
* @param orderExtra 支付订单扩展信息
* @param channelOrders 支付通道订单
@@ -93,30 +105,30 @@ public class ClientNoticeService {
public void registerPayNotice(PayOrder order, PayOrderExtra orderExtra, List<PayChannelOrder> channelOrders) {
// 支付订单扩展信息为空则进行查询
if (Objects.isNull(orderExtra)){
Optional<PayOrderExtra> extraOpt = orderExtraManager.findById(order.getId());
Optional<PayOrderExtra> extraOpt = payOrderExtraManager.findById(order.getId());
if (!extraOpt.isPresent()){
log.error("未找到支付扩展信息数据错误订单ID{}",order.getId());
return;
}
orderExtra = extraOpt.get();
}
// 通道支付订单为空则进行查询
if (CollUtil.isEmpty(channelOrders)){
channelOrders = channelOrderManager.findAllByPaymentId(order.getId());
// 判断是否需要进行通知
if (StrUtil.isBlank(orderExtra.getNotifyUrl())){
log.info("支付订单无需通知订单ID{}",order.getId());
}
// 将任务写入到任务表中
ClientNoticeTask task = new ClientNoticeTask()
.setType(ClientNoticeTypeEnum.PAY.getType())
.setUrl(orderExtra.getNotifyUrl())
.setSendCount(0);
// 通道支付订单为空则进行查询
if (CollUtil.isEmpty(channelOrders)){
channelOrders = payChannelOrderManager.findAllByPaymentId(order.getId());
}
// 创建通知任务并保存
ClientNoticeTask task = this.buildPayTask(order, orderExtra, channelOrders);
try {
taskManager.save(task);
} catch (Exception e) {
log.error("注册支付消息通知任务失败数据错误订单ID{}",order.getId());
throw new RuntimeException(e);
}
try {
// 同时触发一次通知, 如果成功发送, 任务结束
this.sendData(task, LocalDateTime.now());
@@ -126,9 +138,9 @@ public class ClientNoticeService {
}
/**
* 构建出任务对象
* 构建出支付通知任务对象
*/
private void buildTask(PayOrder order, PayOrderExtra orderExtra, List<PayChannelOrder> channelOrders){
private ClientNoticeTask buildPayTask(PayOrder order, PayOrderExtra orderExtra, List<PayChannelOrder> channelOrders){
// 组装内容
List<PayChannelResult> channels = channelOrders.stream()
.map(o->new PayChannelResult().setChannel(o.getChannel()).setWay(o.getPayWay()).setAmount(o.getAmount()))
@@ -155,13 +167,102 @@ public class ClientNoticeService {
payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,config.getSignSecret()));
}
}
return new ClientNoticeTask()
.setUrl(orderExtra.getNotifyUrl())
.setContent(JSONUtil.toJsonStr(payNoticeResult))
.setType(ClientNoticeTypeEnum.PAY.getType())
.setSendCount(0)
.setOrderId(order.getId());
}
/**
* 注册退款消息通知任务
* @param order 退款订单
* @param orderExtra 退款订单扩展信息
* @param channelOrders 退款通道订单
*/
@Async("bigExecutor")
public void registerRefundNotice(RefundOrder order, PayOrderExtra orderExtra, List<RefundChannelOrder> channelOrders) {
// 退款订单扩展信息为空则进行查询
if (Objects.isNull(orderExtra)){
Optional<PayOrderExtra> extraOpt = payOrderExtraManager.findById(order.getId());
if (!extraOpt.isPresent()){
log.error("未找到支付扩展信息数据错误订单ID{}",order.getId());
return;
}
orderExtra = extraOpt.get();
}
// 判断是否需要进行通知
if (StrUtil.isBlank(orderExtra.getNotifyUrl())){
log.info("退款订单无需通知订单ID{}",order.getId());
}
// 通道退款订单为空则进行查询
if (CollUtil.isEmpty(channelOrders)){
channelOrders = refundChannelOrderManager.findAllByRefundId(order.getId());
}
// 创建通知任务并保存
ClientNoticeTask task = this.buildRefundTask(order, orderExtra, channelOrders);
try {
taskManager.save(task);
} catch (Exception e) {
log.error("注册退款消息通知任务失败数据错误订单ID{}",order.getId());
throw new RuntimeException(e);
}
try {
// 同时触发一次通知, 如果成功发送, 任务结束
this.sendData(task, LocalDateTime.now());
} catch (HttpException e) {
this.failHandler(task, LocalDateTime.now());
}
}
/**
* 构建出退款通知任务对象
*/
private ClientNoticeTask buildRefundTask(RefundOrder order, PayOrderExtra orderExtra, List<RefundChannelOrder> channelOrders){
// 组装内容
List<RefundChannelResult> channels = channelOrders.stream()
.map(o->new RefundChannelResult().setChannel(o.getChannel()).setAmount(o.getAmount()))
.collect(Collectors.toList());
RefundNoticeResult payNoticeResult = new RefundNoticeResult()
.setRefundId(order.getId())
.setAsyncPay(order.isAsyncPay())
.setAsyncChannel(order.getAsyncChannel())
.setRefundNo(order.getRefundNo())
.setAmount(order.getAmount())
.setRefundTime(order.getRefundTime())
.setCreateTime(order.getCreateTime())
.setStatus(order.getStatus())
.setAttach(orderExtra.getAttach())
.setRefundChannels(channels);
PlatformConfig config = configService.getConfig();
// 是否需要签名
if (orderExtra.isNoticeSign()){
// 签名
if (Objects.equals(config.getSignType(), PaySignTypeEnum.MD5.getCode())){
payNoticeResult.setSign(PaySignUtil.md5Sign(payNoticeResult,config.getSignSecret()));
} else {
payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,config.getSignSecret()));
}
}
return new ClientNoticeTask()
.setUrl(orderExtra.getNotifyUrl())
.setContent(JSONUtil.toJsonStr(payNoticeResult))
.setType(ClientNoticeTypeEnum.PAY.getType())
.setSendCount(0)
.setOrderId(order.getId());
}
/**
* 从redis中执行任务, 通过定时任务触发
*/
@Async("asyncExecutor")
public void taskRun(long start, long end){
public void taskStart(long start, long end){
// 查询Redis任务表,获取任务
Set<String> taskIds = redisClient.zrangeByScore(KEY, start, end);
// 发起一个异步任务,
@@ -199,7 +300,7 @@ public class ClientNoticeService {
}
/**
* 处理任务, 出现异常直接抛出
* 发送通知数据, 如果失败, 注册下次重发的任务
*/
private void sendData(ClientNoticeTask task, LocalDateTime now){
HttpResponse execute = HttpUtil.createPost(task.getUrl())
@@ -220,35 +321,25 @@ public class ClientNoticeService {
*/
private void successHandler(ClientNoticeTask task){
// 记录成功并保存
task.setSendCount(task.getSendCount() + 1);
task.setSuccess(true);
taskManager.updateById(task);
}
/**
* 失败处理, 首先发送次数+1, 然后
* 失败处理, 首先发送次数+1, 然后注册后推指定时间的重试任务
*/
private void failHandler(ClientNoticeTask task, LocalDateTime now){
// 次数+1
task.setSendCount(task.getSendCount() + 1);
// 注册任务到redis中
this.pushRedis(task, now);
// 更新任务
// 判断发送次数是否未超过15次, 注册任务到redis中
if (task.getSendCount() < 16){
// 根据当前次数和时间计算出毫秒值
Integer delay = DELAY_TIME.get(task.getSendCount());
long taskTime = LocalDateTimeUtil.timestamp(now) + delay;
redisClient.zadd(KEY, String.valueOf(task.getId()), taskTime);
}
// 更新任务信息
taskManager.updateById(task);
}
/**
* 注册到Redis任务列表中
*/
private void pushRedis(ClientNoticeTask task, LocalDateTime now){
// 判断发送次数是否超过16次
if (task.getSendCount() > 16){
return;
}
// 根据当前次数和时间计算出毫秒值
Integer delay = DELAY_TIME.get(task.getSendCount());
long taskTime = LocalDateTimeUtil.timestamp(now) + delay;
redisClient.zadd(KEY, String.valueOf(task.getId()), taskTime);
}
}

View File

@@ -6,6 +6,7 @@ import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
import cn.bootx.platform.daxpay.param.pay.PayParam;
import cn.bootx.platform.daxpay.service.common.context.ApiInfoLocal;
import cn.bootx.platform.daxpay.service.common.context.AsyncPayLocal;
import cn.bootx.platform.daxpay.service.common.context.NoticeLocal;
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
@@ -95,16 +96,26 @@ public class PayAssistService {
*/
private void initNotice(PayParam payParam){
NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo();
ApiInfoLocal apiInfo = PaymentContextLocal.get().getApiInfo();
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
// 异步回调
if (!payParam.isNotNotify()){
noticeInfo.setNotifyUrl(payParam.getReturnUrl());
if (StrUtil.isNotBlank(payParam.getNotifyUrl())){
// 异步回调为开启状态
if (!payParam.isNotNotify() && apiInfo.isNotice()){
// 首先读取请求参数
noticeInfo.setNotifyUrl(payParam.getNotifyUrl());
// 读取接口配置
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
noticeInfo.setNotifyUrl(apiInfo.getNoticeUrl());
}
// 读取平台配置
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
noticeInfo.setNotifyUrl(platform.getNotifyUrl());
}
}
// 同步回调
noticeInfo.setReturnUrl(payParam.getReturnUrl());
noticeInfo.setNotifyUrl(payParam.getReturnUrl());
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
noticeInfo.setNotifyUrl(platform.getNotifyUrl());
}
// 退出回调地址
noticeInfo.setQuitUrl(payParam.getQuitUrl());
}
@@ -150,19 +161,24 @@ public class PayAssistService {
* @param payParam 支付参数
* @param paymentId 支付订单id
*/
public void updatePayOrderExtra(PayParam payParam,Long paymentId){
public PayOrderExtra updatePayOrderExtra(PayParam payParam,Long paymentId){
ApiInfoLocal apiInfo = PaymentContextLocal.get().getApiInfo();
PayOrderExtra payOrderExtra = payOrderExtraManager.findById(paymentId)
.orElseThrow(() -> new DataNotExistException("支付订单不存在"));
String notifyUrl = PaymentContextLocal.get().getNoticeInfo().getNotifyUrl();
String returnUrl = PaymentContextLocal.get().getNoticeInfo().getReturnUrl();
NoticeLocal noticeInfo = PaymentContextLocal.get()
.getNoticeInfo();
String notifyUrl = noticeInfo.getNotifyUrl();
String returnUrl = noticeInfo.getReturnUrl();
payOrderExtra.setReqTime(payParam.getReqTime())
.setReqSign(payParam.getSign())
.setNotNotify(payParam.isNotNotify())
.setNotifyUrl(notifyUrl)
.setReturnUrl(returnUrl)
.setNoticeSign(apiInfo.isNoticeSign())
.setAttach(payParam.getAttach())
.setClientIp(payParam.getClientIp());
payOrderExtraManager.updateById(payOrderExtra);
return payOrderExtraManager.updateById(payOrderExtra);
}
/**

View File

@@ -12,6 +12,7 @@ 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;
import cn.bootx.platform.daxpay.service.core.payment.notice.service.ClientNoticeService;
import cn.bootx.platform.daxpay.service.core.payment.pay.factory.PayStrategyFactory;
@@ -220,18 +221,22 @@ public class PayService {
// 5.2支付发起成功处理
payStrategyList.forEach(AbsPayStrategy::doSuccessHandler);
// 6.1 如果异步支付完成, 进行订单完成处理, 并触发通知
// 6.1 如果异步支付完成, 进行订单完成处理
AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();
if (asyncPayInfo.isPayComplete()) {
payOrder.setGatewayOrderNo(asyncPayInfo.getGatewayOrderNo())
.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
clientNoticeService.registerPayNotice(payOrder,null,null);
}
// 6.2 更新支付订单和扩展参数
payOrderService.updateById(payOrder);
payAssistService.updatePayOrderExtra(payParam,payOrder.getId());
PayOrderExtra payOrderExtra = payAssistService.updatePayOrderExtra(payParam, payOrder.getId());
// 订单完成, 触发通知
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())) {
clientNoticeService.registerPayNotice(payOrder, payOrderExtra,null);
}
// 7. 组装返回参数
return PayBuilder.buildPayResultByPayOrder(payOrder);

View File

@@ -22,7 +22,7 @@ import static cn.bootx.platform.daxpay.code.PayChannelEnum.ASYNC_TYPE_CODE;
* @author xxm
* @since 2023/7/4
*/
public class PayRefundStrategyFactory {
public class RefundStrategyFactory {
/**
* 根据传入的支付通道创建策略
@@ -34,22 +34,22 @@ public class PayRefundStrategyFactory {
PayChannelEnum channelEnum = PayChannelEnum.findByCode(refundChannelParam.getChannel());
switch (channelEnum) {
case ALI:
strategy = SpringUtil.getBean(AliPayRefundStrategy.class);
strategy = SpringUtil.getBean(AliRefundStrategy.class);
break;
case WECHAT:
strategy = SpringUtil.getBean(WeChatPayRefundStrategy.class);
strategy = SpringUtil.getBean(WeChatRefundStrategy.class);
break;
case UNION_PAY:
strategy = SpringUtil.getBean(UnionPayRefundStrategy.class);
strategy = SpringUtil.getBean(UnionRefundStrategy.class);
break;
case CASH:
strategy = SpringUtil.getBean(CashPayRefundStrategy.class);
strategy = SpringUtil.getBean(CashRefundStrategy.class);
break;
case WALLET:
strategy = SpringUtil.getBean(WalletPayRefundStrategy.class);
strategy = SpringUtil.getBean(WalletRefundStrategy.class);
break;
case VOUCHER:
strategy = SpringUtil.getBean(VoucherPayRefundStrategy.class);
strategy = SpringUtil.getBean(VoucherRefundStrategy.class);
break;
default:
throw new PayUnsupportedMethodException();

View File

@@ -3,21 +3,24 @@ package cn.bootx.platform.daxpay.service.core.payment.refund.service;
import cn.bootx.platform.common.core.exception.ValidationFailedException;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.pay.RefundChannelParam;
import cn.bootx.platform.daxpay.param.pay.RefundParam;
import cn.bootx.platform.daxpay.service.common.context.ApiInfoLocal;
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.context.RefundLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
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.dao.RefundOrderManager;
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.order.refund.entity.RefundOrderExtra;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
@@ -42,12 +45,14 @@ import static cn.bootx.platform.daxpay.code.RefundStatusEnum.SUCCESS;
@Slf4j
@Service
@RequiredArgsConstructor
public class PayRefundAssistService {
public class RefundAssistService {
private final PayOrderQueryService payOrderQueryService;
private final PayRefundOrderManager payRefundOrderManager;
private final RefundOrderManager refundOrderManager;
private final PayRefundChannelOrderManager payRefundChannelOrderManager;
private final RefundOrderExtraManager refundOrderExtraManager;
private final RefundChannelOrderManager payRefundChannelOrderManager;
/**
* 初始化上下文
@@ -62,11 +67,18 @@ public class PayRefundAssistService {
*/
private void initNotice(RefundParam param) {
NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo();
ApiInfoLocal apiInfo = PaymentContextLocal.get().getApiInfo();
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
// 异步回调
if (!param.isNotNotify()){
// 异步回调为开启状态
if (!param.isNotNotify() && apiInfo.isNotice()){
// 首先读取请求参数
noticeInfo.setNotifyUrl(param.getNotifyUrl());
if (StrUtil.isNotBlank(param.getNotifyUrl())){
// 读取接口配置
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
noticeInfo.setNotifyUrl(apiInfo.getNoticeUrl());
}
// 读取平台配置
if (StrUtil.isNotBlank(noticeInfo.getNotifyUrl())){
noticeInfo.setNotifyUrl(platform.getNotifyUrl());
}
}
@@ -97,9 +109,6 @@ public class PayRefundAssistService {
if (CollUtil.isEmpty(param.getRefundChannels())) {
throw new ValidationFailedException("退款通道参数不能为空");
}
// if (Objects.isNull(param.getRefundNo())) {
// throw new ValidationFailedException("部分退款时退款单号必传");
// }
}
// 简单退款校验
@@ -127,7 +136,7 @@ public class PayRefundAssistService {
// 退款号唯一校验
if (StrUtil.isNotBlank(param.getRefundNo())
&& payRefundOrderManager.existsByRefundNo(param.getRefundNo())){
&& refundOrderManager.existsByRefundNo(param.getRefundNo())){
throw new PayFailureException("退款单号已存在");
}
}
@@ -136,7 +145,7 @@ public class PayRefundAssistService {
* 预先创建退款相关订单并保存, 使用新事务, 防止丢单
*/
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public PayRefundOrder createOrderAndChannel(RefundParam refundParam, PayOrder payOrder, List<PayRefundChannelOrder> refundChannelOrders) {
public RefundOrder createOrderAndChannel(RefundParam refundParam, PayOrder payOrder, List<RefundChannelOrder> refundChannelOrders) {
// 此次的总退款金额
Integer amount = refundParam.getRefundChannels()
.stream()
@@ -145,7 +154,7 @@ public class PayRefundAssistService {
int refundableBalance = payOrder.getRefundableBalance();
// 生成退款订单
PayRefundOrder refundOrder = new PayRefundOrder()
RefundOrder refundOrder = new RefundOrder()
.setPaymentId(payOrder.getId())
.setStatus(RefundStatusEnum.PROGRESS.getCode())
.setBusinessNo(payOrder.getBusinessNo())
@@ -154,8 +163,7 @@ public class PayRefundAssistService {
.setAmount(amount)
.setRefundableBalance(refundableBalance)
.setTitle(payOrder.getTitle())
.setClientIp(refundParam.getClientIp())
.setReqId(PaymentContextLocal.get().getRequestInfo().getReqId());
.setReason(refundParam.getReason());
// 退款参数中是否存在异步通道
RefundChannelParam asyncChannel = refundParam.getRefundChannels()
@@ -175,16 +183,41 @@ public class PayRefundAssistService {
if(StrUtil.isBlank(refundOrder.getRefundNo())){
refundOrder.setRefundNo(String.valueOf(refundOrder.getId()));
}
RefundOrderExtra refundOrderExtra = this.createRefundOrderExtra(refundParam, refundOrder.getId());
refundChannelOrders.forEach(r->r.setRefundId(refundOrder.getId()));
payRefundChannelOrderManager.saveAll(refundChannelOrders);
return payRefundOrderManager.save(refundOrder);
return refundOrderManager.save(refundOrder);
}
/**
* 创建退款扩展订单
*/
public RefundOrderExtra createRefundOrderExtra(RefundParam refundParam, Long refundOrderId){
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
ApiInfoLocal apiInfo = PaymentContextLocal.get().getApiInfo();
NoticeLocal notice = PaymentContextLocal.get().getNoticeInfo();
String reqId = PaymentContextLocal.get()
.getRequestInfo()
.getReqId();
RefundOrderExtra orderExtra = new RefundOrderExtra()
.setClientIp(refundParam.getClientIp())
.setReqId(reqId)
.setReqTime(refundParam.getReqTime())
.setAttach(refundParam.getAttach())
.setReqSign(refundParam.getSign())
.setReqSignType(platform.getSignType())
.setNoticeSign(apiInfo.isNoticeSign())
.setNotifyUrl(notice.getNotifyUrl());
orderExtra.setId(refundOrderId);
return orderExtra;
}
/**
* 更新退款成功信息
*/
@Transactional(rollbackFor = Exception.class)
public void updateOrderAndChannel(PayRefundOrder refundOrder, List<PayRefundChannelOrder> refundChannelOrders){
public void updateOrderAndChannel(RefundOrder refundOrder, List<RefundChannelOrder> refundChannelOrders){
RefundLocal asyncRefundInfo = PaymentContextLocal.get().getRefundInfo();
refundOrder.setStatus(asyncRefundInfo.getStatus().getCode())
.setGatewayOrderNo(asyncRefundInfo.getGatewayOrderNo());
@@ -192,7 +225,7 @@ public class PayRefundAssistService {
if (Objects.equals(refundOrder.getStatus(), SUCCESS.getCode())){
refundOrder.setRefundTime(LocalDateTime.now());
}
payRefundOrderManager.updateById(refundOrder);
refundOrderManager.updateById(refundOrder);
payRefundChannelOrderManager.updateAllById(refundChannelOrders);
}
@@ -200,7 +233,7 @@ public class PayRefundAssistService {
* 更新退款错误信息
*/
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void updateOrderByError(PayRefundOrder refundOrder){
public void updateOrderByError(RefundOrder refundOrder){
RefundLocal asyncRefundInfo = PaymentContextLocal.get().getRefundInfo();
refundOrder.setErrorCode(asyncRefundInfo.getErrorCode());
refundOrder.setErrorMsg(asyncRefundInfo.getErrorMsg());

View File

@@ -17,9 +17,10 @@ import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManage
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.service.PayOrderService;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.payment.refund.factory.PayRefundStrategyFactory;
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.service.ClientNoticeService;
import cn.bootx.platform.daxpay.service.core.payment.refund.factory.RefundStrategyFactory;
import cn.bootx.platform.daxpay.service.func.AbsRefundStrategy;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
@@ -32,10 +33,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -47,12 +45,14 @@ import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class PayRefundService {
public class RefundService {
private final PayRefundAssistService payRefundAssistService;;
private final RefundAssistService refundAssistService;;
private final PayOrderService payOrderService;
private final ClientNoticeService clientNoticeService;
private final PayChannelOrderManager payChannelOrderManager;
private final LockTemplate lockTemplate;
@@ -86,9 +86,9 @@ public class PayRefundService {
*/
private RefundResult refundAdapter(RefundParam param, boolean simple){
// 获取支付订单
PayOrder payOrder = payRefundAssistService.getPayOrder(param);
PayOrder payOrder = refundAssistService.getPayOrder(param);
// 第一次检查退款参数, 校验一些特殊情况
payRefundAssistService.checkAndDisposeParam(param, payOrder);
refundAssistService.checkAndDisposeParam(param, payOrder);
// 组装退款参数, 处理全部退款和简单退款情况
List<PayChannelOrder> payChannelOrders = payChannelOrderManager.findAllByPaymentId(payOrder.getId());
@@ -118,7 +118,7 @@ public class PayRefundService {
}
try {
// 退款上下文初始化
payRefundAssistService.initRefundContext(param);
refundAssistService.initRefundContext(param);
// 分支付通道进行退款
return this.refundByChannel(param,payOrder,payChannelOrders);
} finally {
@@ -139,7 +139,7 @@ public class PayRefundService {
List<RefundChannelParam> refundChannels = refundParam.getRefundChannels();
// 1.2获取退款参数方式通过工厂生成对应的策略组
List<AbsRefundStrategy> payRefundStrategies = PayRefundStrategyFactory.createAsyncLast(refundChannels);
List<AbsRefundStrategy> payRefundStrategies = RefundStrategyFactory.createAsyncLast(refundChannels);
if (CollectionUtil.isEmpty(payRefundStrategies)) {
throw new PayUnsupportedMethodException();
}
@@ -156,7 +156,7 @@ public class PayRefundService {
payRefundStrategies.forEach(AbsRefundStrategy::generateChannelOrder);
// 退款操作的预处理, 使用独立的新事物进行发起, 返回创建成功的退款订单, 成功后才可以进行下一阶段的操作
PayRefundOrder refundOrder = SpringUtil.getBean(this.getClass()).preRefundMethod(refundParam, payOrder, payRefundStrategies);
RefundOrder refundOrder = SpringUtil.getBean(this.getClass()).preRefundMethod(refundParam, payOrder, payRefundStrategies);
// 设置退款订单对象
payRefundStrategies.forEach(r->r.setRefundOrder(refundOrder));
@@ -170,7 +170,7 @@ public class PayRefundService {
payRefundStrategies.forEach(AbsRefundStrategy::doSuccessHandler);
// 4.进行成功处理, 分别处理退款订单, 通道退款订单, 支付订单
List<PayRefundChannelOrder> refundChannelOrders = payRefundStrategies.stream()
List<RefundChannelOrder> refundChannelOrders = payRefundStrategies.stream()
.map(AbsRefundStrategy::getRefundChannelOrder)
.collect(Collectors.toList());
this.successHandler(refundOrder, refundChannelOrders, payOrder);
@@ -190,7 +190,7 @@ public class PayRefundService {
* 退款一阶段: 进行支付订单和支付通道订单的预扣, 预创建退款订单并保存, 使用独立的新事物进行发起
*/
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class )
public PayRefundOrder preRefundMethod(RefundParam refundParam, PayOrder payOrder, List<AbsRefundStrategy> payRefundStrategies) {
public RefundOrder preRefundMethod(RefundParam refundParam, PayOrder payOrder, List<AbsRefundStrategy> payRefundStrategies) {
// --------------------------- 支付订单 -------------------------------------
// 预扣支付相关订单要退款的金额并进行更新
payRefundStrategies.forEach(AbsRefundStrategy::doPreDeductOrderHandler);
@@ -208,19 +208,19 @@ public class PayRefundService {
.setStatus(PayStatusEnum.REFUNDING.getCode());
payOrderService.updateById(payOrder);
// ----------------------- 退款订单 -------------------------
List<PayRefundChannelOrder> refundChannelOrders = payRefundStrategies.stream()
List<RefundChannelOrder> refundChannelOrders = payRefundStrategies.stream()
.map(AbsRefundStrategy::getRefundChannelOrder)
.collect(Collectors.toList());
return payRefundAssistService.createOrderAndChannel(refundParam, payOrder,refundChannelOrders);
return refundAssistService.createOrderAndChannel(refundParam, payOrder,refundChannelOrders);
}
/**
* 成功处理, 更新退款订单, 退款通道订单, 支付订单, 支付通道订单
*/
private void successHandler(PayRefundOrder payRefundOrder, List<PayRefundChannelOrder> refundChannelOrders, PayOrder payOrder) {
private void successHandler(RefundOrder refundOrder, List<RefundChannelOrder> refundChannelOrders, PayOrder payOrder) {
RefundLocal asyncRefundInfo = PaymentContextLocal.get().getRefundInfo();
// 剩余可退款余额
int refundableBalance = payRefundOrder.getRefundableBalance();
int refundableBalance = refundOrder.getRefundableBalance();
// 设置支付订单状态
if (asyncRefundInfo.getStatus() == RefundStatusEnum.PROGRESS) {
// 设置为退款中
@@ -235,14 +235,20 @@ public class PayRefundService {
payOrderService.updateById(payOrder);
// 更新退款订单和相关通道订单
payRefundAssistService.updateOrderAndChannel(payRefundOrder,refundChannelOrders);
refundAssistService.updateOrderAndChannel(refundOrder,refundChannelOrders);
// 发送通知
List<String> list = Arrays.asList(PayStatusEnum.REFUNDING.getCode(), PayStatusEnum.REFUNDED.getCode());
if (list.contains(payOrder.getStatus())){
clientNoticeService.registerRefundNotice(refundOrder, null, refundChannelOrders);
}
}
/**
* 失败处理, 只更新退款订单, 通道订单不进行错误更新
*/
private void errorHandler(PayRefundOrder refundOrder) {
private void errorHandler(RefundOrder refundOrder) {
// 记录退款失败的记录
payRefundAssistService.updateOrderByError(refundOrder);
refundAssistService.updateOrderByError(refundOrder);
}
}

View File

@@ -25,7 +25,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class AliPayRefundStrategy extends AbsRefundStrategy {
public class AliRefundStrategy extends AbsRefundStrategy {
private final AliPayConfigService alipayConfigService;
private final AliPayRefundService aliRefundService;

View File

@@ -19,7 +19,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class CashPayRefundStrategy extends AbsRefundStrategy {
public class CashRefundStrategy extends AbsRefundStrategy {
private final CashRecordService cashRecordService;
/**

View File

@@ -16,7 +16,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class UnionPayRefundStrategy extends AbsRefundStrategy {
public class UnionRefundStrategy extends AbsRefundStrategy {
/**
* 策略标识
*

View File

@@ -24,7 +24,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class VoucherPayRefundStrategy extends AbsRefundStrategy {
public class VoucherRefundStrategy extends AbsRefundStrategy {
private final VoucherPayService voucherPayService;
private final VoucherQueryService voucherQueryService;

View File

@@ -24,7 +24,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class WalletPayRefundStrategy extends AbsRefundStrategy {
public class WalletRefundStrategy extends AbsRefundStrategy {
private final WalletPayService walletPayService;

View File

@@ -25,7 +25,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
@Scope(SCOPE_PROTOTYPE)
@Component
@RequiredArgsConstructor
public class WeChatPayRefundStrategy extends AbsRefundStrategy {
public class WeChatRefundStrategy extends AbsRefundStrategy {
private final WeChatPayConfigService weChatPayConfigService;

View File

@@ -12,10 +12,11 @@ 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.service.PayOrderQueryService;
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderManager;
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.service.ClientNoticeService;
import cn.bootx.platform.daxpay.service.core.payment.repair.factory.RefundRepairStrategyFactory;
import cn.bootx.platform.daxpay.service.core.payment.repair.result.RefundRepairResult;
import cn.bootx.platform.daxpay.service.core.record.repair.entity.PayRepairRecord;
@@ -45,11 +46,13 @@ public class RefundRepairService {
private final PayOrderQueryService payOrderQueryService;
private final ClientNoticeService clientNoticeService;
private final PayChannelOrderManager payChannelOrderManager;
private final PayRefundOrderManager refundOrderManager;
private final RefundOrderManager refundOrderManager;
private final PayRefundChannelOrderManager refundChannelOrderManager;
private final RefundChannelOrderManager refundChannelOrderManager;
private final PayRepairRecordService recordService;
@@ -57,7 +60,7 @@ public class RefundRepairService {
* 修复退款单
*/
@Transactional(rollbackFor = Exception.class)
public RefundRepairResult repair(PayRefundOrder refundOrder, RefundRepairWayEnum repairType){
public RefundRepairResult repair(RefundOrder refundOrder, RefundRepairWayEnum repairType){
// 获取关联支付单
PayOrder payOrder = payOrderQueryService.findById(refundOrder.getPaymentId())
@@ -67,17 +70,17 @@ public class RefundRepairService {
.stream()
.collect(Collectors.toMap(PayChannelOrder::getChannel, Function.identity(), CollectorsFunction::retainLatest));
// 异步通道退款单
Map<String, PayRefundChannelOrder> refundChannelOrderMap = refundChannelOrderManager.findAllByRefundId(refundOrder.getId())
Map<String, RefundChannelOrder> refundChannelOrderMap = refundChannelOrderManager.findAllByRefundId(refundOrder.getId())
.stream()
.collect(Collectors.toMap(PayRefundChannelOrder::getChannel, Function.identity(), CollectorsFunction::retainLatest));
.collect(Collectors.toMap(RefundChannelOrder::getChannel, Function.identity(), CollectorsFunction::retainLatest));
// 2 初始化修复参数
List<String> channels = new ArrayList<>(payChannelOrderMap.keySet());
List<AbsRefundRepairStrategy> repairStrategies = RefundRepairStrategyFactory.createAsyncLast(channels);
for (AbsRefundRepairStrategy repairStrategy : repairStrategies) {
PayChannelOrder payChannelOrder = payChannelOrderMap.get(repairStrategy.getChannel().getCode());
PayRefundChannelOrder payRefundChannelOrder = refundChannelOrderMap.get(repairStrategy.getChannel().getCode());
repairStrategy.initRepairParam(refundOrder, payRefundChannelOrder, payOrder, payChannelOrder);
RefundChannelOrder refundChannelOrder = refundChannelOrderMap.get(repairStrategy.getChannel().getCode());
repairStrategy.initRepairParam(refundOrder, refundChannelOrder, payOrder, payChannelOrder);
}
// 根据不同的类型执行对应的修复逻辑
@@ -103,7 +106,7 @@ public class RefundRepairService {
/**
* 退款成功, 更新退款单和支付单
*/
private RefundRepairResult success(PayRefundOrder refundOrder, PayOrder payOrder, List<AbsRefundRepairStrategy> repairStrategies) {
private RefundRepairResult success(RefundOrder refundOrder, PayOrder payOrder, List<AbsRefundRepairStrategy> repairStrategies) {
RepairLocal repairInfo = PaymentContextLocal.get().getRepairInfo();
// 订单相关状态
PayStatusEnum beforePayStatus = PayStatusEnum.findByCode(payOrder.getStatus());
@@ -127,7 +130,7 @@ public class RefundRepairService {
List<PayChannelOrder> payChannelOrders = repairStrategies.stream()
.map(AbsRefundRepairStrategy::getPayChannelOrder)
.collect(Collectors.toList());
List<PayRefundChannelOrder> refundChannelOrders = repairStrategies
List<RefundChannelOrder> refundChannelOrders = repairStrategies
.stream()
.map(AbsRefundRepairStrategy::getRefundChannelOrder)
.collect(Collectors.toList());
@@ -138,6 +141,12 @@ public class RefundRepairService {
payChannelOrderManager.updateAllById(payChannelOrders);
refundChannelOrderManager.updateAllById(refundChannelOrders);
// 发送通知
List<String> list = Arrays.asList(PayStatusEnum.REFUNDING.getCode(), PayStatusEnum.REFUNDED.getCode());
if (list.contains(payOrder.getStatus())){
clientNoticeService.registerRefundNotice(refundOrder, null, refundChannelOrders);
}
return new RefundRepairResult()
.setBeforePayStatus(beforePayStatus)
.setAfterPayStatus(afterPayRefundStatus)
@@ -149,7 +158,7 @@ public class RefundRepairService {
/**
* 退款失败, 关闭退款单并将失败的退款金额归还回订单
*/
private RefundRepairResult close(PayRefundOrder refundOrder, PayOrder payOrder, List<AbsRefundRepairStrategy> repairStrategies) {
private RefundRepairResult close(RefundOrder refundOrder, PayOrder payOrder, List<AbsRefundRepairStrategy> repairStrategies) {
// 要返回的状态
RefundRepairResult repairResult = new RefundRepairResult();
@@ -182,7 +191,7 @@ public class RefundRepairService {
List<PayChannelOrder> payChannelOrders = repairStrategies.stream()
.map(AbsRefundRepairStrategy::getPayChannelOrder)
.collect(Collectors.toList());
List<PayRefundChannelOrder> refundChannelOrders = repairStrategies
List<RefundChannelOrder> refundChannelOrders = repairStrategies
.stream()
.map(AbsRefundRepairStrategy::getRefundChannelOrder)
.collect(Collectors.toList());
@@ -224,7 +233,7 @@ public class RefundRepairService {
* 退款订单的修复记录
* 退款中 -> 退款成功
*/
private PayRepairRecord refundRepairRecord(PayRefundOrder refundOrder, RefundRepairWayEnum repairType, RefundRepairResult repairResult){
private PayRepairRecord refundRepairRecord(RefundOrder refundOrder, RefundRepairWayEnum repairType, RefundRepairResult repairResult){
// 修复后的状态
String afterStatus = Optional.ofNullable(repairResult.getAfterRefundStatus()).map(RefundStatusEnum::getCode).orElse(null);
// 修复发起来源

View File

@@ -9,7 +9,7 @@ import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletPaySer
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletQueryService;
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletRecordService;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.func.AbsRefundRepairStrategy;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
@@ -65,7 +65,7 @@ public class WalletRefundRepairStrategy extends AbsRefundRepairStrategy {
@Override
public void doSuccessHandler() {
PayChannelOrder payChannelOrder = this.getPayChannelOrder();
PayRefundChannelOrder refundChannelOrder = this.getRefundChannelOrder();
RefundChannelOrder refundChannelOrder = this.getRefundChannelOrder();
// 判断是全部退款还是部分退款
if (Objects.equals(payChannelOrder.getRefundableBalance(), 0)){
//全部退款

View File

@@ -12,8 +12,8 @@ import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
import cn.bootx.platform.daxpay.service.code.RefundRepairWayEnum;
import cn.bootx.platform.daxpay.service.common.context.RepairLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.PayRefundOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderManager;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.bootx.platform.daxpay.service.core.payment.repair.result.RefundRepairResult;
import cn.bootx.platform.daxpay.service.core.payment.repair.service.RefundRepairService;
import cn.bootx.platform.daxpay.service.core.payment.sync.factory.RefundSyncStrategyFactory;
@@ -39,8 +39,8 @@ import java.util.Objects;
@Slf4j
@Service
@RequiredArgsConstructor
public class PayRefundSyncService {
private final PayRefundOrderManager refundOrderManager;
public class RefundSyncService {
private final RefundOrderManager refundOrderManager;
private final PaySyncRecordService paySyncRecordService;
@@ -54,7 +54,7 @@ public class PayRefundSyncService {
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public SyncResult sync(RefundSyncParam param){
// 先获取退款单
PayRefundOrder refundOrder;
RefundOrder refundOrder;
if (Objects.nonNull(param.getRefundId())){
refundOrder = refundOrderManager.findById(param.getRefundId())
.orElseThrow(() -> new PayFailureException("未查询到退款订单"));
@@ -77,7 +77,7 @@ public class PayRefundSyncService {
* 退款订单信息同步
*/
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public SyncResult syncRefundOrder(PayRefundOrder refundOrder) {
public SyncResult syncRefundOrder(RefundOrder refundOrder) {
// 加锁
LockInfo lock = lockTemplate.lock("sync:refund:" + refundOrder.getId(),10000,200);
if (Objects.isNull(lock)) {
@@ -140,7 +140,7 @@ public class PayRefundSyncService {
* @see RefundSyncStatusEnum 同步返回类型
* @see RefundStatusEnum 退款单状态
*/
private boolean checkSyncStatus(RefundGatewaySyncResult syncResult, PayRefundOrder order){
private boolean checkSyncStatus(RefundGatewaySyncResult syncResult, RefundOrder order){
RefundSyncStatusEnum syncStatus = syncResult.getSyncStatus();
String orderStatus = order.getStatus();
// 退款完成
@@ -165,7 +165,7 @@ public class PayRefundSyncService {
/**
* 进行退款订单和支付订单的补偿
*/
private RefundRepairResult repairHandler(RefundGatewaySyncResult syncResult, PayRefundOrder order){
private RefundRepairResult repairHandler(RefundGatewaySyncResult syncResult, RefundOrder order){
RefundSyncStatusEnum syncStatusEnum = syncResult.getSyncStatus();
RefundRepairResult repair = new RefundRepairResult();
// 对支付网关同步的结果进行处理
@@ -197,7 +197,7 @@ public class PayRefundSyncService {
* @param repairOrderNo 修复号
* @param errorMsg 错误信息
*/
private void saveRecord(PayRefundOrder refundOrder, RefundGatewaySyncResult syncResult, boolean repair, String repairOrderNo, String errorMsg){
private void saveRecord(RefundOrder refundOrder, RefundGatewaySyncResult syncResult, boolean repair, String repairOrderNo, String errorMsg){
PaySyncRecord paySyncRecord = new PaySyncRecord()
.setOrderId(refundOrder.getId())
.setOrderNo(refundOrder.getRefundNo())

View File

@@ -52,11 +52,7 @@ public class PayApiConfig extends MpBaseEntity implements EntityBaseFunction<Pay
@DbColumn(comment = "是否开启回调通知")
private boolean notice;
@DbColumn(comment = "只有异步支付才进行通知")
private boolean onlyAsyncNotice;
@Deprecated
@DbColumn(comment = "默认回调地址")
@DbColumn(comment = "默认通知地址")
private String noticeUrl;
@DbColumn(comment = "请求参数是否签名")

View File

@@ -60,6 +60,7 @@ public class PayApiConfigService {
.setReqSign(api.isReqSign())
.setResSign(api.isResSign())
.setNotice(api.isNotice())
.setNoticeUrl(api.getNoticeUrl())
.setNoticeSign(api.isNoticeSign())
.setRecord(api.isRecord());
}

View File

@@ -38,6 +38,10 @@ public class WeChatPayConfigDto extends BaseDto implements Serializable {
@Schema(description = "同步跳转地址")
private String returnUrl;
/** 接口版本, 使用v2还是v3接口 */
@Schema(description = "接口版本")
private String apiVersion;
@Schema(description = "商户平台「API安全」中的 APIv2 密钥")
@SensitiveInfo
private String apiKeyV2;

View File

@@ -27,30 +27,22 @@ public class PayOrderExtraDto extends BaseDto {
@Schema(description = "支付终端ip")
private String clientIp;
/** 是否不需要异步通知,以最后一次为准 */
@Schema(description = "是否不需要异步通知")
private boolean notNotify;
/** 异步通知地址 */
@Schema(description = "异步通知地址,以最后一次为准")
private String notifyUrl;
/** 签名类型 */
@Schema(description = "签名类型")
private String signType;
private String reqSignType;
/** 签名,以最后一次为准 */
@Schema(description = "签名")
private String sign;
private String reqSign;
/** 商户扩展参数,回调时会原样返回 */
@Schema(description = "商户扩展参数")
private String attach;
/** API版本号 */
@Schema(description = "API版本号")
private String apiVersion;
/** 请求时间,时间戳转时间, 以最后一次为准 */
@Schema(description = "请求时间,传输时间戳,以最后一次为准")
private LocalDateTime reqTime;

View File

@@ -21,7 +21,7 @@ import java.time.LocalDateTime;
@Data
@Accessors(chain = true)
@Schema(title = "退款记录")
public class PayRefundOrderDto extends BaseDto {
public class RefundOrderDto extends BaseDto {
@Schema(description = "支付号")
private Long paymentId;

View File

@@ -40,7 +40,7 @@ public class PayApiConfigDto extends BaseDto {
@Schema(description = "是否开启回调通知")
private boolean notice;
@Schema(description = "默认回调地址")
@Schema(description = "默认通知回调地址")
private String noticeUrl;
@Schema(description = "请求参数是否签名")

View File

@@ -6,7 +6,7 @@ import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
import cn.bootx.platform.daxpay.service.common.context.CallbackLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.payment.callback.service.PayCallbackService;
import cn.bootx.platform.daxpay.service.core.payment.callback.service.PayRefundCallbackService;
import cn.bootx.platform.daxpay.service.core.payment.callback.service.RefundCallbackService;
import cn.bootx.platform.daxpay.service.core.record.callback.entity.PayCallbackRecord;
import cn.bootx.platform.daxpay.service.core.record.callback.service.PayCallbackRecordService;
import cn.hutool.json.JSONUtil;
@@ -28,7 +28,7 @@ public abstract class AbsCallbackStrategy implements PayStrategy {
@Resource
private PayCallbackService payCallbackService;
@Resource
private PayRefundCallbackService refundCallbackService;
private RefundCallbackService refundCallbackService;
/**
* 回调处理入口

View File

@@ -4,8 +4,8 @@ import cn.bootx.platform.daxpay.code.RefundStatusEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
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.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import lombok.Getter;
import java.util.Objects;
@@ -17,8 +17,8 @@ import java.util.Objects;
*/
@Getter
public abstract class AbsRefundRepairStrategy implements PayStrategy{
private PayRefundOrder refundOrder;
private PayRefundChannelOrder refundChannelOrder;
private RefundOrder refundOrder;
private RefundChannelOrder refundChannelOrder;
private PayOrder payOrder;
private PayChannelOrder payChannelOrder;
@@ -31,8 +31,8 @@ public abstract class AbsRefundRepairStrategy implements PayStrategy{
/**
* 初始化参数
*/
public void initRepairParam(PayRefundOrder refundOrder,
PayRefundChannelOrder refundChannelOrder,
public void initRepairParam(RefundOrder refundOrder,
RefundChannelOrder refundChannelOrder,
PayOrder payOrder,
PayChannelOrder payChannelOrder){
this.refundOrder = refundOrder;
@@ -46,7 +46,7 @@ public abstract class AbsRefundRepairStrategy implements PayStrategy{
*/
public void doSuccessHandler(){
PayChannelOrder payChannelOrder = this.getPayChannelOrder();
PayRefundChannelOrder refundChannelOrder = this.getRefundChannelOrder();
RefundChannelOrder refundChannelOrder = this.getRefundChannelOrder();
// 判断是全部退款还是部分退款, 更新订单状态
if (Objects.equals(payChannelOrder.getRefundableBalance(), 0)){
@@ -65,7 +65,7 @@ public abstract class AbsRefundRepairStrategy implements PayStrategy{
*/
public void doCloseHandler(){
PayChannelOrder payChannelOrder = this.getPayChannelOrder();
PayRefundChannelOrder refundChannelOrder = this.getRefundChannelOrder();
RefundChannelOrder refundChannelOrder = this.getRefundChannelOrder();
int refundableBalance = payChannelOrder.getRefundableBalance() + payChannelOrder.getAmount();
payChannelOrder.setRefundableBalance(refundableBalance);
// 判断是支付完成还是部分退款, 修改支付订单状态

View File

@@ -6,8 +6,8 @@ import cn.bootx.platform.daxpay.param.pay.RefundChannelParam;
import cn.bootx.platform.daxpay.param.pay.RefundParam;
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.refund.entity.PayRefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import lombok.Getter;
import lombok.Setter;
@@ -27,7 +27,7 @@ public abstract class AbsRefundStrategy implements PayStrategy{
private PayOrder payOrder = null;
/** 退款订单 已经持久化, 后续需要更新 */
private PayRefundOrder refundOrder = null;
private RefundOrder refundOrder = null;
/** 当前通道的订单 */
private PayChannelOrder payChannelOrder = null;
@@ -39,7 +39,7 @@ public abstract class AbsRefundStrategy implements PayStrategy{
private RefundChannelParam refundChannelParam = null;
/** 当前通道的退款订单 未持久化, 需要后续更新 */
private PayRefundChannelOrder refundChannelOrder;
private RefundChannelOrder refundChannelOrder;
/**
* 初始化参数
@@ -96,7 +96,7 @@ public abstract class AbsRefundStrategy implements PayStrategy{
public void generateChannelOrder() {
int refundableAmount = this.getPayChannelOrder().getRefundableBalance() - this.getRefundChannelParam().getAmount();
this.refundChannelOrder = new PayRefundChannelOrder()
this.refundChannelOrder = new RefundChannelOrder()
.setPayChannelId(this.getPayChannelOrder().getId())
.setAsync(this.getPayChannelOrder().isAsync())
.setChannel(this.getPayChannelOrder().getChannel())

View File

@@ -1,7 +1,7 @@
package cn.bootx.platform.daxpay.service.func;
import cn.bootx.platform.daxpay.code.PaySyncStatusEnum;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.PayRefundOrder;
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult;
import lombok.Getter;
@@ -13,12 +13,12 @@ import lombok.Getter;
@Getter
public abstract class AbsRefundSyncStrategy implements PayStrategy{
private PayRefundOrder refundOrder;
private RefundOrder refundOrder;
/**
* 初始化参数
*/
public void initRefundParam(PayRefundOrder refundOrder){
public void initRefundParam(RefundOrder refundOrder){
this.refundOrder = refundOrder;
}

View File

@@ -61,13 +61,6 @@ public class AliPayReturnParam {
@JsonAlias("app_id")
private String app_id;
/**
* 调用的接口版本固定为1.0。
*/
@Schema(description = "调用的接口版本")
@JsonAlias("version")
private String version;
/**
* 签名算法类型,目前支持 RSA2 和 RSA推荐使用RSA2
*/

View File

@@ -18,7 +18,7 @@ import lombok.experimental.Accessors;
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Accessors(chain = true)
@Schema(title = "支付退款查询参数")
public class PayRefundOrderQuery extends QueryOrder {
public class RefundOrderQuery extends QueryOrder {
@Schema(description = "退款号")
private Long id;