fix: 短信超时返回成功状态避免前端报错

超时情况下短信可能已发送成功,返回 success: true + uncertain: true

🤖 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-21 20:55:31 -08:00
parent d36a58341d
commit 188075b2be
4 changed files with 63 additions and 12 deletions

View File

@ -272,7 +272,15 @@
"Bash($env:DATABASE_URL=\"postgresql://postgres:password@localhost:5432/rwa_identity?schema=public\")", "Bash($env:DATABASE_URL=\"postgresql://postgres:password@localhost:5432/rwa_identity?schema=public\")",
"Bash(docker cp:*)", "Bash(docker cp:*)",
"Bash(timeout 120 docker compose:*)", "Bash(timeout 120 docker compose:*)",
"Bash(docker network create:*)" "Bash(docker network create:*)",
"Bash(find backend/services -type d -name migrations -exec sh -c 'echo \"\"=== {} ===\"\" && ls -1 \"\"$1\"\" | wc -l' _ {} ;)",
"Bash(git commit -m \"$\\(cat <<''EOF''\nrefactor: 简化启动流程和优化向导页文案\n\n- 简化 splash 页面跳转逻辑:账号已创建直接进主页,首次启动进向导页\n- 优化向导页第5页文案更亲切的标题和更清晰的说明\n- 改进推荐码输入框和扫码图标颜色:黑色文字与白色底色形成更好对比\n- 简化\"恢复账号\"按钮文字\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
"Bash(timeout 30 git push:*)",
"Bash(ping:*)",
"Bash(ipconfig:*)",
"Bash(flutter run:*)",
"Bash(flutter devices:*)",
"Bash(npx qrcode:*)"
], ],
"deny": [], "deny": [],
"ask": [] "ask": []

BIN
SEED01-qrcode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -10,6 +10,7 @@ export interface SmsSendResult {
bizId?: string; bizId?: string;
code?: string; code?: string;
message?: string; message?: string;
uncertain?: boolean; // 超时情况下短信可能已发送
} }
// 重试配置 // 重试配置
@ -24,11 +25,14 @@ const RETRY_CONFIG = {
'ENOTFOUND', // DNS 解析失败 'ENOTFOUND', // DNS 解析失败
'ServiceUnavailable', 'ServiceUnavailable',
], ],
// 不重试的错误(可能短信已发送成功,只是响应慢 // 超时错误(短信可能已发送成功,返回成功但标记为不确定
noRetryErrors: [ timeoutErrors: [
'ConnectTimeout', 'ConnectTimeout',
'ReadTimeout', 'ReadTimeout',
'ETIMEDOUT', 'ETIMEDOUT',
],
// 不重试的业务错误
noRetryErrors: [
'BUSINESS_LIMIT_CONTROL', // 流控 'BUSINESS_LIMIT_CONTROL', // 流控
], ],
}; };
@ -167,9 +171,23 @@ export class SmsService implements OnModuleInit {
(lastError as any).code = result.code; (lastError as any).code = result.code;
} catch (error: any) { } catch (error: any) {
lastError = error; lastError = error;
const errorInfo = error.message || error.code || '';
// 超时错误:短信可能已发送成功,返回成功但标记为不确定
if (this.isTimeoutError(errorInfo)) {
this.logger.warn(
`[SMS] 超时但可能已发送成功: ${error.message}`,
);
return {
success: true,
uncertain: true,
code: 'TIMEOUT_UNCERTAIN',
message: '请求超时,验证码可能已发送,请稍等片刻',
};
}
// 检查是否是可重试的错误 // 检查是否是可重试的错误
if (!this.isRetryableError(error.message || error.code || '')) { if (!this.isRetryableError(errorInfo)) {
this.logger.error(`[SMS] 不可重试错误: ${error.message}`); this.logger.error(`[SMS] 不可重试错误: ${error.message}`);
return { return {
success: false, success: false,
@ -250,6 +268,15 @@ export class SmsService implements OnModuleInit {
); );
} }
/**
*
*/
private isTimeoutError(errorInfo: string): boolean {
return RETRY_CONFIG.timeoutErrors.some(
(timeout) => errorInfo.includes(timeout),
);
}
/** /**
* *
*/ */

View File

@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart';
import '../../../../core/di/injection_container.dart'; import '../../../../core/di/injection_container.dart';
import '../../../../core/storage/storage_keys.dart';
/// USDT /// USDT
/// IDaccountSequence /// IDaccountSequence
@ -67,15 +68,30 @@ class _DepositUsdtPageState extends ConsumerState<DepositUsdtPage> {
_accountSequence = userSerialNum; _accountSequence = userSerialNum;
// //
final secureStorage = ref.read(secureStorageProvider);
final cachedWalletReady = await secureStorage.read(key: StorageKeys.isWalletReady);
if (cachedWalletReady == 'true') {
// ready使
debugPrint('[DepositUsdtPage] 本地存储显示钱包已就绪');
_isWalletReady = true;
} else {
// API检查
try { try {
final walletInfo = await accountService.getWalletInfo(userSerialNum); final walletInfo = await accountService.getWalletInfo(userSerialNum);
_isWalletReady = walletInfo.isReady; _isWalletReady = walletInfo.isReady;
debugPrint('[DepositUsdtPage] 钱包状态: ${walletInfo.status}, isReady: $_isWalletReady'); debugPrint('[DepositUsdtPage] 钱包状态: ${walletInfo.status}, isReady: $_isWalletReady');
// API返回ready
if (_isWalletReady) {
await secureStorage.write(key: StorageKeys.isWalletReady, value: 'true');
}
} catch (e) { } catch (e) {
debugPrint('[DepositUsdtPage] 获取钱包状态失败: $e'); debugPrint('[DepositUsdtPage] 获取钱包状态失败: $e');
_isWalletReady = false; _isWalletReady = false;
} }
}
// //
if (_isWalletReady) { if (_isWalletReady) {