基础库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

328 lines
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. _config(domain, apiVersion: _apiVersion);
  31. }
  32. return _dio;
  33. }
  34. // 配置网络请求,基础地址,代理地址,如:192.168.0.123:8888(代理地址生产环境无效)
  35. // apiVersion 接口版本
  36. void _config(String baseUrl, {String proxyUrl, String apiVersion}) {
  37. _dio = Dio(BaseOptions(
  38. method: "post",
  39. baseUrl: baseUrl,
  40. connectTimeout: 15000,
  41. receiveTimeout: 15000,
  42. contentType: Headers.jsonContentType,
  43. followRedirects: true));
  44. _dio.interceptors.add(_NetInterceptors());
  45. _dio.interceptors.add(LogInterceptor());
  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 = '';
  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. static Future<dynamic> post(String path,
  132. {Map<String, dynamic> params}) async {
  133. if (params == null) {
  134. params = {};
  135. }
  136. // Map<String, dynamic> sign = await signParams(params);
  137. Map<String, dynamic> sign = 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. // 请求错误
  150. const bool inProduction = const bool.fromEnvironment("dart.vm.product");
  151. if (!inProduction) {
  152. Fluttertoast.showToast(msg: response.statusMessage);
  153. }
  154. // log.e(response.statusMessage);
  155. return {};
  156. }
  157. var result = response.data;
  158. // if (result['success'] == 0 || result['success'] == '0') {
  159. // print('error: ' + result['msg']);
  160. // Fluttertoast.showToast(
  161. // msg: result['msg'],
  162. // toastLength: Toast.LENGTH_SHORT,
  163. // gravity: ToastGravity.BOTTOM,
  164. // );
  165. // return {};
  166. // }
  167. return result;
  168. }
  169. static Future<dynamic> post2(String path,
  170. {Map<String, dynamic> params}) async {
  171. // if (params == null) {
  172. // params = {};
  173. // }
  174. // Map<String, dynamic> sign = await signParams(params);
  175. // Response response;
  176. // try {
  177. // Dio dio = await NetUtil.getInstance().dio;
  178. // response = await dio.post(path, data: sign);
  179. // } on DioError catch (e) {
  180. // _formatError(e);
  181. // }
  182. // if (response == null) {
  183. // return {};
  184. // }
  185. // if (response.statusCode != 200) {
  186. // const bool inProduction = const bool.fromEnvironment("dart.vm.product");
  187. // if (!inProduction) {
  188. // Fluttertoast.showToast(msg: response.statusMessage);
  189. // }
  190. // log.e(response.statusMessage);
  191. // return {};
  192. // }
  193. // var result = jsonDecode(response.data);
  194. // if (result['success'] == 0 || result['success'] == '0') {
  195. // print('error: ' + result['msg']);
  196. // Fluttertoast.showToast(
  197. // msg: result['msg'],
  198. // toastLength: Toast.LENGTH_SHORT,
  199. // gravity: ToastGravity.BOTTOM,
  200. // );
  201. // return result;
  202. // }
  203. // return result['data'];
  204. }
  205. /*
  206. * error统一处理
  207. */
  208. static void _formatError(DioError e) {
  209. // if (e.type == DioErrorType.CONNECT_TIMEOUT) {
  210. // log.d('连接超时: ${e.toString()}');
  211. // } else if (e.type == DioErrorType.SEND_TIMEOUT) {
  212. // log.d('请求超时: ${e.toString()}');
  213. // } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
  214. // log.d('响应超时: ${e.toString()}');
  215. // } else if (e.type == DioErrorType.RESPONSE) {
  216. // log.d('出现异常: ${e.toString()}');
  217. // } else if (e.type == DioErrorType.CANCEL) {
  218. // log.d('请求取消: ${e.toString()}');
  219. // } else {
  220. // log.d('未知错误: ${e.toString()}');
  221. // }
  222. }
  223. static void request(String path,
  224. {String method = 'POST',
  225. Map<String, dynamic> params,
  226. Map<String, File> multiFiles,
  227. OnSuccess onSuccess,
  228. OnError onError}) async {
  229. if (params == null) {
  230. params = {};
  231. }
  232. signParams(params).then((sign) async {
  233. print('params => ${sign.toString()}');
  234. Dio dio = await NetUtil.getInstance().dio;
  235. if (multiFiles != null && multiFiles.length > 0) {
  236. for (String key in multiFiles.keys) {
  237. var file = await MultipartFile.fromFile(multiFiles[key].path);
  238. sign[key] = file;
  239. }
  240. }
  241. FormData formdata = FormData.fromMap(sign);
  242. return dio.request(path,
  243. data: formdata, options: Options(method: method));
  244. }).then((response) {
  245. var result = jsonDecode(response.data);
  246. if (result['success'] == 0 || result['success'] == '0') {
  247. print('error: ' + result['msg']);
  248. Fluttertoast.showToast(
  249. msg: result['msg'],
  250. toastLength: Toast.LENGTH_SHORT,
  251. gravity: ToastGravity.BOTTOM,
  252. );
  253. if (onError != null) {
  254. onError(result['msg'] ?? '未知错误');
  255. }
  256. return;
  257. }
  258. if (onSuccess != null) {
  259. onSuccess(result['data']);
  260. }
  261. }).catchError((error) {
  262. onError(error.toString());
  263. });
  264. }
  265. }
  266. /**
  267. * @description: 网络请求拦截器
  268. * @param {type}
  269. * @return:
  270. */
  271. class _NetInterceptors extends InterceptorsWrapper {
  272. @override
  273. Future onRequest(RequestOptions options) {
  274. print("${options?.method} => ${options?.path}");
  275. return super.onRequest(options);
  276. }
  277. @override
  278. Future onResponse(Response response) {
  279. print("response[${response?.statusCode}] => ${response?.data}");
  280. return super.onResponse(response);
  281. // String data = response?.data;
  282. // Map<String, dynamic> map = json.decode(data);
  283. // var success = map['success'];
  284. // if (success != null && '$success' == '1') {
  285. // return super.onResponse(response);
  286. // } else {
  287. // response.data = response?.data['msg'] ?? '未知错误';
  288. // return NetUtil._dio.reject(Response(data: response));
  289. // }
  290. }
  291. @override
  292. Future onError(DioError err) {
  293. print("ERROR[${err?.response?.statusCode}] => PATH: ${err?.request?.path}");
  294. return super.onError(err);
  295. }
  296. }