Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-05-06 14:14:19 +08:00
parent 1a8c348af1
commit 07843a5e77
239 changed files with 3175 additions and 13237 deletions

View File

@@ -1,7 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:PiliPlus/common/dial_prefix.dart';
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
import 'package:PiliPlus/common/widgets/radio_widget.dart';
import 'package:PiliPlus/http/init.dart';
@@ -15,18 +13,14 @@ import 'package:PiliPlus/utils/accounts/account.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:PiliPlus/utils/theme_utils.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart';
class LoginPageController extends GetxController
with GetSingleTickerProviderStateMixin {
final TextEditingController telTextController = TextEditingController();
final TextEditingController usernameTextController = TextEditingController();
final TextEditingController passwordTextController = TextEditingController();
final TextEditingController smsCodeTextController = TextEditingController();
final TextEditingController cookieTextController = TextEditingController();
late final codeInfo =
@@ -34,27 +28,19 @@ class LoginPageController extends GetxController
late final TabController tabController;
late final Gt3FlutterPlugin captcha = Gt3FlutterPlugin();
late final CaptchaDataModel captchaData = CaptchaDataModel();
late final RxInt qrCodeLeftTime = 180.obs;
late final RxString statusQRCode = ''.obs;
late var selectedCountryCodeId = Login.dialPrefix.first;
late String captchaKey = '';
late final RxInt smsSendCooldown = 0.obs;
late int smsSendTimestamp = 0;
// 定时器
Timer? qrCodeTimer;
Timer? smsSendCooldownTimer;
bool _isReq = false;
@override
void onInit() {
super.onInit();
tabController = TabController(length: 4, vsync: this)
tabController = TabController(length: 3, vsync: this)
..addListener(_handleTabChange);
}
@@ -64,11 +50,8 @@ class LoginPageController extends GetxController
..removeListener(_handleTabChange)
..dispose();
qrCodeTimer?.cancel();
smsSendCooldownTimer?.cancel();
telTextController.dispose();
usernameTextController.dispose();
passwordTextController.dispose();
smsCodeTextController.dispose();
cookieTextController.dispose();
super.onClose();
}
@@ -137,103 +120,14 @@ class LoginPageController extends GetxController
onSuccess();
}
if (PlatformUtils.isDesktop) {
showDialog<Map<String, dynamic>>(
context: Get.context!,
builder: (context) => GeetestWebviewDialog(geeGt, geeChallenge),
).then((res) {
if (res != null) {
updateCaptchaData(res);
}
});
} else {
final registerData = Gt3RegisterData(
challenge: geeChallenge,
gt: geeGt,
success: true,
);
captcha
..addEventHandler(
onShow: (Map<String, dynamic> message) {},
onClose: (Map<String, dynamic> message) {
SmartDialog.showToast('关闭验证');
},
onResult: (Map<String, dynamic> message) {
if (kDebugMode) debugPrint("Captcha result: $message");
final String code = message["code"];
if (code == "1") {
// 发送 message["result"] 中的数据向 B 端的业务服务接口进行查询
updateCaptchaData(message['result']);
} else {
// 终端用户完成验证失败,自动重试 If the verification fails, it will be automatically retried.
if (kDebugMode) debugPrint("Captcha result code : $code");
}
},
onError: (Map<String, dynamic> message) {
SmartDialog.showToast("Captcha onError: $message");
String code = message["code"];
// 处理验证中返回的错误 Handling errors returned in verification
if (Platform.isAndroid) {
// Android 平台
if (code == "-2") {
// Dart 调用异常 Call exception
} else if (code == "-1") {
// Gt3RegisterData 参数不合法 Parameter is invalid
} else if (code == "201") {
// 网络无法访问 Network inaccessible
} else if (code == "202") {
// Json 解析错误 Analysis error
} else if (code == "204") {
// WebView 加载超时,请检查是否混淆极验 SDK Load timed out
} else if (code == "204_1") {
// WebView 加载前端页面错误,请查看日志 Error loading front-end page, please check the log
} else if (code == "204_2") {
// WebView 加载 SSLError
} else if (code == "206") {
// gettype 接口错误或返回为 null API error or return null
} else if (code == "207") {
// getphp 接口错误或返回为 null API error or return null
} else if (code == "208") {
// ajax 接口错误或返回为 null API error or return null
} else {
// 更多错误码参考开发文档 More error codes refer to the development document
// https://docs.geetest.com/sensebot/apirefer/errorcode/android
}
}
if (Platform.isIOS) {
// iOS 平台
if (code == "-1009") {
// 网络无法访问 Network inaccessible
} else if (code == "-1004") {
// 无法查找到 HOST Unable to find HOST
} else if (code == "-1002") {
// 非法的 URL Illegal URL
} else if (code == "-1001") {
// 网络超时 Network timeout
} else if (code == "-999") {
// 请求被意外中断, 一般由用户进行取消操作导致 The interrupted request was usually caused by the user cancelling the operation
} else if (code == "-21") {
// 使用了重复的 challenge Duplicate challenges are used
// 检查获取 challenge 是否进行了缓存 Check if the fetch challenge is cached
} else if (code == "-20") {
// 尝试过多, 重新引导用户触发验证即可 Try too many times, lead the user to request verification again
} else if (code == "-10") {
// 预判断时被封禁, 不会再进行图形验证 Banned during pre-judgment, and no more image captcha verification
} else if (code == "-2") {
// Dart 调用异常 Call exception
} else if (code == "-1") {
// Gt3RegisterData 参数不合法 Parameter is invalid
} else {
// 更多错误码参考开发文档 More error codes refer to the development document
// https://docs.geetest.com/sensebot/apirefer/errorcode/ios
}
}
},
)
..startCaptcha(registerData);
}
showDialog<Map<String, dynamic>>(
context: Get.context!,
builder: (context) => GeetestWebviewDialog(geeGt, geeChallenge),
).then((res) {
if (res != null) {
updateCaptchaData(res);
}
});
}
// cookie登录
@@ -536,167 +430,6 @@ class LoginPageController extends GetxController
// }
}
// 短信验证码登录
Future<void> loginBySmsCode() async {
if (telTextController.text.isEmpty) {
SmartDialog.showToast('手机号不能为空');
return;
}
if (captchaKey.isEmpty) {
SmartDialog.showToast('请先点击获取验证码');
return;
}
if (smsCodeTextController.text.isEmpty) {
SmartDialog.showToast('验证码不能为空');
return;
}
if (DateTime.now().millisecondsSinceEpoch - smsSendTimestamp >
1000 * 60 * 5) {
SmartDialog.showToast('验证码已过期,请重新获取');
return;
}
final webKeyRes = await LoginHttp.getWebKey();
if (!webKeyRes['status']) {
SmartDialog.showToast(webKeyRes['msg']);
return;
}
String key = webKeyRes['data']['key'];
final res = await LoginHttp.loginBySms(
tel: telTextController.text,
code: smsCodeTextController.text,
captchaKey: captchaKey,
cid: selectedCountryCodeId.countryId,
key: key,
);
if (res['status']) {
SmartDialog.showToast('登录成功');
final data = res['data'];
await setAccount(data['token_info'], data['cookie_info']['cookies']);
Get.back();
} else {
SmartDialog.showToast(res['msg']);
}
}
// app端验证码
Future<void> sendSmsCode() async {
if (telTextController.text.isEmpty) {
SmartDialog.showToast('手机号不能为空');
return;
}
// String? guestId;
// final webKeyRes = await LoginHttp.getWebKey();
// if (!webKeyRes['status']) {
// SmartDialog.showToast(webKeyRes['msg']);
// } else {
// String key = webKeyRes['data']['key'];
// final guestIdRes = await LoginHttp.getGuestId(key);
// if (!guestIdRes['status']) {
// SmartDialog.showToast(guestIdRes['msg']);
// } else {
// guestId = guestIdRes['data']['guest_id'];
// }
// }
// final preCaptureRes = await LoginHttp.preCapture();
// if (!preCaptureRes['status']) {
// SmartDialog.showToast("获取验证码失败,请尝试其它登录方式\n"
// "(${preCaptureRes['code']}) ${preCaptureRes['msg']}");
// return;
// }
// String geeGt = preCaptureRes['data']['gee_gt']!;
// String geeChallenge = preCaptureRes['data']['gee_challenge'];
// captchaData.token = preCaptureRes['data']['recaptcha_token']!;
// getCaptcha(geeGt, geeChallenge, () async {
// final safeCenterSendSmsCodeRes =
// await LoginHttp.safeCenterSmsCode(
// tmpCode: currentUri.queryParameters['tmp_token']!,
// geeChallenge: geeChallenge,
// geeSeccode: captchaData.seccode!,
// geeValidate: captchaData.validate!,
// recaptchaToken: captchaData.token!,
// refererUrl: url,
// );
// if (!safeCenterSendSmsCodeRes['status']) {
// SmartDialog.showToast("发送短信验证码失败,请尝试其它登录方式\n"
// "(${safeCenterSendSmsCodeRes['code']}) ${safeCenterSendSmsCodeRes['msg']}");
// return;
// }
// SmartDialog.showToast("短信验证码已发送,请查收");
// captchaKey = safeCenterSendSmsCodeRes['data']['captcha_key'];
final res = await LoginHttp.sendSmsCode(
tel: telTextController.text,
cid: selectedCountryCodeId.countryId,
// deviceTouristId: guestId,
geeValidate: captchaData.validate,
geeSeccode: captchaData.seccode,
geeChallenge: captchaData.geetest?.challenge,
recaptchaToken: captchaData.token,
);
if (res['status']) {
SmartDialog.showToast('发送成功');
smsSendTimestamp = DateTime.now().millisecondsSinceEpoch;
smsSendCooldown.value = 60;
captchaKey = res['data']['captcha_key'];
smsSendCooldownTimer = Timer.periodic(const Duration(seconds: 1), (
timer,
) {
smsSendCooldown.value = 60 - timer.tick;
if (smsSendCooldown <= 0) {
smsSendCooldownTimer?.cancel();
smsSendCooldown.value = 0;
}
});
} else {
// handle login result
switch (res['code']) {
case 0:
case -105:
String? captureUrl = res['data']?['recaptcha_url'];
String? geeGt;
String? geeChallenge;
if (captureUrl != null && captureUrl.isNotEmpty) {
Uri captureUri = Uri.parse(captureUrl);
captchaData.token = captureUri.queryParameters['recaptcha_token'];
geeGt = captureUri.queryParameters['gee_gt'];
geeChallenge = captureUri.queryParameters['gee_challenge'];
}
if (!isGeeArgumentValid(geeGt, geeChallenge)) {
if (kDebugMode) {
debugPrint(
'验证信息错误:${res["msg"]}\n返回内容:${res["data"]},尝试另一个验证码接口',
);
}
final preCaptureRes = await LoginHttp.preCapture();
if (!preCaptureRes['status'] || preCaptureRes['data'] == null) {
SmartDialog.showToast(
"获取验证码失败,请尝试其它登录方式\n"
"(${preCaptureRes['code']}) ${preCaptureRes['msg']} ${preCaptureRes['data']}",
);
return;
}
geeGt = preCaptureRes['data']['gee_gt'];
geeChallenge = preCaptureRes['data']['gee_challenge'];
captchaData.token = preCaptureRes['data']['recaptcha_token'];
}
if (!isGeeArgumentValid(geeGt, geeChallenge)) {
SmartDialog.showToast("获取验证码失败,请尝试其它登录方式\n");
return;
}
getCaptcha(geeGt!, geeChallenge!, sendSmsCode);
break;
default:
SmartDialog.showToast(res['msg']);
break;
}
}
}
bool isGeeArgumentValid(String? geeGt, String? geeChallenge) {
return geeGt?.isNotEmpty == true &&
geeChallenge?.isNotEmpty == true &&