diff --git a/backend/services/docker-compose.yml b/backend/services/docker-compose.yml index 2b44dbdd..aeadc6e2 100644 --- a/backend/services/docker-compose.yml +++ b/backend/services/docker-compose.yml @@ -177,6 +177,8 @@ services: - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=wallet-service - KAFKA_GROUP_ID=wallet-service-group + # Identity Service - 用于短信验证和密码验证 + - IDENTITY_SERVICE_URL=http://identity-service:3000 depends_on: postgres: condition: service_healthy diff --git a/backend/services/wallet-service/src/application/services/wallet-application.service.ts b/backend/services/wallet-service/src/application/services/wallet-application.service.ts index 9f5c1614..e6ab159b 100644 --- a/backend/services/wallet-service/src/application/services/wallet-application.service.ts +++ b/backend/services/wallet-service/src/application/services/wallet-application.service.ts @@ -1253,14 +1253,14 @@ export class WalletApplicationService { // =============== Withdrawal =============== /** - * 提现手续费 (固定费用,可配置) + * 提现手续费率 (0.1%) */ - private readonly WITHDRAWAL_FEE = 1; // 1 USDT + private readonly WITHDRAWAL_FEE_RATE = 0.001; /** * 最小提现金额 */ - private readonly MIN_WITHDRAWAL_AMOUNT = 10; // 10 USDT + private readonly MIN_WITHDRAWAL_AMOUNT = 100; // 100 USDT /** * 请求提现 @@ -1281,10 +1281,12 @@ export class WalletApplicationService { }> { const userId = BigInt(command.userId); const amount = Money.USDT(command.amount); - const fee = Money.USDT(this.WITHDRAWAL_FEE); + // 计算手续费 = 金额 * 费率 + const feeAmount = command.amount * this.WITHDRAWAL_FEE_RATE; + const fee = Money.USDT(feeAmount); const totalRequired = amount.add(fee); - this.logger.log(`Processing withdrawal request for user ${userId}: ${command.amount} USDT to ${command.toAddress}`); + this.logger.log(`Processing withdrawal request for user ${userId}: ${command.amount} USDT to ${command.toAddress}, fee: ${feeAmount}`); // 验证最小提现金额 if (command.amount < this.MIN_WITHDRAWAL_AMOUNT) { @@ -1303,7 +1305,7 @@ export class WalletApplicationService { // 验证余额是否足够 if (wallet.balances.usdt.available.lessThan(totalRequired)) { throw new BadRequestException( - `余额不足: 需要 ${totalRequired.value} USDT (金额 ${command.amount} + 手续费 ${this.WITHDRAWAL_FEE}), 当前可用 ${wallet.balances.usdt.available.value} USDT`, + `余额不足: 需要 ${totalRequired.value} USDT (金额 ${command.amount} + 手续费 ${feeAmount.toFixed(2)}), 当前可用 ${wallet.balances.usdt.available.value} USDT`, ); } @@ -1333,7 +1335,7 @@ export class WalletApplicationService { amount: Money.signed(-totalRequired.value, 'USDT'), balanceAfter: wallet.balances.usdt.available, refOrderId: savedOrder.orderNo, - memo: `Withdrawal freeze: ${command.amount} USDT + ${this.WITHDRAWAL_FEE} USDT fee`, + memo: `Withdrawal freeze: ${command.amount} USDT + ${feeAmount.toFixed(2)} USDT fee (${this.WITHDRAWAL_FEE_RATE * 100}%)`, }); await this.ledgerRepo.save(freezeEntry); @@ -1344,8 +1346,8 @@ export class WalletApplicationService { userId: userId.toString(), walletId: wallet.walletId.toString(), amount: command.amount.toString(), - fee: this.WITHDRAWAL_FEE.toString(), - netAmount: (command.amount - this.WITHDRAWAL_FEE).toString(), + fee: feeAmount.toString(), + netAmount: (command.amount - feeAmount).toString(), assetType: 'USDT', chainType: command.chainType, toAddress: command.toAddress, diff --git a/backend/services/wallet-service/src/infrastructure/external/identity/identity-client.service.ts b/backend/services/wallet-service/src/infrastructure/external/identity/identity-client.service.ts index 5a4f1c4f..17cc7a5e 100644 --- a/backend/services/wallet-service/src/infrastructure/external/identity/identity-client.service.ts +++ b/backend/services/wallet-service/src/infrastructure/external/identity/identity-client.service.ts @@ -12,7 +12,7 @@ export class IdentityClientService { private readonly httpClient: AxiosInstance; constructor(private readonly configService: ConfigService) { - const baseUrl = this.configService.get('IDENTITY_SERVICE_URL', 'http://localhost:3001'); + const baseUrl = this.configService.get('IDENTITY_SERVICE_URL', 'http://localhost:3000'); this.httpClient = axios.create({ baseURL: baseUrl, @@ -106,7 +106,7 @@ export class IdentityClientService { this.logger.log(`发送提取验证短信: userId=${userId}`); await this.httpClient.post( - '/sms/send-withdraw-code', + '/user/sms/send-withdraw-code', {}, { headers: { @@ -141,7 +141,7 @@ export class IdentityClientService { this.logger.log(`验证提取短信验证码: userId=${userId}`); const response = await this.httpClient.post( - '/sms/verify-withdraw-code', + '/user/sms/verify-withdraw-code', { code: smsCode }, { headers: { @@ -183,7 +183,7 @@ export class IdentityClientService { this.logger.log(`验证登录密码: userId=${userId}`); const response = await this.httpClient.post( - '/verify-password', + '/user/verify-password', { password }, { headers: { diff --git a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_confirm_page.dart b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_confirm_page.dart index 0656b306..2bdfc259 100644 --- a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_confirm_page.dart +++ b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_confirm_page.dart @@ -51,7 +51,7 @@ class _WithdrawConfirmPageState extends ConsumerState { String? _maskedPhoneNumber; /// 手续费率 - final double _feeRate = 0.001; + final double _feeRate = 0.001; // 0.1% @override void initState() { @@ -465,7 +465,7 @@ class _WithdrawConfirmPageState extends ConsumerState { const SizedBox(height: 16), _buildDetailRow('提取网络', _getNetworkName(widget.params.network)), const SizedBox(height: 12), - _buildDetailRow('接收地址', _formatAddress(widget.params.address)), + _buildDetailRow('接收账号', _formatAddress(widget.params.address)), const SizedBox(height: 12), _buildDetailRow('提取数量', '${widget.params.amount.toStringAsFixed(2)} 绿积分'), const SizedBox(height: 12), diff --git a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart index ac4c2299..b97d350a 100644 --- a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart +++ b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart @@ -56,7 +56,7 @@ class _WithdrawUsdtPageState extends ConsumerState { final double _feeRate = 0.001; // 0.1% /// 最小提款金额 - final double _minAmount = 10.0; + final double _minAmount = 100.0; @override void initState() { @@ -181,7 +181,7 @@ class _WithdrawUsdtPageState extends ConsumerState { // 验证地址 if (address.isEmpty) { - _showErrorSnackBar('请输入接收地址'); + _showErrorSnackBar('请输入接收账号'); return; } @@ -331,7 +331,7 @@ class _WithdrawUsdtPageState extends ConsumerState { String _getNetworkDescription(WithdrawNetwork network) { switch (network) { case WithdrawNetwork.kava: - return 'Kava EVM 网络'; + return 'Kava安全网络'; case WithdrawNetwork.bsc: return 'BNB Smart Chain 网络'; } @@ -674,7 +674,7 @@ class _WithdrawUsdtPageState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - '接收地址', + '接收账号', style: TextStyle( fontSize: 16, fontFamily: 'Inter', @@ -966,7 +966,7 @@ class _WithdrawUsdtPageState extends ConsumerState { ], ), const SizedBox(height: 12), - _buildNoticeItem('请确保接收地址正确,错误地址将导致资产丢失'), + _buildNoticeItem('请确保接收账号正确,错误账号将导致资产丢失'), _buildNoticeItem('请选择正确的网络,不同网络之间不可互转'), _buildNoticeItem('提取需要进行手机短信验证'), _buildNoticeItem('提取通常在 1-30 分钟内到账'),