Some checks failed
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / build (push) Has been cancelled
331 lines
12 KiB
Dart
Executable File
331 lines
12 KiB
Dart
Executable File
import 'dart:io';
|
||
import 'dart:math';
|
||
import 'dart:convert';
|
||
|
||
import 'package:fpdart/fpdart.dart';
|
||
import 'package:get/get.dart';
|
||
import 'package:kaer_with_panels/app/mixins/kr_app_bar_opacity_mixin.dart';
|
||
import 'package:kaer_with_panels/app/services/api_service/api.dart';
|
||
import 'package:kaer_with_panels/app/model/enum/kr_request_type.dart';
|
||
import 'package:kaer_with_panels/app/model/response/kr_is_register.dart';
|
||
import 'package:kaer_with_panels/app/model/response/kr_login_data.dart';
|
||
import 'package:kaer_with_panels/app/network/base_response.dart';
|
||
import 'package:kaer_with_panels/app/network/http_error.dart';
|
||
import 'package:kaer_with_panels/app/network/http_util.dart';
|
||
|
||
import '../../utils/kr_common_util.dart';
|
||
import '../../utils/kr_log_util.dart';
|
||
import '../../utils/kr_aes_util.dart';
|
||
import '../kr_device_info_service.dart';
|
||
import '../kr_site_config_service.dart';
|
||
import '../../common/app_config.dart';
|
||
import 'package:dio/dio.dart' as dio;
|
||
|
||
class KRAuthApi {
|
||
/// 检查账号是否已注册(仅支持邮箱)
|
||
Future<Either<HttpError, bool>> kr_isRegister(String email) async {
|
||
final Map<String, dynamic> data = <String, dynamic>{};
|
||
data['email'] = email;
|
||
|
||
final deviceId = KRDeviceInfoService().deviceId ?? 'unknown';
|
||
KRLogUtil.kr_i('设备ID: $deviceId', tag: 'KRAuthApi');
|
||
data["identifier"] = deviceId;
|
||
|
||
BaseResponse<KRIsRegister> baseResponse = await HttpUtil.getInstance()
|
||
.request<KRIsRegister>(Api.kr_isRegister, data,
|
||
method: HttpMethod.POST, isShowLoading: true);
|
||
|
||
if (!baseResponse.isSuccess) {
|
||
return left(
|
||
HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
|
||
}
|
||
|
||
return right(baseResponse.model.kr_isRegister);
|
||
}
|
||
|
||
/// 注册(仅支持邮箱+密码,验证码和邀请码可选)
|
||
Future<Either<HttpError, String>> kr_register(
|
||
String email,
|
||
String password,
|
||
{String? code,
|
||
String? inviteCode}) async {
|
||
final Map<String, dynamic> data = <String, dynamic>{};
|
||
data['email'] = email;
|
||
data["code"] = code;
|
||
// data['password'] = password;
|
||
// data["identifier"] = KRDeviceInfoService().deviceId ?? 'unknown';
|
||
|
||
// 验证码是可选的,只有在提供时才发送
|
||
// if (code != null && code.isNotEmpty) {
|
||
//
|
||
// }
|
||
|
||
// 邀请码是可选的
|
||
// if (inviteCode != null && inviteCode.isNotEmpty) {
|
||
// data["invite"] = inviteCode;
|
||
// }
|
||
|
||
BaseResponse<KRLoginData> baseResponse = await HttpUtil.getInstance()
|
||
.request<KRLoginData>(Api.kr_register, data,
|
||
method: HttpMethod.POST, isShowLoading: true);
|
||
if (!baseResponse.isSuccess) {
|
||
return left(
|
||
HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
|
||
}
|
||
|
||
return right(baseResponse.model.kr_token.toString());
|
||
}
|
||
|
||
/// 验证验证码(仅支持邮箱)
|
||
Future<Either<HttpError, bool>> kr_checkVerificationCode(
|
||
String email, String code, int type) async {
|
||
final Map<String, dynamic> data = <String, dynamic>{};
|
||
data['email'] = email;
|
||
data['code'] = code;
|
||
data['type'] = type;
|
||
|
||
BaseResponse<KRIsRegister> baseResponse = await HttpUtil.getInstance()
|
||
.request<KRIsRegister>(Api.kr_checkVerificationCode, data,
|
||
method: HttpMethod.POST, isShowLoading: true);
|
||
if (!baseResponse.isSuccess) {
|
||
return left(
|
||
HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
|
||
}
|
||
if (baseResponse.model.kr_isRegister) {
|
||
return right(true);
|
||
} else {
|
||
return left(HttpError(msg: "error.70001".tr, code: 70001));
|
||
}
|
||
}
|
||
|
||
/// 登录(仅支持邮箱+密码)
|
||
Future<Either<HttpError, String>> kr_login(
|
||
String email, String password) async {
|
||
final Map<String, dynamic> data = <String, dynamic>{};
|
||
data['email'] = email;
|
||
data['password'] = password;
|
||
|
||
final deviceId = KRDeviceInfoService().deviceId ?? 'unknown';
|
||
KRLogUtil.kr_i('设备ID: $deviceId', tag: 'KRAuthApi');
|
||
// data["identifier"] = deviceId;
|
||
|
||
BaseResponse<KRLoginData> baseResponse = await HttpUtil.getInstance()
|
||
.request<KRLoginData>(Api.kr_login, data,
|
||
method: HttpMethod.POST, isShowLoading: true);
|
||
if (!baseResponse.isSuccess) {
|
||
return left(
|
||
HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
|
||
}
|
||
|
||
return right(baseResponse.model.kr_token.toString());
|
||
}
|
||
|
||
/// 发送验证码(仅支持邮箱)
|
||
/// type: 1=登录, 2=注册, 3=重置密码
|
||
Future<Either<HttpError, bool>> kr_sendCode(String email, int type) async {
|
||
final Map<String, dynamic> data = <String, dynamic>{};
|
||
data['email'] = email;
|
||
data['type'] = type;
|
||
|
||
BaseResponse<dynamic> baseResponse = await HttpUtil.getInstance()
|
||
.request<dynamic>(Api.kr_sendCode, data,
|
||
method: HttpMethod.POST, isShowLoading: true);
|
||
if (!baseResponse.isSuccess) {
|
||
return left(
|
||
HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
|
||
}
|
||
|
||
return right(true);
|
||
}
|
||
|
||
/// 删除账号
|
||
Future<Either<HttpError, String>> kr_deleteAccount(String code) async {
|
||
final Map<String, dynamic> data = <String, dynamic>{};
|
||
data['code'] = code;
|
||
|
||
BaseResponse<dynamic> baseResponse = await HttpUtil.getInstance()
|
||
.request<dynamic>(Api.kr_deleteAccount, data,
|
||
method: HttpMethod.DELETE, isShowLoading: true);
|
||
if (!baseResponse.isSuccess) {
|
||
return left(
|
||
HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
|
||
}
|
||
|
||
return right("");
|
||
}
|
||
|
||
/// 忘记密码-设置新密码(仅支持邮箱)
|
||
Future<Either<HttpError, String>> kr_setNewPsdByForgetPsd(
|
||
String email, String code, String password) async {
|
||
final Map<String, dynamic> data = <String, dynamic>{};
|
||
data['email'] = email;
|
||
data['password'] = password;
|
||
data["code"] = code;
|
||
data["identifier"] = KRDeviceInfoService().deviceId ?? 'unknown';
|
||
|
||
BaseResponse<KRLoginData> baseResponse = await HttpUtil.getInstance()
|
||
.request<KRLoginData>(Api.kr_setNewPsdByForgetPsd, data,
|
||
method: HttpMethod.POST, isShowLoading: true);
|
||
if (!baseResponse.isSuccess) {
|
||
return left(
|
||
HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
|
||
}
|
||
|
||
return right(baseResponse.model.kr_token.toString());
|
||
}
|
||
|
||
/// 设备登录(游客登录)
|
||
Future<Either<HttpError, String>> kr_deviceLogin() async {
|
||
try {
|
||
KRLogUtil.kr_i('🔐 开始设备登录', tag: 'KRAuthApi');
|
||
|
||
// 获取设备信息
|
||
final deviceInfoService = KRDeviceInfoService();
|
||
final deviceId = deviceInfoService.deviceId;
|
||
final userAgent = deviceInfoService.getUserAgent();
|
||
|
||
if (deviceId == null) {
|
||
print('❌ 设备ID为空,无法登录');
|
||
return left(HttpError(msg: '设备ID获取失败', code: -1));
|
||
}
|
||
|
||
print('📱 设备ID: $deviceId');
|
||
print('📱 User-Agent: $userAgent');
|
||
KRLogUtil.kr_i('📱 设备ID: $deviceId', tag: 'KRAuthApi');
|
||
KRLogUtil.kr_i('📱 User-Agent: $userAgent', tag: 'KRAuthApi');
|
||
|
||
// 构建请求数据
|
||
Map<String, dynamic> data = {
|
||
'identifier': deviceId,
|
||
'user_agent': userAgent,
|
||
};
|
||
|
||
print('📤 原始请求数据: $data');
|
||
|
||
// 检查是否需要加密
|
||
final siteConfigService = KRSiteConfigService();
|
||
final needEncryption = siteConfigService.isDeviceSecurityEnabled();
|
||
|
||
print('🔒 是否需要加密: $needEncryption');
|
||
KRLogUtil.kr_i('🔒 是否需要加密: $needEncryption', tag: 'KRAuthApi');
|
||
|
||
String? requestBody;
|
||
if (needEncryption) {
|
||
// 加密请求数据
|
||
print('🔐 加密请求数据...');
|
||
final encrypted = KRAesUtil.encryptJson(data, AppConfig.kr_encryptionKey);
|
||
requestBody = '{"data":"${encrypted['data']}","time":"${encrypted['time']}"}';
|
||
print('🔐 加密后请求体: $requestBody');
|
||
KRLogUtil.kr_i('🔐 加密后请求体', tag: 'KRAuthApi');
|
||
} else {
|
||
// 使用明文
|
||
requestBody = jsonEncode(data);
|
||
print('📝 明文请求体: $requestBody');
|
||
}
|
||
|
||
// 使用 Dio 直接发送请求(因为需要特殊的加密处理)
|
||
final dioInstance = dio.Dio();
|
||
final baseUrl = AppConfig.getInstance().baseUrl;
|
||
final url = '$baseUrl${Api.kr_deviceLogin}';
|
||
|
||
print('📤 请求URL: $url');
|
||
KRLogUtil.kr_i('📤 请求URL: $url', tag: 'KRAuthApi');
|
||
|
||
// 设置请求头
|
||
final headers = <String, String>{
|
||
'Content-Type': 'application/json',
|
||
};
|
||
|
||
if (needEncryption) {
|
||
headers['Login-Type'] = 'device';
|
||
}
|
||
|
||
print('📤 请求头: $headers');
|
||
|
||
// 配置Dio实例的超时设置
|
||
dioInstance.options.connectTimeout = const Duration(seconds: 10);
|
||
dioInstance.options.sendTimeout = const Duration(seconds: 10);
|
||
dioInstance.options.receiveTimeout = const Duration(seconds: 10);
|
||
|
||
final response = await dioInstance.post(
|
||
url,
|
||
data: requestBody,
|
||
options: dio.Options(
|
||
headers: headers,
|
||
),
|
||
);
|
||
|
||
print('📥 响应状态码: ${response.statusCode}');
|
||
print('📥 响应数据: ${response.data}');
|
||
KRLogUtil.kr_i('📥 响应状态码: ${response.statusCode}', tag: 'KRAuthApi');
|
||
KRLogUtil.kr_i('📥 响应数据: ${response.data}', tag: 'KRAuthApi');
|
||
|
||
if (response.statusCode == 200) {
|
||
Map<String, dynamic> responseData = response.data as Map<String, dynamic>;
|
||
|
||
// 检查是否需要解密响应
|
||
if (needEncryption && responseData.containsKey('data')) {
|
||
final dataField = responseData['data'];
|
||
if (dataField is Map<String, dynamic> &&
|
||
dataField.containsKey('data') &&
|
||
dataField.containsKey('time')) {
|
||
print('🔓 解密响应数据...');
|
||
final decrypted = KRAesUtil.decryptJson(
|
||
dataField['data'] as String,
|
||
dataField['time'] as String,
|
||
AppConfig.kr_encryptionKey,
|
||
);
|
||
responseData['data'] = decrypted;
|
||
print('🔓 解密后数据: ${responseData['data']}');
|
||
KRLogUtil.kr_i('🔓 解密成功', tag: 'KRAuthApi');
|
||
}
|
||
}
|
||
|
||
if (responseData['code'] == 200) {
|
||
final token = responseData['data']['token'] as String;
|
||
print('✅ 设备登录成功');
|
||
print('🎫 Token: ${token.substring(0, min(20, token.length))}...');
|
||
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
KRLogUtil.kr_i('✅ 设备登录成功', tag: 'KRAuthApi');
|
||
return right(token);
|
||
} else {
|
||
final msg = responseData['msg'] ?? '登录失败';
|
||
print('❌ 登录失败: $msg');
|
||
return left(HttpError(msg: msg, code: responseData['code']));
|
||
}
|
||
} else {
|
||
print('❌ HTTP错误: ${response.statusCode}');
|
||
return left(HttpError(msg: 'HTTP错误', code: response.statusCode ?? -1));
|
||
}
|
||
} on dio.DioException catch (e) {
|
||
print('❌ Dio异常: ${e.type}');
|
||
print('❌ 错误信息: ${e.message}');
|
||
KRLogUtil.kr_e('❌ 设备登录Dio异常: ${e.message}', tag: 'KRAuthApi');
|
||
return left(HttpError(msg: '网络请求失败: ${e.message}', code: -1));
|
||
} catch (e, stackTrace) {
|
||
print('❌ 设备登录异常: $e');
|
||
print('📚 堆栈跟踪: $stackTrace');
|
||
KRLogUtil.kr_e('❌ 设备登录异常: $e', tag: 'KRAuthApi');
|
||
return left(HttpError(msg: '设备登录失败: $e', code: -1));
|
||
}
|
||
}
|
||
|
||
String _kr_getUserAgent() {
|
||
if (Platform.isAndroid) {
|
||
return 'android';
|
||
} else if (Platform.isIOS) {
|
||
return 'ios';
|
||
} else if (Platform.isMacOS) {
|
||
return 'mac';
|
||
} else if (Platform.isWindows) {
|
||
return 'windows';
|
||
} else if (Platform.isLinux) {
|
||
return 'linux';
|
||
} else if (Platform.isFuchsia) {
|
||
return 'harmony';
|
||
} else {
|
||
return 'unknown';
|
||
}
|
||
}
|
||
}
|