fix: mob geetest (#2341)

* fix: mob geetest

* geetest ios patch

---------

Co-authored-by: dom <githubaccount56556@proton.me>
This commit is contained in:
My-Responsitories
2026-06-07 02:54:44 +00:00
committed by GitHub
parent 3b9403a329
commit b67756c152
13 changed files with 222 additions and 265 deletions

View File

@@ -19,7 +19,6 @@ 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 {
@@ -34,8 +33,6 @@ 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;
@@ -125,115 +122,19 @@ class LoginPageController extends GetxController
String geeChallenge,
VoidCallback onSuccess,
) {
void updateCaptchaData(Map json) {
captchaData
..validate = json['geetest_validate']
..seccode = json['geetest_seccode']
..geetest = GeetestData(
challenge: json['geetest_challenge'],
gt: geeGt,
);
SmartDialog.showToast('验证成功');
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);
}
GeetestWebviewDialog.geetest(geeGt, geeChallenge).then((res) {
if (res is Map) {
captchaData
..validate = res['geetest_validate']
..seccode = res['geetest_seccode']
..geetest = GeetestData(
challenge: res['geetest_challenge'],
gt: geeGt,
);
SmartDialog.showToast('验证成功');
onSuccess();
}
});
}
static String validateCookie(String cookie) {

View File

@@ -1,5 +1,5 @@
import 'dart:convert' show jsonDecode, jsonEncode;
import 'dart:io' show Platform, Directory, File;
import 'dart:convert' show base64, jsonDecode, jsonEncode, utf8;
import 'dart:io' show Platform;
import 'package:PiliPlus/http/browser_ua.dart';
import 'package:PiliPlus/http/init.dart';
@@ -20,6 +20,13 @@ class GeetestWebviewDialog extends StatefulWidget {
@override
State<GeetestWebviewDialog> createState() => _GeetestWebviewDialogState();
static Future geetest(String gt, String challenge) {
return showDialog(
context: Get.context!,
builder: (context) => GeetestWebviewDialog(gt, challenge),
);
}
}
class _GeetestWebviewDialogState extends State<GeetestWebviewDialog> {
@@ -30,6 +37,9 @@ class _GeetestWebviewDialogState extends State<GeetestWebviewDialog> {
Webview? _linuxWebview;
late bool _linuxWebviewLoading = true;
String _showJs(String response) =>
't=Geetest($response).onSuccess(()=>R("success",t.getValidate())).onError(o=>R("error",o)).onClose(o=>R("close",o));t.onReady(()=>t.verify())';
@override
void initState() {
super.initState();
@@ -122,6 +132,8 @@ class _GeetestWebviewDialogState extends State<GeetestWebviewDialog> {
}
} else if (msgStr.startsWith("error:")) {
debugPrint('geetest error: $msgStr');
} else if (msgStr.startsWith('close:')) {
Get.back();
}
});
@@ -136,27 +148,15 @@ class _GeetestWebviewDialogState extends State<GeetestWebviewDialog> {
<!DOCTYPE html><html><head></head><body>
<script src="$_geetestJsUri"></script>
<script>
function R(n,o){
window.webkit.messageHandlers.msgToNative.postMessage(n + ':' + JSON.stringify(o));
}
let t=Geetest($response).onSuccess(()=>R("success",t.getValidate())).onError((o)=>R("error",o));
t.onReady(()=>t.verify());
R=(n,o)=>webkit.messageHandlers.msgToNative.postMessage(n+':'+JSON.stringify(o))
${_showJs(response)}
</script>
</body></html>
''';
final tempDir = Directory.systemTemp;
final file = File(
'${tempDir.path}/geetest_${DateTime.now().millisecondsSinceEpoch}.html',
_linuxWebview!.launch(
'data:text/html;base64,${base64.encode(utf8.encode(html))}',
);
await file.writeAsString(html);
if (!mounted) {
_closeLinuxWebview();
return;
}
_linuxWebview!.launch('file://${file.path}');
if (mounted) {
setState(() {
@@ -205,7 +205,7 @@ class _GeetestWebviewDialogState extends State<GeetestWebviewDialog> {
return AlertDialog(
title: const Text('验证码'),
content: SizedBox(
width: 300,
width: 320,
height: 400,
child: InAppWebView(
webViewEnvironment: webViewEnvironment,
@@ -217,11 +217,31 @@ class _GeetestWebviewDialogState extends State<GeetestWebviewDialog> {
algorithmicDarkeningAllowed: true,
useShouldOverrideUrlLoading: true,
userAgent: BrowserUa.mob,
mixedContentMode: MixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW,
mixedContentMode: .MIXED_CONTENT_ALWAYS_ALLOW,
incognito: true,
allowFileAccess: false,
allowsLinkPreview: false,
allowContentAccess: false,
useOnDownloadStart: false,
geolocationEnabled: false,
thirdPartyCookiesEnabled: false,
enterpriseAuthenticationAppLinkPolicyEnabled: false,
saveFormData: false,
safeBrowsingEnabled: false,
isFraudulentWebsiteWarningEnabled: false,
domStorageEnabled: false,
databaseEnabled: false,
cacheEnabled: false,
cacheMode: .LOAD_NO_CACHE,
horizontalScrollBarEnabled: false,
verticalScrollBarEnabled: false,
overScrollMode: .NEVER,
),
initialData: InAppWebViewInitialData(
data:
'<!DOCTYPE html><html><head></head><body><script src="$_geetestJsUri"></script><script>function R(n,o){flutter_inappwebview.callHandler(n,o)}</script></body></html>',
'<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width"></head><body><script src="$_geetestJsUri"></script><script>R=flutter_inappwebview.callHandler</script></body></html>',
),
onWebViewCreated: (ctr) {
ctr
@@ -242,16 +262,17 @@ class _GeetestWebviewDialogState extends State<GeetestWebviewDialog> {
callback: (args) {
debugPrint('geetest error: $args');
},
)
..addJavaScriptHandler(
handlerName: 'close',
callback: (args) => Get.back(),
);
},
onLoadStop: (ctr, _) async {
final config = await _future;
if (!mounted) return;
if (config case Success(:final response)) {
ctr.evaluateJavascript(
source:
'let t=Geetest($response).onSuccess(()=>R("success",t.getValidate())).onError((o)=>R("error",o));t.onReady(()=>t.verify());',
);
ctr.evaluateJavascript(source: _showJs(response));
} else {
config.toast();
Get.back();