2026-03-17 22:07:19 +08:00
|
|
|
|
import db from '../config/database';
|
|
|
|
|
|
import { AuditService } from './AuditService';
|
|
|
|
|
|
import { AIService } from './AIService';
|
|
|
|
|
|
import { SovereigntyIdentityService } from './SovereigntyIdentityService';
|
|
|
|
|
|
import { FeatureGovernanceService } from '../core/governance/FeatureGovernanceService';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [BIZ_SOV_03] 跨境资金主权结算协议 (Sovereignty Settlement)
|
|
|
|
|
|
* 负责基于租户 DID 身份进行跨国、跨币种的直接主权结算,绕过传统银行中转
|
|
|
|
|
|
*/
|
|
|
|
|
|
export class SovereigntySettlementService {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发起主权结算
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async initiateSettlement(
|
|
|
|
|
|
tenantId: string,
|
|
|
|
|
|
amount: number,
|
|
|
|
|
|
currency: string,
|
|
|
|
|
|
traceId: string
|
|
|
|
|
|
): Promise<string | null> {
|
|
|
|
|
|
// Feature Flag Check
|
|
|
|
|
|
if (!(await FeatureGovernanceService.isEnabled('BIZ_SOV_SETTLEMENT', tenantId))) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 1. 获取租户主权身份 DID
|
|
|
|
|
|
const identity = await SovereigntyIdentityService.getIdentity(tenantId);
|
|
|
|
|
|
if (!identity) {
|
|
|
|
|
|
throw new Error('Sovereignty Identity not initialized');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 调用 AGI 结算引擎生成结算证明 (模拟主权区块链交互)
|
|
|
|
|
|
const settlementHash = 'SETTLE-' + Math.random().toString(36).substring(7).toUpperCase();
|
|
|
|
|
|
|
|
|
|
|
|
await db.transaction(async (trx) => {
|
|
|
|
|
|
// 3. 记录结算单
|
|
|
|
|
|
const [id] = await trx('cf_sovereignty_payouts').insert({
|
|
|
|
|
|
tenant_id: tenantId,
|
|
|
|
|
|
amount,
|
|
|
|
|
|
currency,
|
|
|
|
|
|
settlement_hash: settlementHash,
|
|
|
|
|
|
status: 'PENDING'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 模拟主权网关回调执行
|
|
|
|
|
|
await this.executeSettlement(id, tenantId, traceId);
|
|
|
|
|
|
|
|
|
|
|
|
// 审计记录
|
|
|
|
|
|
await AuditService.log({
|
2026-03-18 13:38:05 +08:00
|
|
|
|
tenantId: tenantId,
|
|
|
|
|
|
userId: 'SYSTEM',
|
|
|
|
|
|
module: 'SOVEREIGNTY_SETTLEMENT',
|
|
|
|
|
|
action: 'SOVEREIGNTY_SETTLEMENT_CREATED',
|
|
|
|
|
|
resourceType: 'FINANCE_PAYOUT',
|
|
|
|
|
|
resourceId: id.toString(),
|
|
|
|
|
|
traceId: traceId,
|
|
|
|
|
|
afterSnapshot: JSON.stringify({ amount, currency, settlementHash }),
|
|
|
|
|
|
result: 'success',
|
|
|
|
|
|
source: 'node',
|
|
|
|
|
|
metadata: { did: identity.did }
|
2026-03-17 22:07:19 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return settlementHash;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行结算 (V27.0 Sovereignty Flow)
|
|
|
|
|
|
*/
|
|
|
|
|
|
private static async executeSettlement(payoutId: number, tenantId: string, traceId: string): Promise<void> {
|
|
|
|
|
|
// 模拟结算成功
|
|
|
|
|
|
await db('cf_sovereignty_payouts')
|
|
|
|
|
|
.where({ id: payoutId })
|
|
|
|
|
|
.update({
|
|
|
|
|
|
status: 'SETTLED',
|
|
|
|
|
|
updated_at: db.fn.now()
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await AuditService.log({
|
2026-03-18 13:38:05 +08:00
|
|
|
|
tenantId: tenantId,
|
|
|
|
|
|
userId: 'SYSTEM',
|
|
|
|
|
|
module: 'SOVEREIGNTY_SETTLEMENT',
|
|
|
|
|
|
action: 'SOVEREIGNTY_SETTLEMENT_EXECUTED',
|
|
|
|
|
|
resourceType: 'FINANCE_PAYOUT',
|
|
|
|
|
|
resourceId: payoutId.toString(),
|
|
|
|
|
|
traceId: traceId,
|
|
|
|
|
|
afterSnapshot: JSON.stringify({ status: 'SETTLED' }),
|
|
|
|
|
|
result: 'success',
|
|
|
|
|
|
source: 'node',
|
|
|
|
|
|
metadata: { timestamp: new Date().toISOString() }
|
2026-03-17 22:07:19 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取租户所有主权结算记录
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async getSettlementHistory(tenantId: string) {
|
|
|
|
|
|
return await db('cf_sovereignty_payouts')
|
|
|
|
|
|
.where({ tenant_id: tenantId })
|
|
|
|
|
|
.orderBy('created_at', 'desc');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|