chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
<?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-domain</artifactId>
<dependencies>
<dependency>
<groupId>com.xspaceagi</groupId>
<artifactId>app-platform-pay-spec</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.xspaceagi</groupId>
<artifactId>app-platform-pay-sdk</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,16 @@
package com.xspaceagi.pay.domain.gateway;
import com.xspaceagi.pay.sdk.dto.MerchantOnboardingResponse;
import com.xspaceagi.pay.sdk.dto.MerchantOnboardingUpdateRequest;
import com.xspaceagi.pay.sdk.dto.MerchantOnboardingUpsertRequest;
import com.xspaceagi.pay.spec.gateway.PayGatewayOutbound;
/** 调用 qiming-pay {@code /open-api/merchant-onboarding};出站上下文由应用层解析后传入。 */
public interface MerchantOnboardingGateway {
MerchantOnboardingResponse add(PayGatewayOutbound outbound, MerchantOnboardingUpsertRequest request);
MerchantOnboardingResponse update(PayGatewayOutbound outbound, MerchantOnboardingUpdateRequest request);
MerchantOnboardingResponse getByClientId(PayGatewayOutbound outbound);
}

View File

@@ -0,0 +1,13 @@
package com.xspaceagi.pay.domain.gateway;
import com.xspaceagi.pay.sdk.dto.PayConfigResponse;
import com.xspaceagi.pay.spec.dto.PayGatewayConnectivityResponse;
import com.xspaceagi.pay.spec.gateway.PayGatewayOutbound;
/** 调用 qiming-pay 支付配置 Open API出站上下文由应用层解析后传入。 */
public interface PaymentConfigGateway {
PayConfigResponse queryPayConfig(PayGatewayOutbound outbound);
PayGatewayConnectivityResponse checkConnectivity(PayGatewayOutbound outbound);
}

View File

@@ -0,0 +1,26 @@
package com.xspaceagi.pay.domain.gateway;
import com.xspaceagi.pay.sdk.dto.CashierSessionCreateResponse;
import com.xspaceagi.pay.sdk.dto.PaymentOrderCreateResponse;
import com.xspaceagi.pay.sdk.dto.ScanOrderStatusQueryResponse;
import com.xspaceagi.pay.spec.gateway.PayGatewayOutbound;
/** 调用 qiming-pay 扫码支付 Open API出站上下文由应用层解析后传入。 */
public interface PaymentScanGateway {
PaymentOrderCreateResponse createOrder(
PayGatewayOutbound outbound, String bizOrderNo, long orderAmount, String subject, String ext);
CashierSessionCreateResponse createCashierSession(
PayGatewayOutbound outbound,
String gatewayPaymentOrderNo,
long orderAmount,
String subject,
String bizRedirectUrl);
/**
* @param syncFromChannel true 时网关会向支付渠道查询并落库
*/
ScanOrderStatusQueryResponse queryOrderStatus(
PayGatewayOutbound outbound, String gatewayPaymentOrderNo, boolean syncFromChannel);
}

View File

@@ -0,0 +1,29 @@
package com.xspaceagi.pay.domain.model;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayDeveloperAccountModel {
private Long id;
private Long tenantId;
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;
private Date created;
private Date modified;
}

View File

@@ -0,0 +1,5 @@
package com.xspaceagi.pay.domain.model;
import java.util.List;
public record PayDeveloperAccountPageSlice(List<PayDeveloperAccountModel> records, long total) {}

View File

@@ -0,0 +1,39 @@
package com.xspaceagi.pay.domain.model;
import com.xspaceagi.pay.spec.enums.PayBizNotifyStatus;
import com.xspaceagi.pay.sdk.enums.PayChannel;
import com.xspaceagi.pay.sdk.enums.PayMode;
import com.xspaceagi.pay.spec.enums.PayOrderGatewaySyncStatus;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayOrderModel {
private Long id;
private Long tenantId;
private String bizOrderNo;
private String bizScene;
private Long orderAmount;
private String subject;
private String ext;
private PayMode payMode;
private PayChannel payChannel;
private Long platformFee;
private Long providerFee;
private Long netAmount;
private String gatewayPaymentOrderNo;
private PayOrderGatewaySyncStatus gatewaySyncStatus;
private PayBizNotifyStatus bizNotifyStatus;
private String gatewayLastError;
private String gatewayOrderStatus;
private Date paidAt;
private Date created;
private Date modified;
}

View File

@@ -0,0 +1,5 @@
package com.xspaceagi.pay.domain.model;
import java.util.List;
public record PayOrderPageSlice(List<PayOrderModel> records, long total) {}

View File

@@ -0,0 +1,27 @@
package com.xspaceagi.pay.domain.repository;
import com.xspaceagi.pay.domain.model.PayDeveloperAccountModel;
import com.xspaceagi.pay.domain.model.PayDeveloperAccountPageSlice;
import java.util.Date;
import java.util.List;
import java.util.Optional;
public interface PayDeveloperAccountRepository {
Optional<PayDeveloperAccountModel> findById(long id);
Optional<PayDeveloperAccountModel> findByTenantIdAndUserId(long tenantId, long userId);
PayDeveloperAccountModel save(PayDeveloperAccountModel model);
void deleteById(long id);
PayDeveloperAccountPageSlice pageByTenantAndFilters(
long tenantId,
Long userIdEq,
List<Long> userIdIn,
Date createdStart,
Date createdEnd,
int page,
int pageSize);
}

View File

@@ -0,0 +1,68 @@
package com.xspaceagi.pay.domain.repository;
import com.xspaceagi.pay.domain.model.PayOrderModel;
import com.xspaceagi.pay.domain.model.PayOrderPageSlice;
import com.xspaceagi.pay.spec.enums.PayBizNotifyStatus;
import com.xspaceagi.pay.sdk.enums.PayChannel;
import com.xspaceagi.pay.spec.enums.PayOrderGatewaySyncStatus;
import java.util.Date;
import java.util.List;
import java.util.Optional;
public interface PayOrderRepository {
Optional<PayOrderModel> findById(Long id);
/** 调度/内部任务按主键加载时显式带租户,避免多租户插件与线程上下文不一致时误判为「无此单」。 */
Optional<PayOrderModel> findByTenantIdAndId(long tenantId, long id);
Optional<PayOrderModel> findByTenantIdAndBizOrderNo(long tenantId, String bizOrderNo);
Optional<PayOrderModel> findLatestByTenantIdAndBizOrderNo(long tenantId, String bizOrderNo);
Optional<PayOrderModel> findByTenantIdAndGatewayPaymentOrderNo(long tenantId, String gatewayPaymentOrderNo);
List<PayOrderModel> listByBizNotifyAndGatewaySyncAndGatewayNoPresent(
PayBizNotifyStatus bizNotifyStatus, PayOrderGatewaySyncStatus gatewaySyncStatus);
/**
* 网关状态补偿候选:已同步网关、有网关单号,且本地 {@code gatewayOrderStatus} 仍未终态(不限制 {@code bizNotifyStatus})。
*
* @param createdAfter 仅包含该时间之后创建的订单
* @param limit 单次扫描上限
*/
List<PayOrderModel> listGatewayReconcileCandidates(Date createdAfter, int limit);
/**
* 网关建单未成功补偿候选:无网关单号、同步非 SUCCESS且本地尚未 FAILED+NOTIFIED 闭环。
* {@link PayOrderGatewaySyncStatus#PENDING} 仅当 {@code modified/created} 早于 {@code pendingStaleBefore} 才入选(避免与进行中的建单抢跑)。
*/
List<PayOrderModel> listGatewaySyncFailureCandidates(Date createdAfter, Date pendingStaleBefore, int limit);
PayOrderPageSlice pageByTenantAndFilters(
long tenantId,
Date createdStart,
Date createdEnd,
String gatewayOrderStatus,
PayChannel payChannel,
String bizOrderNo,
String gatewayPaymentOrderNo,
int page,
int pageSize);
PayOrderModel save(PayOrderModel order);
/**
* 将 FAILED 同步状态 CAS 为 PENDING用于失败重试防并发。
*
* @return 影响行数1 表示抢占成功
*/
int casUpdateGatewaySyncFromFailedToPending(long id, long tenantId, String bizOrderNo);
/**
* 业务通知状态 CAS 迁移(如 POLLING → NOTIFIED / TIMEOUT
*
* @return true 表示当前实例赢得竞争
*/
boolean casTransitionBizNotifyStatus(long id, PayBizNotifyStatus expectedCurrent, PayBizNotifyStatus newStatus);
}