基础库
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 

327 рядки
9.6 KiB

  1. import 'package:dio/dio.dart';
  2. import 'package:dio/adapter.dart';
  3. import 'dart:io';
  4. import 'dart:ui';
  5. import 'dart:convert';
  6. import 'package:convert/convert.dart';
  7. import 'package:crypto/crypto.dart';
  8. import 'package:zhiying_comm/zhiying_comm.dart';
  9. import 'package:package_info/package_info.dart';
  10. import 'package:device_info/device_info.dart';
  11. import 'package:fluttertoast/fluttertoast.dart';
  12. typedef OnSuccess = dynamic Function(dynamic data);
  13. typedef OnError = dynamic Function(String e);
  14. class NetUtil {
  15. static final String APPKEY = "123";
  16. Dio _dio;
  17. static String _apiVersion;
  18. NetUtil._() {}
  19. static NetUtil _instance;
  20. static NetUtil getInstance() {
  21. if (_instance == null) {
  22. _instance = NetUtil._();
  23. }
  24. return _instance;
  25. }
  26. get dio async {
  27. if (_dio == null) {
  28. var setting = await NativeUtil.getSetting();
  29. String domain = setting['domain']; //'http://www.hairuyi.com/';
  30. String version = setting['version']; //'42';
  31. _config(domain, apiVersion: _apiVersion);
  32. }
  33. return _dio;
  34. }
  35. // 配置网络请求,基础地址,代理地址,如:192.168.0.123:8888(代理地址生产环境无效)
  36. // apiVersion 接口版本
  37. void _config(String baseUrl, {String proxyUrl, String apiVersion}) {
  38. _dio = Dio(BaseOptions(
  39. method: "post",
  40. baseUrl: baseUrl,
  41. connectTimeout: 15000,
  42. receiveTimeout: 15000,
  43. contentType: Headers.formUrlEncodedContentType,
  44. followRedirects: true));
  45. _dio.interceptors.add(_NetInterceptors());
  46. _apiVersion = apiVersion;
  47. const bool inProduction = const bool.fromEnvironment("dart.vm.product");
  48. if (proxyUrl != null && proxyUrl != '' && !inProduction) {
  49. _setProxy(proxyUrl);
  50. }
  51. }
  52. void _setProxy(String proxyUrl) {
  53. (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
  54. (HttpClient client) {
  55. client.findProxy = (uri) {
  56. return "PROXY $proxyUrl";
  57. };
  58. client.badCertificateCallback =
  59. (X509Certificate cert, String host, int port) => true;
  60. };
  61. }
  62. /// 统一添加必要的参数
  63. static Future<Map<String, dynamic>> signParams(
  64. Map<String, dynamic> params) async {
  65. if (_apiVersion != null) {
  66. params["version"] = _apiVersion;
  67. }
  68. if (Platform.isIOS) {
  69. params["platform"] = "iOS";
  70. DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
  71. IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
  72. params["systemVersion"] = iosInfo.systemVersion;
  73. } else if (Platform.isAndroid) {
  74. params["platform"] = "Android";
  75. DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
  76. AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
  77. String androidVersion = androidInfo.version.release;
  78. params["systemVersion"] = "Android $androidVersion";
  79. }
  80. PackageInfo packageInfo = await PackageInfo.fromPlatform();
  81. String version = packageInfo.version; //版本号
  82. params["appVersion"] = version;
  83. int width = window.physicalSize.width.floor();
  84. int height = window.physicalSize.height.floor();
  85. params["resolutionRatio"] = "$width*$height";
  86. String token = await NativeUtil.getToken();
  87. if (token != null &&
  88. token != '' &&
  89. (!params.containsKey('token') || params['token'] == '')) {
  90. params['token'] = token;
  91. }
  92. params["time"] = getNowTime();
  93. // 过滤空字段,过滤首尾空格
  94. Map<String, dynamic> filters = Map<String, dynamic>();
  95. params.forEach((key, value) {
  96. if (key != '' && value != '') {
  97. filters[key] = (value is String) ? value.trim() : value;
  98. }
  99. });
  100. params = filters;
  101. List<String> list = List<String>();
  102. params.forEach((key, value) {
  103. list.add(key.toString() + value.toString());
  104. });
  105. params["sign"] = signWithArray(list);
  106. return params;
  107. }
  108. /// 签名
  109. static String signWithArray(List<String> params) {
  110. params.sort();
  111. String result = "";
  112. result += APPKEY;
  113. params.forEach((param) {
  114. result += param;
  115. });
  116. result += APPKEY;
  117. return generateMd5(result);
  118. }
  119. // md5 加密
  120. static String generateMd5(String data) {
  121. var content = new Utf8Encoder().convert(data);
  122. var digest = md5.convert(content);
  123. // 这里其实就是 digest.toString()
  124. return hex.encode(digest.bytes);
  125. }
  126. /// 获取时间戳,单位:秒
  127. static String getNowTime() {
  128. int timestamp = (DateTime.now().millisecondsSinceEpoch / 1000).floor();
  129. return "$timestamp";
  130. }
  131. @Deprecated('方法弃用,建议使用 NetUtil.requet')
  132. static Future<dynamic> post(String path,
  133. {Map<String, dynamic> params}) async {
  134. if (params == null) {
  135. params = {};
  136. }
  137. Map<String, dynamic> sign = await signParams(params);
  138. Response response;
  139. try {
  140. Dio dio = await NetUtil.getInstance().dio;
  141. response = await dio.post(path, data: sign);
  142. } on DioError catch (e) {
  143. _formatError(e);
  144. }
  145. if (response == null) {
  146. return {};
  147. }
  148. if (response.statusCode != 200) {
  149. const bool inProduction = const bool.fromEnvironment("dart.vm.product");
  150. if (!inProduction) {
  151. Fluttertoast.showToast(msg: response.statusMessage);
  152. }
  153. // log.e(response.statusMessage);
  154. return {};
  155. }
  156. var result = jsonDecode(response.data);
  157. if (result['success'] == 0 || result['success'] == '0') {
  158. print('error: ' + result['msg']);
  159. Fluttertoast.showToast(
  160. msg: result['msg'],
  161. toastLength: Toast.LENGTH_SHORT,
  162. gravity: ToastGravity.BOTTOM,
  163. );
  164. return {};
  165. }
  166. return result['data'];
  167. }
  168. static Future<dynamic> post2(String path,
  169. {Map<String, dynamic> params}) async {
  170. // if (params == null) {
  171. // params = {};
  172. // }
  173. // Map<String, dynamic> sign = await signParams(params);
  174. // Response response;
  175. // try {
  176. // Dio dio = await NetUtil.getInstance().dio;
  177. // response = await dio.post(path, data: sign);
  178. // } on DioError catch (e) {
  179. // _formatError(e);
  180. // }
  181. // if (response == null) {
  182. // return {};
  183. // }
  184. // if (response.statusCode != 200) {
  185. // const bool inProduction = const bool.fromEnvironment("dart.vm.product");
  186. // if (!inProduction) {
  187. // Fluttertoast.showToast(msg: response.statusMessage);
  188. // }
  189. // log.e(response.statusMessage);
  190. // return {};
  191. // }
  192. // var result = jsonDecode(response.data);
  193. // if (result['success'] == 0 || result['success'] == '0') {
  194. // print('error: ' + result['msg']);
  195. // Fluttertoast.showToast(
  196. // msg: result['msg'],
  197. // toastLength: Toast.LENGTH_SHORT,
  198. // gravity: ToastGravity.BOTTOM,
  199. // );
  200. // return result;
  201. // }
  202. // return result['data'];
  203. }
  204. /*
  205. * error统一处理
  206. */
  207. static void _formatError(DioError e) {
  208. // if (e.type == DioErrorType.CONNECT_TIMEOUT) {
  209. // log.d('连接超时: ${e.toString()}');
  210. // } else if (e.type == DioErrorType.SEND_TIMEOUT) {
  211. // log.d('请求超时: ${e.toString()}');
  212. // } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
  213. // log.d('响应超时: ${e.toString()}');
  214. // } else if (e.type == DioErrorType.RESPONSE) {
  215. // log.d('出现异常: ${e.toString()}');
  216. // } else if (e.type == DioErrorType.CANCEL) {
  217. // log.d('请求取消: ${e.toString()}');
  218. // } else {
  219. // log.d('未知错误: ${e.toString()}');
  220. // }
  221. }
  222. static void request(String path,
  223. {String method = 'POST',
  224. Map<String, dynamic> params,
  225. Map<String, File> multiFiles,
  226. OnSuccess onSuccess,
  227. OnError onError}) async {
  228. if (params == null) {
  229. params = {};
  230. }
  231. signParams(params).then((sign) async {
  232. print('params => ${sign.toString()}');
  233. Dio dio = await NetUtil.getInstance().dio;
  234. if (multiFiles != null && multiFiles.length > 0) {
  235. for (String key in multiFiles.keys) {
  236. var file = await MultipartFile.fromFile(multiFiles[key].path);
  237. sign[key] = file;
  238. }
  239. }
  240. FormData formdata = FormData.fromMap(sign);
  241. return dio.request(path,
  242. data: formdata, options: Options(method: method));
  243. }).then((response) {
  244. var result = jsonDecode(response.data);
  245. if (result['success'] == 0 || result['success'] == '0') {
  246. print('error: ' + result['msg']);
  247. Fluttertoast.showToast(
  248. msg: result['msg'],
  249. toastLength: Toast.LENGTH_SHORT,
  250. gravity: ToastGravity.BOTTOM,
  251. );
  252. if (onError != null) {
  253. onError(result['msg'] ?? '未知错误');
  254. }
  255. return;
  256. }
  257. if (onSuccess != null) {
  258. onSuccess(result['data']);
  259. }
  260. }).catchError((error) {
  261. onError(error.toString());
  262. });
  263. }
  264. }
  265. /**
  266. * @description: 网络请求拦截器
  267. * @param {type}
  268. * @return:
  269. */
  270. class _NetInterceptors extends InterceptorsWrapper {
  271. @override
  272. Future onRequest(RequestOptions options) {
  273. print("${options?.method} => ${options?.path}");
  274. return super.onRequest(options);
  275. }
  276. @override
  277. Future onResponse(Response response) {
  278. print("response[${response?.statusCode}] => ${response?.data}");
  279. return super.onResponse(response);
  280. // String data = response?.data;
  281. // Map<String, dynamic> map = json.decode(data);
  282. // var success = map['success'];
  283. // if (success != null && '$success' == '1') {
  284. // return super.onResponse(response);
  285. // } else {
  286. // response.data = response?.data['msg'] ?? '未知错误';
  287. // return NetUtil._dio.reject(Response(data: response));
  288. // }
  289. }
  290. @override
  291. Future onError(DioError err) {
  292. print("ERROR[${err?.response?.statusCode}] => PATH: ${err?.request?.path}");
  293. return super.onError(err);
  294. }
  295. }