package com.gxwebsoft.payment.controller; import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.payment.constants.PaymentConstants; import com.gxwebsoft.payment.dto.PaymentRequest; import com.gxwebsoft.payment.dto.PaymentResponse; import com.gxwebsoft.payment.dto.PaymentStatusUpdateRequest; import com.gxwebsoft.payment.dto.PaymentWithOrderRequest; import com.gxwebsoft.payment.enums.PaymentType; import com.gxwebsoft.payment.exception.PaymentException; import com.gxwebsoft.payment.service.PaymentService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; import java.math.BigDecimal; import java.util.List; import java.util.Map; /** * 统一支付控制器 * 提供所有支付方式的统一入口 * * @author 科技小王子 * @since 2025-01-26 */ @Slf4j @Validated @Tag(name = "统一支付接口", description = "支持所有支付方式的统一支付接口") @RestController("unifiedPaymentController") @RequestMapping("/api/payment") public class PaymentController extends BaseController { @Resource(name = "unifiedPaymentServiceImpl") private PaymentService paymentService; @Operation(summary = "创建支付订单", description = "支持微信、支付宝、银联等多种支付方式") @PostMapping("/create") public ApiResult createPayment(@Valid @RequestBody PaymentRequest request) { log.info("收到支付请求: {}", request); final User loginUser = getLoginUser(); if(loginUser == null){ return fail("请先登录"); } request.setUserId(loginUser.getUserId()); if(request.getTenantId() == null){ request.setTenantId(loginUser.getTenantId()); } try { PaymentResponse response = paymentService.createPayment(request); return this.success("支付订单创建成功", response); } catch (PaymentException e) { log.error("支付订单创建失败: {}", e.getMessage()); return fail(e.getMessage()); } catch (Exception e) { log.error("支付订单创建系统错误: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "创建支付订单(包含订单信息)", description = "统一支付模块:创建订单并发起支付") @PostMapping("/create-with-order") public ApiResult createPaymentWithOrder(@Valid @RequestBody PaymentWithOrderRequest request) { log.info("收到支付与订单创建请求: {}", request); final User loginUser = getLoginUser(); if(loginUser == null){ return fail("请先登录"); } // 设置用户信息 if(request.getTenantId() == null){ request.setTenantId(loginUser.getTenantId()); } try { PaymentResponse response = paymentService.createPaymentWithOrder(request, loginUser); return this.success("订单创建并发起支付成功", response); } catch (PaymentException e) { log.error("创建支付订单失败: {}", e.getMessage()); return fail(e.getMessage()); } catch (Exception e) { log.error("创建支付订单系统错误: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "查询支付状态", description = "查询指定订单的支付状态") @GetMapping("/query") public ApiResult queryPayment( @Parameter(description = "订单号", required = true) @RequestParam @NotBlank(message = "订单号不能为空") String orderNo, @Parameter(description = "支付类型", required = true) @RequestParam @NotNull(message = "支付类型不能为空") PaymentType paymentType, @Parameter(description = "租户ID", required = true) @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { log.info("查询支付状态: orderNo={}, paymentType={}, tenantId={}", orderNo, paymentType, tenantId); // 参数验证 if (orderNo == null || orderNo.trim().isEmpty()) { return fail("订单号不能为空"); } if (paymentType == null) { return fail("支付类型不能为空"); } if (tenantId == null || tenantId <= 0) { return fail("租户ID不能为空且必须为正数"); } try { PaymentResponse response = paymentService.queryPayment(orderNo, paymentType, tenantId); return this.success("支付状态查询成功", response); } catch (PaymentException e) { log.error("支付状态查询失败: {}", e.getMessage()); return fail(e.getMessage()); } catch (Exception e) { log.error("支付状态查询系统错误: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "申请退款", description = "申请订单退款") @PostMapping("/refund") public ApiResult refund( @Parameter(description = "订单号", required = true) @RequestParam @NotBlank(message = "订单号不能为空") String orderNo, @Parameter(description = "退款单号", required = true) @RequestParam @NotBlank(message = "退款单号不能为空") String refundNo, @Parameter(description = "支付类型", required = true) @RequestParam @NotNull(message = "支付类型不能为空") PaymentType paymentType, @Parameter(description = "订单总金额", required = true) @RequestParam @NotNull(message = "订单总金额不能为空") @Positive(message = "订单总金额必须大于0") BigDecimal totalAmount, @Parameter(description = "退款金额", required = true) @RequestParam @NotNull(message = "退款金额不能为空") @Positive(message = "退款金额必须大于0") BigDecimal refundAmount, @Parameter(description = "退款原因") @RequestParam(required = false) String reason, @Parameter(description = "租户ID", required = true) @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { log.info("申请退款: orderNo={}, refundNo={}, paymentType={}, totalAmount={}, refundAmount={}, tenantId={}", orderNo, refundNo, paymentType, totalAmount, refundAmount, tenantId); try { PaymentResponse response = paymentService.refund(orderNo, refundNo, paymentType, totalAmount, refundAmount, reason, tenantId); return this.success("退款申请成功", response); } catch (PaymentException e) { log.error("退款申请失败: {}", e.getMessage()); return fail(e.getMessage()); } catch (Exception e) { log.error("退款申请系统错误: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "查询退款状态", description = "查询指定退款单的状态") @GetMapping("/refund/query") public ApiResult queryRefund( @Parameter(description = "退款单号", required = true) @RequestParam @NotBlank(message = "退款单号不能为空") String refundNo, @Parameter(description = "支付类型", required = true) @RequestParam @NotNull(message = "支付类型不能为空") PaymentType paymentType, @Parameter(description = "租户ID", required = true) @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { log.info("查询退款状态: refundNo={}, paymentType={}, tenantId={}", refundNo, paymentType, tenantId); try { PaymentResponse response = paymentService.queryRefund(refundNo, paymentType, tenantId); return this.success("退款状态查询成功", response); } catch (PaymentException e) { log.error("退款状态查询失败: {}", e.getMessage()); return fail(e.getMessage()); } catch (Exception e) { log.error("退款状态查询系统错误: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "关闭订单", description = "关闭未支付的订单") @PostMapping("/close") public ApiResult closeOrder( @Parameter(description = "订单号", required = true) @RequestParam @NotBlank(message = "订单号不能为空") String orderNo, @Parameter(description = "支付类型", required = true) @RequestParam @NotNull(message = "支付类型不能为空") PaymentType paymentType, @Parameter(description = "租户ID", required = true) @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { log.info("关闭订单: orderNo={}, paymentType={}, tenantId={}", orderNo, paymentType, tenantId); try { boolean result = paymentService.closeOrder(orderNo, paymentType, tenantId); return success(result ? "订单关闭成功" : "订单关闭失败", result); } catch (PaymentException e) { log.error("订单关闭失败: {}", e.getMessage()); return fail(e.getMessage()); } catch (Exception e) { log.error("订单关闭系统错误: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "获取支持的支付类型", description = "获取系统支持的所有支付类型列表") @GetMapping("/types") public ApiResult getSupportedPaymentTypes() { try { List paymentTypes = paymentService.getSupportedPaymentTypes(); return this.>success("获取支付类型成功", paymentTypes); } catch (Exception e) { log.error("获取支付类型失败: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "获取支付策略信息", description = "获取指定支付类型的策略信息") @GetMapping("/strategy/{paymentType}") public ApiResult getPaymentStrategyInfo( @Parameter(description = "支付类型", required = true) @PathVariable @NotNull(message = "支付类型不能为空") PaymentType paymentType) { try { Map strategyInfo = paymentService.getPaymentStrategyInfo(paymentType); if (strategyInfo == null) { return fail("不支持的支付类型: " + paymentType); } return success("获取策略信息成功", strategyInfo); } catch (Exception e) { log.error("获取策略信息失败: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "获取所有支付策略信息", description = "获取系统所有支付策略的详细信息") @GetMapping("/strategies") public ApiResult getAllPaymentStrategyInfo() { try { List> strategiesInfo = paymentService.getAllPaymentStrategyInfo(); return this.>>success("获取所有策略信息成功", strategiesInfo); } catch (Exception e) { log.error("获取所有策略信息失败: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "检查支付类型支持情况", description = "检查指定支付类型的功能支持情况") @GetMapping("/support/{paymentType}") public ApiResult checkPaymentTypeSupport( @Parameter(description = "支付类型", required = true) @PathVariable @NotNull(message = "支付类型不能为空") PaymentType paymentType) { try { Map support = Map.of( "supported", paymentService.isPaymentTypeSupported(paymentType), "refundSupported", paymentService.isRefundSupported(paymentType), "querySupported", paymentService.isQuerySupported(paymentType), "closeSupported", paymentService.isCloseSupported(paymentType), "notifyNeeded", paymentService.isNotifyNeeded(paymentType) ); return this.>success("检查支持情况成功", support); } catch (Exception e) { log.error("检查支持情况失败: {}", e.getMessage(), e); return fail(PaymentConstants.ErrorMessage.SYSTEM_ERROR); } } @Operation(summary = "手动更新支付状态", description = "用于手动同步支付状态,通常用于异常情况处理") @PutMapping("/update-status") public ApiResult updatePaymentStatus(@Valid @RequestBody PaymentStatusUpdateRequest request) { log.info("收到支付状态更新请求: {}", request); try { // 查询并更新支付状态 PaymentResponse response = paymentService.queryPayment( request.getOrderNo(), PaymentType.WECHAT_NATIVE, request.getTenantId() ); return this.success("支付状态更新成功", response); } catch (Exception e) { log.error("更新支付状态失败: {}", e.getMessage(), e); return fail("更新支付状态失败: " + e.getMessage()); } } @Operation(summary = "检查支付配置", description = "检查指定租户的支付配置是否完整") @GetMapping("/config/check") public ApiResult checkPaymentConfig( @Parameter(description = "租户ID", required = true) @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { log.info("检查支付配置,租户ID: {}", tenantId); try { Map configStatus = paymentService.checkPaymentConfig(tenantId); return this.>success("配置检查完成", configStatus); } catch (Exception e) { log.error("检查支付配置失败: {}", e.getMessage(), e); return fail("检查支付配置失败: " + e.getMessage()); } } @Operation(summary = "查询用户最近的支付订单", description = "当orderNo缺失时,查询用户最近创建的支付订单") @GetMapping("/query-recent") public ApiResult queryRecentPayment( @Parameter(description = "支付类型", required = true) @RequestParam @NotNull(message = "支付类型不能为空") PaymentType paymentType, @Parameter(description = "租户ID", required = true) @RequestParam @NotNull(message = "租户ID不能为空") @Positive(message = "租户ID必须为正数") Integer tenantId) { log.info("查询用户最近支付订单: paymentType={}, tenantId={}", paymentType, tenantId); final User loginUser = getLoginUser(); if(loginUser == null){ return fail("请先登录"); } try { // 这里需要实现查询用户最近订单的逻辑 // 可以通过用户ID和租户ID查询最近创建的订单 return fail("此功能需要实现查询用户最近订单的业务逻辑"); } catch (Exception e) { log.error("查询用户最近支付订单失败: {}", e.getMessage(), e); return fail("查询失败: " + e.getMessage()); } } }