fix(planting-service): 修复跨服务调用使用错误标识符导致的500错误

问题根源:
- getBalance 调用使用 userId.toString() (纯数字如 "14")
- wallet-service 按 accountSequence 查找钱包失败后尝试创建新钱包
- 但 userId 已存在,触发唯一约束冲突导致500错误

修复内容:
1. planting-application.service.ts:
   - createOrder: getBalance(userId.toString()) → getBalance(accountSequence)
   - payOrder: getBalance(userId.toString()) → getBalance(walletIdentifier)

2. payment-compensation.service.ts:
   - 注入 IPlantingOrderRepository 获取订单的 accountSequence
   - handleUnfreeze/handleRetryConfirm 添加 accountSequence 参数

3. wallet-service.client.ts:
   - ensureRegionAccounts 接口添加 provinceTeamAccount/cityTeamAccount 字段

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-26 01:48:22 -08:00
parent aae4f1e360
commit 24a46521f3
3 changed files with 30 additions and 5 deletions

View File

@ -1,4 +1,4 @@
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { Injectable, Logger, OnModuleInit, Inject } from '@nestjs/common';
import {
PaymentCompensationRepository,
PaymentCompensationRecord,
@ -7,6 +7,7 @@ import {
FailureStage,
} from '../../infrastructure/persistence/repositories/payment-compensation.repository';
import { WalletServiceClient } from '../../infrastructure/external/wallet-service.client';
import { IPlantingOrderRepository, PLANTING_ORDER_REPOSITORY } from '../../domain/repositories/planting-order.repository';
/**
*
@ -30,6 +31,8 @@ export class PaymentCompensationService implements OnModuleInit {
constructor(
private readonly compensationRepo: PaymentCompensationRepository,
private readonly walletService: WalletServiceClient,
@Inject(PLANTING_ORDER_REPOSITORY)
private readonly orderRepository: IPlantingOrderRepository,
) {}
onModuleInit() {
@ -137,12 +140,25 @@ export class PaymentCompensationService implements OnModuleInit {
}
}
/**
* accountSequence
*/
private async getAccountSequence(orderNo: string): Promise<string> {
const order = await this.orderRepository.findByOrderNo(orderNo);
if (!order) {
throw new Error(`Order ${orderNo} not found`);
}
return order.accountSequence;
}
/**
*
*/
private async handleUnfreeze(record: PaymentCompensationRecord): Promise<void> {
const accountSequence = await this.getAccountSequence(record.orderNo);
await this.walletService.unfreezeForPlanting({
userId: record.userId.toString(),
accountSequence,
orderId: record.orderNo,
});
this.logger.log(`Unfroze funds for order ${record.orderNo}`);
@ -152,8 +168,10 @@ export class PaymentCompensationService implements OnModuleInit {
*
*/
private async handleRetryConfirm(record: PaymentCompensationRecord): Promise<void> {
const accountSequence = await this.getAccountSequence(record.orderNo);
await this.walletService.confirmPlantingDeduction({
userId: record.userId.toString(),
accountSequence,
orderId: record.orderNo,
});
this.logger.log(`Confirmed deduction for order ${record.orderNo}`);

View File

@ -82,8 +82,8 @@ export class PlantingApplicationService {
): Promise<CreateOrderResult> {
this.logger.log(`Creating order for user ${accountSequence}, treeCount: ${treeCount}`);
// 检查余额
const balance = await this.walletService.getBalance(userId.toString());
// 检查余额 - 使用 accountSequence 进行跨服务调用
const balance = await this.walletService.getBalance(accountSequence);
const requiredAmount = treeCount * PRICE_PER_TREE;
if (balance.available < requiredAmount) {
throw new Error(
@ -219,8 +219,9 @@ export class PlantingApplicationService {
throw new Error('请先选择并确认省市');
}
// 2. 验证钱包余额 (先检查,不扣款)
const balance = await this.walletService.getBalance(userId.toString());
// 2. 验证钱包余额 (先检查,不扣款) - 使用 accountSequence 进行跨服务调用
const walletIdentifier = accountSequence || order.accountSequence;
const balance = await this.walletService.getBalance(walletIdentifier);
if (balance.available < order.totalAmount) {
throw new Error(
`余额不足: 需要 ${order.totalAmount} USDT, 当前可用 ${balance.available} USDT`,

View File

@ -399,6 +399,8 @@ export class WalletServiceClient {
}): Promise<{
provinceAccount: { accountSequence: string; created: boolean };
cityAccount: { accountSequence: string; created: boolean };
provinceTeamAccount: { accountSequence: string; created: boolean };
cityTeamAccount: { accountSequence: string; created: boolean };
}> {
try {
return await this.withRetry(
@ -408,6 +410,8 @@ export class WalletServiceClient {
this.httpService.post<{
provinceAccount: { accountSequence: string; created: boolean };
cityAccount: { accountSequence: string; created: boolean };
provinceTeamAccount: { accountSequence: string; created: boolean };
cityTeamAccount: { accountSequence: string; created: boolean };
}>(
`${this.baseUrl}/api/v1/wallets/ensure-region-accounts`,
params,
@ -427,6 +431,8 @@ export class WalletServiceClient {
return {
provinceAccount: { accountSequence: `9${params.provinceCode}`, created: true },
cityAccount: { accountSequence: `8${params.cityCode}`, created: true },
provinceTeamAccount: { accountSequence: `7${params.provinceCode}`, created: true },
cityTeamAccount: { accountSequence: `6${params.cityCode}`, created: true },
};
}
throw error;