import 'package:flutter/foundation.dart'; import '../../../core/network/api_client.dart'; import '../../../core/errors/exceptions.dart'; /// KYC 状态枚举 enum KycStatusType { notStarted, // 未开始 phoneVerified, // 手机已验证 idPending, // 身份验证中 idVerified, // 身份已验证 completed, // 已完成 rejected, // 已拒绝 } /// KYC 状态响应 class KycStatusResponse { final bool phoneVerified; final String kycStatus; final String? realName; final String? idCardNumber; final DateTime? kycVerifiedAt; final String? rejectedReason; final String? phoneNumber; KycStatusResponse({ required this.phoneVerified, required this.kycStatus, this.realName, this.idCardNumber, this.kycVerifiedAt, this.rejectedReason, this.phoneNumber, }); factory KycStatusResponse.fromJson(Map json) { return KycStatusResponse( phoneVerified: json['phoneVerified'] as bool? ?? false, kycStatus: json['kycStatus'] as String? ?? 'NOT_STARTED', realName: json['realName'] as String?, idCardNumber: json['idCardNumber'] as String?, kycVerifiedAt: json['kycVerifiedAt'] != null ? DateTime.parse(json['kycVerifiedAt'] as String) : null, rejectedReason: json['rejectedReason'] as String?, phoneNumber: json['phoneNumber'] as String?, ); } KycStatusType get statusType { switch (kycStatus) { case 'NOT_STARTED': return KycStatusType.notStarted; case 'PHONE_VERIFIED': return KycStatusType.phoneVerified; case 'ID_PENDING': return KycStatusType.idPending; case 'ID_VERIFIED': return KycStatusType.idVerified; case 'COMPLETED': return KycStatusType.completed; case 'REJECTED': return KycStatusType.rejected; default: return KycStatusType.notStarted; } } bool get isCompleted => statusType == KycStatusType.completed; bool get needsPhoneVerification => !phoneVerified; bool get needsIdVerification => statusType == KycStatusType.notStarted || statusType == KycStatusType.phoneVerified || statusType == KycStatusType.rejected; } /// 身份验证响应 class IdVerificationResponse { final String requestId; final String status; final String? failureReason; final String? kycStatus; IdVerificationResponse({ required this.requestId, required this.status, this.failureReason, this.kycStatus, }); factory IdVerificationResponse.fromJson(Map json) { return IdVerificationResponse( requestId: json['requestId'] as String, status: json['status'] as String, failureReason: json['failureReason'] as String?, kycStatus: json['kycStatus'] as String?, ); } bool get isSuccess => status == 'SUCCESS'; bool get isFailed => status == 'FAILED'; } /// KYC 服务 class KycService { static const String _tag = '[KycService]'; final ApiClient _apiClient; KycService(this._apiClient); /// 获取 KYC 状态 Future getKycStatus() async { debugPrint('$_tag getKycStatus() - 获取 KYC 状态'); try { final response = await _apiClient.get('/user/kyc/status'); debugPrint('$_tag getKycStatus() - 响应: ${response.statusCode}'); if (response.data == null) { throw const ApiException('获取 KYC 状态失败: 空响应'); } final responseData = response.data as Map; final data = responseData['data'] as Map; return KycStatusResponse.fromJson(data); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag getKycStatus() - 异常: $e'); throw ApiException('获取 KYC 状态失败: $e'); } } /// 发送 KYC 手机验证码 Future sendKycVerifySms() async { debugPrint('$_tag sendKycVerifySms() - 发送验证码'); try { final response = await _apiClient.post('/user/kyc/send-verify-sms'); debugPrint('$_tag sendKycVerifySms() - 响应: ${response.statusCode}'); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag sendKycVerifySms() - 异常: $e'); throw ApiException('发送验证码失败: $e'); } } /// 验证手机号 (KYC 流程) Future verifyPhoneForKyc(String smsCode) async { debugPrint('$_tag verifyPhoneForKyc() - 验证手机号'); try { final response = await _apiClient.post( '/user/kyc/verify-phone', data: {'smsCode': smsCode}, ); debugPrint('$_tag verifyPhoneForKyc() - 响应: ${response.statusCode}'); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag verifyPhoneForKyc() - 异常: $e'); throw ApiException('验证失败: $e'); } } /// 提交身份证验证 Future submitIdVerification({ required String realName, required String idCardNumber, }) async { debugPrint('$_tag submitIdVerification() - 提交身份验证'); try { final response = await _apiClient.post( '/user/kyc/submit-id', data: { 'realName': realName, 'idCardNumber': idCardNumber, }, ); debugPrint('$_tag submitIdVerification() - 响应: ${response.statusCode}'); if (response.data == null) { throw const ApiException('提交身份验证失败: 空响应'); } final responseData = response.data as Map; final data = responseData['data'] as Map; return IdVerificationResponse.fromJson(data); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag submitIdVerification() - 异常: $e'); throw ApiException('提交身份验证失败: $e'); } } // ============ 更换手机号相关 ============ /// 获取手机号状态 Future getPhoneStatus() async { debugPrint('$_tag getPhoneStatus() - 获取手机号状态'); try { final response = await _apiClient.get('/user/phone-status'); debugPrint('$_tag getPhoneStatus() - 响应: ${response.statusCode}'); if (response.data == null) { throw const ApiException('获取手机号状态失败: 空响应'); } final responseData = response.data as Map; final data = responseData['data'] as Map; return PhoneStatusResponse.fromJson(data); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag getPhoneStatus() - 异常: $e'); throw ApiException('获取手机号状态失败: $e'); } } /// 发送旧手机验证码(更换手机号第一步) Future sendOldPhoneCode() async { debugPrint('$_tag sendOldPhoneCode() - 发送旧手机验证码'); try { final response = await _apiClient.post('/user/change-phone/send-old-code'); debugPrint('$_tag sendOldPhoneCode() - 响应: ${response.statusCode}'); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag sendOldPhoneCode() - 异常: $e'); throw ApiException('发送验证码失败: $e'); } } /// 验证旧手机验证码(更换手机号第二步) Future verifyOldPhoneCode(String smsCode) async { debugPrint('$_tag verifyOldPhoneCode() - 验证旧手机验证码'); try { final response = await _apiClient.post( '/user/change-phone/verify-old', data: {'smsCode': smsCode}, ); debugPrint('$_tag verifyOldPhoneCode() - 响应: ${response.statusCode}'); if (response.data == null) { throw const ApiException('验证失败: 空响应'); } final responseData = response.data as Map; final data = responseData['data'] as Map; return data['changePhoneToken'] as String; } on ApiException { rethrow; } catch (e) { debugPrint('$_tag verifyOldPhoneCode() - 异常: $e'); throw ApiException('验证失败: $e'); } } /// 发送新手机验证码(更换手机号第三步) Future sendNewPhoneCode({ required String newPhoneNumber, required String changePhoneToken, }) async { debugPrint('$_tag sendNewPhoneCode() - 发送新手机验证码'); try { final response = await _apiClient.post( '/user/change-phone/send-new-code', data: { 'newPhoneNumber': newPhoneNumber, 'changePhoneToken': changePhoneToken, }, ); debugPrint('$_tag sendNewPhoneCode() - 响应: ${response.statusCode}'); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag sendNewPhoneCode() - 异常: $e'); throw ApiException('发送验证码失败: $e'); } } /// 确认更换手机号(更换手机号第四步) Future confirmChangePhone({ required String newPhoneNumber, required String smsCode, required String changePhoneToken, }) async { debugPrint('$_tag confirmChangePhone() - 确认更换手机号'); try { final response = await _apiClient.post( '/user/change-phone/confirm', data: { 'newPhoneNumber': newPhoneNumber, 'smsCode': smsCode, 'changePhoneToken': changePhoneToken, }, ); debugPrint('$_tag confirmChangePhone() - 响应: ${response.statusCode}'); } on ApiException { rethrow; } catch (e) { debugPrint('$_tag confirmChangePhone() - 异常: $e'); throw ApiException('更换手机号失败: $e'); } } } /// 手机号状态响应 class PhoneStatusResponse { final bool isBound; final bool isVerified; final String? phoneNumber; final DateTime? verifiedAt; PhoneStatusResponse({ required this.isBound, required this.isVerified, this.phoneNumber, this.verifiedAt, }); factory PhoneStatusResponse.fromJson(Map json) { return PhoneStatusResponse( isBound: json['isBound'] as bool? ?? false, isVerified: json['isVerified'] as bool? ?? false, phoneNumber: json['phoneNumber'] as String?, verifiedAt: json['verifiedAt'] != null ? DateTime.parse(json['verifiedAt'] as String) : null, ); } }