import 'dart:convert'; import 'dart:math'; import 'package:crypto/crypto.dart'; import 'package:dio/dio.dart'; import 'package:encrypt/encrypt.dart'; import '../common/constants.dart'; import '../models/login/index.dart'; import '../utils/login.dart'; import '../utils/utils.dart'; import 'index.dart'; class LoginHttp { static String deviceId = LoginUtils.genDeviceId(); static String buvid = LoginUtils.buvid(); static String host = 'passport.bilibili.com'; static Map headers = { 'Host': host, 'buvid': buvid, 'env': 'prod', 'app-key': 'android_hd', 'user-agent': Constants.userAgent, 'x-bili-trace-id': Constants.traceId, 'x-bili-aurora-eid': '', 'x-bili-aurora-zone': '', 'bili-http-engine': 'cronet', 'content-type': 'application/x-www-form-urlencoded; charset=utf-8', }; static Future> getHDcode() async { var params = { 'appkey': Constants.appKey, // 'local_id': 'Y952A395BB157D305D8A8340FC2AAECECE17', 'local_id': '0', //精确到秒的时间戳 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), 'platform': 'android', 'mobi_app': 'android_hd', }; String sign = Utils.appSign( params, Constants.appKey, Constants.appSec, ); var res = await Request() .post(Api.getTVCode, queryParameters: {...params, 'sign': sign}); print(res); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { return {'status': false, 'msg': res.data['message']}; } } static Future codePoll(String authCode) async { var params = { 'appkey': Constants.appKey, 'auth_code': authCode, 'local_id': '0', 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), }; String sign = Utils.appSign( params, Constants.appKey, Constants.appSec, ); var res = await Request() .post(Api.qrcodePoll, queryParameters: {...params, 'sign': sign}); return { 'status': res.data['code'] == 0, 'code': res.data['code'], 'data': res.data['data'], 'msg': res.data['message'] }; } static Future queryCaptcha() async { var res = await Request().get(Api.getCaptcha); if (res.data['code'] == 0) { return { 'status': true, 'data': CaptchaDataModel.fromJson(res.data['data']), }; } else { return {'status': false, 'data': res.message}; } } // 获取salt与PubKey static Future getWebKey() async { var res = await Request().get(Api.getWebKey); //data: {'disable_rcmd': 0, 'local_id': LoginUtils.generateBuvid()}); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { return {'status': false, 'data': {}, 'msg': res.data['message']}; } } static Future sendSmsCode({ required String cid, required String tel, // String? deviceTouristId, String? gee_challenge, String? gee_seccode, String? gee_validate, String? recaptcha_token, }) async { int timestamp = DateTime.now().millisecondsSinceEpoch; var data = { 'appkey': Constants.appKey, 'build': '1462100', 'buvid': buvid, 'c_locale': 'zh_CN', 'cid': cid, // if (deviceTouristId != null) 'device_tourist_id': deviceTouristId, 'disable_rcmd': '0', if (gee_challenge != null) 'gee_challenge': gee_challenge, if (gee_seccode != null) 'gee_seccode': gee_seccode, if (gee_validate != null) 'gee_validate': gee_validate, 'local_id': buvid, // https://chinggg.github.io/post/appre/ 'login_session_id': md5.convert(utf8.encode(buvid + timestamp.toString())).toString(), 'mobi_app': 'android_hd', 'platform': 'android', if (recaptcha_token != null) 'recaptcha_token': recaptcha_token, 's_locale': 'zh_CN', 'statistics': Constants.statistics, 'tel': tel, 'ts': (timestamp ~/ 1000).toString(), }; String sign = Utils.appSign( data, Constants.appKey, Constants.appSec, ); var res = await Request().post( Api.appSmsCode, data: {...data, 'sign': sign}, options: Options( contentType: Headers.formUrlEncodedContentType, headers: headers, ), ); print(res); if (res.data['code'] == 0 && res.data['data']['recaptcha_url'] == "") { return {'status': true, 'data': res.data['data']}; } else { return { 'status': false, 'code': res.data['code'], 'msg': res.data['message'], 'data': res.data['data'] }; } } // static Future getGuestId(String key) async { // dynamic publicKey = RSAKeyParser().parse(key); // var params = { // 'appkey': Constants.appKey, // 'build': '1462100', // 'buvid': buvid, // 'c_locale': 'zh_CN', // 'channel': 'yingyongbao', // 'deviceInfo': 'xxxxxx', // 'disable_rcmd': '0', // 'dt': Uri.encodeComponent(Encrypter(RSA(publicKey: publicKey)) // .encrypt(generateRandomString(16)) // .base64), // 'local_id': buvid, // 'mobi_app': 'android_hd', // 'platform': 'android', // 's_locale': 'zh_CN', // 'statistics': Constants.statistics, // 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), // }; // String sign = Utils.appSign( // params, // Constants.appKey, // Constants.appSec, // ); // var res = await Request().post(Api.getGuestId, // queryParameters: {...params, 'sign': sign}, // options: Options( // contentType: Headers.formUrlEncodedContentType, // headers: headers, // )); // print("getGuestId: $res"); // if (res.data['code'] == 0) { // return {'status': true, 'data': res.data['data']}; // } else { // return {'status': false, 'msg': res.data['message']}; // } // } // app端密码登录 static Future loginByPwd({ required String username, required String password, required String key, required String salt, String? gee_challenge, String? gee_seccode, String? gee_validate, String? recaptcha_token, }) async { dynamic publicKey = RSAKeyParser().parse(key); print(publicKey); String passwordEncrypted = Encrypter(RSA(publicKey: publicKey)).encrypt(salt + password).base64; Map data = { 'appkey': Constants.appKey, 'bili_local_id': deviceId, 'build': '1462100', 'buvid': buvid, 'c_locale': 'zh_CN', 'channel': 'yingyongbao', 'device': 'phone', 'device_id': deviceId, //'device_meta': '', 'device_name': 'vivo', 'device_platform': 'Android14vivo', 'disable_rcmd': '0', 'dt': Uri.encodeComponent(Encrypter(RSA(publicKey: publicKey)) .encrypt(LoginUtils.generateRandomString(16)) .base64), 'from_pv': 'main.homepage.avatar-nologin.all.click', 'from_url': Uri.encodeComponent('bilibili://pegasus/promo'), if (gee_challenge != null) 'gee_challenge': gee_challenge, if (gee_seccode != null) 'gee_seccode': gee_seccode, if (gee_validate != null) 'gee_validate': gee_validate, 'local_id': buvid, //LoginUtils.generateBuvid(), 'mobi_app': 'android_hd', 'password': passwordEncrypted, 'permission': 'ALL', 'platform': 'android', if (recaptcha_token != null) 'recaptcha_token': recaptcha_token, 's_locale': 'zh_CN', 'statistics': Constants.statistics, 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), 'username': username, }; String sign = Utils.appSign( data, Constants.appKey, Constants.appSec, ); data['sign'] = sign; data.map((key, value) { print('$key: $value'); return MapEntry(key, value); }); var res = await Request().post( Api.loginByPwdApi, data: data, options: Options( contentType: Headers.formUrlEncodedContentType, headers: headers, //responseType: ResponseType.plain ), ); print(res); if (res.data['code'] == 0) { return { 'status': true, 'data': res.data['data'], 'msg': res.data['message'], }; } else { return { 'status': false, 'code': res.data['code'], 'msg': res.data['message'], 'data': res.data['data'] }; } } // app端短信验证码登录 static Future loginBySms({ required String captchaKey, required String tel, required String code, required String cid, required String key, }) async { dynamic publicKey = RSAKeyParser().parse(key); Map data = { 'appkey': Constants.appKey, 'bili_local_id': deviceId, 'build': '1462100', 'buvid': buvid, 'c_locale': 'zh_CN', 'captcha_key': captchaKey, 'channel': 'yingyongbao', 'cid': cid, 'code': code, 'device': 'phone', 'device_id': deviceId, //'device_meta': '', 'device_name': 'vivo', 'device_platform': 'Android14vivo', // 'device_tourist_id': '', 'disable_rcmd': '0', 'dt': Uri.encodeComponent(Encrypter(RSA(publicKey: publicKey)) .encrypt(LoginUtils.generateRandomString(16)) .base64), 'from_pv': 'main.my-information.my-login.0.click', 'from_url': Uri.encodeComponent('bilibili://user_center/mine'), 'local_id': buvid, 'mobi_app': 'android_hd', 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statistics, 'tel': tel, 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), }; String sign = Utils.appSign( data, Constants.appKey, Constants.appSec, ); data['sign'] = sign; data.map((key, value) { print('$key: $value'); return MapEntry(key, value); }); var res = await Request().post( Api.logInByAppSms, data: data, options: Options( contentType: Headers.formUrlEncodedContentType, headers: headers, //responseType: ResponseType.plain ), ); print(res); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { return { 'status': false, 'code': res.data['code'], 'msg': res.data['message'], 'data': res.data['data'] }; } } // 密码登录时风控验证手机 static Future safeCenterGetInfo({ required String tmpCode, }) async { var res = await Request().get(Api.safeCenterGetInfo, data: { 'tmp_code': tmpCode, }); print(res); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { return { 'status': false, 'code': res.data['code'], 'msg': res.data['message'], 'data': res.data['data'] }; } } // 风控验证手机前的验证码 static Future preCapture() async { var res = await Request().post(Api.preCapture); print(res); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { return { 'status': false, 'code': res.data['code'], 'msg': res.data['message'], 'data': res.data['data'] }; } } // 风控验证手机 static Future safeCenterSmsCode({ String? smsType, required String tmpCode, required String geeChallenge, required String geeSeccode, required String geeValidate, required String recaptchaToken, }) async { var res = await Request().post(Api.safeCenterSmsCode, data: { 'sms_type': smsType ?? 'loginTelCheck', 'tmp_code': tmpCode, 'gee_challenge': geeChallenge, 'gee_seccode': geeSeccode, 'gee_validate': geeValidate, 'recaptcha_token': recaptchaToken, }); print(res); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { return { 'status': false, 'code': res.data['code'], 'msg': res.data['message'], 'data': res.data['data'] }; } } static Future safeCenterSmsVerify( {String? type, required String code, required String tmpCode, required String requestId, required String source, required String captchaKey}) async { var res = await Request().post(Api.safeCenterSmsVerify, data: { 'type': type ?? 'loginTelCheck', 'code': code, 'tmp_code': tmpCode, 'request_id': requestId, 'source': source, 'captcha_key': captchaKey, }); print(res); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { return { 'status': false, 'code': res.data['code'], 'msg': res.data['message'], 'data': res.data['data'] }; } } }