mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-03 11:06:46 +00:00
ref 流程重构
This commit is contained in:
@@ -15,7 +15,6 @@ import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryServ
|
||||
import cn.bootx.platform.daxpay.service.core.payment.allocation.service.AllocationService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.close.service.PayCloseService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderDetailDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderExtraDto;
|
||||
@@ -42,7 +41,6 @@ import java.util.List;
|
||||
public class PayOrderController {
|
||||
private final PayOrderQueryService queryService;
|
||||
private final PayOrderExtraService payOrderExtraService;
|
||||
private final PayChannelOrderService payChannelOrderService;
|
||||
|
||||
private final PayCloseService PayCloseService;
|
||||
private final PaySyncService paySyncService;
|
||||
@@ -71,7 +69,6 @@ public class PayOrderController {
|
||||
PayOrderDetailDto detailDto=new PayOrderDetailDto();
|
||||
detailDto.setPayOrder(order);
|
||||
detailDto.setPayOrderExtra(payOrderExtraService.findById(order.getId()).toDto());
|
||||
detailDto.setPayChannelOrder(payChannelOrderService.findAllByPaymentId(orderNo));
|
||||
return Res.ok(detailDto);
|
||||
}
|
||||
|
||||
@@ -81,30 +78,19 @@ public class PayOrderController {
|
||||
return Res.ok(payOrderExtraService.findById(id).toDto());
|
||||
}
|
||||
|
||||
@Operation(summary = "查询支付订单关联支付通道订单")
|
||||
@GetMapping("/listByChannel")
|
||||
public ResResult<List<PayChannelOrderDto>> listByChannel(String orderNo){
|
||||
return Res.ok(payChannelOrderService.findAllByPaymentId(orderNo));
|
||||
}
|
||||
@Operation(summary = "查询支付通道订单详情")
|
||||
@GetMapping("/getChannel")
|
||||
public ResResult<PayChannelOrderDto> getChannel(Long id){
|
||||
return Res.ok(payChannelOrderService.findById(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "同步支付状态")
|
||||
@PostMapping("/syncById")
|
||||
public ResResult<SyncResult> syncById(Long id){
|
||||
@PostMapping("/syncByOrderNo")
|
||||
public ResResult<SyncResult> syncById(String orderNo){
|
||||
PaySyncParam param = new PaySyncParam();
|
||||
param.setPaymentId(id);
|
||||
param.setOrderNo(orderNo);
|
||||
return Res.ok(paySyncService.sync(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "关闭支付记录")
|
||||
@PostMapping("/close")
|
||||
public ResResult<Void> close(Long id){
|
||||
public ResResult<Void> close(String orderNo){
|
||||
PayCloseParam param = new PayCloseParam();
|
||||
param.setPaymentId(id);
|
||||
param.setOrderNo(orderNo);
|
||||
PayCloseService.close(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
@@ -15,14 +15,14 @@ import lombok.EqualsAndHashCode;
|
||||
@Schema(title = "开始分账请求参数")
|
||||
public class AllocationStartParam extends PaymentCommonParam {
|
||||
|
||||
@Schema(description = "支付单ID")
|
||||
private Long paymentId;
|
||||
@Schema(description = "商户分账单号")
|
||||
private String bizAllocationNo;
|
||||
|
||||
@Schema(description = "业务号")
|
||||
private String businessNo;
|
||||
@Schema(description = "支付订单号")
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "分账单号(保证唯一)")
|
||||
private String allocationNo;
|
||||
@Schema(description = "商户订单号")
|
||||
private String bizOrderNo;
|
||||
|
||||
@Schema(description = "分账描述")
|
||||
private String description;
|
||||
|
@@ -16,5 +16,5 @@ public class AllocationSyncParam {
|
||||
private String allocationNo;
|
||||
|
||||
@Schema(description = "商户分账号")
|
||||
private String outAllocationNo;
|
||||
private String bizAllocationNo;
|
||||
}
|
||||
|
@@ -19,5 +19,5 @@ public class PayCloseParam extends PaymentCommonParam {
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "商户订单号")
|
||||
private String outTradeNo;
|
||||
private String bizTradeNo;
|
||||
}
|
||||
|
@@ -22,13 +22,13 @@ public class CommonResult {
|
||||
private String sign;
|
||||
|
||||
@Schema(description = "错误码")
|
||||
private String code;
|
||||
private String code = "0";
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
private String msg;
|
||||
|
||||
@Schema(description = "响应时间")
|
||||
@JsonSerialize(using = LocalDateTimeToTimestampSerializer.class)
|
||||
private LocalDateTime resTime;
|
||||
private LocalDateTime resTime = LocalDateTime.now();
|
||||
|
||||
}
|
||||
|
@@ -1,44 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.result.order;
|
||||
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 支付订单通道响应参数
|
||||
* @author xxm
|
||||
* @since 2024/1/16
|
||||
*/
|
||||
@Data
|
||||
@Schema(title = "支付订单通道响应参数")
|
||||
public class PayChannelOrderResult {
|
||||
|
||||
|
||||
@Schema(description = "异步支付方式")
|
||||
private boolean async;
|
||||
|
||||
@Schema(description = "通道")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "支付方式")
|
||||
private String payWay;
|
||||
|
||||
/**
|
||||
* 第三方支付网关生成的订单号, 用与将记录关联起来
|
||||
*/
|
||||
@Schema(description = "关联网关支付号")
|
||||
private String gatewayOrderNo;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@Schema(description = "支付状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "金额")
|
||||
private Integer amount;
|
||||
|
||||
@Schema(description = "可退款金额")
|
||||
private Integer refundableBalance;
|
||||
}
|
@@ -82,5 +82,4 @@ public class PayOrderResult extends CommonResult {
|
||||
@JsonSerialize(using = LocalDateTimeToTimestampSerializer.class)
|
||||
private LocalDateTime closeTime;
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,50 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.result.order;
|
||||
|
||||
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
|
||||
import cn.bootx.platform.daxpay.serializer.LocalDateTimeToTimestampSerializer;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 支付退款通道明细数据
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "通道退款订单")
|
||||
public class RefundChannelOrderResult {
|
||||
|
||||
@Schema(description = "通道")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "通道支付单id")
|
||||
private Long payChannelId;
|
||||
|
||||
@Schema(description = "异步支付方式")
|
||||
private boolean async;
|
||||
|
||||
@Schema(description = "订单金额")
|
||||
private Integer orderAmount;
|
||||
|
||||
@Schema(description = "退款金额")
|
||||
private Integer amount;
|
||||
|
||||
@Schema(description = "剩余可退余额")
|
||||
private Integer refundableAmount;
|
||||
|
||||
/**
|
||||
* @see RefundStatusEnum
|
||||
*/
|
||||
@Schema(description = "退款状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "退款完成时间")
|
||||
@JsonSerialize(using = LocalDateTimeToTimestampSerializer.class)
|
||||
private LocalDateTime refundTime;
|
||||
|
||||
}
|
@@ -9,7 +9,6 @@ import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 退款订单数据
|
||||
@@ -21,17 +20,11 @@ import java.util.List;
|
||||
@Schema(title = "退款订单数据")
|
||||
public class RefundOrderResult {
|
||||
|
||||
@Schema(description = "退款ID")
|
||||
private Long refundId;
|
||||
|
||||
@Schema(description = "退款号")
|
||||
private String refundNo;
|
||||
|
||||
@Schema(description = "关联支付ID")
|
||||
private Long paymentId;
|
||||
|
||||
@Schema(description = "关联支付业务号")
|
||||
private String businessNo;
|
||||
@Schema(description = "商户退款订单号")
|
||||
private String bizRefundNo;
|
||||
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
@@ -39,25 +32,14 @@ public class RefundOrderResult {
|
||||
@Schema(description = "退款金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Schema(description = "剩余可退")
|
||||
private BigDecimal refundableBalance;
|
||||
|
||||
/**
|
||||
* 异步支付通道发给网关的退款号, 用与将记录关联起来
|
||||
*/
|
||||
@Schema(description = "支付网关订单号")
|
||||
private String gatewayOrderNo;
|
||||
|
||||
@Schema(description = "退款完成时间")
|
||||
@JsonSerialize(using = LocalDateTimeToTimestampSerializer.class)
|
||||
private LocalDateTime refundTime;
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
/**
|
||||
* @see RefundStatusEnum
|
||||
*/
|
||||
@Schema(description = "退款状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "通道退款订单")
|
||||
private List<RefundChannelOrderResult> channels;
|
||||
}
|
||||
|
@@ -0,0 +1,19 @@
|
||||
package cn.bootx.platform.daxpay.result.pay;
|
||||
|
||||
import cn.bootx.platform.daxpay.result.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付关闭响应参数
|
||||
* @author xxm
|
||||
* @since 2024/4/23
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付关闭响应参数")
|
||||
public class PayCloseResult extends CommonResult {
|
||||
}
|
@@ -8,7 +8,7 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* 订单号审查工具类
|
||||
* 各类型订单号审查工具类
|
||||
* @author yxc
|
||||
* @since 2024/4/15
|
||||
*/
|
||||
@@ -24,7 +24,7 @@ public class OrderNoGenerateUtil {
|
||||
/**
|
||||
* 生成支付订单号
|
||||
*/
|
||||
public static String trade() {
|
||||
public static String pay() {
|
||||
StringBuilder orderNo = new StringBuilder();
|
||||
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
|
||||
long id = ATOMIC_LONG.incrementAndGet();
|
||||
|
@@ -40,7 +40,7 @@ public class PaySignUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数转换为map对象. 使用ChatGPT生成, 仅局限于对请求支付相关参数进行签名
|
||||
* 将参数转换为map对象. 使用ChatGPT生成, 仅局限于对支付相关参数和返回值进行签名
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SneakyThrows
|
||||
|
@@ -12,6 +12,6 @@ import lombok.experimental.Accessors;
|
||||
@Accessors(chain = true)
|
||||
public class AllocationLocal {
|
||||
|
||||
/** 网关分账号 */
|
||||
private String gatewayNo;
|
||||
/** 三方系统分账号 */
|
||||
private String outAllocationNo;
|
||||
}
|
||||
|
@@ -23,13 +23,13 @@ public class CallbackLocal {
|
||||
/** 回调参数内容 */
|
||||
private Map<String, String> callbackParam = new HashMap<>();
|
||||
|
||||
/** 订单号, 支付/退款 */
|
||||
private String orderNo;
|
||||
/** 交易号 */
|
||||
private String tradeNo;
|
||||
|
||||
/**
|
||||
* 第三方支付平台订单号
|
||||
* 第三方支付平台交易号
|
||||
*/
|
||||
private String outOrderNo;
|
||||
private String outTradeNo;
|
||||
|
||||
/**
|
||||
* 三方支付系统返回状态
|
||||
@@ -45,7 +45,7 @@ public class CallbackLocal {
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
/** 修复号 */
|
||||
private String payRepairNo;
|
||||
private String repairNo;
|
||||
|
||||
/** 回调类型 */
|
||||
private PaymentTypeEnum callbackType;
|
||||
|
@@ -23,7 +23,4 @@ public class RequestLocal {
|
||||
/** 请求时间,时间戳转时间 */
|
||||
private LocalDateTime reqTime;
|
||||
|
||||
/** 请求链路id */
|
||||
private String reqId;
|
||||
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.alipay.convert;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
|
||||
import cn.bootx.platform.daxpay.service.dto.channel.alipay.AliPayConfigDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.channel.alipay.AliPayRecordDto;
|
||||
@@ -20,10 +19,6 @@ public interface AlipayConvert {
|
||||
|
||||
AlipayConvert CONVERT = Mappers.getMapper(AlipayConvert.class);
|
||||
|
||||
AliPayRecordDto convert(AliPayRecord in);
|
||||
|
||||
GeneralReconcileRecord convertReconcileRecord(AliPayRecord in);
|
||||
|
||||
AliPayConfig convert(AliPayConfigParam in);
|
||||
|
||||
AliPayConfigDto convert(AliPayConfig in);
|
||||
|
@@ -1,45 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.alipay.dao;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord;
|
||||
import cn.bootx.platform.daxpay.service.param.channel.alipay.AliPayRecordQuery;
|
||||
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;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/19
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class AliPayRecordManager extends BaseManager<AliPayRecordMapper, AliPayRecord> {
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public Page<AliPayRecord> page(PageParam pageParam, AliPayRecordQuery param){
|
||||
Page<AliPayRecord> mpPage = MpUtil.getMpPage(pageParam, AliPayRecord.class);
|
||||
QueryWrapper<AliPayRecord> generator = QueryGenerator.generator(param);
|
||||
return this.page(mpPage, generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按时间范围查询
|
||||
*/
|
||||
public List<AliPayRecord> findByDate(LocalDateTime startDate, LocalDateTime endDate){
|
||||
return this.lambdaQuery()
|
||||
.between(AliPayRecord::getGatewayTime, startDate, endDate)
|
||||
.list();
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.alipay.dao;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/2/19
|
||||
*/
|
||||
@Mapper
|
||||
public interface AliPayRecordMapper extends BaseMapper<AliPayRecord> {
|
||||
}
|
@@ -1,60 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.alipay.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.convert.AlipayConvert;
|
||||
import cn.bootx.platform.daxpay.service.dto.channel.alipay.AliPayRecordDto;
|
||||
import cn.bootx.table.modify.annotation.DbColumn;
|
||||
import cn.bootx.table.modify.annotation.DbTable;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 支付宝流水记录
|
||||
* @author xxm
|
||||
* @since 2024/2/19
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@DbTable(comment = "支付宝流水记录")
|
||||
@TableName("pay_alipay_record")
|
||||
public class AliPayRecord extends MpCreateEntity implements EntityBaseFunction<AliPayRecordDto> {
|
||||
|
||||
/** 标题 */
|
||||
@DbColumn(comment = "标题")
|
||||
private String title;
|
||||
|
||||
/** 金额 */
|
||||
@DbColumn(comment = "金额")
|
||||
private Integer amount;
|
||||
|
||||
/**
|
||||
* 业务类型
|
||||
* @see AliPayRecordTypeEnum
|
||||
*/
|
||||
@DbColumn(comment = "业务类型")
|
||||
private String type;
|
||||
|
||||
/** 本地订单号 */
|
||||
@DbColumn(comment = "本地订单号")
|
||||
private Long orderId;
|
||||
|
||||
/** 网关订单号 */
|
||||
@DbColumn(comment = "网关订单号")
|
||||
private String gatewayOrderNo;
|
||||
|
||||
/** 网关完成时间 */
|
||||
@DbColumn(comment = "网关完成时间")
|
||||
private LocalDateTime gatewayTime;
|
||||
|
||||
@Override
|
||||
public AliPayRecordDto toDto() {
|
||||
return AlipayConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -65,7 +65,7 @@ public class AliPayAllocationService {
|
||||
AlipayTradeOrderSettleResponse response = AliPayApi.tradeOrderSettleToResponse(model);
|
||||
// 需要写入到分账订单中
|
||||
String settleNo = response.getSettleNo();
|
||||
PaymentContextLocal.get().getAllocationInfo().setGatewayNo(settleNo);
|
||||
PaymentContextLocal.get().getAllocationInfo().setOutAllocationNo(settleNo);
|
||||
this.verifyErrorMsg(response);
|
||||
}
|
||||
|
||||
|
@@ -89,9 +89,9 @@ public class AliPayCallbackService extends AbsCallbackStrategy {
|
||||
CallbackLocal callback = PaymentContextLocal.get().getCallbackInfo();
|
||||
Map<String, String> callbackParam = callback.getCallbackParam();
|
||||
// 网关订单号
|
||||
callback.setOutOrderNo(callbackParam.get(TRADE_NO));
|
||||
callback.setOutTradeNo(callbackParam.get(TRADE_NO));
|
||||
// 支付订单ID
|
||||
callback.setOrderNo(callbackParam.get(OUT_TRADE_NO));
|
||||
callback.setTradeNo(callbackParam.get(OUT_TRADE_NO));
|
||||
// 支付状态
|
||||
PayStatusEnum payStatus = Objects.equals(callbackParam.get(TRADE_STATUS), NOTIFY_TRADE_SUCCESS) ? PayStatusEnum.SUCCESS : PayStatusEnum.FAIL;
|
||||
callback.setOutStatus(payStatus.getCode());
|
||||
@@ -117,7 +117,7 @@ public class AliPayCallbackService extends AbsCallbackStrategy {
|
||||
CallbackLocal callback = PaymentContextLocal.get().getCallbackInfo();
|
||||
Map<String, String> callbackParam = callback.getCallbackParam();
|
||||
// 退款订单Id
|
||||
callback.setOrderNo(callbackParam.get(OUT_BIZ_NO));
|
||||
callback.setTradeNo(callbackParam.get(OUT_BIZ_NO));
|
||||
// 退款状态
|
||||
callback.setOutStatus(callbackParam.get(TRADE_STATUS));
|
||||
// 退款金额
|
||||
|
@@ -29,13 +29,13 @@ public class AliPayRefundService {
|
||||
/**
|
||||
* 退款, 调用支付宝退款
|
||||
*/
|
||||
public void refund(RefundOrder refundOrder, int amount) {
|
||||
public void refund(RefundOrder refundOrder) {
|
||||
RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo();
|
||||
AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
|
||||
refundModel.setOutTradeNo(String.valueOf(refundOrder.getOrderNo()));
|
||||
refundModel.setOutRequestNo(String.valueOf(refundOrder.getRefundNo()));
|
||||
// 金额转换
|
||||
String refundAmount = String.valueOf(amount*0.01);
|
||||
String refundAmount = String.valueOf(refundOrder.getAmount()*0.01);
|
||||
refundModel.setRefundAmount(refundAmount);
|
||||
|
||||
// 设置退款信息
|
||||
|
@@ -84,14 +84,14 @@ public class UnionPayCallbackService extends AbsCallbackStrategy {
|
||||
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
|
||||
Map<String, String> callbackParam = callbackInfo.getCallbackParam();
|
||||
|
||||
// 网关订单号
|
||||
callbackInfo.setOutOrderNo(callbackParam.get(QUERY_ID));
|
||||
// 支付订单ID
|
||||
callbackInfo.setOrderId(Long.valueOf(callbackParam.get(ORDER_ID)));
|
||||
// 网关支付号
|
||||
callbackInfo.setOutTradeNo(callbackParam.get(QUERY_ID));
|
||||
// 支付号
|
||||
callbackInfo.setTradeNo(callbackParam.get(ORDER_ID));
|
||||
// 支付结果
|
||||
String resultCode = callbackParam.get(UnionPayCode.RESP_CODE);
|
||||
PayStatusEnum payStatus = UnionPayCode.RESP_SUCCESS.equals(resultCode) ? PayStatusEnum.SUCCESS : PayStatusEnum.FAIL;
|
||||
|
||||
// 支付状态
|
||||
callbackInfo.setOutStatus(payStatus.getCode());
|
||||
// 支付金额
|
||||
callbackInfo.setAmount(callbackParam.get(UnionPayCode.TXN_AMT));
|
||||
@@ -114,13 +114,12 @@ public class UnionPayCallbackService extends AbsCallbackStrategy {
|
||||
|
||||
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
|
||||
Map<String, String> callbackParam = callbackInfo.getCallbackParam();
|
||||
// 网关订单号
|
||||
callbackInfo.setOutOrderNo(callbackParam.get(QUERY_ID));
|
||||
// 退款订单Id
|
||||
callbackInfo.setOrderId(Long.valueOf(callbackParam.get(ORDER_ID)));
|
||||
// 网关退款号
|
||||
callbackInfo.setOutTradeNo(callbackParam.get(QUERY_ID));
|
||||
// 退款订单号
|
||||
callbackInfo.setTradeNo(callbackParam.get(ORDER_ID));
|
||||
// 退款金额
|
||||
callbackInfo.setAmount(callbackParam.get(TXN_AMT));
|
||||
|
||||
// 交易状态
|
||||
String resultCode = callbackParam.get(UnionPayCode.RESP_CODE);
|
||||
RefundStatusEnum refundStatus = UnionPayCode.RESP_SUCCESS.equals(resultCode) ? RefundStatusEnum.SUCCESS : RefundStatusEnum.FAIL;
|
||||
|
@@ -28,10 +28,10 @@ public class UnionPayRefundService {
|
||||
/**
|
||||
* 退款方法
|
||||
*/
|
||||
public void refund(RefundOrder refundOrder, PayOrder payOrder, int amount, UnionPayKit unionPayKit) {
|
||||
public void refund(RefundOrder refundOrder, PayOrder payOrder,UnionPayKit unionPayKit) {
|
||||
|
||||
// 金额转换
|
||||
BigDecimal refundAmount = BigDecimal.valueOf(amount * 0.01);
|
||||
BigDecimal refundAmount = BigDecimal.valueOf(refundOrder.getAmount() * 0.01);
|
||||
BigDecimal orderAmount = BigDecimal.valueOf(payOrder.getAmount() * 0.01);
|
||||
|
||||
UnionRefundOrder unionRefundOrder = new UnionRefundOrder();
|
||||
|
@@ -84,10 +84,10 @@ public class WeChatPayCallbackService extends AbsCallbackStrategy {
|
||||
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
|
||||
Map<String, String> callbackParam = callbackInfo.getCallbackParam();
|
||||
|
||||
// 网关订单号
|
||||
callbackInfo.setOutOrderNo(callbackParam.get(TRANSACTION_ID));
|
||||
// 支付订单ID
|
||||
callbackInfo.setOrderId(Long.valueOf(callbackParam.get(OUT_TRADE_NO)));
|
||||
// 网关支付号
|
||||
callbackInfo.setOutTradeNo(callbackParam.get(TRANSACTION_ID));
|
||||
// 支付号
|
||||
callbackInfo.setTradeNo(callbackParam.get(OUT_TRADE_NO));
|
||||
// 支付状态
|
||||
PayStatusEnum payStatus = WxPayKit.codeIsOk(callbackParam.get(RESULT_CODE)) ? PayStatusEnum.SUCCESS : PayStatusEnum.FAIL;
|
||||
callbackInfo.setOutStatus(payStatus.getCode());
|
||||
@@ -119,9 +119,9 @@ public class WeChatPayCallbackService extends AbsCallbackStrategy {
|
||||
callbackParam = WxPayKit.xmlToMap(decryptData);
|
||||
callbackInfo.setCallbackParam(callbackParam);
|
||||
// 网关订单号
|
||||
callbackInfo.setOutOrderNo(callbackParam.get(CALLBACK_REFUND_ID));
|
||||
callbackInfo.setOutTradeNo(callbackParam.get(CALLBACK_REFUND_ID));
|
||||
// 退款订单Id
|
||||
callbackInfo.setOrderId(Long.valueOf(callbackParam.get(CALLBACK_OUT_REFUND_NO)));
|
||||
callbackInfo.setTradeNo(callbackParam.get(CALLBACK_OUT_REFUND_NO));
|
||||
// 退款金额
|
||||
callbackInfo.setAmount(callbackParam.get(CALLBACK_REFUND_FEE));
|
||||
|
||||
|
@@ -36,8 +36,8 @@ public class WechatPayRefundService {
|
||||
* 退款方法
|
||||
* 微信需要同时传输订单金额或退款金额
|
||||
*/
|
||||
public void refund(RefundOrder refundOrder, int amount, WeChatPayConfig weChatPayConfig) {
|
||||
String refundFee = String.valueOf(amount);
|
||||
public void refund(RefundOrder refundOrder, WeChatPayConfig weChatPayConfig) {
|
||||
String refundFee = String.valueOf(refundOrder.getRefundNo());
|
||||
String totalFee = String.valueOf(refundOrder.getAmount());
|
||||
// 设置退款信息
|
||||
RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo();
|
||||
|
@@ -31,6 +31,13 @@ public class AllocationOrderManager extends BaseManager<AllocationOrderMapper, A
|
||||
return findByField(AllocationOrder::getAllocationNo, allocationNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商户分账号查询
|
||||
*/
|
||||
public Optional<AllocationOrder> findByBizAllocationNo(String bizAllocationNo){
|
||||
return findByField(AllocationOrder::getBizAllocationNo, bizAllocationNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
|
@@ -9,8 +9,6 @@ import cn.bootx.platform.daxpay.service.core.order.allocation.convert.Allocation
|
||||
import cn.bootx.platform.daxpay.service.dto.order.allocation.AllocationOrderDto;
|
||||
import cn.bootx.table.modify.annotation.DbColumn;
|
||||
import cn.bootx.table.modify.annotation.DbTable;
|
||||
import cn.bootx.table.modify.mysql.annotation.DbMySqlIndex;
|
||||
import cn.bootx.table.modify.mysql.constants.MySqlIndexType;
|
||||
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -19,6 +17,8 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分账订单
|
||||
* @author xxm
|
||||
@@ -31,25 +31,45 @@ import lombok.experimental.Accessors;
|
||||
@TableName("pay_allocation_order")
|
||||
public class AllocationOrder extends MpBaseEntity implements EntityBaseFunction<AllocationOrderDto> {
|
||||
|
||||
/**
|
||||
* 分账订单号(传输给三方支付系统做关联)
|
||||
*/
|
||||
@DbColumn(comment = "分账订单号")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 分账单号
|
||||
*/
|
||||
@DbMySqlIndex(comment = "分账单号索引", type = MySqlIndexType.UNIQUE)
|
||||
@DbColumn(comment = "分账单号")
|
||||
private String allocationNo;
|
||||
|
||||
/**
|
||||
* 商户分账单号
|
||||
*/
|
||||
@DbColumn(comment = "商户分账单号")
|
||||
private String bizAllocationNo;
|
||||
|
||||
/**
|
||||
* 支付订单ID
|
||||
* 三方系统分账单号
|
||||
*/
|
||||
@DbColumn(comment = "网关分账单号")
|
||||
private String outAllocationNo;
|
||||
|
||||
/** 支付订单ID */
|
||||
@DbColumn(comment = "支付订单ID")
|
||||
private Long paymentId;
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 支付订单号
|
||||
*/
|
||||
@DbColumn(comment = "支付订单号")
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 商户支付订单号
|
||||
*/
|
||||
@DbColumn(comment = "商户支付订单号")
|
||||
private String bizOrderNo;
|
||||
|
||||
/**
|
||||
* 三方系统支付订单号
|
||||
*/
|
||||
@DbColumn(comment = "网关支付订单号")
|
||||
private String outOrderNo;
|
||||
|
||||
/**
|
||||
* 支付订单标题
|
||||
@@ -57,17 +77,6 @@ public class AllocationOrder extends MpBaseEntity implements EntityBaseFunction<
|
||||
@Schema(description = "支付订单标题")
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 网关支付订单号
|
||||
*/
|
||||
@DbColumn(comment = "网关支付订单号")
|
||||
private String gatewayPayOrderNo;
|
||||
|
||||
/**
|
||||
* 网关分账单号
|
||||
*/
|
||||
@DbColumn(comment = "网关分账单号")
|
||||
private String gatewayAllocationNo;
|
||||
|
||||
/**
|
||||
* 所属通道
|
||||
@@ -103,12 +112,23 @@ public class AllocationOrder extends MpBaseEntity implements EntityBaseFunction<
|
||||
private String result;
|
||||
|
||||
/**
|
||||
* 错误原因
|
||||
* 错误码
|
||||
*/
|
||||
@DbColumn(comment = "错误码")
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
private String errorCode;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
@DbColumn(comment = "错误原因")
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
private String errorMsg;
|
||||
|
||||
/** 分账完成时间 */
|
||||
@DbColumn(comment = "分账完成时间")
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
|
@@ -22,9 +22,9 @@ import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupReceiverRe
|
||||
import cn.bootx.platform.daxpay.service.dto.order.allocation.AllocationOrderDetailDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.allocation.AllocationOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.param.order.AllocationOrderQuery;
|
||||
import cn.bootx.platform.daxpay.util.OrderNoGenerateUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -96,12 +96,6 @@ public class AllocationOrderService {
|
||||
public OrderAndDetail createAndUpdate(AllocationStartParam param, PayOrder payOrder, int orderAmount, List<AllocationGroupReceiverResult> receiversByGroups){
|
||||
long orderId = IdUtil.getSnowflakeNextId();
|
||||
|
||||
// 请求号不存在使用订单ID
|
||||
String allocationNo = param.getAllocationNo();
|
||||
if (StrUtil.isBlank(allocationNo)){
|
||||
allocationNo = String.valueOf(orderId);
|
||||
}
|
||||
|
||||
// 订单明细
|
||||
List<AllocationOrderDetail> details = receiversByGroups.stream()
|
||||
.map(o -> {
|
||||
@@ -126,12 +120,14 @@ public class AllocationOrderService {
|
||||
.reduce(0, Integer::sum);
|
||||
// 分账订单
|
||||
AllocationOrder allocationOrder = new AllocationOrder()
|
||||
.setPaymentId(payOrder.getId())
|
||||
.setOrderId(payOrder.getId())
|
||||
.setOrderNo(payOrder.getOrderNo())
|
||||
.setBizOrderNo(payOrder.getBizOrderNo())
|
||||
.setOutOrderNo(payOrder.getOutOrderNo())
|
||||
.setTitle(payOrder.getTitle())
|
||||
.setAllocationNo(allocationNo)
|
||||
.setChannel(payOrder.getAsyncChannel())
|
||||
.setGatewayPayOrderNo(payOrder.getGatewayOrderNo())
|
||||
.setOrderNo(String.valueOf(orderId))
|
||||
.setAllocationNo(OrderNoGenerateUtil.allocation())
|
||||
.setBizAllocationNo(param.getBizAllocationNo())
|
||||
.setChannel(payOrder.getChannel())
|
||||
.setDescription(param.getDescription())
|
||||
.setStatus(AllocationOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
||||
.setAmount(sumAmount);
|
||||
|
@@ -3,15 +3,12 @@ package cn.bootx.platform.daxpay.service.core.order.pay.builder;
|
||||
import cn.bootx.platform.daxpay.code.PayOrderAllocationStatusEnum;
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import cn.bootx.platform.daxpay.param.payment.pay.PayParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.PayResult;
|
||||
import cn.bootx.platform.daxpay.service.common.context.NoticeLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
import cn.bootx.platform.daxpay.util.OrderNoGenerateUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@@ -37,7 +34,7 @@ public class PayBuilder {
|
||||
// 构建支付订单对象
|
||||
PayOrder payOrder = new PayOrder()
|
||||
.setBizOrderNo(payParam.getBizOrderNo())
|
||||
.setOrderNo(OrderNoGenerateUtil.trade())
|
||||
.setOrderNo(OrderNoGenerateUtil.pay())
|
||||
.setTitle(payParam.getTitle())
|
||||
.setDescription(payParam.getDescription())
|
||||
.setStatus(PayStatusEnum.PROGRESS.getCode())
|
||||
@@ -76,24 +73,4 @@ public class PayBuilder {
|
||||
return payOrderExtra;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据支付订单构建支付结果
|
||||
* @param payOrder 支付订单
|
||||
* @return PayResult 支付结果
|
||||
*/
|
||||
public PayResult buildResultByPayOrder(PayOrder payOrder) {
|
||||
PayResult payResult;
|
||||
payResult = new PayResult();
|
||||
payResult.setBizOrderNo(payOrder.getBizOrderNo());
|
||||
payResult.setOrderNo(payOrder.getOrderNo());
|
||||
payResult.setStatus(payOrder.getStatus());
|
||||
|
||||
// 设置支付参数
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();;
|
||||
if (StrUtil.isNotBlank(asyncPayInfo.getPayBody())) {
|
||||
payResult.setPayBody(asyncPayInfo.getPayBody());
|
||||
}
|
||||
return payResult;
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,7 @@
|
||||
package cn.bootx.platform.daxpay.service.core.order.pay.convert;
|
||||
|
||||
import cn.bootx.platform.daxpay.result.order.PayChannelOrderResult;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderExtraDto;
|
||||
import org.mapstruct.Mapper;
|
||||
@@ -23,7 +20,4 @@ public interface PayOrderConvert {
|
||||
|
||||
PayOrderDto convert(PayOrder in);
|
||||
|
||||
PayChannelOrderDto convert(PayChannelOrder in);
|
||||
|
||||
PayChannelOrderResult convertResult(PayChannelOrder in);
|
||||
}
|
||||
|
@@ -1,58 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.order.pay.dao;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 支付订单关联支付时通道信息
|
||||
* @author xxm
|
||||
* @since 2023/12/20
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class PayChannelOrderManager extends BaseManager<PayChannelOrderMapper, PayChannelOrder> {
|
||||
|
||||
/**
|
||||
* 根据订单查找
|
||||
*/
|
||||
public List<PayChannelOrder> findAllByPaymentId(String orderNo){
|
||||
return findAllByField(PayChannelOrder::getPaymentId,orderNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单id和支付通道查询
|
||||
*/
|
||||
public Optional<PayChannelOrder> findByPaymentIdAndChannel(Long paymentId, String channel) {
|
||||
return lambdaQuery()
|
||||
.eq(PayChannelOrder::getPaymentId,paymentId)
|
||||
.eq(PayChannelOrder::getChannel,channel)
|
||||
.oneOpt();
|
||||
}
|
||||
/**
|
||||
* 根据订单id和支付通道查询
|
||||
*/
|
||||
public Optional<PayChannelOrder> findByAsyncChannel(Long paymentId) {
|
||||
return lambdaQuery()
|
||||
.eq(PayChannelOrder::getPaymentId,paymentId)
|
||||
.eq(PayChannelOrder::isAsync,true)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单id删除异步支付记录
|
||||
*/
|
||||
public void deleteByPaymentIdAndAsync(String orderNo){
|
||||
lambdaUpdate()
|
||||
.eq(PayChannelOrder::getPaymentId,orderNo)
|
||||
.eq(PayChannelOrder::isAsync,true)
|
||||
.remove();
|
||||
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.order.pay.dao;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 通道支付订单
|
||||
* @author xxm
|
||||
* @since 2023/12/20
|
||||
*/
|
||||
@Mapper
|
||||
public interface PayChannelOrderMapper extends BaseMapper<PayChannelOrder> {
|
||||
}
|
@@ -1,81 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.order.pay.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import cn.bootx.platform.daxpay.param.channel.AliPayParam;
|
||||
import cn.bootx.platform.daxpay.param.channel.WalletPayParam;
|
||||
import cn.bootx.platform.daxpay.param.channel.WeChatPayParam;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.convert.PayOrderConvert;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayChannelOrderDto;
|
||||
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 2023/12/18
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@DbTable(comment = "支付订单关联支付时通道信息")
|
||||
@TableName("pay_channel_order")
|
||||
@Deprecated
|
||||
public class PayChannelOrder extends MpCreateEntity implements EntityBaseFunction<PayChannelOrderDto> {
|
||||
|
||||
@DbColumn(comment = "支付id")
|
||||
private String paymentId;
|
||||
|
||||
@DbColumn(comment = "异步支付方式")
|
||||
private boolean async;
|
||||
|
||||
@DbColumn(comment = "通道")
|
||||
private String channel;
|
||||
|
||||
@DbColumn(comment = "支付方式")
|
||||
private String payWay;
|
||||
|
||||
@DbColumn(comment = "金额")
|
||||
private Integer amount;
|
||||
|
||||
@DbColumn(comment = "可退款金额")
|
||||
private Integer refundableBalance;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@DbColumn(comment = "支付状态")
|
||||
private String status;
|
||||
|
||||
@DbColumn(comment = "支付完成时间")
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
private LocalDateTime payTime;
|
||||
|
||||
|
||||
/**
|
||||
* @see AliPayParam
|
||||
* @see WeChatPayParam
|
||||
* @see WalletPayParam
|
||||
*/
|
||||
@DbColumn(comment = "附加支付参数")
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
private String channelExtra;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
@Override
|
||||
public PayChannelOrderDto toDto() {
|
||||
return PayOrderConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -8,7 +8,6 @@ import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.param.payment.pay.QueryPayParam;
|
||||
import cn.bootx.platform.daxpay.result.order.PayOrderResult;
|
||||
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.dao.PayOrderManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
@@ -36,7 +35,6 @@ import java.util.Optional;
|
||||
public class PayOrderQueryService {
|
||||
private final PayOrderManager payOrderManager;
|
||||
private final PayOrderExtraManager payOrderExtraManager;
|
||||
private final PayChannelOrderManager payChannelOrderManager;
|
||||
|
||||
/**
|
||||
* 分页
|
||||
@@ -67,6 +65,21 @@ public class PayOrderQueryService {
|
||||
return payOrderManager.findByBizOrderNo(bizOrderNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单号或商户订单号查询
|
||||
*/
|
||||
public Optional<PayOrder> findByBizOrOrderNo(String orderNo, String bizOrderNo) {
|
||||
if (Objects.nonNull(orderNo)){
|
||||
return this.findByOrderNo(orderNo);
|
||||
}
|
||||
if (Objects.nonNull(bizOrderNo)){
|
||||
return this.findByBizOrderNo(bizOrderNo);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询支付记录
|
||||
*/
|
||||
|
@@ -1,8 +1,5 @@
|
||||
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.RefundChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@@ -15,9 +12,4 @@ import org.mapstruct.factory.Mappers;
|
||||
public interface RefundOrderChannelConvert {
|
||||
RefundOrderChannelConvert CONVERT = Mappers.getMapper(RefundOrderChannelConvert.class);
|
||||
|
||||
|
||||
RefundChannelOrderDto convert(RefundChannelOrder in);
|
||||
|
||||
RefundChannelOrderResult convertResult(RefundChannelOrder in);
|
||||
|
||||
}
|
||||
|
@@ -1,39 +0,0 @@
|
||||
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.RefundChannelOrder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 通道退款订单
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
@Deprecated
|
||||
public class RefundChannelOrderManager extends BaseManager<RefundChannelOrderMapper, RefundChannelOrder> {
|
||||
|
||||
/**
|
||||
* 根据退款单ID查找
|
||||
*/
|
||||
public List<RefundChannelOrder> findAllByRefundId(Long paymentId){
|
||||
return findAllByField(RefundChannelOrder::getRefundId,paymentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据退款单ID和退款通道查询
|
||||
*/
|
||||
public Optional<RefundChannelOrder> findByRefundIdAndChannel(Long refundId, String channel) {
|
||||
return lambdaQuery()
|
||||
.eq(RefundChannelOrder::getRefundId,refundId)
|
||||
.eq(RefundChannelOrder::getChannel,channel)
|
||||
.oneOpt();
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.order.refund.dao;
|
||||
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundChannelOrder;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Mapper
|
||||
@Deprecated
|
||||
public interface RefundChannelOrderMapper extends BaseMapper<RefundChannelOrder> {
|
||||
}
|
@@ -1,71 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.order.refund.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.convert.RefundOrderChannelConvert;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto;
|
||||
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/1/17
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@DbTable(comment = "支付退款通道订单")
|
||||
@Accessors(chain = true)
|
||||
@Deprecated
|
||||
@TableName("pay_refund_channel_order")
|
||||
public class RefundChannelOrder extends MpCreateEntity implements EntityBaseFunction<RefundChannelOrderDto> {
|
||||
|
||||
@DbColumn(comment = "关联退款id")
|
||||
private Long refundId;
|
||||
|
||||
@DbColumn(comment = "通道支付单id")
|
||||
private Long payChannelId;
|
||||
|
||||
@DbColumn(comment = "通道")
|
||||
private String channel;
|
||||
|
||||
@DbColumn(comment = "异步支付方式")
|
||||
private boolean async;
|
||||
|
||||
@DbColumn(comment = "订单金额")
|
||||
private Integer orderAmount;
|
||||
|
||||
@DbColumn(comment = "退款金额")
|
||||
private Integer amount;
|
||||
|
||||
@DbColumn(comment = "剩余可退余额")
|
||||
@TableField(updateStrategy = FieldStrategy.ALWAYS)
|
||||
private Integer refundableAmount;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
* @see RefundStatusEnum
|
||||
*/
|
||||
@DbColumn(comment = "退款状态")
|
||||
private String status;
|
||||
|
||||
@DbColumn(comment = "退款完成时间")
|
||||
private LocalDateTime refundTime;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
@Override
|
||||
public RefundChannelOrderDto toDto() {
|
||||
return RefundOrderChannelConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -9,20 +9,15 @@ import cn.bootx.platform.common.spring.util.WebServletUtil;
|
||||
import cn.bootx.platform.daxpay.code.PaymentApiCode;
|
||||
import cn.bootx.platform.daxpay.param.payment.refund.QueryRefundParam;
|
||||
import cn.bootx.platform.daxpay.param.payment.refund.RefundParam;
|
||||
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.RefundOrderChannelConvert;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.convert.RefundOrderConvert;
|
||||
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.common.service.PaymentAssistService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.refund.service.RefundService;
|
||||
import cn.bootx.platform.daxpay.service.core.system.config.dao.PayApiConfigManager;
|
||||
import cn.bootx.platform.daxpay.service.core.system.config.entity.PayApiConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.system.config.service.PayApiConfigService;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundChannelOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundOrderDto;
|
||||
import cn.bootx.platform.daxpay.service.param.order.PayOrderRefundParam;
|
||||
import cn.bootx.platform.daxpay.service.param.order.RefundOrderQuery;
|
||||
@@ -34,10 +29,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 退款
|
||||
@@ -73,25 +66,6 @@ public class RefundOrderService {
|
||||
.orElseThrow(() -> new DataNotExistException("退款订单不存在"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通道退款订单列表查询
|
||||
*/
|
||||
public List<RefundChannelOrderDto> listByChannel(Long refundId){
|
||||
List<RefundChannelOrder> refundOrderChannels = refundOrderChannelManager.findAllByRefundId(refundId);
|
||||
return refundOrderChannels.stream()
|
||||
.map(RefundOrderChannelConvert.CONVERT::convert)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询通道退款订单详情
|
||||
*/
|
||||
public RefundChannelOrderDto findChannelById(Long id) {
|
||||
return refundOrderChannelManager.findById(id)
|
||||
.map(RefundChannelOrder::toDto)
|
||||
.orElseThrow(() -> new DataNotExistException("通道退款订单不存在"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款订单
|
||||
*/
|
||||
@@ -111,16 +85,8 @@ public class RefundOrderService {
|
||||
refundOrder = refundOrderManager.findByRefundNo(param.getRefundNo())
|
||||
.orElseThrow(() -> new DataNotExistException("未查询到支付订单"));
|
||||
}
|
||||
// 查询退款明细
|
||||
List<RefundChannelOrder> refundOrderChannels = refundOrderChannelManager.findAllByRefundId(refundOrder.getId());
|
||||
List<RefundChannelOrderResult> channels = refundOrderChannels.stream()
|
||||
.map(RefundOrderChannelConvert.CONVERT::convertResult)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
RefundOrderResult refundOrderResult = RefundOrderConvert.CONVERT.convertResult(refundOrder);
|
||||
refundOrderResult.setRefundId(refundOrder.getId());
|
||||
refundOrderResult.setChannels(channels);
|
||||
return refundOrderResult;
|
||||
return RefundOrderConvert.CONVERT.convertResult(refundOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,11 +99,10 @@ public class RefundOrderService {
|
||||
.orElse("未知");
|
||||
|
||||
RefundParam refundParam = new RefundParam();
|
||||
refundParam.setPaymentId(param.getPaymentId());
|
||||
refundParam.setOrderNo(param.getOrderNo());
|
||||
refundParam.setReason(param.getReason());
|
||||
refundParam.setReqTime(LocalDateTime.now());
|
||||
refundParam.setClientIp(ip);
|
||||
refundParam.setRefundAll(true);
|
||||
// 手动初始化上下文
|
||||
paymentAssistService.initContext(refundParam);
|
||||
// 初始化接口信息为统一退款
|
||||
|
@@ -18,10 +18,9 @@ import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationO
|
||||
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationOrderDetail;
|
||||
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.OrderAndDetail;
|
||||
import cn.bootx.platform.daxpay.service.core.order.allocation.service.AllocationOrderService;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager;
|
||||
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.payment.allocation.dao.AllocationGroupManager;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationGroup;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.allocation.factory.AllocationFactory;
|
||||
@@ -50,8 +49,6 @@ public class AllocationService {
|
||||
|
||||
private final PayOrderManager payOrderManager;
|
||||
|
||||
private final PayChannelOrderManager payChannelOrderManager;
|
||||
|
||||
private final AllocationGroupManager groupManager;
|
||||
|
||||
private final AllocationOrderManager allocationOrderManager;
|
||||
@@ -61,33 +58,28 @@ public class AllocationService {
|
||||
private final AllocationOrderService allocationOrderService;
|
||||
|
||||
private final AllocationOrderDetailManager allocationOrderDetailManager;
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
/**
|
||||
* 开启分账, 使用分账组进行分账
|
||||
*/
|
||||
public AllocationResult allocation(AllocationStartParam param) {
|
||||
|
||||
PayOrder payOrder = this.getAndCheckPayOrder(param);
|
||||
|
||||
// 查询待分账的通道支付订单
|
||||
PayChannelOrder channelOrder = payChannelOrderManager.findByAsyncChannel(payOrder.getId())
|
||||
.orElseThrow(() -> new DataNotExistException("未查询到支付通道订单"));
|
||||
|
||||
// 查询分账组 未传输使用默认该通道默认分账组
|
||||
AllocationGroup allocationGroup;
|
||||
if (Objects.nonNull(param.getAllocationGroupId())) {
|
||||
allocationGroup = groupManager.findById(param.getAllocationGroupId()).orElseThrow(() -> new DataNotExistException("未查询到分账组"));
|
||||
} else {
|
||||
allocationGroup = groupManager.findDefaultGroup(payOrder.getAsyncChannel()).orElseThrow(() -> new DataNotExistException("未查询到默认分账组"));
|
||||
allocationGroup = groupManager.findDefaultGroup(payOrder.getChannel()).orElseThrow(() -> new DataNotExistException("未查询到默认分账组"));
|
||||
}
|
||||
|
||||
List<AllocationGroupReceiverResult> receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId());
|
||||
|
||||
// 创建分账单和明细并保存, 同时更新支付订单状态 使用事务
|
||||
OrderAndDetail orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, channelOrder.getAmount(), receiversByGroups);
|
||||
OrderAndDetail orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, payOrder.getAmount(), receiversByGroups);
|
||||
|
||||
// 创建分账策略并初始化
|
||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(payOrder.getAsyncChannel());
|
||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(payOrder.getChannel());
|
||||
AllocationOrder order = orderAndDetail.getOrder();
|
||||
List<AllocationOrderDetail> details = orderAndDetail.getDetails();
|
||||
allocationStrategy.initParam(order, details);
|
||||
@@ -108,8 +100,8 @@ public class AllocationService {
|
||||
// 网关分账号
|
||||
String gatewayNo = PaymentContextLocal.get()
|
||||
.getAllocationInfo()
|
||||
.getGatewayNo();
|
||||
order.setGatewayAllocationNo(gatewayNo);
|
||||
.getOutAllocationNo();
|
||||
order.setOutAllocationNo(gatewayNo);
|
||||
allocationOrderManager.updateById(order);
|
||||
|
||||
return new AllocationResult().setOrderId(order.getId())
|
||||
@@ -204,8 +196,8 @@ public class AllocationService {
|
||||
public void sync(AllocationSyncParam param) {
|
||||
// 获取分账订单
|
||||
AllocationOrder allocationOrder = null;
|
||||
if (Objects.nonNull(param.getAllocationId())){
|
||||
allocationOrder = allocationOrderManager.findById(param.getAllocationId())
|
||||
if (Objects.nonNull(param.getAllocationNo())){
|
||||
allocationOrder = allocationOrderManager.findById(param.getBizAllocationNo())
|
||||
.orElseThrow(() -> new DataNotExistException("分账单不存在"));
|
||||
}
|
||||
if (Objects.isNull(allocationOrder)){
|
||||
@@ -273,15 +265,8 @@ public class AllocationService {
|
||||
*/
|
||||
private PayOrder getAndCheckPayOrder(AllocationStartParam param) {
|
||||
// 查询支付单
|
||||
PayOrder payOrder = null;
|
||||
if (Objects.nonNull(param.getPaymentId())){
|
||||
payOrder = payOrderManager.findById(param.getPaymentId())
|
||||
.orElseThrow(() -> new DataNotExistException("未查询到支付订单"));
|
||||
}
|
||||
if (StrUtil.isNotBlank(param.getBusinessNo())){
|
||||
payOrder = payOrderManager.findByBusinessNo(param.getBusinessNo())
|
||||
.orElseThrow(() -> new DataNotExistException("未查询到支付订单"));
|
||||
}
|
||||
PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(param.getOrderNo(), param.getBizOrderNo())
|
||||
.orElseThrow(() -> new DataNotExistException("支付单不存在"));
|
||||
// 判断订单是否可以分账
|
||||
if (!payOrder.isAllocation()){
|
||||
throw new PayFailureException("该订单不允许分账");
|
||||
|
@@ -42,22 +42,22 @@ public class PayCallbackService {
|
||||
public void payCallback() {
|
||||
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
|
||||
// 加锁
|
||||
LockInfo lock = lockTemplate.lock("callback:payment:" + callbackInfo.getOrderId(),10000, 200);
|
||||
LockInfo lock = lockTemplate.lock("callback:payment:" + callbackInfo.getTradeNo(),10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.IGNORE).setMsg("回调正在处理中,忽略本次回调请求");
|
||||
log.warn("订单号: {} 回调正在处理中,忽略本次回调请求", callbackInfo.getOrderId());
|
||||
log.warn("订单号: {} 回调正在处理中,忽略本次回调请求", callbackInfo.getTradeNo());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 获取支付单
|
||||
PayOrder payOrder = payOrderQueryService.findById(callbackInfo.getOrderId()).orElse(null);
|
||||
PayOrder payOrder = payOrderQueryService.findByOrderNo(callbackInfo.getTradeNo()).orElse(null);
|
||||
// 本地支付单不存在,记录回调记录, TODO 需要补单或进行退款
|
||||
if (Objects.isNull(payOrder)) {
|
||||
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.NOT_FOUND).setMsg("支付单不存在,记录回调记录");
|
||||
return;
|
||||
}
|
||||
// 设置订单关联网关订单号
|
||||
payOrder.setGatewayOrderNo(callbackInfo.getOutOrderNo());
|
||||
payOrder.setOutOrderNo(callbackInfo.getOutTradeNo());
|
||||
|
||||
// 成功状态
|
||||
if (Objects.equals(PayCallbackStatusEnum.SUCCESS.getCode(), callbackInfo.getOutStatus())) {
|
||||
@@ -97,7 +97,7 @@ public class PayCallbackService {
|
||||
PaymentContextLocal.get().getRepairInfo().setFinishTime(callbackInfo.getFinishTime());
|
||||
// 执行支付完成修复逻辑
|
||||
PayRepairResult repair = payRepairService.repair(payOrder, PayRepairWayEnum.PAY_SUCCESS);
|
||||
callbackInfo.setPayRepairNo(repair.getRepairNo());
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +117,7 @@ public class PayCallbackService {
|
||||
}
|
||||
// 执行支付关闭修复逻辑
|
||||
PayRepairResult repair = payRepairService.repair(payOrder, PayRepairWayEnum.CLOSE_LOCAL);
|
||||
callbackInfo.setPayRepairNo(repair.getRepairNo());
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -39,15 +39,15 @@ public class RefundCallbackService {
|
||||
|
||||
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
|
||||
// 加锁
|
||||
LockInfo lock = lockTemplate.lock("callback:refund:" + callbackInfo.getOrderId(),10000, 200);
|
||||
LockInfo lock = lockTemplate.lock("callback:refund:" + callbackInfo.getTradeNo(),10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.IGNORE).setMsg("回调正在处理中,忽略本次回调请求");
|
||||
log.warn("订单号: {} 回调正在处理中,忽略本次回调请求", callbackInfo.getOrderId());
|
||||
log.warn("订单号: {} 回调正在处理中,忽略本次回调请求", callbackInfo.getTradeNo());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 获取退款单
|
||||
RefundOrder refundOrder = refundOrderManager.findById(callbackInfo.getOrderId()).orElse(null);
|
||||
RefundOrder refundOrder = refundOrderManager.findByRefundNo(callbackInfo.getTradeNo()).orElse(null);
|
||||
// 退款单不存在,记录回调记录
|
||||
if (Objects.isNull(refundOrder)) {
|
||||
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.NOT_FOUND).setMsg("退款单不存在,记录回调记录");
|
||||
@@ -63,10 +63,10 @@ public class RefundCallbackService {
|
||||
if (Objects.equals(RefundStatusEnum.SUCCESS.getCode(), callbackInfo.getOutStatus())) {
|
||||
PaymentContextLocal.get().getRepairInfo().setFinishTime(callbackInfo.getFinishTime());
|
||||
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.REFUND_SUCCESS);
|
||||
callbackInfo.setPayRepairNo(repair.getRepairNo());
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
} else {
|
||||
RefundRepairResult repair = reflectionService.repair(refundOrder, RefundRepairWayEnum.REFUND_FAIL);
|
||||
callbackInfo.setPayRepairNo(repair.getRepairNo());
|
||||
callbackInfo.setRepairNo(repair.getRepairNo());
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
@@ -2,20 +2,12 @@ package cn.bootx.platform.daxpay.service.core.payment.close.factory;
|
||||
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.close.strategy.*;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.close.strategy.AliPayCloseStrategy;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.close.strategy.UnionPayCloseStrategy;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.close.strategy.WeChatPayCloseStrategy;
|
||||
import cn.bootx.platform.daxpay.service.func.AbsPayCloseStrategy;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.val;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.bootx.platform.daxpay.code.PayChannelEnum.ASYNC_TYPE_CODE;
|
||||
|
||||
/**
|
||||
* 支付关闭策略工厂
|
||||
@@ -29,8 +21,8 @@ public class PayCloseStrategyFactory {
|
||||
* 根据传入的支付通道创建策略
|
||||
* @return 支付策略
|
||||
*/
|
||||
public static AbsPayCloseStrategy create(PayChannelEnum channelEnum) {
|
||||
|
||||
public static AbsPayCloseStrategy create(String channel) {
|
||||
PayChannelEnum channelEnum = PayChannelEnum.findByCode(channel);
|
||||
AbsPayCloseStrategy strategy;
|
||||
switch (channelEnum) {
|
||||
case ALI:
|
||||
@@ -50,59 +42,4 @@ public class PayCloseStrategyFactory {
|
||||
}
|
||||
return strategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的支付类型批量创建策略, 异步支付在后面
|
||||
*/
|
||||
public static List<AbsPayCloseStrategy> createAsyncLast(List<String> channelCodes) {
|
||||
return create(channelCodes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的支付类型批量创建策略, 异步支付在前面
|
||||
*/
|
||||
public static List<AbsPayCloseStrategy> createAsyncFront(List<String> channelCodes) {
|
||||
return create(channelCodes, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的支付类型批量创建策略
|
||||
* @param asyncSort 是否异步支付在后面
|
||||
* @return 支付策略
|
||||
*/
|
||||
private static List<AbsPayCloseStrategy> create(List<String> channelCodes, boolean asyncSort) {
|
||||
if (CollectionUtil.isEmpty(channelCodes)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 同步支付
|
||||
val syncChannels = channelCodes.stream()
|
||||
.filter(code -> !ASYNC_TYPE_CODE.contains(code))
|
||||
.map(PayChannelEnum::findByCode)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 异步支付
|
||||
val asyncChannels = channelCodes.stream()
|
||||
.filter(ASYNC_TYPE_CODE::contains)
|
||||
.map(PayChannelEnum::findByCode)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<PayChannelEnum> sortList = new ArrayList<>(channelCodes.size());
|
||||
|
||||
// 异步在后面
|
||||
if (asyncSort) {
|
||||
sortList.addAll(syncChannels);
|
||||
sortList.addAll(asyncChannels);
|
||||
}
|
||||
else {
|
||||
sortList.addAll(asyncChannels);
|
||||
sortList.addAll(syncChannels);
|
||||
}
|
||||
|
||||
// 此处有一个根据Type的反转排序,
|
||||
return sortList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(PayCloseStrategyFactory::create)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@@ -1,14 +1,13 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.close.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.bootx.platform.common.core.function.CollectorsFunction;
|
||||
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException;
|
||||
import cn.bootx.platform.daxpay.param.payment.pay.PayCloseParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.PayCloseResult;
|
||||
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.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.service.PayOrderQueryService;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
|
||||
@@ -17,7 +16,7 @@ import cn.bootx.platform.daxpay.service.core.payment.notice.service.ClientNotice
|
||||
import cn.bootx.platform.daxpay.service.core.record.close.entity.PayCloseRecord;
|
||||
import cn.bootx.platform.daxpay.service.core.record.close.service.PayCloseRecordService;
|
||||
import cn.bootx.platform.daxpay.service.func.AbsPayCloseStrategy;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.bootx.platform.daxpay.util.PaySignUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -26,11 +25,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 支付关闭和撤销服务
|
||||
@@ -41,7 +36,6 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayCloseService {
|
||||
private final PayChannelOrderManager payChannelOrderManager;
|
||||
private final PayOrderService payOrderService;
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
private final PayCloseRecordService payCloseRecordService;
|
||||
@@ -53,22 +47,15 @@ public class PayCloseService {
|
||||
* 关闭支付
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void close(PayCloseParam param){
|
||||
PayOrder payOrder = null;
|
||||
if (Objects.nonNull(param.getPaymentId())){
|
||||
payOrder = payOrderQueryService.findById(param.getPaymentId())
|
||||
.orElseThrow(() -> new PayFailureException("未查询到支付订单"));
|
||||
}
|
||||
if (Objects.isNull(payOrder)){
|
||||
payOrder = payOrderQueryService.findByBizOrderNo(param.getBusinessNo())
|
||||
.orElseThrow(() -> new PayFailureException("未查询到支付订单"));
|
||||
}
|
||||
public PayCloseResult close(PayCloseParam param){
|
||||
PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(param.getOrderNo(), param.getBizTradeNo())
|
||||
.orElseThrow(() -> new PayFailureException("未查询到支付订单"));
|
||||
LockInfo lock = lockTemplate.lock("payment:close:" + payOrder.getId(),10000, 50);
|
||||
if (Objects.isNull(lock)){
|
||||
throw new RepetitiveOperationException("支付订单已在关闭中,请勿重复发起");
|
||||
}
|
||||
try {
|
||||
this.close(payOrder);
|
||||
return this.close(payOrder);
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
@@ -77,69 +64,42 @@ public class PayCloseService {
|
||||
/**
|
||||
* 关闭支付记录
|
||||
*/
|
||||
private void close(PayOrder payOrder) {
|
||||
List<PayChannelOrder> payChannelOrders;
|
||||
private PayCloseResult close(PayOrder payOrder) {
|
||||
try {
|
||||
// 状态检查, 只有支付中可以进行取消支付
|
||||
if (!Objects.equals(payOrder.getStatus(), PayStatusEnum.PROGRESS.getCode())) {
|
||||
throw new PayFailureException("订单不是支付中, 无法进行关闭订单");
|
||||
}
|
||||
|
||||
// 0.基础数据准备
|
||||
Map<String, PayChannelOrder> orderChannelMap = payChannelOrderManager.findAllByPaymentId(payOrder.getOrderNo())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(PayChannelOrder::getChannel, Function.identity(), CollectorsFunction::retainLatest));
|
||||
|
||||
// 1.获取支付方式, 通过工厂生成对应的策略组
|
||||
List<String> channels = orderChannelMap.values()
|
||||
.stream()
|
||||
.map(PayChannelOrder::getChannel)
|
||||
.collect(Collectors.toList());
|
||||
List<AbsPayCloseStrategy> payCloseStrategies = PayCloseStrategyFactory.createAsyncLast(channels);
|
||||
if (CollectionUtil.isEmpty(payCloseStrategies)) {
|
||||
throw new PayUnsupportedMethodException();
|
||||
}
|
||||
|
||||
// 2.初始化关闭支付的参数
|
||||
for (AbsPayCloseStrategy strategy : payCloseStrategies) {
|
||||
strategy.initCloseParam(payOrder, orderChannelMap.get(strategy.getChannel()
|
||||
.getCode()));
|
||||
}
|
||||
|
||||
// 3.关闭前准备
|
||||
payCloseStrategies.forEach(AbsPayCloseStrategy::doBeforeCloseHandler);
|
||||
|
||||
// 4.执行关闭策略
|
||||
payCloseStrategies.forEach(AbsPayCloseStrategy::doCloseHandler);
|
||||
|
||||
// 5.关闭成功后处理
|
||||
payCloseStrategies.forEach(AbsPayCloseStrategy::doSuccessHandler);
|
||||
|
||||
// 6.更新支付通道订单的状态
|
||||
payChannelOrders = payCloseStrategies.stream()
|
||||
.map(AbsPayCloseStrategy::getChannelOrder)
|
||||
.collect(Collectors.toList());
|
||||
payChannelOrderManager.updateAllById(payChannelOrders);
|
||||
} catch (PayFailureException e) {
|
||||
AbsPayCloseStrategy strategy = PayCloseStrategyFactory.create(payOrder.getChannel());
|
||||
// 设置支付订单
|
||||
strategy.setOrder(payOrder);
|
||||
// 关闭前准备
|
||||
strategy.doBeforeCloseHandler();
|
||||
// 执行关闭策略
|
||||
strategy.doCloseHandler();
|
||||
this.successHandler(payOrder);
|
||||
// 返回结果
|
||||
return this.sign(new PayCloseResult());
|
||||
} catch (Exception e) {
|
||||
// 记录关闭失败的记录
|
||||
this.saveRecord(payOrder, false, e.getMessage());
|
||||
throw e;
|
||||
PayCloseResult payCloseResult = new PayCloseResult();
|
||||
payCloseResult.setCode("1").setMsg(e.getMessage());
|
||||
return this.sign(payCloseResult);
|
||||
}
|
||||
|
||||
// 关闭成功后处理
|
||||
this.successHandler(payOrder, payChannelOrders);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功后处理方法
|
||||
*/
|
||||
private void successHandler(PayOrder payOrder, List<PayChannelOrder> payChannelOrders){
|
||||
private void successHandler(PayOrder payOrder){
|
||||
// 关闭订单
|
||||
payOrder.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(payOrder);
|
||||
// 发送通知
|
||||
clientsService.registerPayNotice(payOrder,null, payChannelOrders);
|
||||
clientsService.registerPayNotice(payOrder,null);
|
||||
this.saveRecord(payOrder,true,null);
|
||||
}
|
||||
|
||||
@@ -150,18 +110,30 @@ public class PayCloseService {
|
||||
String clientIp = PaymentContextLocal.get()
|
||||
.getRequestInfo()
|
||||
.getClientIp();
|
||||
String reqId = PaymentContextLocal.get()
|
||||
.getRequestInfo()
|
||||
.getReqId();
|
||||
PayCloseRecord record = new PayCloseRecord()
|
||||
.setPaymentId(payOrder.getId())
|
||||
.setBusinessNo(payOrder.getBusinessNo())
|
||||
.setAsyncChannel(payOrder.getAsyncChannel())
|
||||
.setOrderNo(payOrder.getOrderNo())
|
||||
.setBizOrderNo(payOrder.getOutOrderNo())
|
||||
.setChannel(payOrder.getChannel())
|
||||
.setClosed(closed)
|
||||
.setErrorMsg(errMsg)
|
||||
.setClientIp(clientIp)
|
||||
.setReqId(reqId);
|
||||
.setClientIp(clientIp);
|
||||
payCloseRecordService.saveRecord(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对返回结果进行签名
|
||||
*/
|
||||
private PayCloseResult sign(PayCloseResult result){
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get()
|
||||
.getPlatformInfo();
|
||||
String signType = platformInfo.getSignType();
|
||||
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
|
||||
result.setSign(PaySignUtil.hmacSha256Sign(result, platformInfo.getSignSecret()));
|
||||
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
|
||||
result.setSign(PaySignUtil.md5Sign(result, platformInfo.getSignSecret()));
|
||||
} else {
|
||||
throw new PayFailureException("未获取到签名方式,请检查");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@@ -1,56 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.close.strategy;
|
||||
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.param.channel.WalletPayParam;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.entity.Wallet;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletPayService;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletQueryService;
|
||||
import cn.bootx.platform.daxpay.service.func.AbsPayCloseStrategy;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 钱包支付关闭策略
|
||||
* @author xxm
|
||||
* @since 2023/12/30
|
||||
*/
|
||||
@Slf4j
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WalletPayCloseStrategy extends AbsPayCloseStrategy {
|
||||
private final WalletPayService walletPayService;
|
||||
private final WalletQueryService walletQueryService;
|
||||
|
||||
private Wallet wallet;
|
||||
|
||||
|
||||
@Override
|
||||
public PayChannelEnum getChannel() {
|
||||
return PayChannelEnum.WALLET;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭前的处理方式
|
||||
*/
|
||||
@Override
|
||||
public void doBeforeCloseHandler() {
|
||||
// 从通道扩展参数中取出钱包参数
|
||||
String channelExtra = this.getChannelOrder().getChannelExtra();
|
||||
WalletPayParam walletPayParam = JSONUtil.toBean(channelExtra, WalletPayParam.class);
|
||||
this.wallet = walletQueryService.getWallet(walletPayParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭操作
|
||||
*/
|
||||
@Override
|
||||
public void doCloseHandler() {
|
||||
walletPayService.close(this.getOrder(),this.wallet);
|
||||
}
|
||||
}
|
@@ -1,15 +1,13 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.common.service;
|
||||
|
||||
import cn.bootx.platform.common.core.code.CommonCode;
|
||||
import cn.bootx.platform.daxpay.param.PaymentCommonParam;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.context.RequestLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
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.param.PaymentCommonParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@@ -53,7 +51,6 @@ public class PaymentAssistService {
|
||||
RequestLocal request = PaymentContextLocal.get().getRequestInfo();
|
||||
request.setClientIp(paymentCommonParam.getClientIp())
|
||||
.setSign(paymentCommonParam.getSign())
|
||||
.setReqTime(paymentCommonParam.getReqTime())
|
||||
.setReqId(MDC.get(CommonCode.TRACE_ID));
|
||||
.setReqTime(paymentCommonParam.getReqTime());
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -21,27 +20,21 @@ import java.util.List;
|
||||
@Schema(title = "退款通知消息")
|
||||
public class RefundNoticeResult {
|
||||
|
||||
@Schema(description = "退款ID")
|
||||
private Long refundId;
|
||||
|
||||
@Schema(description = "退款号")
|
||||
private String refundNo;
|
||||
|
||||
@Schema(description = "是否含有异步通道")
|
||||
private boolean asyncPay;
|
||||
@Schema(description = "商户退款号")
|
||||
private String bizRefundNo;
|
||||
|
||||
/**
|
||||
* @see PayChannelEnum#ASYNC_TYPE_CODE
|
||||
* @see PayChannelEnum
|
||||
*/
|
||||
@Schema(description = "异步通道")
|
||||
private String asyncChannel;
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "退款金额")
|
||||
private Integer amount;
|
||||
|
||||
@Schema(description = "退款通道信息")
|
||||
private List<RefundChannelResult> refundChannels;
|
||||
|
||||
/**
|
||||
* @see RefundStatusEnum
|
||||
*/
|
||||
|
@@ -5,11 +5,9 @@ import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.code.ClientNoticeTypeEnum;
|
||||
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.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.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;
|
||||
@@ -19,9 +17,7 @@ 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;
|
||||
|
||||
/**
|
||||
* 客户系统消息通知任务支撑服务
|
||||
@@ -76,27 +72,23 @@ public class ClientNoticeAssistService {
|
||||
*/
|
||||
public ClientNoticeTask buildRefundTask(RefundOrder order, RefundOrderExtra orderExtra){
|
||||
|
||||
// 创建退款通知内容
|
||||
RefundNoticeResult payNoticeResult = new RefundNoticeResult()
|
||||
.setRefundId(order.getId())
|
||||
.setAsyncPay(order.isAsyncPay())
|
||||
.setAsyncChannel(order.getAsyncChannel())
|
||||
.setRefundNo(order.getRefundNo())
|
||||
.setChannel(order.getChannel())
|
||||
.setAmount(order.getAmount())
|
||||
.setRefundTime(order.getRefundTime())
|
||||
.setCreateTime(order.getCreateTime())
|
||||
.setStatus(order.getStatus())
|
||||
.setAttach(orderExtra.getAttach())
|
||||
.setRefundChannels(channels);
|
||||
.setAttach(orderExtra.getAttach());
|
||||
|
||||
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()));
|
||||
}
|
||||
// 签名
|
||||
if (Objects.equals(config.getSignType(), PaySignTypeEnum.MD5.getCode())){
|
||||
payNoticeResult.setSign(PaySignUtil.md5Sign(payNoticeResult,config.getSignSecret()));
|
||||
} else if (Objects.equals(config.getSignType(), PaySignTypeEnum.HMAC_SHA256.getCode())) {
|
||||
payNoticeResult.setSign(PaySignUtil.hmacSha256Sign(payNoticeResult,config.getSignSecret()));
|
||||
} else {
|
||||
}
|
||||
return new ClientNoticeTask()
|
||||
.setUrl(orderExtra.getNotifyUrl())
|
||||
|
@@ -36,8 +36,8 @@ public class PayReturnService {
|
||||
*/
|
||||
public String alipay(AliPayReturnParam param){
|
||||
PayOrderExtra payOrderExtra = payOrderExtraManager.findById(param.getOut_trade_no()).orElse(null);
|
||||
PayOrder prOrder = payOrderQueryService.findById(param.getOut_trade_no()).orElse(null);
|
||||
if (Objects.isNull(payOrderExtra) || Objects.isNull(prOrder)){
|
||||
PayOrder payOrder = payOrderQueryService.findById(param.getOut_trade_no()).orElse(null);
|
||||
if (Objects.isNull(payOrderExtra) || Objects.isNull(payOrder)){
|
||||
return StrUtil.format("{}/result/error?msg={}", properties.getFrontH5Url(), URLEncodeUtil.encode("支付订单有问题,请排查"));
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class PayReturnService {
|
||||
returnUrl = platformConfigService.getConfig().getReturnUrl();
|
||||
}
|
||||
if (StrUtil.isNotBlank(returnUrl)){
|
||||
return StrUtil.format("{}?paymentId={}&businessNo={}", payOrderExtra.getReturnUrl(),prOrder.getId(),prOrder.getBusinessNo());
|
||||
return StrUtil.format("{}?orderNo={}&bizOrderNo={}", payOrderExtra.getReturnUrl(),payOrder.getOrderNo(),payOrder.getBizOrderNo());
|
||||
}
|
||||
// 跳转到默认页
|
||||
return StrUtil.format("{}/result/success?msg={}", properties.getFrontH5Url(), URLEncodeUtil.encode("支付成功..."));
|
||||
@@ -72,7 +72,7 @@ public class PayReturnService {
|
||||
returnUrl = platformConfigService.getConfig().getReturnUrl();
|
||||
}
|
||||
if (StrUtil.isNotBlank(returnUrl)){
|
||||
return StrUtil.format("{}?paymentId={}&businessNo={}", payOrderExtra.getReturnUrl(),prOrder.getId(),prOrder.getBusinessNo());
|
||||
return StrUtil.format("{}?orderNo={}&bizOrderNo={}", payOrderExtra.getReturnUrl(),prOrder.getOrderNo(), prOrder.getBizOrderNo());
|
||||
}
|
||||
// 跳转到默认页
|
||||
return StrUtil.format("{}/result/success?msg={}", properties.getFrontH5Url(), URLEncodeUtil.encode("支付成功..."));
|
||||
|
@@ -3,8 +3,10 @@ package cn.bootx.platform.daxpay.service.core.payment.pay.service;
|
||||
import cn.bootx.platform.common.core.util.CollUtil;
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.param.payment.pay.PayParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.PayResult;
|
||||
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.PayLocal;
|
||||
@@ -17,6 +19,7 @@ import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService;
|
||||
import cn.bootx.platform.daxpay.util.PaySignUtil;
|
||||
import cn.bootx.platform.daxpay.util.PayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
@@ -227,4 +230,37 @@ public class PayAssistService {
|
||||
throw new PayFailureException("支付金额超过限额");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据支付订单构建支付结果
|
||||
* @param payOrder 支付订单
|
||||
* @return PayResult 支付结果
|
||||
*/
|
||||
public PayResult buildResult(PayOrder payOrder) {
|
||||
PayResult payResult;
|
||||
payResult = new PayResult();
|
||||
payResult.setBizOrderNo(payOrder.getBizOrderNo());
|
||||
payResult.setOrderNo(payOrder.getOrderNo());
|
||||
payResult.setStatus(payOrder.getStatus());
|
||||
|
||||
// 设置支付参数
|
||||
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();;
|
||||
if (StrUtil.isNotBlank(asyncPayInfo.getPayBody())) {
|
||||
payResult.setPayBody(asyncPayInfo.getPayBody());
|
||||
}
|
||||
|
||||
// 进行签名
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get()
|
||||
.getPlatformInfo();
|
||||
String signType = platformInfo.getSignType();
|
||||
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
|
||||
payResult.setSign(PaySignUtil.hmacSha256Sign(payResult, platformInfo.getSignSecret()));
|
||||
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
|
||||
payResult.setSign(PaySignUtil.md5Sign(payResult, platformInfo.getSignSecret()));
|
||||
} else {
|
||||
throw new PayFailureException("未获取到签名方式,请检查");
|
||||
}
|
||||
return payResult;
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import cn.bootx.platform.daxpay.param.payment.pay.PayParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.PayResult;
|
||||
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.builder.PayBuilder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderExtraManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
|
||||
@@ -132,7 +131,7 @@ public class PayService {
|
||||
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())){
|
||||
clientNoticeService.registerPayNotice(payOrder, payInfo.getPayOrderExtra());
|
||||
}
|
||||
return PayBuilder.buildResultByPayOrder(payOrder);
|
||||
return payAssistService.buildResult(payOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,6 +184,6 @@ public class PayService {
|
||||
// 查询通道订单
|
||||
clientNoticeService.registerPayNotice(payOrder, payOrderExtra);
|
||||
}
|
||||
return PayBuilder.buildResultByPayOrder(payOrder);
|
||||
return payAssistService.buildResult(payOrder);
|
||||
}
|
||||
}
|
||||
|
@@ -3,10 +3,7 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy;
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.common.sequence.func.Sequence;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.convert.AlipayConvert;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliPayRecordManager;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfigService;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayReconcileService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
|
||||
@@ -23,7 +20,6 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
@@ -40,8 +36,6 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy {
|
||||
|
||||
private final AliPayReconcileService reconcileService;
|
||||
|
||||
private final AliPayRecordManager recordManager;
|
||||
|
||||
private final AliPayConfigService configService;
|
||||
|
||||
private final DaxPaySequenceHandler daxPaySequenceHandler;
|
||||
@@ -108,7 +102,6 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy {
|
||||
LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(this.getRecordOrder().getDate());
|
||||
LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime);
|
||||
LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime);
|
||||
List<AliPayRecord> records = recordManager.findByDate(start, end);
|
||||
return records.stream().map(AlipayConvert.CONVERT::convertReconcileRecord).collect(Collectors.toList());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy;
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.common.sequence.func.Sequence;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.convert.UnionPayConvert;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayConfigService;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayReconcileService;
|
||||
@@ -24,7 +23,6 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
@@ -99,8 +97,7 @@ public class UnionPayReconcileStrategy extends AbsReconcileStrategy {
|
||||
LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(this.getRecordOrder().getDate());
|
||||
LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime);
|
||||
LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime);
|
||||
List<UnionPayRecord> records = recordManager.findByDate(start, end);
|
||||
return records.stream().map(UnionPayConvert.CONVERT::convertReconcileRecord).collect(Collectors.toList());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -106,8 +106,7 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy {
|
||||
LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(this.getRecordOrder().getDate());
|
||||
LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime);
|
||||
LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime);
|
||||
List<WeChatPayRecord> records = recordManager.findByDate(start, end);
|
||||
return records.stream().map(WeChatConvert.CONVERT::convertReconcileRecord).collect(Collectors.toList());
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,22 +1,23 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.refund.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
|
||||
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.payment.refund.RefundParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.RefundResult;
|
||||
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.RefundOrderExtraManager;
|
||||
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.order.refund.entity.RefundOrderExtra;
|
||||
import cn.bootx.platform.daxpay.util.OrderNoGenerateUtil;
|
||||
import cn.bootx.platform.daxpay.util.PaySignUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -40,8 +41,6 @@ import static cn.bootx.platform.daxpay.code.RefundStatusEnum.SUCCESS;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RefundAssistService {
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final RefundOrderExtraManager refundOrderExtraManager;
|
||||
@@ -55,7 +54,7 @@ public class RefundAssistService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化通知相关上下文
|
||||
* 初始化退款通知相关上下文
|
||||
*/
|
||||
private void initNotice(RefundParam param) {
|
||||
NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo();
|
||||
@@ -76,39 +75,6 @@ public class RefundAssistService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据退款参数获取退款订单
|
||||
*/
|
||||
public RefundOrder getRefundOrder(RefundParam param){
|
||||
// 查询退款单
|
||||
RefundOrder refundOrder = null;
|
||||
if (Objects.nonNull(param.getrefun())){
|
||||
refundOrder = refundOrderManager.findById(param.getRefundNo())
|
||||
.orElseThrow(() -> new DataNotExistException("未查询到支付订单"));
|
||||
}
|
||||
if (Objects.isNull(refundOrder)){
|
||||
refundOrder = refundOrderManager.findByRefundNo(param.getRefundNo())
|
||||
.orElseThrow(() -> new DataNotExistException("未查询到支付订单"));
|
||||
}
|
||||
return refundOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据退款参数获取支付订单
|
||||
*/
|
||||
public PayOrder getPayOrder(RefundParam param){
|
||||
PayOrder payOrder = null;
|
||||
if (Objects.nonNull(param.getOrderNo())){
|
||||
payOrder = payOrderQueryService.findByOrderNo(param.getOrderNo())
|
||||
.orElseThrow(() -> new PayFailureException("未查询到支付订单"));
|
||||
}
|
||||
if (Objects.isNull(payOrder)){
|
||||
payOrder = payOrderQueryService.findByBizOrderNo(param.getBizOrderNo())
|
||||
.orElseThrow(() -> new PayFailureException("未查询到支付订单"));
|
||||
}
|
||||
return payOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并处理退款参数
|
||||
*/
|
||||
@@ -173,6 +139,7 @@ public class RefundAssistService {
|
||||
.setRefundNo(asyncRefundInfo.getOutRefundNo());
|
||||
// 退款成功更新退款时间
|
||||
if (Objects.equals(refundOrder.getStatus(), SUCCESS.getCode())){
|
||||
// TODO 读取网关返回的退款时间
|
||||
refundOrder.setRefundTime(LocalDateTime.now());
|
||||
}
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
@@ -186,9 +153,33 @@ public class RefundAssistService {
|
||||
RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo();
|
||||
refundOrder.setErrorCode(refundInfo.getErrorCode());
|
||||
refundOrder.setErrorMsg(refundInfo.getErrorMsg());
|
||||
// 退款失败不保存剩余可退余额, 否则数据看起开会产生困惑
|
||||
refundOrder.setRefundableBalance(null);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据退款订单信息构建出返回结果
|
||||
*/
|
||||
public RefundResult buildResult(RefundOrder refundOrder){
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get()
|
||||
.getPlatformInfo();
|
||||
|
||||
RefundResult refundResult = new RefundResult();
|
||||
refundResult.setRefundNo(refundOrder.getRefundNo())
|
||||
.setBizRefundNo(refundOrder.getBizRefundNo());
|
||||
refundResult.setCode(refundOrder.getStatus())
|
||||
.setMsg(refundOrder.getErrorMsg())
|
||||
.setCode(refundOrder.getErrorCode());
|
||||
|
||||
// 进行签名
|
||||
String signType = platformInfo.getSignType();
|
||||
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
|
||||
refundResult.setSign(PaySignUtil.hmacSha256Sign(refundOrder, platformInfo.getSignSecret()));
|
||||
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
|
||||
refundResult.setSign(PaySignUtil.md5Sign(refundOrder, platformInfo.getSignSecret()));
|
||||
} else {
|
||||
throw new PayFailureException("未获取到签名方式,请检查");
|
||||
}
|
||||
return refundResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ package cn.bootx.platform.daxpay.service.core.payment.refund.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.bootx.platform.common.core.function.CollectorsFunction;
|
||||
import cn.bootx.platform.common.core.util.ValidationUtil;
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
|
||||
@@ -11,11 +10,10 @@ import cn.bootx.platform.daxpay.param.payment.refund.RefundParam;
|
||||
import cn.bootx.platform.daxpay.result.pay.RefundResult;
|
||||
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.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.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.refund.factory.RefundStrategyFactory;
|
||||
@@ -28,9 +26,10 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 支付退款服务
|
||||
@@ -50,6 +49,8 @@ public class RefundService {
|
||||
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
/**
|
||||
@@ -70,7 +71,7 @@ public class RefundService {
|
||||
// 判断是否是首次发起退款
|
||||
Optional<RefundOrder> refund = refundOrderManager.findByBizRefundNo(param.getBizRefundNo());
|
||||
if (refund.isPresent()){
|
||||
return this.repeatRefund(param,refund.get());
|
||||
return this.repeatRefund(refund.get());
|
||||
} else {
|
||||
return this.firstRefund(param);
|
||||
}
|
||||
@@ -85,7 +86,8 @@ public class RefundService {
|
||||
public RefundResult firstRefund(RefundParam param){
|
||||
|
||||
// 获取支付订单
|
||||
PayOrder payOrder = refundAssistService.getPayOrder(param);
|
||||
PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(param.getOrderNo(), param.getBizOrderNo())
|
||||
.orElseThrow(() -> new DataNotExistException("支付订单不存在"));
|
||||
// 检查退款参数
|
||||
refundAssistService.checkAndParam(param, payOrder);
|
||||
|
||||
@@ -97,10 +99,8 @@ public class RefundService {
|
||||
refundStrategy.setPayOrder(payOrder);
|
||||
// 进行退款前预处理
|
||||
refundStrategy.doBeforeRefundHandler();
|
||||
|
||||
// 退款操作的预处理, 使用独立的新事物进行发起, 返回创建成功的退款订单, 成功后才可以进行下一阶段的操作
|
||||
RefundOrder refundOrder = SpringUtil.getBean(this.getClass()).preRefundMethod(param, payOrder);
|
||||
|
||||
try {
|
||||
// 3.2 执行退款策略
|
||||
refundStrategy.doRefundHandler();
|
||||
@@ -112,9 +112,7 @@ public class RefundService {
|
||||
refundAssistService.updateOrderByError(refundOrder);
|
||||
}
|
||||
SpringUtil.getBean(this.getClass()).successHandler(refundOrder, payOrder);
|
||||
return new RefundResult()
|
||||
.setBizRefundNo(refundOrder.getBizRefundNo())
|
||||
.setRefundNo(refundOrder.getRefundNo());
|
||||
return refundAssistService.buildResult(refundOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,37 +135,33 @@ public class RefundService {
|
||||
* 1. 查出相关退款订单
|
||||
* 2. 构建退款策略, 发起退款
|
||||
*/
|
||||
public RefundResult repeatRefund(RefundParam param, RefundOrder refundOrder){
|
||||
public RefundResult repeatRefund(RefundOrder refundOrder){
|
||||
// 退款失败才可以重新发起退款, 重新发起退款
|
||||
if (!Objects.equals(refundOrder.getStatus(), RefundStatusEnum.FAIL.getCode())){
|
||||
throw new PayFailureException("只有失败状态的才可以重新发起退款");
|
||||
}
|
||||
|
||||
// 获取支付订单
|
||||
PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(refundOrder.getOrderNo(), refundOrder.getBizOrderNo())
|
||||
.orElseThrow(() -> new DataNotExistException("支付订单不存在"));
|
||||
AbsRefundStrategy refundStrategy = RefundStrategyFactory.create(refundOrder.getRefundNo());
|
||||
|
||||
// 设置退款订单对象
|
||||
refundStrategy.setRefundOrder(refundOrder);
|
||||
|
||||
// 退款前准备操作
|
||||
refundStrategy.doBeforeRefundHandler();
|
||||
try {
|
||||
// 3.1 退款前准备操作
|
||||
refundStrategy.forEach(AbsRefundStrategy::doBeforeRefundHandler);
|
||||
// 3.2 执行退款策略
|
||||
refundStrategy.forEach(AbsRefundStrategy::doRefundHandler);
|
||||
// 3.3 执行退款发起成功后操作
|
||||
refundStrategy.forEach(AbsRefundStrategy::doSuccessHandler);
|
||||
|
||||
// 4.进行成功处理, 分别处理退款订单, 通道退款订单, 支付订单
|
||||
List<RefundChannelOrder> refundChannelOrders = refundStrategy.stream()
|
||||
.map(AbsRefundStrategy::getRefundChannelOrder)
|
||||
.collect(Collectors.toList());
|
||||
this.successHandler(refundOrder, refundChannelOrders, payOrder);
|
||||
// 执行退款策略
|
||||
refundStrategy.doRefundHandler();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// 5. 失败处理, 所有记录都会回滚, 可以调用退款重试
|
||||
// 失败处理, 所有记录都会回滚, 可以调用退款重试
|
||||
PaymentContextLocal.get().getRefundInfo().setStatus(RefundStatusEnum.FAIL);
|
||||
// 记录退款失败的记录
|
||||
refundAssistService.updateOrderByError(refundOrder);
|
||||
}
|
||||
// 退款发起成功处理
|
||||
SpringUtil.getBean(this.getClass()).successHandler(refundOrder, payOrder);
|
||||
return refundAssistService.buildResult(refundOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -48,6 +48,6 @@ public class AliRefundStrategy extends AbsRefundStrategy {
|
||||
*/
|
||||
@Override
|
||||
public void doRefundHandler() {
|
||||
aliRefundService.refund(this.getRefundOrder(), this.getRefundParam().getAmount());
|
||||
aliRefundService.refund(this.getRefundOrder());
|
||||
}
|
||||
}
|
||||
|
@@ -53,6 +53,6 @@ public class UnionRefundStrategy extends AbsRefundStrategy {
|
||||
@Override
|
||||
public void doRefundHandler() {
|
||||
UnionPayKit unionPayKit = unionPayConfigService.initPayService(unionPayConfig);
|
||||
unionPayRefundService.refund(this.getRefundOrder(), this.getPayOrder(), this.getRefundParam().getAmount(), unionPayKit);
|
||||
unionPayRefundService.refund(this.getRefundOrder(), this.getPayOrder(), unionPayKit);
|
||||
}
|
||||
}
|
||||
|
@@ -56,6 +56,6 @@ public class WalletRefundStrategy extends AbsRefundStrategy {
|
||||
@Override
|
||||
public void doRefundHandler() {
|
||||
// 不包含异步支付, 则只在支付订单中进行扣减, 等待异步退款完成, 再进行退款
|
||||
walletPayService.refund(this.wallet, this.getRefundParam().getAmount());
|
||||
walletPayService.refund(this.wallet, this.getRefundOrder().getAmount());
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ public class WeChatRefundStrategy extends AbsRefundStrategy {
|
||||
*/
|
||||
@Override
|
||||
public void doRefundHandler() {
|
||||
wechatPayRefundService.refund(this.getRefundOrder(), this.getRefundParam().getAmount(), this.weChatPayConfig);
|
||||
wechatPayRefundService.refund(this.getRefundOrder(), this.weChatPayConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,13 +1,10 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.repair.service;
|
||||
|
||||
import cn.bootx.platform.common.core.function.CollectorsFunction;
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
|
||||
import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
|
||||
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.pay.service.PayOrderService;
|
||||
import cn.bootx.platform.daxpay.service.core.payment.notice.service.ClientNoticeService;
|
||||
@@ -26,7 +23,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -43,8 +39,6 @@ public class PayRepairService {
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final PayChannelOrderManager channelOrderManager;
|
||||
|
||||
private final PayRepairRecordService recordService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
@@ -7,14 +7,10 @@ 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.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.service.PayOrderQueryService;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
|
||||
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;
|
||||
@@ -50,8 +46,6 @@ public class RefundRepairService {
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final PayChannelOrderManager payChannelOrderManager;
|
||||
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final PayRepairRecordService recordService;
|
||||
|
@@ -7,8 +7,6 @@ import cn.bootx.platform.daxpay.param.channel.WalletPayParam;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.entity.Wallet;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletPayService;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wallet.service.WalletQueryService;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
|
||||
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;
|
||||
|
@@ -29,13 +29,13 @@ import lombok.experimental.Accessors;
|
||||
@TableName("pay_callback_record")
|
||||
public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunction<PayCallbackRecordDto> {
|
||||
|
||||
/** 本地订单id */
|
||||
@DbColumn(comment = "本地订单id")
|
||||
private Long orderId;
|
||||
/** 本地交易号 */
|
||||
@DbColumn(comment = "本地交易号")
|
||||
private String tradeNo;
|
||||
|
||||
/** 支付网关订单号 */
|
||||
/** 三方支付交易号 */
|
||||
@DbColumn(comment = "支付网关订单号")
|
||||
private String gatewayOrderNo;
|
||||
private String outOrderNo;
|
||||
|
||||
/**
|
||||
* 支付通道
|
||||
@@ -63,9 +63,14 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
|
||||
private String status;
|
||||
|
||||
|
||||
/** 修复号 */
|
||||
@Schema(description = "修复号")
|
||||
private String repairOrderNo;
|
||||
|
||||
/** 错误码 */
|
||||
@DbColumn(comment = "错误码")
|
||||
private String errorCode;
|
||||
|
||||
/** 提示信息 */
|
||||
@DbColumn(comment = "提示信息")
|
||||
private String msg;
|
||||
|
@@ -24,20 +24,20 @@ import lombok.experimental.Accessors;
|
||||
@TableName("pay_close_record")
|
||||
public class PayCloseRecord extends MpCreateEntity implements EntityBaseFunction<PayCloseRecordDto> {
|
||||
|
||||
/** 支付记录id */
|
||||
@DbColumn(comment = "支付记录id")
|
||||
private Long paymentId;
|
||||
/** 订单号 */
|
||||
@DbColumn(comment = "订单号")
|
||||
private String orderNo;
|
||||
|
||||
/** 业务号 */
|
||||
@DbColumn(comment = "业务号")
|
||||
private String businessNo;
|
||||
/** 商户订单号 */
|
||||
@DbColumn(comment = "商户订单号")
|
||||
private String bizOrderNo;
|
||||
|
||||
/**
|
||||
* 关闭的异步支付通道, 可以为空
|
||||
* @see PayChannelEnum#getCode()
|
||||
* 关闭的支付通道
|
||||
* @see PayChannelEnum
|
||||
*/
|
||||
@DbColumn(comment = "关闭的异步支付通道")
|
||||
private String asyncChannel;
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 是否关闭成功
|
||||
@@ -45,6 +45,9 @@ public class PayCloseRecord extends MpCreateEntity implements EntityBaseFunction
|
||||
@DbColumn(comment = "是否关闭成功")
|
||||
private boolean closed;
|
||||
|
||||
@DbColumn(comment = "错误码")
|
||||
private String code;
|
||||
|
||||
@DbColumn(comment = "错误消息")
|
||||
private String errorMsg;
|
||||
|
||||
@@ -52,10 +55,6 @@ public class PayCloseRecord extends MpCreateEntity implements EntityBaseFunction
|
||||
@DbColumn(comment = "客户端IP")
|
||||
private String clientIp;
|
||||
|
||||
/** 请求链路ID */
|
||||
@DbColumn(comment = "请求链路ID")
|
||||
private String reqId;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
|
@@ -1,55 +0,0 @@
|
||||
package cn.bootx.platform.daxpay.service.dto.order.pay;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.dto.BaseDto;
|
||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 支付订单关联通道信息
|
||||
* @author xxm
|
||||
* @since 2024/1/9
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "支付订单关联通道信息")
|
||||
public class PayChannelOrderDto extends BaseDto {
|
||||
|
||||
@Schema(description = "支付id")
|
||||
private String paymentId;
|
||||
|
||||
@Schema(description = "异步支付方式")
|
||||
private boolean async;
|
||||
|
||||
@Schema(description = "通道")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "支付方式")
|
||||
private String payWay;
|
||||
|
||||
/**
|
||||
* 异步支付通道发给网关的退款号, 用与将记录关联起来
|
||||
*/
|
||||
@Schema(description = "关联网关支付号")
|
||||
private String gatewayOrderNo;
|
||||
|
||||
@Schema(description = "金额")
|
||||
private Integer amount;
|
||||
|
||||
@Schema(description = "可退款金额")
|
||||
private Integer refundableBalance;
|
||||
/**
|
||||
* 支付状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@Schema(description = "支付状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "支付时间")
|
||||
private LocalDateTime payTime;
|
||||
}
|
@@ -8,5 +8,4 @@ import java.util.List;
|
||||
public class PayOrderDetailDto {
|
||||
private PayOrderDto payOrder;
|
||||
private PayOrderExtraDto payOrderExtra;
|
||||
private List<PayChannelOrderDto> payChannelOrder;
|
||||
}
|
||||
|
@@ -107,10 +107,10 @@ public abstract class AbsCallbackStrategy implements PayStrategy {
|
||||
PayCallbackRecord payNotifyRecord = new PayCallbackRecord()
|
||||
.setChannel(this.getChannel().getCode())
|
||||
.setNotifyInfo(JSONUtil.toJsonStr(callbackInfo.getCallbackParam()))
|
||||
.setOrderId(callbackInfo.getOrderId())
|
||||
.setGatewayOrderNo(callbackInfo.getOutOrderNo())
|
||||
.setOrderId(callbackInfo.getTradeNo())
|
||||
.setGatewayOrderNo(callbackInfo.getOutTradeNo())
|
||||
.setCallbackType(callbackInfo.getCallbackType().getCode())
|
||||
.setRepairOrderNo(callbackInfo.getPayRepairNo())
|
||||
.setRepairOrderNo(callbackInfo.getRepairNo())
|
||||
.setStatus(callbackInfo.getCallbackStatus().getCode())
|
||||
.setMsg(callbackInfo.getMsg());
|
||||
callbackRecordService.save(payNotifyRecord);
|
||||
|
@@ -1,7 +1,5 @@
|
||||
package cn.bootx.platform.daxpay.service.func;
|
||||
|
||||
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 lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -18,13 +16,6 @@ public abstract class AbsPayCloseStrategy implements PayStrategy{
|
||||
/** 支付订单 */
|
||||
private PayOrder order = null;
|
||||
|
||||
/** 支付通道订单 */
|
||||
private PayChannelOrder channelOrder = null;
|
||||
|
||||
public void initCloseParam(PayOrder order, PayChannelOrder channelOrder){
|
||||
this.order = order;
|
||||
this.channelOrder = channelOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭前的处理方式
|
||||
@@ -36,11 +27,4 @@ public abstract class AbsPayCloseStrategy implements PayStrategy{
|
||||
*/
|
||||
public abstract void doCloseHandler();
|
||||
|
||||
/**
|
||||
* 关闭成功的处理方式
|
||||
*/
|
||||
public void doSuccessHandler() {
|
||||
// 更新通道支付订单的状态为关闭
|
||||
this.getChannelOrder().setStatus(PayStatusEnum.CLOSE.getCode());
|
||||
}
|
||||
}
|
||||
|
@@ -2,9 +2,7 @@ package cn.bootx.platform.daxpay.service.func;
|
||||
|
||||
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.RefundChannelOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
|
||||
import lombok.Getter;
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package cn.bootx.platform.daxpay.service.func;
|
||||
|
||||
import cn.bootx.platform.daxpay.param.payment.refund.RefundParam;
|
||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
|
||||
import lombok.Getter;
|
||||
@@ -22,9 +21,6 @@ public abstract class AbsRefundStrategy implements PayStrategy{
|
||||
/** 退款订单 */
|
||||
private RefundOrder refundOrder = null;
|
||||
|
||||
/** 退款参数 */
|
||||
private RefundParam refundParam;
|
||||
|
||||
|
||||
/**
|
||||
* 退款前对处理, 主要进行配置的加载和检查
|
||||
|
@@ -17,7 +17,7 @@ public class PayOrderRefundParam {
|
||||
|
||||
/** 支付订单号 */
|
||||
@Schema(description = "支付订单号")
|
||||
private Long orderNo;
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 支付通道
|
||||
|
Reference in New Issue
Block a user