fix(mining-app): QR码解析加固 + debugPrint排查
- 清除不可见字符(BOM/零宽空格) - 三级宽松解析:正则→Uri.parse→兜底phone=提取 - 添加 [QR_SCAN] 调试日志定位实际扫码值 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
8c31dee000
commit
03cc5bc324
|
|
@ -570,6 +570,7 @@ class _SendSharesPageState extends ConsumerState<SendSharesPage> {
|
|||
if (result == null) return;
|
||||
|
||||
// 解析二维码内容
|
||||
debugPrint('[QR_SCAN] scanner returned: "$result"');
|
||||
final phone = parseTransferQrCode(result);
|
||||
if (phone != null) {
|
||||
setState(() {
|
||||
|
|
|
|||
|
|
@ -250,37 +250,42 @@ class _QrScannerSheetState extends State<QrScannerSheet> {
|
|||
/// 返回手机号,解析失败返回 null
|
||||
String? parseTransferQrCode(String qrCode) {
|
||||
try {
|
||||
final trimmed = qrCode.trim();
|
||||
// 去除首尾空白及不可见字符(BOM、零宽空格等)
|
||||
final trimmed = qrCode.trim().replaceAll(RegExp(r'[\u200B-\u200D\uFEFF\u00A0]'), '');
|
||||
|
||||
// 使用正则表达式匹配,兼容有无 / 的格式
|
||||
// durian://transfer/?phone=xxx 或 durian://transfer?phone=xxx
|
||||
final regex = RegExp(r'^durian://transfer/?[?]phone=(\d{11})$');
|
||||
debugPrint('[QR_SCAN] raw length=${qrCode.length}, trimmed length=${trimmed.length}');
|
||||
debugPrint('[QR_SCAN] raw codeUnits=${qrCode.codeUnits}');
|
||||
debugPrint('[QR_SCAN] trimmed="$trimmed"');
|
||||
|
||||
// 方案1:宽松正则 - 只要包含 durian://transfer 和 phone=11位数字
|
||||
final regex = RegExp(r'durian://transfer[/?].*?phone=(\d{11})');
|
||||
final match = regex.firstMatch(trimmed);
|
||||
|
||||
if (match != null) {
|
||||
debugPrint('[QR_SCAN] regex matched, phone=${match.group(1)}');
|
||||
return match.group(1);
|
||||
}
|
||||
|
||||
// 备用方案:使用 Uri.parse
|
||||
final uri = Uri.parse(trimmed);
|
||||
|
||||
// 检查 scheme
|
||||
if (uri.scheme != 'durian') return null;
|
||||
|
||||
// 检查 host (即 authority 部分)
|
||||
if (uri.host != 'transfer') return null;
|
||||
|
||||
// 获取 phone 参数
|
||||
final phone = uri.queryParameters['phone'];
|
||||
if (phone == null || phone.isEmpty) return null;
|
||||
|
||||
// 简单验证手机号格式
|
||||
if (phone.length != 11 || !RegExp(r'^\d{11}$').hasMatch(phone)) {
|
||||
return null;
|
||||
// 方案2:Uri.parse
|
||||
final uri = Uri.tryParse(trimmed);
|
||||
if (uri != null && uri.scheme == 'durian') {
|
||||
final phone = uri.queryParameters['phone'];
|
||||
if (phone != null && RegExp(r'^\d{11}$').hasMatch(phone)) {
|
||||
debugPrint('[QR_SCAN] Uri.parse matched, phone=$phone');
|
||||
return phone;
|
||||
}
|
||||
}
|
||||
|
||||
return phone;
|
||||
// 方案3:最宽松兜底 - 字符串中任何 phone=11位数字
|
||||
final fallback = RegExp(r'phone=(\d{11})').firstMatch(trimmed);
|
||||
if (fallback != null) {
|
||||
debugPrint('[QR_SCAN] fallback matched, phone=${fallback.group(1)}');
|
||||
return fallback.group(1);
|
||||
}
|
||||
|
||||
debugPrint('[QR_SCAN] all parsing failed for: "$trimmed"');
|
||||
return null;
|
||||
} catch (e) {
|
||||
debugPrint('[QR_SCAN] exception: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue