import 'package:dio/dio.dart'; import 'package:dio/adapter.dart'; import 'package:zhiying_comm/util/empty_util.dart'; import 'dart:io'; import 'dart:convert'; import 'package:zhiying_comm/zhiying_comm.dart'; import 'global_config.dart'; import 'shared_prefe_util.dart'; class Api { final String path; Map params; final NetMethod method; static Dio _dio; static get _net async { if (_dio == null) { var setting = await NativeUtil.getSetting(); String domain = setting['domain']; //'http://www.hairuyi.com/'; _config(domain, proxyUrl: '192.168.0.112:8888'); } return _dio; } Api(this.path, {this.params, this.method = NetMethod.POST}) { this.params = params ?? {}; } Future onCache() async { String cacheKey = getRequestParamsCachedKey(params, path); // 读取缓存 Map cacheMap = await SharedPreferencesUtil.getNetCacheResult(cacheKey); if (!EmptyUtil.isEmpty(cacheMap) && cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE || cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}') && !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; } return {}; } Future onRequest() async { Map result = {}; try { Dio net = await _net; Map headers = await _getHeaders(); var responds = await net.request(path, data: params, options: Options(method: enumToString(method), headers: headers)); result = responds.data is Map ? responds.data : jsonDecode(responds.data); String cacheKey = getRequestParamsCachedKey(params, path); _setCallBackCacheData(cacheKey, responds.data is Map ? jsonEncode(responds.data) : responds.data); } on DioError catch (e) { _formatError(e); } return result; } // 获取headers,headers保存各种签名认证信息 Future> _getHeaders() async { Map headers = Map(); headers['device'] = 'wx_applet'; headers['Platform'] = 'wx_applet'; // token 读取SP缓存中的用户token String token = await SharedPreferencesUtil.getStringValue( GlobalConfig.SHARED_KEY_TOKEN) ?? ''; const bool inProduction = const bool.fromEnvironment("dart.vm.product"); if (!inProduction && token != '') { token = '7f7bdb785dcb02a4536bea2ffe299eda352e127f'; } if (token != null && token != '') { headers['token'] = token; } return headers; } /// 配置网络请求,基础地址,代理地址,如:192.168.0.123:8888(代理地址生产环境无效) /// apiVersion 接口版本 static void _config(String baseUrl, {String proxyUrl}) { _dio = Dio(BaseOptions( method: "post", baseUrl: baseUrl, connectTimeout: 15000, receiveTimeout: 15000, contentType: Headers.jsonContentType, followRedirects: true, )); _dio.interceptors.add(_NetInterceptors()); // _dio.interceptors.add(LogInterceptor()); const bool inProduction = const bool.fromEnvironment("dart.vm.product"); if (proxyUrl != null && proxyUrl != '' && !inProduction) { _setProxy(proxyUrl); } } /// 设置代理 static void _setProxy(String proxyUrl) { (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) { client.findProxy = (uri) { return "PROXY $proxyUrl"; }; client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; }; } /// 获取请求缓存成功的数据 static Future _onCallBackCacheData( OnCache onCache, String cacheKey) async { // 读取缓存 Map cacheMap = await SharedPreferencesUtil.getNetCacheResult(cacheKey); if (!EmptyUtil.isEmpty(cacheMap) && cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE || cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}') && !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { onCache(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); return; } return; } /// 缓存请求成功的数据 static void _setCallBackCacheData(String cacheKey, String value) async { SharedPreferencesUtil.setNetCacheResult(cacheKey, value); } /// 根据请求参数,获取缓存的数据 static Future getRequestCachedData(String url, {Map params}) async { Map cacheMap = await SharedPreferencesUtil.getNetCacheResult( getRequestParamsCachedKey(params, url)); if (!EmptyUtil.isEmpty(cacheMap) && cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE || cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}') && !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; } return null; } /// 判断后台返回是否成功 static bool isSuccess(Map data) { try { if (!EmptyUtil.isEmpty(data) && (data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE || data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}')) { return true; } } catch (e) { return false; } return false; } /// 根据请求参数,获取缓存的Key static String getRequestParamsCachedKey( Map map, String path) { if (EmptyUtil.isEmpty(map)) { return EncodeUtil.generateMd5(path); } return EncodeUtil.generateMd5(path + map.toString()); } /// 签名 static String signWithArray(List params) { // 字母升序 params.sort(); String result = ""; // result += secret_key; params.forEach((param) { result += param; }); // result += secret_key; return EncodeUtil.generateMd5(result); } /* * error统一处理 */ static void _formatError(DioError e) { if (e.type == DioErrorType.CONNECT_TIMEOUT) { Logger.error('连接超时: ${e.toString()}'); } else if (e.type == DioErrorType.SEND_TIMEOUT) { Logger.error('请求超时: ${e.toString()}'); } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) { Logger.error('响应超时: ${e.toString()}'); } else if (e.type == DioErrorType.RESPONSE) { Logger.error('出现异常: ${e.toString()}'); } else if (e.type == DioErrorType.CANCEL) { Logger.error('请求取消: ${e.toString()}'); } else { Logger.error('未知错误: ${e.toString()}'); } } } /** * @description: 网络请求拦截器 * @param {type} * @return: */ class _NetInterceptors extends InterceptorsWrapper { @override Future onRequest(RequestOptions options) { Logger.net(options?.uri?.toString(), data: options.data.toString()); // TODO 加密? return super.onRequest(options); } @override Future onResponse(Response response) { Logger.endNet(response?.request?.uri?.toString(), data: response?.data?.toString() ?? ''); // TODO 解密? return super.onResponse(response); } @override Future onError(DioError err) { // Logger.error(err); return super.onError(err); } }