chore: initialize qiming workspace repository
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xspaceagi</groupId>
|
||||
<artifactId>app-platform-pay</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>app-platform-pay-spec</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.xspaceagi</groupId>
|
||||
<artifactId>app-platform-pay-sdk</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.xspaceagi</groupId>
|
||||
<artifactId>system-spec</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.xspaceagi.pay.spec;
|
||||
|
||||
/** 支付网关对外文案常量。 */
|
||||
public final class PayGatewayMessages {
|
||||
|
||||
private PayGatewayMessages() {}
|
||||
|
||||
/** 网络不可达、超时、响应不可解析等无法拿到网关业务 JSON 时使用。 */
|
||||
public static final String CONNECT_FAILED = "支付网关连接失败";
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.xspaceagi.pay.spec;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/** 支付调度相关时间常量(建单宽限期、补偿扫描等共用)。 */
|
||||
public final class PayOrderScheduleConstants {
|
||||
|
||||
private PayOrderScheduleConstants() {}
|
||||
|
||||
/** 本地 {@code gatewaySyncStatus=PENDING} 且无网关单号超过该时间视为可重试/可补偿关单。 */
|
||||
public static final Duration STALE_GATEWAY_SYNC_PENDING = Duration.ofMinutes(1);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PageResult<T> {
|
||||
private List<T> records;
|
||||
private long total;
|
||||
/** 当前页,从 1 开始 */
|
||||
private long page;
|
||||
private long pageSize;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayDeveloperAccountAdminPageRequest {
|
||||
|
||||
/** 用户名/昵称模糊关键字;先查用户表再按 userId 过滤开发者账户(与系统用户列表检索规则一致,最多取前 500 条匹配用户) */
|
||||
private String userNameKeyword;
|
||||
|
||||
private Long userId;
|
||||
private LocalDateTime createdStart;
|
||||
private LocalDateTime createdEnd;
|
||||
private Integer page;
|
||||
private Integer pageSize;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayDeveloperAccountAdminSaveRequest {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String email;
|
||||
private String phone;
|
||||
private String realName;
|
||||
private String idCardNo;
|
||||
private String idCardFrontPhotoUrl;
|
||||
private String idCardBackPhotoUrl;
|
||||
private String bankName;
|
||||
private String branchName;
|
||||
private String bankCardNo;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayDeveloperAccountAdminUserQueryRequest {
|
||||
|
||||
private Long userId;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayDeveloperAccountByIdRequest {
|
||||
|
||||
private Long id;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import java.util.Date;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayDeveloperAccountResponse {
|
||||
|
||||
private Long id;
|
||||
private Long tenantId;
|
||||
/** 关联 {@code user.id} */
|
||||
private Long userId;
|
||||
private String userName;
|
||||
private String email;
|
||||
private String phone;
|
||||
private String realName;
|
||||
private String idCardNo;
|
||||
/** 身份证正面照片 URL */
|
||||
private String idCardFrontPhotoUrl;
|
||||
/** 身份证反面照片 URL */
|
||||
private String idCardBackPhotoUrl;
|
||||
private String bankName;
|
||||
private String branchName;
|
||||
private String bankCardNo;
|
||||
private Date created;
|
||||
private Date modified;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayDeveloperAccountUserSaveRequest {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String email;
|
||||
private String phone;
|
||||
private String realName;
|
||||
private String idCardNo;
|
||||
private String idCardFrontPhotoUrl;
|
||||
private String idCardBackPhotoUrl;
|
||||
private String bankName;
|
||||
private String branchName;
|
||||
private String bankCardNo;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayGatewayConnectivityResponse {
|
||||
|
||||
/** 是否成功联通 */
|
||||
private boolean reachable;
|
||||
|
||||
/** 不可达时的原因说明 */
|
||||
private String message;
|
||||
|
||||
/** 当前租户配置的支付网关基址 */
|
||||
private String gatewayBaseUrl;
|
||||
|
||||
/** 网关返回的服务器时间戳(毫秒) */
|
||||
private Long gatewayServerTimeMillis;
|
||||
|
||||
/** 本次探测往返耗时(毫秒) */
|
||||
private Long latencyMillis;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import com.xspaceagi.pay.sdk.enums.PayChannel;
|
||||
import com.xspaceagi.pay.sdk.enums.PayMode;
|
||||
import com.xspaceagi.pay.sdk.enums.PaymentStatus;
|
||||
import com.xspaceagi.pay.spec.enums.PayBizNotifyStatus;
|
||||
import com.xspaceagi.pay.spec.enums.PayOrderGatewaySyncStatus;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayOrderItemResponse {
|
||||
|
||||
private Long id;
|
||||
private Long tenantId;
|
||||
private String bizOrderNo;
|
||||
private String bizScene;
|
||||
/** 订单金额(元) */
|
||||
private BigDecimal orderAmount;
|
||||
private String subject;
|
||||
private PayMode payMode;
|
||||
private PayChannel payChannel;
|
||||
/** 平台服务费(元) */
|
||||
private BigDecimal platformFee;
|
||||
/** 渠道手续费(元) */
|
||||
private BigDecimal providerFee;
|
||||
/** 实收金额(元) */
|
||||
private BigDecimal netAmount;
|
||||
private String gatewayPaymentOrderNo;
|
||||
private PayOrderGatewaySyncStatus gatewaySyncStatus;
|
||||
private PayBizNotifyStatus bizNotifyStatus;
|
||||
private String gatewayOrderStatus;
|
||||
private PaymentStatus paymentStatus;
|
||||
private Date paidAt;
|
||||
private Date created;
|
||||
private Date modified;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import com.xspaceagi.pay.sdk.enums.PayChannel;
|
||||
import com.xspaceagi.pay.sdk.enums.PaymentStatus;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayOrderPageQueryRequest {
|
||||
|
||||
/** 创建时间起始(含),可选 */
|
||||
private LocalDateTime createdStart;
|
||||
|
||||
/** 创建时间结束(含),可选 */
|
||||
private LocalDateTime createdEnd;
|
||||
|
||||
/** 支付状态 */
|
||||
private PaymentStatus paymentStatus;
|
||||
|
||||
/** 支付渠道,可选 */
|
||||
private PayChannel payChannel;
|
||||
|
||||
/** 业务订单号,可选 */
|
||||
private String bizOrderNo;
|
||||
|
||||
/** 网关支付单号,可选 */
|
||||
private String gatewayPaymentOrderNo;
|
||||
|
||||
@Min(1)
|
||||
private Integer page;
|
||||
|
||||
@Min(1)
|
||||
@Max(200)
|
||||
private Integer pageSize;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xspaceagi.pay.spec.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/** 支付结果通知载荷:随 {@link com.xspaceagi.pay.spec.event.PayOrderSettlementNotifyEvent} 在系统内投递。 */
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayResultNotifyPayload {
|
||||
|
||||
private Long tenantId;
|
||||
|
||||
/** 业务场景标识(平台侧落库字段,与 Open API 建单请求无直接对应) */
|
||||
private String bizScene;
|
||||
|
||||
private String bizOrderNo;
|
||||
|
||||
private String gatewayPaymentOrderNo;
|
||||
|
||||
/** {@link com.xspaceagi.pay.spec.enums.PaymentOrderStatus} 名,超时时可能为 null */
|
||||
private String paymentOrderStatus;
|
||||
|
||||
private Long orderAmount;
|
||||
|
||||
private String paidAt;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.xspaceagi.pay.spec.enums;
|
||||
|
||||
public enum PayBizNotifyStatus {
|
||||
/** 轮询中 */
|
||||
POLLING,
|
||||
/** 已通知(含支付成功、失败/关闭等终态,已通过进程内事件投递) */
|
||||
NOTIFIED,
|
||||
/** 轮询耗尽仍未拿到明确终态(业务宜主动查单) */
|
||||
TIMEOUT
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.xspaceagi.pay.spec.enums;
|
||||
|
||||
public enum PayOrderGatewaySyncStatus {
|
||||
PENDING,
|
||||
SUCCESS,
|
||||
FAILED
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.xspaceagi.pay.spec.event;
|
||||
|
||||
import com.xspaceagi.pay.spec.dto.PayResultNotifyPayload;
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
* 支付结果通知事件,由支付模块发布;其他模块通过 {@code @EventListener} 订阅。
|
||||
*
|
||||
* <p><b>订阅示例</b></p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* // 按场景过滤:仅处理订阅智能体单
|
||||
* @EventListener(condition = "#event.payload.bizScene == 'SUBSCRIBE_AGENT'")
|
||||
* public void onSubscribeAgentSettled(PayOrderSettlementNotifyEvent event) {
|
||||
* PayResultNotifyPayload p = event.getPayload();
|
||||
* }
|
||||
*
|
||||
* // 或方法内判断多场景
|
||||
* @EventListener
|
||||
* public void onSubscribeAgent(PayOrderSettlementNotifyEvent event) {
|
||||
* if (!"SUBSCRIBE_AGENT".equals(event.getPayload().getBizScene())) {
|
||||
* return;
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p>监听逻辑若较重,可在方法上再加 {@code @Async}(需启用异步支持),并保持幂等。</p>
|
||||
*/
|
||||
@Value
|
||||
public class PayOrderSettlementNotifyEvent {
|
||||
|
||||
PayResultNotifyPayload payload;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.xspaceagi.pay.spec.exception;
|
||||
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
|
||||
/**
|
||||
* 支付网关业务失败:对外 {@code code} 仍为平台 {@link ErrorCodeEnum#SYS_ERROR},{@code displayCode} 为网关 code。
|
||||
*/
|
||||
public class PayGatewayBizException extends BizException {
|
||||
|
||||
private final String displayCode;
|
||||
|
||||
public PayGatewayBizException(String gatewayCode, String gatewayMessage) {
|
||||
super(ErrorCodeEnum.SYS_ERROR.getCode(), gatewayMessage);
|
||||
this.displayCode = gatewayCode;
|
||||
}
|
||||
|
||||
public String getDisplayCode() {
|
||||
return displayCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.xspaceagi.pay.spec.exception;
|
||||
|
||||
import com.xspaceagi.pay.spec.PayGatewayMessages;
|
||||
|
||||
/**
|
||||
* 调用 qiming-pay 支付网关失败。若响应体为 {@code ApiResponse} JSON,{@link #gatewayCode} 为网关 {@code code},
|
||||
* {@link #getMessage()} 为网关 {@code message};无 {@code gatewayCode} 且为传输类失败时为 {@link PayGatewayMessages#CONNECT_FAILED}。
|
||||
*/
|
||||
public class PayGatewayClientException extends RuntimeException {
|
||||
|
||||
private final String gatewayCode;
|
||||
|
||||
/** 传输/协议类失败,对外固定文案。 */
|
||||
public PayGatewayClientException() {
|
||||
this(null, PayGatewayMessages.CONNECT_FAILED);
|
||||
}
|
||||
|
||||
public PayGatewayClientException(String message) {
|
||||
this(null, message);
|
||||
}
|
||||
|
||||
public PayGatewayClientException(String gatewayCode, String gatewayMessage) {
|
||||
super(gatewayMessage != null && !gatewayMessage.isBlank() ? gatewayMessage : PayGatewayMessages.CONNECT_FAILED);
|
||||
this.gatewayCode = gatewayCode;
|
||||
}
|
||||
|
||||
public String getGatewayCode() {
|
||||
return gatewayCode;
|
||||
}
|
||||
|
||||
public String getGatewayMessage() {
|
||||
return getMessage();
|
||||
}
|
||||
|
||||
public boolean hasGatewayApiError() {
|
||||
return gatewayCode != null && !gatewayCode.isBlank();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.xspaceagi.pay.spec.gateway;
|
||||
|
||||
/** 调用 qiming-pay Open API 时的出站上下文 */
|
||||
public record PayGatewayOutbound(String baseUrl, String clientId, String clientSecret) {}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.xspaceagi.pay.spec.gateway;
|
||||
|
||||
/** 可选注入 {@link PayGatewayOutboundCacheEvictor} 时的空安全调用。 */
|
||||
public final class PayGatewayOutboundCacheEvictSupport {
|
||||
|
||||
private PayGatewayOutboundCacheEvictSupport() {}
|
||||
|
||||
public static void evictIfPresent(PayGatewayOutboundCacheEvictor evictor, Long tenantId) {
|
||||
if (evictor != null && tenantId != null) {
|
||||
evictor.evict(tenantId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xspaceagi.pay.spec.gateway;
|
||||
|
||||
/**
|
||||
* 租户支付网关出站凭证缓存失效(如 {@code paymentGateway}、client 密钥变更后调用)。
|
||||
*/
|
||||
public interface PayGatewayOutboundCacheEvictor {
|
||||
|
||||
void evict(long tenantId);
|
||||
}
|
||||
Reference in New Issue
Block a user