feat(payment): 初始化支付模块核心代码
- 添加支付常量类PaymentConstants,定义支付状态、微信、支付宝、银联等相关常量 - 创建微信支付类型常量类WechatPayType,支持JSAPI、NATIVE、H5、APP支付方式 - 新增支付控制器PaymentController,提供创建支付、查询状态、退款等统一接口 - 实现支付回调控制器PaymentNotifyController,处理微信、支付宝、银联异步通知 - 添加支付请求数据传输对象PaymentRequest,支持多种支付方式参数校验 - 定义支付响应、状态更新请求等相关DTO类- 集成Swagger注解,完善接口文档说明- 添加参数校验和异常处理机制,确保支付流程安全可靠
This commit is contained in:
360
java/payment/controller/PaymentController.java
Normal file
360
java/payment/controller/PaymentController.java
Normal file
@@ -0,0 +1,360 @@
|
||||
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.<PaymentResponse>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.<PaymentResponse>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.<PaymentResponse>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.<PaymentResponse>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.<PaymentResponse>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<PaymentType> paymentTypes = paymentService.getSupportedPaymentTypes();
|
||||
return this.<List<PaymentType>>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<String, Object> 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<Map<String, Object>> strategiesInfo = paymentService.getAllPaymentStrategyInfo();
|
||||
return this.<List<Map<String, Object>>>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<String, Boolean> 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.<Map<String, Boolean>>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.<PaymentResponse>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<String, Object> configStatus = paymentService.checkPaymentConfig(tenantId);
|
||||
return this.<Map<String, Object>>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());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user