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:
parent
d36a58341d
commit
188075b2be
|
|
@ -272,7 +272,15 @@
|
|||
"Bash($env:DATABASE_URL=\"postgresql://postgres:password@localhost:5432/rwa_identity?schema=public\")",
|
||||
"Bash(docker cp:*)",
|
||||
"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": [],
|
||||
"ask": []
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -10,6 +10,7 @@ export interface SmsSendResult {
|
|||
bizId?: string;
|
||||
code?: string;
|
||||
message?: string;
|
||||
uncertain?: boolean; // 超时情况下短信可能已发送
|
||||
}
|
||||
|
||||
// 重试配置
|
||||
|
|
@ -24,11 +25,14 @@ const RETRY_CONFIG = {
|
|||
'ENOTFOUND', // DNS 解析失败
|
||||
'ServiceUnavailable',
|
||||
],
|
||||
// 不重试的错误(可能短信已发送成功,只是响应慢)
|
||||
noRetryErrors: [
|
||||
// 超时错误(短信可能已发送成功,返回成功但标记为不确定)
|
||||
timeoutErrors: [
|
||||
'ConnectTimeout',
|
||||
'ReadTimeout',
|
||||
'ETIMEDOUT',
|
||||
],
|
||||
// 不重试的业务错误
|
||||
noRetryErrors: [
|
||||
'BUSINESS_LIMIT_CONTROL', // 流控
|
||||
],
|
||||
};
|
||||
|
|
@ -167,9 +171,23 @@ export class SmsService implements OnModuleInit {
|
|||
(lastError as any).code = result.code;
|
||||
} catch (error: any) {
|
||||
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}`);
|
||||
return {
|
||||
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),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 睡眠函数
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import '../../../../core/di/injection_container.dart';
|
||||
import '../../../../core/storage/storage_keys.dart';
|
||||
|
||||
/// 充值 USDT 页面
|
||||
/// 显示用户ID(accountSequence)二维码作为充值地址
|
||||
|
|
@ -67,14 +68,29 @@ class _DepositUsdtPageState extends ConsumerState<DepositUsdtPage> {
|
|||
|
||||
_accountSequence = userSerialNum;
|
||||
|
||||
// 检查钱包状态
|
||||
try {
|
||||
final walletInfo = await accountService.getWalletInfo(userSerialNum);
|
||||
_isWalletReady = walletInfo.isReady;
|
||||
debugPrint('[DepositUsdtPage] 钱包状态: ${walletInfo.status}, isReady: $_isWalletReady');
|
||||
} catch (e) {
|
||||
debugPrint('[DepositUsdtPage] 获取钱包状态失败: $e');
|
||||
_isWalletReady = false;
|
||||
// 先从本地存储检查钱包状态
|
||||
final secureStorage = ref.read(secureStorageProvider);
|
||||
final cachedWalletReady = await secureStorage.read(key: StorageKeys.isWalletReady);
|
||||
|
||||
if (cachedWalletReady == 'true') {
|
||||
// 本地已标记为 ready,直接使用
|
||||
debugPrint('[DepositUsdtPage] 本地存储显示钱包已就绪');
|
||||
_isWalletReady = true;
|
||||
} else {
|
||||
// 本地未标记,调用API检查
|
||||
try {
|
||||
final walletInfo = await accountService.getWalletInfo(userSerialNum);
|
||||
_isWalletReady = walletInfo.isReady;
|
||||
debugPrint('[DepositUsdtPage] 钱包状态: ${walletInfo.status}, isReady: $_isWalletReady');
|
||||
|
||||
// 如果API返回ready,保存到本地存储
|
||||
if (_isWalletReady) {
|
||||
await secureStorage.write(key: StorageKeys.isWalletReady, value: 'true');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('[DepositUsdtPage] 获取钱包状态失败: $e');
|
||||
_isWalletReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果钱包已就绪,查询余额和真实钱包地址
|
||||
|
|
|
|||
Loading…
Reference in New Issue