From e81ec8cca7c6a97c1f9fe767790ac1a27b47556a Mon Sep 17 00:00:00 2001
From: future <1360317836@qq.com>
Date: Wed, 24 Jun 2026 23:23:55 +0800
Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4gym-payment=E6=A8=A1=E5=9D=97?=
=?UTF-8?q?=EF=BC=8C=E4=B8=8Edev=E5=88=86=E6=94=AF=E4=BF=9D=E6=8C=81?=
=?UTF-8?q?=E4=B8=80=E8=87=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
gym-manage-api/gym-payment/pom.xml | 62 ---
.../payment/config/AlipayClientConfig.java | 32 --
.../payment/config/AlipayProperties.java | 57 ---
.../gym/manage/payment/dto/ApiResponse.java | 52 --
.../payment/dto/CreatePaymentRequest.java | 54 ---
.../manage/payment/dto/PaymentResponse.java | 54 ---
.../payment/handler/PaymentHandler.java | 140 ------
.../payment/service/PaymentService.java | 59 ---
.../service/impl/PaymentServiceImpl.java | 445 ------------------
gym-manage-api/manage-app/pom.xml | 5 -
gym-manage-api/pom.xml | 1 -
11 files changed, 961 deletions(-)
delete mode 100644 gym-manage-api/gym-payment/pom.xml
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayClientConfig.java
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayProperties.java
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/ApiResponse.java
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/CreatePaymentRequest.java
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/PaymentResponse.java
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/handler/PaymentHandler.java
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/PaymentService.java
delete mode 100644 gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/impl/PaymentServiceImpl.java
diff --git a/gym-manage-api/gym-payment/pom.xml b/gym-manage-api/gym-payment/pom.xml
deleted file mode 100644
index fc273a9..0000000
--- a/gym-manage-api/gym-payment/pom.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
- 4.0.0
-
-
- cn.novalon.gym.manage
- gym-manage-api
- 1.0.0
-
-
- cn.novalon.gym.manage
- gym-payment
- jar
-
- Gym Payment
- 支付模块 - 支付宝App支付
-
-
-
-
- org.springframework.boot
- spring-boot-starter-webflux
-
-
-
-
- cn.novalon.gym.manage
- manage-common
- ${project.version}
-
-
-
-
- com.alipay.sdk
- alipay-sdk-java
- 4.35.120.ALL
-
-
-
-
- com.google.code.gson
- gson
- 2.10.1
-
-
-
-
- org.projectlombok
- lombok
- true
-
-
-
-
- io.swagger.core.v3
- swagger-annotations
- 2.2.19
-
-
-
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayClientConfig.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayClientConfig.java
deleted file mode 100644
index e0b747e..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayClientConfig.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package cn.novalon.gym.manage.payment.config;
-
-import com.alipay.api.AlipayClient;
-import com.alipay.api.DefaultAlipayClient;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * 支付宝客户端配置
- */
-@Configuration
-public class AlipayClientConfig {
-
- private final AlipayProperties alipayProperties;
-
- public AlipayClientConfig(AlipayProperties alipayProperties) {
- this.alipayProperties = alipayProperties;
- }
-
- @Bean
- public AlipayClient alipayClient() {
- return new DefaultAlipayClient(
- alipayProperties.getGateway(),
- alipayProperties.getAppId(),
- alipayProperties.getAppPrivateKey(),
- "json",
- alipayProperties.getCharset(),
- alipayProperties.getAlipayPublicKey(),
- alipayProperties.getSignType()
- );
- }
-}
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayProperties.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayProperties.java
deleted file mode 100644
index f78fd71..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/config/AlipayProperties.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package cn.novalon.gym.manage.payment.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * 支付宝配置属性
- * 沙箱环境配置
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "alipay")
-public class AlipayProperties {
-
- /**
- * 应用ID
- */
- private String appId;
-
- /**
- * 应用私钥 (PKCS#8格式)
- */
- private String appPrivateKey;
-
- /**
- * 支付宝公钥
- */
- private String alipayPublicKey;
-
- /**
- * 签名方式
- */
- private String signType = "RSA2";
-
- /**
- * 编码格式
- */
- private String charset = "UTF-8";
-
- /**
- * 网关地址
- * 沙箱环境: https://openapi-sandbox.dl.alipaydev.com/gateway.do
- * 正式环境: https://openapi.alipay.com/gateway.do
- */
- private String gateway;
-
- /**
- * 异步通知地址
- */
- private String notifyUrl;
-
- /**
- * 是否沙箱环境
- */
- private boolean sandbox = true;
-}
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/ApiResponse.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/ApiResponse.java
deleted file mode 100644
index b01b20a..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/ApiResponse.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package cn.novalon.gym.manage.payment.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 统一API响应
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class ApiResponse {
-
- private int code;
- private String message;
- private T data;
-
- public static ApiResponse success(T data) {
- return ApiResponse.builder()
- .code(200)
- .message("success")
- .data(data)
- .build();
- }
-
- public static ApiResponse success(String message, T data) {
- return ApiResponse.builder()
- .code(200)
- .message(message)
- .data(data)
- .build();
- }
-
- public static ApiResponse error(int code, String message) {
- return ApiResponse.builder()
- .code(code)
- .message(message)
- .data(null)
- .build();
- }
-
- public static ApiResponse error(String message) {
- return ApiResponse.builder()
- .code(500)
- .message(message)
- .data(null)
- .build();
- }
-}
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/CreatePaymentRequest.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/CreatePaymentRequest.java
deleted file mode 100644
index 5b1347e..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/CreatePaymentRequest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package cn.novalon.gym.manage.payment.dto;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-/**
- * 创建支付请求DTO
- */
-@Data
-@Schema(description = "创建支付请求")
-public class CreatePaymentRequest {
-
- @Schema(description = "会员ID")
- private Long memberId;
-
- @Schema(description = "订单类型: MEMBER_CARD-会员卡, GROUP_COURSE-团课, GOODS-商品")
- private String orderType;
-
- @Schema(description = "商品描述")
- private String goodsDesc;
-
- @Schema(description = "交易金额(单位:分)")
- private String transAmt;
-
- @Schema(description = "交易类型: ALIPAY-支付宝, WECHAT-微信")
- private String tradeType;
-
- @Schema(description = "备注")
- private String remark;
-
- @Schema(description = "账户号")
- private String acctId;
-
- @Schema(description = "过期时间(yyyyMMddHHmmss)")
- private String timeExpire;
-
- @Schema(description = "延迟入账标识")
- private String delayAcctFlag;
-
- @Schema(description = "手续费标识")
- private Integer feeFlag;
-
- @Schema(description = "禁用支付方式")
- private String limitPayType;
-
- @Schema(description = "渠道号")
- private String channelNo;
-
- @Schema(description = "支付场景")
- private String payScene;
-
- @Schema(description = "异步通知URL")
- private String notifyUrl;
-}
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/PaymentResponse.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/PaymentResponse.java
deleted file mode 100644
index 50fd4cb..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/dto/PaymentResponse.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package cn.novalon.gym.manage.payment.dto;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 支付响应DTO
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@Schema(description = "支付响应")
-public class PaymentResponse {
-
- @Schema(description = "订单ID")
- private String orderId;
-
- @Schema(description = "支付状态: PENDING-待支付, SUCCESS-成功, FAIL-失败, CLOSED-关闭")
- private String status;
-
- @Schema(description = "支付链接(App支付返回 scheme)")
- private String payUrl;
-
- @Schema(description = "二维码链接 (扫码支付)")
- private String qrCode;
-
- @Schema(description = "完整支付信息")
- private String payInfo;
-
- @Schema(description = "H5支付链接")
- private String h5PayUrl;
-
- @Schema(description = "错误码")
- private String errorCode;
-
- @Schema(description = "错误消息")
- private String errorMsg;
-
- @Schema(description = "交易金额(分)")
- private String transAmt;
-
- @Schema(description = "商品描述")
- private String goodsDesc;
-
- @Schema(description = "交易类型")
- private String tradeType;
-
- @Schema(description = "支付成功时间")
- private String payTime;
-}
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/handler/PaymentHandler.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/handler/PaymentHandler.java
deleted file mode 100644
index e402f0c..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/handler/PaymentHandler.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package cn.novalon.gym.manage.payment.handler;
-
-import cn.novalon.gym.manage.payment.dto.ApiResponse;
-import cn.novalon.gym.manage.payment.dto.CreatePaymentRequest;
-import cn.novalon.gym.manage.payment.dto.PaymentResponse;
-import cn.novalon.gym.manage.payment.service.PaymentService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import org.springframework.web.reactive.function.server.ServerRequest;
-import org.springframework.web.reactive.function.server.ServerResponse;
-import reactor.core.publisher.Mono;
-import reactor.core.publisher.MonoSink;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 支付处理器
- * 提供支付宝App支付相关接口
- */
-@Slf4j
-@Component
-@Tag(name = "支付管理", description = "支付宝App支付接口")
-public class PaymentHandler {
-
- private final PaymentService paymentService;
-
- public PaymentHandler(PaymentService paymentService) {
- this.paymentService = paymentService;
- }
-
- @Operation(summary = "创建支付订单", description = "创建支付宝App支付订单")
- public Mono createPayment(ServerRequest request) {
- return request.bodyToMono(CreatePaymentRequest.class)
- .flatMap(createReq -> {
- log.info("[Payment] 创建支付订单: memberId={}, orderType={}, goodsDesc={}, transAmt={}",
- createReq.getMemberId(), createReq.getOrderType(), createReq.getGoodsDesc(), createReq.getTransAmt());
-
- PaymentResponse result = paymentService.alipayAppPay(createReq);
-
- if ("FAIL".equals(result.getStatus())) {
- return ServerResponse.ok()
- .bodyValue(ApiResponse.error(result.getErrorMsg()));
- }
-
- return ServerResponse.ok()
- .bodyValue(ApiResponse.success(result));
- })
- .onErrorResume(e -> {
- log.error("[Payment] 创建支付订单异常", e);
- return ServerResponse.ok()
- .bodyValue(ApiResponse.error("创建支付订单失败: " + e.getMessage()));
- });
- }
-
- @Operation(summary = "创建扫码支付订单", description = "创建支付宝扫码支付订单,返回二维码链接")
- public Mono createQrCodePayment(ServerRequest request) {
- return request.bodyToMono(CreatePaymentRequest.class)
- .flatMap(createReq -> {
- log.info("[Payment] 创建扫码支付订单: memberId={}, orderType={}, goodsDesc={}, transAmt={}",
- createReq.getMemberId(), createReq.getOrderType(), createReq.getGoodsDesc(), createReq.getTransAmt());
-
- PaymentResponse result = paymentService.alipayQrCodePay(createReq);
-
- if ("FAIL".equals(result.getStatus())) {
- return ServerResponse.ok()
- .bodyValue(ApiResponse.error(result.getErrorMsg()));
- }
-
- return ServerResponse.ok()
- .bodyValue(ApiResponse.success(result));
- })
- .onErrorResume(e -> {
- log.error("[Payment] 创建扫码支付订单异常", e);
- return ServerResponse.ok()
- .bodyValue(ApiResponse.error("创建扫码支付订单失败: " + e.getMessage()));
- });
- }
-
- @Operation(summary = "查询支付状态", description = "查询支付订单状态")
- public Mono getPaymentStatus(ServerRequest request) {
- String orderId = request.pathVariable("orderId");
- log.info("[Payment] 查询支付状态: orderId={}", orderId);
-
- PaymentResponse result = paymentService.getPaymentStatus(orderId);
- return ServerResponse.ok()
- .bodyValue(ApiResponse.success(result));
- }
-
- @Operation(summary = "支付宝异步通知", description = "接收支付宝异步回调通知")
- public Mono alipayNotify(ServerRequest request) {
- return request.bodyToMono(Map.class)
- .flatMap(params -> {
- log.info("[Payment] 收到支付宝异步通知: params={}", params);
-
- // 转换Map类型
- Map notifyParams = new HashMap<>();
- if (params instanceof Map) {
- ((Map, ?>) params).forEach((key, value) ->
- notifyParams.put(String.valueOf(key), String.valueOf(value)));
- }
-
- String result = paymentService.handleAlipayNotify(notifyParams);
- return ServerResponse.ok()
- .bodyValue(result);
- })
- .onErrorResume(e -> {
- log.error("[Payment] 异步通知处理异常", e);
- return ServerResponse.ok()
- .bodyValue("fail");
- });
- }
-
- @Operation(summary = "申请退款", description = "申请支付退款")
- public Mono refundPayment(ServerRequest request) {
- String orderId = request.pathVariable("orderId");
-
- return request.bodyToMono(Map.class)
- .flatMap(body -> {
- String refundAmt = String.valueOf(body.get("refundAmt"));
- log.info("[Payment] 申请退款: orderId={}, refundAmt={}", orderId, refundAmt);
-
- boolean success = paymentService.refund(orderId, refundAmt);
- if (success) {
- return ServerResponse.ok()
- .bodyValue(ApiResponse.success("退款申请成功"));
- } else {
- return ServerResponse.ok()
- .bodyValue(ApiResponse.error("退款申请失败"));
- }
- })
- .onErrorResume(e -> {
- log.error("[Payment] 退款异常: orderId={}", orderId, e);
- return ServerResponse.ok()
- .bodyValue(ApiResponse.error("退款失败: " + e.getMessage()));
- });
- }
-}
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/PaymentService.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/PaymentService.java
deleted file mode 100644
index 7170ce5..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/PaymentService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package cn.novalon.gym.manage.payment.service;
-
-import cn.novalon.gym.manage.payment.dto.CreatePaymentRequest;
-import cn.novalon.gym.manage.payment.dto.PaymentResponse;
-
-/**
- * 支付服务接口
- */
-public interface PaymentService {
-
- /**
- * 创建支付订单
- *
- * @param request 创建支付请求
- * @return 支付响应
- */
- PaymentResponse createPayment(CreatePaymentRequest request);
-
- /**
- * 查询支付状态
- *
- * @param orderId 订单ID
- * @return 支付响应
- */
- PaymentResponse getPaymentStatus(String orderId);
-
- /**
- * 支付宝App支付
- *
- * @param request 创建支付请求
- * @return 支付响应
- */
- PaymentResponse alipayAppPay(CreatePaymentRequest request);
-
- /**
- * 支付宝扫码支付(二维码支付)
- *
- * @param request 创建支付请求
- * @return 支付响应(包含二维码链接)
- */
- PaymentResponse alipayQrCodePay(CreatePaymentRequest request);
-
- /**
- * 处理支付宝异步通知
- *
- * @param params 通知参数
- * @return 处理结果
- */
- String handleAlipayNotify(java.util.Map params);
-
- /**
- * 申请退款
- *
- * @param orderId 订单ID
- * @param refundAmt 退款金额(分)
- * @return 退款结果
- */
- boolean refund(String orderId, String refundAmt);
-}
diff --git a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/impl/PaymentServiceImpl.java b/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/impl/PaymentServiceImpl.java
deleted file mode 100644
index 2731d27..0000000
--- a/gym-manage-api/gym-payment/src/main/java/cn/novalon/gym/manage/payment/service/impl/PaymentServiceImpl.java
+++ /dev/null
@@ -1,445 +0,0 @@
-package cn.novalon.gym.manage.payment.service.impl;
-
-import cn.novalon.gym.manage.common.util.RedisUtil;
-import cn.novalon.gym.manage.payment.config.AlipayProperties;
-import cn.novalon.gym.manage.payment.dto.CreatePaymentRequest;
-import cn.novalon.gym.manage.payment.dto.PaymentResponse;
-import cn.novalon.gym.manage.payment.service.PaymentService;
-import com.alipay.api.AlipayApiException;
-import com.alipay.api.AlipayClient;
-import com.alipay.api.internal.util.AlipaySignature;
-import com.alipay.api.request.AlipayTradeAppPayRequest;
-import com.alipay.api.request.AlipayTradePrecreateRequest;
-import com.alipay.api.request.AlipayTradeQueryRequest;
-import com.alipay.api.request.AlipayTradeRefundRequest;
-import com.alipay.api.response.AlipayTradeAppPayResponse;
-import com.alipay.api.response.AlipayTradePrecreateResponse;
-import com.alipay.api.response.AlipayTradeQueryResponse;
-import com.alipay.api.response.AlipayTradeRefundResponse;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * 支付服务实现
- * App支付 (alipay.trade.app.pay)
- */
-@Slf4j
-@Service
-public class PaymentServiceImpl implements PaymentService {
-
- private static final String PROCESSED_TRADE_PREFIX = "alipay:processed:trade:";
- private static final String REFUND_ORDER_PREFIX = "alipay:refund:order:";
- private static final String ORDER_CACHE_PREFIX = "alipay:order:";
- private static final long IDEMPOTENT_EXPIRE_SECONDS = 86400; // 24小时过期
-
- private final AlipayClient alipayClient;
- private final AlipayProperties alipayProperties;
- private final RedisUtil redisUtil;
-
- /**
- * 订单本地缓存 (作为Redis的二级缓存)
- */
- private final Map localOrderCache = new ConcurrentHashMap<>();
-
- public PaymentServiceImpl(AlipayClient alipayClient, AlipayProperties alipayProperties, RedisUtil redisUtil) {
- this.alipayClient = alipayClient;
- this.alipayProperties = alipayProperties;
- this.redisUtil = redisUtil;
- }
-
- @Override
- public PaymentResponse createPayment(CreatePaymentRequest request) {
- // App支付使用 alipay.trade.app.pay
- return alipayAppPay(request);
- }
-
- @Override
- public PaymentResponse getPaymentStatus(String orderId) {
- // 先查本地缓存
- PaymentResponse cached = localOrderCache.get(orderId);
- if (cached != null && "SUCCESS".equals(cached.getStatus())) {
- return cached;
- }
-
- // 查Redis缓存
- PaymentResponse redisCached = getOrderFromRedis(orderId);
- if (redisCached != null && "SUCCESS".equals(redisCached.getStatus())) {
- localOrderCache.put(orderId, redisCached);
- return redisCached;
- }
-
- try {
- AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
- queryRequest.setBizContent("{\"out_trade_no\":\"" + orderId + "\"}");
-
- AlipayTradeQueryResponse response = alipayClient.execute(queryRequest);
- if (response.isSuccess()) {
- Date sendPayDate = response.getSendPayDate();
- String payTimeStr = sendPayDate != null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(sendPayDate) : null;
-
- PaymentResponse result = PaymentResponse.builder()
- .orderId(orderId)
- .status(response.getTradeStatus())
- .payTime(payTimeStr)
- .transAmt(response.getTotalAmount())
- .build();
-
- if ("TRADE_SUCCESS".equals(response.getTradeStatus())) {
- result.setStatus("SUCCESS");
- // 更新缓存
- saveOrderToRedis(orderId, result);
- localOrderCache.put(orderId, result);
- }
- return result;
- }
- } catch (AlipayApiException e) {
- log.error("查询支付状态失败: orderId={}", orderId, e);
- }
-
- return PaymentResponse.builder()
- .orderId(orderId)
- .status(cached != null ? cached.getStatus() : (redisCached != null ? redisCached.getStatus() : "PENDING"))
- .build();
- }
-
- @Override
- public PaymentResponse alipayAppPay(CreatePaymentRequest request) {
- // 生成订单号
- String orderId = generateOrderId();
-
- try {
- AlipayTradeAppPayRequest payRequest = new AlipayTradeAppPayRequest();
- payRequest.setNotifyUrl(alipayProperties.getNotifyUrl());
-
- // 构建业务参数 (测试金额:固定1分钱)
- String bizContent = "{\"out_trade_no\":\"" + orderId + "\","
- + "\"total_amount\":\"0.01\","
- + "\"subject\":\"" + request.getGoodsDesc() + "\","
- + "\"product_code\":\"QUICK_MSECURITY_PAY\","
- + "\"timeout_express\":\"30m\"}";
-
- log.info("[Alipay] App支付请求: orderId={}, bizContent={}", orderId, bizContent);
-
- payRequest.setBizContent(bizContent);
-
- AlipayTradeAppPayResponse response = alipayClient.sdkExecute(payRequest);
-
- if (response.isSuccess()) {
- String payUrl = response.getBody();
-
- // App唤起支付宝的scheme格式: alipay://...
- // 实际使用时,前端使用 plus.runtime.openURL(payUrl) 唤起支付宝
- log.info("[Alipay] App支付创建成功: orderId={}, payUrl={}", orderId, payUrl);
-
- PaymentResponse result = PaymentResponse.builder()
- .orderId(orderId)
- .status("PENDING")
- .payUrl(payUrl)
- .payInfo(response.getBody())
- .goodsDesc(request.getGoodsDesc())
- .transAmt(request.getTransAmt())
- .tradeType(request.getTradeType())
- .build();
-
- // 缓存订单到Redis和本地
- saveOrderToRedis(orderId, result);
- localOrderCache.put(orderId, result);
-
- return result;
- } else {
- log.error("[Alipay] App支付创建失败: orderId={}, error={}", orderId, response.getMsg());
- return PaymentResponse.builder()
- .orderId(orderId)
- .status("FAIL")
- .errorCode(response.getCode())
- .errorMsg(response.getMsg())
- .build();
- }
- } catch (AlipayApiException e) {
- log.error("[Alipay] App支付异常: orderId={}", orderId, e);
- String errCode = e.getErrCode() != null ? e.getErrCode() : "NETWORK_ERROR";
- String errMsg = e.getErrMsg() != null ? e.getErrMsg() : extractErrorMessage(e);
- return PaymentResponse.builder()
- .orderId(orderId)
- .status("FAIL")
- .errorCode(errCode)
- .errorMsg(errMsg)
- .build();
- }
- }
-
- /**
- * 支付宝扫码支付 (alipay.trade.precreate)
- * 生成付款二维码,用户使用支付宝扫码完成支付
- */
- @Override
- public PaymentResponse alipayQrCodePay(CreatePaymentRequest request) {
- String orderId = generateOrderId();
-
- try {
- AlipayTradePrecreateRequest precreateRequest = new AlipayTradePrecreateRequest();
- precreateRequest.setNotifyUrl(alipayProperties.getNotifyUrl());
-
- // 构建业务参数
- String bizContent = "{\"out_trade_no\":\"" + orderId + "\","
- + "\"total_amount\":\"0.01\","
- + "\"subject\":\"" + request.getGoodsDesc() + "\","
- + "\"timeout_express\":\"30m\"}";
-
- log.info("[Alipay] 扫码支付请求: orderId={}, bizContent={}", orderId, bizContent);
-
- precreateRequest.setBizContent(bizContent);
- AlipayTradePrecreateResponse response = alipayClient.execute(precreateRequest);
-
- if (response.isSuccess()) {
- String qrCode = response.getQrCode(); // 二维码链接
-
- log.info("[Alipay] 扫码支付创建成功: orderId={}, qrCode={}", orderId, qrCode);
-
- PaymentResponse result = PaymentResponse.builder()
- .orderId(orderId)
- .status("PENDING")
- .qrCode(qrCode)
- .payInfo(response.getBody())
- .goodsDesc(request.getGoodsDesc())
- .transAmt(request.getTransAmt())
- .tradeType("QRCODE")
- .build();
-
- // 缓存订单到Redis和本地
- saveOrderToRedis(orderId, result);
- localOrderCache.put(orderId, result);
-
- return result;
- } else {
- log.error("[Alipay] 扫码支付创建失败: orderId={}, error={}", orderId, response.getMsg());
- return PaymentResponse.builder()
- .orderId(orderId)
- .status("FAIL")
- .errorCode(response.getCode())
- .errorMsg(response.getMsg())
- .build();
- }
- } catch (AlipayApiException e) {
- log.error("[Alipay] 扫码支付异常: orderId={}", orderId, e);
- String errCode = e.getErrCode() != null ? e.getErrCode() : "NETWORK_ERROR";
- String errMsg = e.getErrMsg() != null ? e.getErrMsg() : extractErrorMessage(e);
- return PaymentResponse.builder()
- .orderId(orderId)
- .status("FAIL")
- .errorCode(errCode)
- .errorMsg(errMsg)
- .build();
- }
- }
-
- @Override
- public String handleAlipayNotify(Map params) {
- String outTradeNo = params.get("out_trade_no");
-
- try {
- // 1. 幂等处理:检查是否已处理过该通知(使用Redis)
- if (isTradeProcessed(outTradeNo)) {
- log.info("[Alipay] 幂等处理:通知已处理,跳过, outTradeNo={}", outTradeNo);
- return "success";
- }
-
- // 2. 验签
- boolean signVerified = AlipaySignature.rsaCheckV1(
- params,
- alipayProperties.getAlipayPublicKey(),
- alipayProperties.getCharset(),
- alipayProperties.getSignType()
- );
-
- if (!signVerified) {
- log.warn("[Alipay] 异步通知验签失败: outTradeNo={}", outTradeNo);
- return "fail";
- }
-
- // 3. 关键信息校验
- // 校验 app_id 是否匹配
- String notifyAppId = params.get("app_id");
- if (!alipayProperties.getAppId().equals(notifyAppId)) {
- log.warn("[Alipay] app_id 不匹配: expected={}, actual={}", alipayProperties.getAppId(), notifyAppId);
- return "fail";
- }
-
- // 校验卖家ID (seller_id)
- String sellerId = params.get("seller_id");
- if (sellerId != null && !sellerId.isEmpty()) {
- // 商家ID校验逻辑根据实际情况添加
- log.debug("[Alipay] 卖家ID校验: seller_id={}", sellerId);
- }
-
- // 校验交易金额
- String notifyTotalAmount = params.get("total_amount");
- PaymentResponse cachedOrder = getOrderFromRedis(outTradeNo);
- if (cachedOrder != null && notifyTotalAmount != null) {
- // 金额校验:确保通知金额与订单金额一致(防止金额篡改)
- log.debug("[Alipay] 交易金额校验: orderId={}, amount={}", outTradeNo, notifyTotalAmount);
- }
-
- String tradeStatus = params.get("trade_status");
- log.info("[Alipay] 异步通知验签成功: outTradeNo={}, tradeStatus={}", outTradeNo, tradeStatus);
-
- // 4. 判断交易状态
- if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
- // 更新订单状态
- if (cachedOrder != null) {
- cachedOrder.setStatus("SUCCESS");
- cachedOrder.setPayTime(params.get("gmt_payment"));
- saveOrderToRedis(outTradeNo, cachedOrder);
- localOrderCache.put(outTradeNo, cachedOrder);
- }
-
- // 5. 标记为已处理(幂等,使用Redis)
- markTradeProcessed(outTradeNo);
-
- return "success";
- }
-
- return "fail";
- } catch (AlipayApiException e) {
- log.error("[Alipay] 异步通知处理异常: outTradeNo={}", outTradeNo, e);
- return "fail";
- }
- }
-
- @Override
- public boolean refund(String orderId, String refundAmt) {
- // 1. 退款幂等检查:防止重复退款(使用Redis)
- if (isOrderRefunded(orderId)) {
- log.info("[Alipay] 退款幂等:订单已退款过,跳过, orderId={}", orderId);
- return true;
- }
-
- try {
- AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
- refundRequest.setBizContent("{\"out_trade_no\":\"" + orderId + "\",\"refund_amount\":\"" + refundAmt + "\"}");
-
- AlipayTradeRefundResponse response = alipayClient.execute(refundRequest);
- if (response.isSuccess()) {
- // 2. 校验退款是否真正成功:必须判断 fund_change=Y
- String fundChange = response.getFundChange();
- if ("Y".equals(fundChange)) {
- log.info("[Alipay] 退款成功: orderId={}, refundAmt={}, fundChange={}", orderId, refundAmt, fundChange);
- // 标记为已退款(幂等,使用Redis)
- markOrderRefunded(orderId);
- return true;
- } else {
- log.warn("[Alipay] 退款返回Y但fund_change!=Y: orderId={}, fundChange={}", orderId, fundChange);
- return false;
- }
- } else {
- log.error("[Alipay] 退款失败: orderId={}, error={}", orderId, response.getMsg());
- }
- } catch (AlipayApiException e) {
- log.error("[Alipay] 退款异常: orderId={}", orderId, e);
- }
- return false;
- }
-
- // ==================== Redis操作方法 ====================
-
- /**
- * 检查交易是否已处理(幂等)
- */
- private boolean isTradeProcessed(String outTradeNo) {
- try {
- return Boolean.TRUE.equals(redisUtil.hasKey(PROCESSED_TRADE_PREFIX + outTradeNo).block());
- } catch (Exception e) {
- log.error("[Alipay] 检查交易处理状态异常: outTradeNo={}", outTradeNo, e);
- return false;
- }
- }
-
- /**
- * 标记交易已处理(幂等)
- */
- private void markTradeProcessed(String outTradeNo) {
- try {
- redisUtil.setWithExpire(PROCESSED_TRADE_PREFIX + outTradeNo, "1", IDEMPOTENT_EXPIRE_SECONDS).block();
- } catch (Exception e) {
- log.error("[Alipay] 标记交易处理状态异常: outTradeNo={}", outTradeNo, e);
- }
- }
-
- /**
- * 检查订单是否已退款(幂等)
- */
- private boolean isOrderRefunded(String orderId) {
- try {
- return Boolean.TRUE.equals(redisUtil.hasKey(REFUND_ORDER_PREFIX + orderId).block());
- } catch (Exception e) {
- log.error("[Alipay] 检查订单退款状态异常: orderId={}", orderId, e);
- return false;
- }
- }
-
- /**
- * 标记订单已退款(幂等)
- */
- private void markOrderRefunded(String orderId) {
- try {
- redisUtil.setWithExpire(REFUND_ORDER_PREFIX + orderId, "1", IDEMPOTENT_EXPIRE_SECONDS).block();
- } catch (Exception e) {
- log.error("[Alipay] 标记订单退款状态异常: orderId={}", orderId, e);
- }
- }
-
- /**
- * 从Redis获取订单
- */
- private PaymentResponse getOrderFromRedis(String orderId) {
- try {
- return redisUtil.get(ORDER_CACHE_PREFIX + orderId, PaymentResponse.class).block();
- } catch (Exception e) {
- log.error("[Alipay] 获取Redis订单异常: orderId={}", orderId, e);
- return null;
- }
- }
-
- /**
- * 保存订单到Redis
- */
- private void saveOrderToRedis(String orderId, PaymentResponse response) {
- try {
- redisUtil.setWithExpire(ORDER_CACHE_PREFIX + orderId, response, IDEMPOTENT_EXPIRE_SECONDS).block();
- } catch (Exception e) {
- log.error("[Alipay] 保存订单到Redis异常: orderId={}", orderId, e);
- }
- }
-
- /**
- * 生成订单号
- */
- private String generateOrderId() {
- String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
- String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
- return timestamp + uuid;
- }
-
- /**
- * 提取异常中的错误信息(兜底)
- */
- private String extractErrorMessage(AlipayApiException e) {
- Throwable cause = e.getCause();
- if (cause != null && cause.getMessage() != null && cause.getMessage().contains("504")) {
- return "支付宝沙箱网关连接超时(504),请检查服务器网络能否访问 openapi-sandbox.dl.alipaydev.com";
- }
- if (cause != null) {
- return "网络异常: " + cause.getClass().getSimpleName() + " - " + (cause.getMessage() != null ? cause.getMessage().substring(0, Math.min(cause.getMessage().length(), 200)) : "");
- }
- if (e.getMessage() != null) {
- return "支付宝接口异常: " + (e.getMessage().length() > 200 ? e.getMessage().substring(0, 200) : e.getMessage());
- }
- return "支付宝接口调用失败,请稍后重试";
- }
-}
diff --git a/gym-manage-api/manage-app/pom.xml b/gym-manage-api/manage-app/pom.xml
index ed55a4e..7a15e65 100644
--- a/gym-manage-api/manage-app/pom.xml
+++ b/gym-manage-api/manage-app/pom.xml
@@ -48,11 +48,6 @@
gym-checkIn
${project.version}
-
- cn.novalon.gym.manage
- gym-payment
- ${project.version}
-
cn.novalon.gym.manage
gym-dataCount
diff --git a/gym-manage-api/pom.xml b/gym-manage-api/pom.xml
index 69441c7..8746a4a 100644
--- a/gym-manage-api/pom.xml
+++ b/gym-manage-api/pom.xml
@@ -47,7 +47,6 @@
gym-checkIn
gym-dataCount
gym-auth
- gym-payment