mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-13 07:45:41 +08:00
refactor(payment): 订单关闭入口统一, 网关/普通收归单一接口(type 分流), 权限收敛 trade:order:manage, dev 移除 /** 全量放行, /unipay/close 支持网关订单
This commit is contained in:
@@ -50,14 +50,4 @@ public class GatewayPayOrderAdminController {
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(gatewayPayOrderAdminService.sync(id));
|
||||
}
|
||||
|
||||
@PermCode(code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭订单")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
gatewayPayOrderAdminService.close(id, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,4 @@ public class NormalPayOrderAdminController {
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(normalPayOrderAdminService.sync(id));
|
||||
}
|
||||
|
||||
@PermCode(code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭/撤销订单")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
normalPayOrderAdminService.close(id, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.daxpay.open.payment.admin.controller.trade;
|
||||
|
||||
import cn.daxpay.open.payment.admin.service.trade.OrderCloseAdminService;
|
||||
import cn.daxpay.open.platform.core.annotation.PermCode;
|
||||
import cn.daxpay.open.platform.core.code.PermCodes;
|
||||
import cn.daxpay.open.platform.core.rest.Res;
|
||||
import cn.daxpay.open.platform.core.rest.result.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/// # 订单关闭(统一入口, 管理)
|
||||
///
|
||||
/// 收归网关支付/普通支付的关闭入口, 前端按 type 区分; 权限由路由层统一校验 trade:order:manage。
|
||||
@Validated
|
||||
@Tag(name = "订单关闭(统一入口)")
|
||||
@RestController
|
||||
@RequestMapping("/admin/order")
|
||||
@RequiredArgsConstructor
|
||||
public class OrderCloseAdminController {
|
||||
|
||||
private final OrderCloseAdminService orderCloseAdminService;
|
||||
|
||||
@PermCode(menuCode = PermCodes.Trade.Order.MENU, code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭/撤销订单(网关/普通统一入口)")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@NotBlank String type,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
orderCloseAdminService.close(id, type, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,15 @@
|
||||
package cn.daxpay.open.payment.admin.service.trade;
|
||||
|
||||
import cn.daxpay.open.payment.trade.enums.GatewayOrderStatusEnum;
|
||||
import cn.daxpay.open.payment.trade.enums.PayTradeTypeEnum;
|
||||
import cn.daxpay.open.payment.trade.order.convert.GatewayPayOrderConvert;
|
||||
import cn.daxpay.open.payment.trade.order.dao.GatewayPayOrderManager;
|
||||
import cn.daxpay.open.payment.trade.order.dao.PayTradeManager;
|
||||
import cn.daxpay.open.payment.trade.order.entity.GatewayPayOrder;
|
||||
import cn.daxpay.open.payment.trade.order.entity.PayTrade;
|
||||
import cn.daxpay.open.payment.trade.order.param.GatewayPayOrderQuery;
|
||||
import cn.daxpay.open.payment.trade.order.result.GatewayPayOrderResult;
|
||||
import cn.daxpay.open.payment.trade.order.service.TradeOrderDetailAssembler;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.close.PayCloseService;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.sync.PaySyncService;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.pay.common.PayUniHandleService;
|
||||
import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPaySyncResult;
|
||||
import cn.daxpay.open.platform.common.translate.service.TransService;
|
||||
import cn.daxpay.open.platform.core.code.CommonErrorCode;
|
||||
import cn.daxpay.open.platform.core.exception.BizInfoException;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import cn.daxpay.open.platform.core.rest.param.PageParam;
|
||||
import cn.daxpay.open.platform.core.rest.result.PageResult;
|
||||
@@ -24,18 +17,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/// # 网关支付业务单管理服务
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GatewayPayOrderAdminService {
|
||||
|
||||
private final GatewayPayOrderManager gatewayPayOrderManager;
|
||||
private final PayTradeManager payTradeManager;
|
||||
private final PaySyncService paySyncService;
|
||||
private final PayCloseService payCloseService;
|
||||
private final PayUniHandleService payUniHandleService;
|
||||
private final TransService transService;
|
||||
private final TradeOrderDetailAssembler tradeOrderDetailAssembler;
|
||||
|
||||
@@ -64,25 +52,6 @@ public class GatewayPayOrderAdminService {
|
||||
}
|
||||
|
||||
public NormalPaySyncResult sync(Long id) {
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.GATEWAY.getCode())
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
return paySyncService.syncPayOrder(trade);
|
||||
}
|
||||
|
||||
public void close(Long id, boolean useCancel) {
|
||||
GatewayPayOrder order = gatewayPayOrderManager.findById(id)
|
||||
// 支付: 支付订单不存在
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
if (!List.of(GatewayOrderStatusEnum.WAIT_PAY.getCode(), GatewayOrderStatusEnum.PAYING.getCode())
|
||||
.contains(order.getStatus())) {
|
||||
// 支付: 订单不是支付中无法进行关闭订单
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.pay.closeNotPaying");
|
||||
}
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.GATEWAY.getCode()).orElse(null);
|
||||
if (trade != null) {
|
||||
payCloseService.closeOrder(trade, useCancel);
|
||||
} else {
|
||||
payUniHandleService.gatewayOrderClose(order);
|
||||
}
|
||||
return paySyncService.syncByContainer(id, PayTradeTypeEnum.GATEWAY.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,10 @@ package cn.daxpay.open.payment.admin.service.trade;
|
||||
import cn.daxpay.open.payment.trade.enums.PayTradeTypeEnum;
|
||||
import cn.daxpay.open.payment.trade.order.convert.NormalPayOrderConvert;
|
||||
import cn.daxpay.open.payment.trade.order.dao.NormalPayOrderManager;
|
||||
import cn.daxpay.open.payment.trade.order.dao.PayTradeManager;
|
||||
import cn.daxpay.open.payment.trade.order.entity.NormalPayOrder;
|
||||
import cn.daxpay.open.payment.trade.order.entity.PayTrade;
|
||||
import cn.daxpay.open.payment.trade.order.param.NormalPayOrderQuery;
|
||||
import cn.daxpay.open.payment.trade.order.result.NormalPayOrderResult;
|
||||
import cn.daxpay.open.payment.trade.order.service.TradeOrderDetailAssembler;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.close.PayCloseService;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.sync.PaySyncService;
|
||||
import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPaySyncResult;
|
||||
import cn.daxpay.open.platform.common.translate.service.TransService;
|
||||
@@ -28,9 +25,7 @@ import org.springframework.stereotype.Service;
|
||||
public class NormalPayOrderAdminService {
|
||||
|
||||
private final NormalPayOrderManager normalPayOrderManager;
|
||||
private final PayTradeManager payTradeManager;
|
||||
private final PaySyncService paySyncService;
|
||||
private final PayCloseService payCloseService;
|
||||
private final TransService transService;
|
||||
private final TradeOrderDetailAssembler tradeOrderDetailAssembler;
|
||||
|
||||
@@ -63,15 +58,6 @@ public class NormalPayOrderAdminService {
|
||||
|
||||
/// 同步支付状态(传入业务订单ID)
|
||||
public NormalPaySyncResult sync(Long id) {
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.NORMAL.getCode())
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
return paySyncService.syncPayOrder(trade);
|
||||
}
|
||||
|
||||
/// 关闭/撤销订单(传入业务订单ID)
|
||||
public void close(Long id, boolean useCancel) {
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.NORMAL.getCode())
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
payCloseService.closeOrder(trade, useCancel);
|
||||
return paySyncService.syncByContainer(id, PayTradeTypeEnum.NORMAL.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.daxpay.open.payment.admin.service.trade;
|
||||
|
||||
import cn.daxpay.open.payment.trade.runtime.service.close.PayCloseService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/// # 订单关闭统一管理服务
|
||||
///
|
||||
/// 收归网关支付与普通支付的关闭入口, 委托 [PayCloseService.closeByContainer]。
|
||||
/// 网关预下单未生成 Trade 的兜底关单由 closeByContainer 内部处理, 本服务不重复实现。
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OrderCloseAdminService {
|
||||
|
||||
private final PayCloseService payCloseService;
|
||||
|
||||
/// 关闭/撤销订单(统一入口)
|
||||
///
|
||||
/// @param id 业务容器ID(pay_gateway_order / pay_normal_order 主键)
|
||||
/// @param type 容器类型: gateway=网关支付, normal=普通支付
|
||||
/// @param useCancel 是否以撤销方式关闭
|
||||
public void close(Long id, String type, boolean useCancel) {
|
||||
payCloseService.closeByContainer(id, type, useCancel);
|
||||
}
|
||||
}
|
||||
@@ -54,14 +54,4 @@ public class AppAdminGatewayPayOrderController {
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(gatewayPayOrderService.sync(id));
|
||||
}
|
||||
|
||||
@PermCode(code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭订单")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
gatewayPayOrderService.close(id, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,4 @@ public class AppAdminNormalPayOrderController {
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(normalPayOrderService.sync(id));
|
||||
}
|
||||
|
||||
@PermCode(code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭/撤销订单")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
normalPayOrderService.close(id, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.daxpay.open.payment.app.admin.controller.trade;
|
||||
|
||||
import cn.daxpay.open.payment.app.admin.service.trade.AppAdminOrderCloseService;
|
||||
import cn.daxpay.open.platform.core.annotation.PermCode;
|
||||
import cn.daxpay.open.platform.core.code.PermCodes;
|
||||
import cn.daxpay.open.platform.core.rest.Res;
|
||||
import cn.daxpay.open.platform.core.rest.result.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/// # 订单关闭(统一入口, 运营移动端)
|
||||
///
|
||||
/// 收归网关支付/普通支付的关闭入口, 前端按 type 区分; 权限由路由层统一校验 trade:order:manage。
|
||||
@Validated
|
||||
@Tag(name = "订单关闭(统一入口)")
|
||||
@RestController
|
||||
@RequestMapping("/app-admin/order")
|
||||
@RequiredArgsConstructor
|
||||
public class AppAdminOrderCloseController {
|
||||
|
||||
private final AppAdminOrderCloseService appAdminOrderCloseService;
|
||||
|
||||
@PermCode(menuCode = PermCodes.Trade.Order.MENU, code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭/撤销订单(网关/普通统一入口)")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@NotBlank String type,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
appAdminOrderCloseService.close(id, type, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,4 @@ public class AppAdminGatewayPayOrderService {
|
||||
public NormalPaySyncResult sync(Long id) {
|
||||
return gatewayPayOrderAdminService.sync(id);
|
||||
}
|
||||
|
||||
/// 关闭订单
|
||||
public void close(Long id, boolean useCancel) {
|
||||
gatewayPayOrderAdminService.close(id, useCancel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,4 @@ public class AppAdminNormalPayOrderService {
|
||||
public NormalPaySyncResult sync(Long id) {
|
||||
return normalPayOrderAdminService.sync(id);
|
||||
}
|
||||
|
||||
/// 关闭/撤销订单
|
||||
public void close(Long id, boolean useCancel) {
|
||||
normalPayOrderAdminService.close(id, useCancel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.daxpay.open.payment.app.admin.service.trade;
|
||||
|
||||
import cn.daxpay.open.payment.admin.service.trade.OrderCloseAdminService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/// # 运营移动端-订单关闭统一服务
|
||||
///
|
||||
/// 逻辑转发至 [OrderCloseAdminService]。
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AppAdminOrderCloseService {
|
||||
|
||||
private final OrderCloseAdminService orderCloseAdminService;
|
||||
|
||||
/// 关闭/撤销订单(统一入口)
|
||||
public void close(Long id, String type, boolean useCancel) {
|
||||
orderCloseAdminService.close(id, type, useCancel);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.daxpay.open.payment.trade.runtime.service.close;
|
||||
|
||||
import cn.daxpay.open.payment.common.context.PaymentContext;
|
||||
import cn.daxpay.open.payment.trade.enums.GatewayOrderStatusEnum;
|
||||
import cn.daxpay.open.payment.trade.enums.PayFundStatusEnum;
|
||||
import cn.daxpay.open.payment.trade.enums.PayTradeTypeEnum;
|
||||
import cn.daxpay.open.payment.strategy.PaymentStrategyFactory;
|
||||
@@ -54,28 +55,71 @@ public class PayCloseService {
|
||||
private final LockExecutor lockExecutor;
|
||||
private final PaymentContext paymentContext;
|
||||
|
||||
/// 按容器ID关闭/撤销订单(含网关预下单未生成 Trade 的兜底)
|
||||
///
|
||||
/// 供容器视角的对外 Service(Admin/Merchant)调用, 消除两端重复的容器状态校验与预下单分支。
|
||||
public void closeByContainer(Long containerId, String tradeType, boolean useCancel) {
|
||||
// 网关: 预下单后可能尚未生成 Trade
|
||||
if (Objects.equals(tradeType, PayTradeTypeEnum.GATEWAY.getCode())) {
|
||||
GatewayPayOrder order = gatewayPayOrderManager.findById(containerId)
|
||||
.orElseThrow(() -> new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.payOrderNotExist"));
|
||||
if (!List.of(GatewayOrderStatusEnum.WAIT_PAY.getCode(), GatewayOrderStatusEnum.PAYING.getCode())
|
||||
.contains(order.getStatus())) {
|
||||
// 支付: 订单不是支付中, 无法进行关闭订单
|
||||
throw new BizInfoException(DaxPayErrorCode.TRADE_STATUS_ERROR, "pay.error.pay.closeNotPaying");
|
||||
}
|
||||
PayTrade trade = payTradeManager.findByContainerId(containerId, tradeType).orElse(null);
|
||||
if (Objects.nonNull(trade)) {
|
||||
this.closeOrder(trade, useCancel);
|
||||
} else {
|
||||
payUniHandleService.gatewayOrderClose(order);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 普通支付等其他形态: 直接反查 Trade 关单
|
||||
PayTrade trade = payTradeManager.findByContainerId(containerId, tradeType)
|
||||
.orElseThrow(() -> new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.payOrderNotExist"));
|
||||
this.closeOrder(trade, useCancel);
|
||||
}
|
||||
|
||||
/// 关闭支付(商户 API)
|
||||
///
|
||||
/// 同时支持普通支付与网关支付两种容器:
|
||||
/// - orderNo 优先按 tradeNo(平台支付订单号)查资金交易; 未命中再按网关容器 orderNo 反查(运营友好, 与退款服务对齐)
|
||||
/// - bizOrderNo 回退: 先普通容器再网关容器, 委托 [closeByContainer] 复用网关预下单无 Trade 的兜底关单
|
||||
public void close(NormalPayCloseParam param) {
|
||||
if (StrUtil.isBlank(param.getOrderNo()) && Objects.isNull(param.getBizOrderNo())) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.orderNoRequired");
|
||||
}
|
||||
PayTrade trade = null;
|
||||
// orderNo 优先: 先按 tradeNo 查资金交易(实体自带 tradeType, 直接 closeOrder)
|
||||
if (StrUtil.isNotBlank(param.getOrderNo())) {
|
||||
trade = payTradeManager.findByTradeNo(param.getOrderNo()).orElse(null);
|
||||
}
|
||||
if (Objects.isNull(trade) && Objects.nonNull(param.getBizOrderNo())) {
|
||||
NormalPayOrder normalOrder = payNormalOrderManager.findByBizOrderNo(param.getBizOrderNo())
|
||||
.orElse(null);
|
||||
if (Objects.nonNull(normalOrder)) {
|
||||
trade = payTradeManager.findByContainerId(normalOrder.getId(), PayTradeTypeEnum.NORMAL.getCode())
|
||||
.orElse(null);
|
||||
PayTrade trade = payTradeManager.findByTradeNo(param.getOrderNo()).orElse(null);
|
||||
if (Objects.nonNull(trade)) {
|
||||
this.closeOrder(trade, param.isUseCancel());
|
||||
return;
|
||||
}
|
||||
// tradeNo 未命中: 尝试用网关容器 orderNo 反查
|
||||
GatewayPayOrder gateway = gatewayPayOrderManager.findByOrderNo(param.getOrderNo()).orElse(null);
|
||||
if (Objects.nonNull(gateway)) {
|
||||
this.closeByContainer(gateway.getId(), PayTradeTypeEnum.GATEWAY.getCode(), param.isUseCancel());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Objects.isNull(trade)) {
|
||||
// 支付: 支付订单不存在
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.payOrderNotExist");
|
||||
// bizOrderNo 回退: 先普通再网关, 委托 closeByContainer(含网关无 Trade 兜底)
|
||||
if (Objects.nonNull(param.getBizOrderNo())) {
|
||||
NormalPayOrder normalOrder = payNormalOrderManager.findByBizOrderNo(param.getBizOrderNo()).orElse(null);
|
||||
if (Objects.nonNull(normalOrder)) {
|
||||
this.closeByContainer(normalOrder.getId(), PayTradeTypeEnum.NORMAL.getCode(), param.isUseCancel());
|
||||
return;
|
||||
}
|
||||
GatewayPayOrder gatewayOrder = gatewayPayOrderManager.findByBizOrderNo(param.getBizOrderNo()).orElse(null);
|
||||
if (Objects.nonNull(gatewayOrder)) {
|
||||
this.closeByContainer(gatewayOrder.getId(), PayTradeTypeEnum.GATEWAY.getCode(), param.isUseCancel());
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.closeOrder(trade, param.isUseCancel());
|
||||
// 支付: 支付订单不存在
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.payOrderNotExist");
|
||||
}
|
||||
|
||||
/// 关闭支付记录
|
||||
|
||||
@@ -13,12 +13,12 @@ import lombok.EqualsAndHashCode;
|
||||
@Schema(title = "支付关闭参数")
|
||||
public class NormalPayCloseParam extends MerchantPaymentCommonParam {
|
||||
|
||||
/// 支付订单号/商户订单号/通道订单号至少要传输一个,支付订单号 > 商户订单号 > 通道订单号
|
||||
/// 平台支付订单号(tradeNo)或网关订单号(orderNo), 优先按 tradeNo 查, 未命中按网关 orderNo 反查
|
||||
@Schema(description = "订单号")
|
||||
@Size(max = 100, message = "{validation.field.orderNo.size}")
|
||||
private String orderNo;
|
||||
|
||||
/// 支付订单号/商户订单号/通道订单号至少要传输一个,支付订单号 > 商户订单号 > 通道订单号
|
||||
/// 商户订单号, 支持普通支付与网关支付两种容器, 先普通容器再网关容器查询
|
||||
@Schema(description = "商户订单号")
|
||||
@Size(max = 100, message = "{validation.field.bizOrderNo.size}")
|
||||
private String bizOrderNo;
|
||||
|
||||
@@ -56,14 +56,4 @@ public class MchGatewayPayOrderController {
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(mchGatewayPayOrderService.sync(id));
|
||||
}
|
||||
|
||||
@PermCode(code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭订单")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
mchGatewayPayOrderService.close(id, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,4 @@ public class MchNormalPayOrderController {
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id) {
|
||||
return Res.ok(mchNormalPayOrderService.sync(id));
|
||||
}
|
||||
|
||||
@PermCode(code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭/撤销订单")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
mchNormalPayOrderService.close(id, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.daxpay.open.payment.merchant.controller.trade;
|
||||
|
||||
import cn.daxpay.open.payment.merchant.service.trade.MchOrderCloseService;
|
||||
import cn.daxpay.open.platform.core.annotation.PermCode;
|
||||
import cn.daxpay.open.platform.core.code.PermCodes;
|
||||
import cn.daxpay.open.platform.core.rest.Res;
|
||||
import cn.daxpay.open.platform.core.rest.result.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/// # 订单关闭(统一入口, 商户)
|
||||
///
|
||||
/// 收归网关支付/普通支付的关闭入口, 前端按 type 区分; 权限由路由层统一校验 trade:order:manage。
|
||||
@Validated
|
||||
@Tag(name = "订单关闭(统一入口)")
|
||||
@RestController
|
||||
@RequestMapping("/mch/order")
|
||||
@RequiredArgsConstructor
|
||||
public class MchOrderCloseController {
|
||||
|
||||
private final MchOrderCloseService mchOrderCloseService;
|
||||
|
||||
@PermCode(menuCode = PermCodes.Trade.Order.MENU, code = PermCodes.Action.MANAGE)
|
||||
@Operation(summary = "关闭/撤销订单(网关/普通统一入口)")
|
||||
@PostMapping("/close")
|
||||
public Result<Void> close(
|
||||
@NotNull(message = "{validation.field.id.notNull}") Long id,
|
||||
@NotBlank String type,
|
||||
@RequestParam(defaultValue = "false") boolean useCancel) {
|
||||
mchOrderCloseService.close(id, type, useCancel);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,16 @@
|
||||
package cn.daxpay.open.payment.merchant.service.trade;
|
||||
|
||||
import cn.daxpay.open.payment.common.context.PaymentContext;
|
||||
import cn.daxpay.open.payment.trade.enums.GatewayOrderStatusEnum;
|
||||
import cn.daxpay.open.payment.trade.enums.PayTradeTypeEnum;
|
||||
import cn.daxpay.open.payment.trade.order.convert.GatewayPayOrderConvert;
|
||||
import cn.daxpay.open.payment.trade.order.dao.GatewayPayOrderManager;
|
||||
import cn.daxpay.open.payment.trade.order.dao.PayTradeManager;
|
||||
import cn.daxpay.open.payment.trade.order.entity.GatewayPayOrder;
|
||||
import cn.daxpay.open.payment.trade.order.entity.PayTrade;
|
||||
import cn.daxpay.open.payment.trade.order.param.GatewayPayOrderQuery;
|
||||
import cn.daxpay.open.payment.trade.order.result.GatewayPayOrderResult;
|
||||
import cn.daxpay.open.payment.trade.order.service.TradeOrderDetailAssembler;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.close.PayCloseService;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.pay.common.PayUniHandleService;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.sync.PaySyncService;
|
||||
import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPaySyncResult;
|
||||
import cn.daxpay.open.platform.core.code.CommonCode;
|
||||
import cn.daxpay.open.platform.core.code.CommonErrorCode;
|
||||
import cn.daxpay.open.platform.core.exception.BizInfoException;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import cn.daxpay.open.platform.core.rest.param.PageParam;
|
||||
@@ -25,8 +19,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/// # 网关支付业务单(商户端)
|
||||
///
|
||||
/// 强制按 [PaymentContext#getMchNo] 过滤;行级隔离另由 TenantLine 兜底。
|
||||
@@ -36,10 +28,7 @@ public class MchGatewayPayOrderService {
|
||||
|
||||
private final PaymentContext paymentContext;
|
||||
private final GatewayPayOrderManager gatewayPayOrderManager;
|
||||
private final PayTradeManager payTradeManager;
|
||||
private final PaySyncService paySyncService;
|
||||
private final PayCloseService payCloseService;
|
||||
private final PayUniHandleService payUniHandleService;
|
||||
private final TradeOrderDetailAssembler tradeOrderDetailAssembler;
|
||||
|
||||
/// 分页查询(强制当前商户)
|
||||
@@ -67,27 +56,7 @@ public class MchGatewayPayOrderService {
|
||||
|
||||
/// 同步支付状态
|
||||
public NormalPaySyncResult sync(Long id) {
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.GATEWAY.getCode())
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
return paySyncService.syncPayOrder(trade);
|
||||
}
|
||||
|
||||
/// 关闭/撤销订单
|
||||
public void close(Long id, boolean useCancel) {
|
||||
GatewayPayOrder order = gatewayPayOrderManager.findById(id)
|
||||
// 支付: 支付订单不存在
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
if (!List.of(GatewayOrderStatusEnum.WAIT_PAY.getCode(), GatewayOrderStatusEnum.PAYING.getCode())
|
||||
.contains(order.getStatus())) {
|
||||
// 支付: 订单不是支付中无法进行关闭订单
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.error.pay.closeNotPaying");
|
||||
}
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.GATEWAY.getCode()).orElse(null);
|
||||
if (trade != null) {
|
||||
payCloseService.closeOrder(trade, useCancel);
|
||||
} else {
|
||||
payUniHandleService.gatewayOrderClose(order);
|
||||
}
|
||||
return paySyncService.syncByContainer(id, PayTradeTypeEnum.GATEWAY.getCode());
|
||||
}
|
||||
|
||||
/// 解析并强制写入当前商户号
|
||||
|
||||
@@ -4,13 +4,10 @@ import cn.daxpay.open.payment.common.context.PaymentContext;
|
||||
import cn.daxpay.open.payment.trade.enums.PayTradeTypeEnum;
|
||||
import cn.daxpay.open.payment.trade.order.convert.NormalPayOrderConvert;
|
||||
import cn.daxpay.open.payment.trade.order.dao.NormalPayOrderManager;
|
||||
import cn.daxpay.open.payment.trade.order.dao.PayTradeManager;
|
||||
import cn.daxpay.open.payment.trade.order.entity.NormalPayOrder;
|
||||
import cn.daxpay.open.payment.trade.order.entity.PayTrade;
|
||||
import cn.daxpay.open.payment.trade.order.param.NormalPayOrderQuery;
|
||||
import cn.daxpay.open.payment.trade.order.result.NormalPayOrderResult;
|
||||
import cn.daxpay.open.payment.trade.order.service.TradeOrderDetailAssembler;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.close.PayCloseService;
|
||||
import cn.daxpay.open.payment.trade.runtime.service.sync.PaySyncService;
|
||||
import cn.daxpay.open.payment.unipay.result.trade.pay.NormalPaySyncResult;
|
||||
import cn.daxpay.open.platform.core.code.CommonCode;
|
||||
@@ -31,9 +28,7 @@ public class MchNormalPayOrderService {
|
||||
|
||||
private final PaymentContext paymentContext;
|
||||
private final NormalPayOrderManager normalPayOrderManager;
|
||||
private final PayTradeManager payTradeManager;
|
||||
private final PaySyncService paySyncService;
|
||||
private final PayCloseService payCloseService;
|
||||
private final TradeOrderDetailAssembler tradeOrderDetailAssembler;
|
||||
|
||||
/// 分页查询(强制当前商户)
|
||||
@@ -61,16 +56,7 @@ public class MchNormalPayOrderService {
|
||||
|
||||
/// 同步支付状态(传入业务订单ID)
|
||||
public NormalPaySyncResult sync(Long id) {
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.NORMAL.getCode())
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
return paySyncService.syncPayOrder(trade);
|
||||
}
|
||||
|
||||
/// 关闭/撤销订单(传入业务订单ID)
|
||||
public void close(Long id, boolean useCancel) {
|
||||
PayTrade trade = payTradeManager.findByContainerId(id, PayTradeTypeEnum.NORMAL.getCode())
|
||||
.orElseThrow(() -> new DataNotExistException("pay.error.payOrderNotExist"));
|
||||
payCloseService.closeOrder(trade, useCancel);
|
||||
return paySyncService.syncByContainer(id, PayTradeTypeEnum.NORMAL.getCode());
|
||||
}
|
||||
|
||||
/// 解析并强制写入当前商户号
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.daxpay.open.payment.merchant.service.trade;
|
||||
|
||||
import cn.daxpay.open.payment.trade.runtime.service.close.PayCloseService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/// # 订单关闭统一管理服务(商户端)
|
||||
///
|
||||
/// 收归网关支付与普通支付的关闭入口, 委托 [PayCloseService#closeByContainer]。
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MchOrderCloseService {
|
||||
|
||||
private final PayCloseService payCloseService;
|
||||
|
||||
/// 关闭/撤销订单(统一入口)
|
||||
///
|
||||
/// @param id 业务容器ID(pay_gateway_order / pay_normal_order 主键)
|
||||
/// @param type 容器类型: gateway=网关支付, normal=普通支付
|
||||
/// @param useCancel 是否以撤销方式关闭
|
||||
public void close(Long id, String type, boolean useCancel) {
|
||||
payCloseService.closeByContainer(id, type, useCancel);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,6 @@ daxpay:
|
||||
- '/test/**'
|
||||
- '/error'
|
||||
- '/favicon.ico'
|
||||
- '/**'
|
||||
# 审计日志配置
|
||||
audit-log:
|
||||
ip2region:
|
||||
@@ -109,6 +108,8 @@ daxpay:
|
||||
# 查询模式: VECTOR_INDEX(推荐) 或 CACHE
|
||||
search-type: VECTOR_INDEX
|
||||
config:
|
||||
# 交易定时同步开关(dev 环境开启)
|
||||
trade-sync-enabled: true
|
||||
# 平台公私钥(证书)配置, 用于接口请求/回调的 RSA 签名与验签
|
||||
key-config:
|
||||
# 私钥配置
|
||||
|
||||
Reference in New Issue
Block a user