@@ -10,12 +10,12 @@ class UserInfoModel { | |||||
String username; | String username; | ||||
List<String> perms; | List<String> perms; | ||||
String registerInviteCodeEnable; | String registerInviteCodeEnable; | ||||
bool isTBAuth; | |||||
bool isTBAuth; // 是否淘宝授权 | |||||
// 获取模糊手机号码 | // 获取模糊手机号码 | ||||
get blurMobile => !EmptyUtil.isEmpty(mobile) ? mobile.length == 11 ? '${mobile.substring(0, 3)}****${mobile.substring(7, mobile.length)}' : mobile : mobile; | get blurMobile => !EmptyUtil.isEmpty(mobile) ? mobile.length == 11 ? '${mobile.substring(0, 3)}****${mobile.substring(7, mobile.length)}' : mobile : mobile; | ||||
UserInfoModel({this.token, this.userId, this.username, this.perms, this.registerInviteCodeEnable}); | |||||
UserInfoModel({this.token, this.userId, this.username, this.perms, this.registerInviteCodeEnable, this.isTBAuth = false}); | |||||
UserInfoModel.fromJson(Map<String, dynamic> json) { | UserInfoModel.fromJson(Map<String, dynamic> json) { | ||||
token = json['token']; | token = json['token']; | ||||
@@ -28,15 +28,25 @@ class UserInfoNotifier with ChangeNotifier { | |||||
} | } | ||||
return _userInfo; | return _userInfo; | ||||
} | } | ||||
/// 更新淘宝授权 | /// 更新淘宝授权 | ||||
void updateUserAuth(bool isAuth){ | |||||
if(_userInfo != null){ | |||||
void updateUserAuth(bool isAuth) { | |||||
if (null == _userInfo) { | |||||
getUserInfoModel().then((user) { | |||||
if (user != null) { | |||||
_userInfo = user; | |||||
_userInfo.isTBAuth = isAuth; | |||||
Logger.log('upate data TBAuth'); | |||||
notifyListeners(); | |||||
} | |||||
}); | |||||
} else { | |||||
_userInfo.isTBAuth = isAuth; | _userInfo.isTBAuth = isAuth; | ||||
Logger.log('upate data TBAuth'); | |||||
notifyListeners(); | notifyListeners(); | ||||
} | } | ||||
} | } | ||||
/// 更新用户数据 | /// 更新用户数据 | ||||
void setUserInfo(UserInfoModel loginUser) async { | void setUserInfo(UserInfoModel loginUser) async { | ||||
print('${loginUser.toString()}'); | print('${loginUser.toString()}'); | ||||
@@ -73,7 +83,7 @@ class UserInfoNotifier with ChangeNotifier { | |||||
String userInfoJson = await SharedPreferencesUtil.getStringValue( | String userInfoJson = await SharedPreferencesUtil.getStringValue( | ||||
GlobalConfig.SHARED_KEY_USER_INFO); | GlobalConfig.SHARED_KEY_USER_INFO); | ||||
if (userInfoJson == null || userInfoJson == '') { | if (userInfoJson == null || userInfoJson == '') { | ||||
_userInfo = UserInfoModel(); | |||||
_userInfo = UserInfoModel(); | |||||
} else { | } else { | ||||
_userInfo = UserInfoModel.fromJson(jsonDecode(userInfoJson)); | _userInfo = UserInfoModel.fromJson(jsonDecode(userInfoJson)); | ||||
} | } | ||||
@@ -1,3 +1,4 @@ | |||||
import 'dart:collection'; | |||||
import 'dart:convert'; | import 'dart:convert'; | ||||
import 'dart:io'; | import 'dart:io'; | ||||
import 'dart:ui'; | import 'dart:ui'; | ||||
@@ -77,53 +78,46 @@ class NetUtil { | |||||
/// 设置代理 | /// 设置代理 | ||||
void _setProxy(String proxyUrl) { | void _setProxy(String proxyUrl) { | ||||
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = | |||||
(HttpClient client) { | |||||
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) { | |||||
client.findProxy = (uri) { | client.findProxy = (uri) { | ||||
return "PROXY $proxyUrl"; | return "PROXY $proxyUrl"; | ||||
}; | }; | ||||
client.badCertificateCallback = | |||||
(X509Certificate cert, String host, int port) => true; | |||||
client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; | |||||
}; | }; | ||||
} | } | ||||
/// 同步请求 | /// 同步请求 | ||||
static Future<dynamic> post(String path, | |||||
{Map<String, dynamic> params, | |||||
NetMethod method = NetMethod.POST, | |||||
bool cache = false}) async { | |||||
static Future<dynamic> post(String path, {Map<String, dynamic> params, NetMethod method = NetMethod.POST, bool cache = false}) async { | |||||
if (params == null) { | if (params == null) { | ||||
params = {}; | params = {}; | ||||
} | } | ||||
// 根据请求参数,获取缓存的Key | // 根据请求参数,获取缓存的Key | ||||
String cacheKey = getRequestParamsCachedKey(params, path); | String cacheKey = getRequestParamsCachedKey(params, path); | ||||
// 参数签名 TODO 加密? | // 参数签名 TODO 加密? | ||||
Map<String, dynamic> sign = await signParams(params); | |||||
// post请求的参数 | |||||
Map<String, dynamic> bodyParams = params; | |||||
// 请求头参数 | |||||
Map<String, dynamic> headParam = await _getMustHeadParams(); | |||||
Response response; | Response response; | ||||
try { | try { | ||||
String token = await SharedPreferencesUtil.getStringValue( | |||||
GlobalConfig.SHARED_KEY_TOKEN) ?? | |||||
''; | |||||
Dio dio = await NetUtil.getInstance().dio; | Dio dio = await NetUtil.getInstance().dio; | ||||
response = await dio.request(path, | |||||
data: sign, | |||||
options: Options(method: enumToString(method), headers: {'token': token, 'app_version': sign['app_version']}), | |||||
// options: Options(method: enumToString(method), headers: sign), | |||||
response = await dio.request( | |||||
path, | |||||
data: !EmptyUtil.isEmpty(bodyParams) ? bodyParams : null, | |||||
options: Options(method: enumToString(method), headers: headParam), | |||||
); | ); | ||||
} on DioError catch (e) { | } on DioError catch (e) { | ||||
_formatError(e); | _formatError(e); | ||||
} | } | ||||
try { | try { | ||||
var result = | |||||
response.data is Map ? response.data : jsonDecode(response.data); | |||||
var result = response.data is Map ? response.data : jsonDecode(response.data); | |||||
// TODO 解密? | // TODO 解密? | ||||
if (isSuccess(result)) { | if (isSuccess(result)) { | ||||
// 缓存成功的数据 | // 缓存成功的数据 | ||||
if (cache) { | if (cache) { | ||||
_setCallBackCacheData(cacheKey, | |||||
response.data is Map ? jsonEncode(response.data) : response.data); | |||||
_setCallBackCacheData(cacheKey, response.data is Map ? jsonEncode(response.data) : response.data); | |||||
} | } | ||||
return result; | return result; | ||||
// 缓存返回的数据 | // 缓存返回的数据 | ||||
@@ -145,12 +139,7 @@ class NetUtil { | |||||
} | } | ||||
/// 异步请求 | /// 异步请求 | ||||
static void request(String path, | |||||
{NetMethod method = NetMethod.GET, | |||||
Map<String, dynamic> params, | |||||
OnSuccess onSuccess, | |||||
OnError onError, | |||||
OnCache onCache}) async { | |||||
static void request(String path, {NetMethod method = NetMethod.GET, Map<String, dynamic> params, OnSuccess onSuccess, OnError onError, OnCache onCache}) async { | |||||
if (params == null) { | if (params == null) { | ||||
params = {}; | params = {}; | ||||
} | } | ||||
@@ -173,11 +162,7 @@ class NetUtil { | |||||
} | } | ||||
if (onError != null) { | if (onError != null) { | ||||
onError(!EmptyUtil.isEmpty(result) | |||||
? !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_MSG]) | |||||
? result[GlobalConfig.HTTP_RESPONSE_KEY_MSG] | |||||
: '未知错误' | |||||
: '未知错误'); | |||||
onError(!EmptyUtil.isEmpty(result) ? !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_MSG]) ? result[GlobalConfig.HTTP_RESPONSE_KEY_MSG] : '未知错误' : '未知错误'); | |||||
} | } | ||||
} catch (e) { | } catch (e) { | ||||
Logger.error('error: ' + e.toString()); | Logger.error('error: ' + e.toString()); | ||||
@@ -190,8 +175,85 @@ class NetUtil { | |||||
} | } | ||||
/// 统一添加必要的参数 | /// 统一添加必要的参数 | ||||
static Future<Map<String, dynamic>> signParams( | |||||
Map<String, dynamic> params) async { | |||||
// static Future<Map<String, dynamic>> signParams(Map<String, dynamic> params) async { | |||||
// // 应用信息 | |||||
// PackageInfo packageInfo = await PackageInfo.fromPlatform(); | |||||
// // 原生传的信息 | |||||
// Map setting = await NativeUtil.getSetting(); | |||||
// | |||||
// if (Platform.isIOS) { | |||||
// IosDeviceInfo iosInfo = await DeviceInfoPlugin().iosInfo; | |||||
// // 设备 | |||||
// params["platform"] = "ios"; | |||||
// // 设备系统版本 | |||||
// params["system_version"] = iosInfo?.systemVersion; | |||||
// // 设备型号 如:iPhone 11pro | |||||
// params['device_model'] = iosInfo?.name; | |||||
// // 设备型号,如:MLMF2LL/A | |||||
// // params['device_number'] = iosInfo?.model; | |||||
// // 设备ID | |||||
// params['device_id'] = iosInfo?.identifierForVendor; | |||||
// } else if (Platform.isAndroid) { | |||||
// AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo; | |||||
// // 设备 | |||||
// params["platform"] = "android"; | |||||
// // 设备系统版本 | |||||
// params["system_version"] = "Android ${androidInfo?.version?.release}"; | |||||
// // 设备型号 如:iPhone 11pro | |||||
// params['device_model'] = androidInfo?.model; | |||||
// // 设备型号,如:MLMF2LL/A | |||||
// // params['device_number'] = androidInfo?.id; | |||||
// // 设备Id | |||||
// params['device_id'] = androidInfo?.androidId; | |||||
// } | |||||
// // 应用版本号 | |||||
// params["app_version_name"] = packageInfo.version; | |||||
// params["app_version"] = -1 ;// packageInfo.buildNumber; | |||||
// // 分辨率 | |||||
// params["solution"] = | |||||
// "${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}"; | |||||
// | |||||
// // 站长ID | |||||
// String masterId = setting['master_id']; | |||||
// if (null != masterId && | |||||
// masterId != '' && | |||||
// (!params.containsKey('master_id') || params['master_id'] == '')) { | |||||
// params['master_id'] = masterId; | |||||
// } | |||||
// | |||||
// // secret_key | |||||
// params['secret_key'] = setting['secret_key']; | |||||
// | |||||
// // token 读取SP缓存中的用户token | |||||
// String token = await SharedPreferencesUtil.getStringValue( | |||||
// GlobalConfig.SHARED_KEY_TOKEN); | |||||
// if (!EmptyUtil.isEmpty(token)) { | |||||
// params['token'] = token; | |||||
// } | |||||
// | |||||
// // 当前时间戳:秒 | |||||
// params["time"] = TimeUtil.getNowTime(); | |||||
// | |||||
// // 过滤空字段,过滤首尾空格 | |||||
// Map<String, dynamic> filters = Map<String, dynamic>(); | |||||
// params.forEach((key, value) { | |||||
// if (key != '' && value != '') { | |||||
// filters[key] = (value is String) ? value.trim() : value; | |||||
// } | |||||
// }); | |||||
// params = filters; | |||||
// | |||||
// List<String> list = List<String>(); | |||||
// params.forEach((key, value) { | |||||
// list.add(key.toString() + value.toString()); | |||||
// }); | |||||
// params["sign"] = signWithArray(list); | |||||
// return params; | |||||
// } | |||||
/// 获取必须的请求参数(用于请求头部) | |||||
static Future<Map<String, String>> _getMustHeadParams() async { | |||||
Map<String, String> params = new HashMap<String, String>(); | |||||
// 应用信息 | // 应用信息 | ||||
PackageInfo packageInfo = await PackageInfo.fromPlatform(); | PackageInfo packageInfo = await PackageInfo.fromPlatform(); | ||||
// 原生传的信息 | // 原生传的信息 | ||||
@@ -202,56 +264,47 @@ class NetUtil { | |||||
// 设备 | // 设备 | ||||
params["platform"] = "ios"; | params["platform"] = "ios"; | ||||
// 设备系统版本 | // 设备系统版本 | ||||
params["system_version"] = iosInfo?.systemVersion; | |||||
params["os_version"] = iosInfo?.systemVersion?.toString(); | |||||
// 设备型号 如:iPhone 11pro | // 设备型号 如:iPhone 11pro | ||||
params['device_model'] = iosInfo?.name; | |||||
// 设备型号,如:MLMF2LL/A | |||||
// params['device_number'] = iosInfo?.model; | |||||
params['device_model'] = iosInfo?.name?.toString(); | |||||
// 设备ID | // 设备ID | ||||
params['device_id'] = iosInfo?.identifierForVendor; | |||||
params['device_id'] = iosInfo?.identifierForVendor?.toString(); | |||||
} else if (Platform.isAndroid) { | } else if (Platform.isAndroid) { | ||||
AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo; | AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo; | ||||
// 设备 | // 设备 | ||||
params["platform"] = "android"; | params["platform"] = "android"; | ||||
// 设备系统版本 | // 设备系统版本 | ||||
params["system_version"] = "Android ${androidInfo?.version?.release}"; | |||||
params["os_version"] = "Android ${androidInfo?.version?.release}"; | |||||
// 设备型号 如:iPhone 11pro | // 设备型号 如:iPhone 11pro | ||||
params['device_model'] = androidInfo?.model; | |||||
// 设备型号,如:MLMF2LL/A | |||||
// params['device_number'] = androidInfo?.id; | |||||
params['device_model'] = androidInfo?.model?.toString(); | |||||
// 设备Id | // 设备Id | ||||
params['device_id'] = androidInfo?.androidId; | |||||
params['device_id'] = androidInfo?.androidId?.toString(); | |||||
} | } | ||||
// 应用版本号 | // 应用版本号 | ||||
params["app_version_name"] = packageInfo.version; | |||||
params["app_version"] = packageInfo.buildNumber; | |||||
params["app_version_name"] = packageInfo.version?.toString(); | |||||
params["app_version"] = packageInfo.buildNumber?.toString(); | |||||
// 分辨率 | // 分辨率 | ||||
params["solution"] = | |||||
"${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}"; | |||||
params["solution"] = "${window.physicalSize.width.floor()}*${window.physicalSize.height.floor()}"; | |||||
// 站长ID | // 站长ID | ||||
String masterId = setting['master_id']; | String masterId = setting['master_id']; | ||||
if (null != masterId && | |||||
masterId != '' && | |||||
(!params.containsKey('master_id') || params['master_id'] == '')) { | |||||
params['master_id'] = masterId; | |||||
if (null != masterId && masterId != '' && (!params.containsKey('master_id') || params['master_id'] == '')) { | |||||
params['master_id'] = masterId ?? 'template_database'; | |||||
} | } | ||||
// secret_key | |||||
params['secret_key'] = setting['secret_key']; | |||||
// token 读取SP缓存中的用户token | // token 读取SP缓存中的用户token | ||||
String token = await SharedPreferencesUtil.getStringValue( | |||||
GlobalConfig.SHARED_KEY_TOKEN); | |||||
String token = await SharedPreferencesUtil.getStringValue(GlobalConfig.SHARED_KEY_TOKEN); | |||||
if (!EmptyUtil.isEmpty(token)) { | if (!EmptyUtil.isEmpty(token)) { | ||||
params['token'] = token; | params['token'] = token; | ||||
} | } | ||||
// secret_key | |||||
params['secret_key'] = setting['secret_key'] ?? ''; | |||||
// 当前时间戳:秒 | // 当前时间戳:秒 | ||||
params["time"] = TimeUtil.getNowTime(); | params["time"] = TimeUtil.getNowTime(); | ||||
// 过滤空字段,过滤首尾空格 | // 过滤空字段,过滤首尾空格 | ||||
Map<String, dynamic> filters = Map<String, dynamic>(); | |||||
Map<String, String> filters = Map<String, String>(); | |||||
params.forEach((key, value) { | params.forEach((key, value) { | ||||
if (key != '' && value != '') { | if (key != '' && value != '') { | ||||
filters[key] = (value is String) ? value.trim() : value; | filters[key] = (value is String) ? value.trim() : value; | ||||
@@ -261,25 +314,23 @@ class NetUtil { | |||||
List<String> list = List<String>(); | List<String> list = List<String>(); | ||||
params.forEach((key, value) { | params.forEach((key, value) { | ||||
list.add(key.toString() + value.toString()); | |||||
list.add(key.toString() + '=' + value.toString() + '&'); | |||||
}); | }); | ||||
params["sign"] = signWithArray(list); | params["sign"] = signWithArray(list); | ||||
params.remove('secret_key'); | |||||
return params; | return params; | ||||
} | } | ||||
/// 获取请求缓存成功的数据 | /// 获取请求缓存成功的数据 | ||||
static Future<void> _onCallBackCacheData( | |||||
OnCache onCache, String cacheKey) async { | |||||
static Future<void> _onCallBackCacheData(OnCache onCache, String cacheKey) async { | |||||
// 读取缓存 | // 读取缓存 | ||||
Map<String, dynamic> cacheMap = | |||||
await SharedPreferencesUtil.getNetCacheResult(cacheKey); | |||||
Map<String, dynamic> cacheMap = await SharedPreferencesUtil.getNetCacheResult(cacheKey); | |||||
if (!EmptyUtil.isEmpty(cacheMap) && | if (!EmptyUtil.isEmpty(cacheMap) && | ||||
cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && | 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}') && | |||||
(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])) { | !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | ||||
onCache(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); | onCache(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); | ||||
return; | return; | ||||
@@ -293,17 +344,12 @@ class NetUtil { | |||||
} | } | ||||
/// 根据请求参数,获取缓存的数据 | /// 根据请求参数,获取缓存的数据 | ||||
static Future<dynamic> getRequestCachedData(String url, | |||||
{Map<String, dynamic> params}) async { | |||||
Map<String, dynamic> cacheMap = | |||||
await SharedPreferencesUtil.getNetCacheResult( | |||||
getRequestParamsCachedKey(params, url)); | |||||
static Future<dynamic> getRequestCachedData(String url, {Map<String, dynamic> params}) async { | |||||
Map<String, dynamic> cacheMap = await SharedPreferencesUtil.getNetCacheResult(getRequestParamsCachedKey(params, url)); | |||||
if (!EmptyUtil.isEmpty(cacheMap) && | if (!EmptyUtil.isEmpty(cacheMap) && | ||||
cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && | 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}') && | |||||
(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])) { | !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | ||||
return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | ||||
} | } | ||||
@@ -314,10 +360,8 @@ class NetUtil { | |||||
static bool isSuccess(Map<String, dynamic> data) { | static bool isSuccess(Map<String, dynamic> data) { | ||||
try { | try { | ||||
if (!EmptyUtil.isEmpty(data) && | if (!EmptyUtil.isEmpty(data) && | ||||
(data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == | |||||
GlobalConfig.RESPONSE_SUCCESS_CODE || | |||||
data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == | |||||
'${GlobalConfig.RESPONSE_SUCCESS_CODE}')) { | |||||
(data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == GlobalConfig.RESPONSE_SUCCESS_CODE || | |||||
data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == '${GlobalConfig.RESPONSE_SUCCESS_CODE}')) { | |||||
return true; | return true; | ||||
} | } | ||||
} catch (e) { | } catch (e) { | ||||
@@ -327,8 +371,7 @@ class NetUtil { | |||||
} | } | ||||
/// 根据请求参数,获取缓存的Key | /// 根据请求参数,获取缓存的Key | ||||
static String getRequestParamsCachedKey( | |||||
Map<String, dynamic> map, String path) { | |||||
static String getRequestParamsCachedKey(Map<String, dynamic> map, String path) { | |||||
if (EmptyUtil.isEmpty(map)) { | if (EmptyUtil.isEmpty(map)) { | ||||
return EncodeUtil.generateMd5(path); | return EncodeUtil.generateMd5(path); | ||||
} | } | ||||
@@ -336,11 +379,7 @@ class NetUtil { | |||||
} | } | ||||
// 七牛云文件上传 | // 七牛云文件上传 | ||||
static Future uploadFile(String url, File file, | |||||
{String method = 'POST', | |||||
Map<String, dynamic> params, | |||||
OnSuccess onSuccess, | |||||
OnError onError}) async { | |||||
static Future uploadFile(String url, File file, {String method = 'POST', Map<String, dynamic> params, OnSuccess onSuccess, OnError onError}) async { | |||||
if (params == null) { | if (params == null) { | ||||
params = {}; | params = {}; | ||||
} | } | ||||
@@ -362,11 +401,10 @@ class NetUtil { | |||||
// 字母升序 | // 字母升序 | ||||
params.sort(); | params.sort(); | ||||
String result = ""; | String result = ""; | ||||
// result += secret_key; | |||||
params.forEach((param) { | params.forEach((param) { | ||||
result += param; | result += param; | ||||
}); | }); | ||||
// result += secret_key; | |||||
result = result.substring(0, result.length - 1); | |||||
return EncodeUtil.generateMd5(result); | return EncodeUtil.generateMd5(result); | ||||
} | } | ||||
@@ -405,8 +443,7 @@ class _NetInterceptors extends InterceptorsWrapper { | |||||
@override | @override | ||||
Future onResponse(Response response) { | Future onResponse(Response response) { | ||||
Logger.endNet(response?.request?.uri?.toString(), | |||||
data: response?.data?.toString() ?? ''); | |||||
Logger.endNet(response?.request?.uri?.toString(), data: response?.data?.toString() ?? ''); | |||||
// TODO 解密? | // TODO 解密? | ||||
return super.onResponse(response); | return super.onResponse(response); | ||||
} | } | ||||
@@ -10,13 +10,14 @@ import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||
class TaobaoAuth { | class TaobaoAuth { | ||||
static ProfileModel _profile; | |||||
// static ProfileModel _profile; | |||||
// 淘宝授权 | // 淘宝授权 | ||||
static auth(BuildContext context) async { | static auth(BuildContext context) async { | ||||
bool isAuth = await TaobaoAuth.isAuth(); | bool isAuth = await TaobaoAuth.isAuth(); | ||||
if (isAuth) { | if (isAuth) { | ||||
Fluttertoast.showToast(msg: '你已经授权过了'); | Fluttertoast.showToast(msg: '你已经授权过了'); | ||||
Provider.of<UserInfoNotifier>(context, listen: false).updateUserAuth(true); | |||||
return; | return; | ||||
} | } | ||||
@@ -26,8 +27,7 @@ class TaobaoAuth { | |||||
return TaobaoAuthAlert(); | return TaobaoAuthAlert(); | ||||
}); | }); | ||||
if (isConfirm != null && isConfirm == true) { | if (isConfirm != null && isConfirm == true) { | ||||
Map<String, dynamic> data = Map<String, dynamic>.from( | |||||
await NetUtil.post('/api/v1/taobao/auth', method: NetMethod.GET)); | |||||
Map<String, dynamic> data = Map<String, dynamic>.from(await NetUtil.post('/api/v1/taobao/auth', method: NetMethod.GET)); | |||||
Logger.debug(data); | Logger.debug(data); | ||||
if (data['code'] != 1) { | if (data['code'] != 1) { | ||||
return; | return; | ||||
@@ -36,20 +36,15 @@ class TaobaoAuth { | |||||
print("授权链接" + url); | print("授权链接" + url); | ||||
TradeResult result; | TradeResult result; | ||||
if (Platform.isAndroid) { | if (Platform.isAndroid) { | ||||
result = await FlutterAlibc.openByUrl( | |||||
url: url, backUrl: "alisdk://", isAuth: true); | |||||
// TradeResult result = await FlutterAlibc.openByUrl(url: ''); | |||||
Logger.debug('${result.errorCode} ${result.errorMessage} '); | |||||
result = await FlutterAlibc.openByUrl(url: url, backUrl: "alisdk://", isAuth: true); | |||||
} else if (Platform.isIOS) { | } else if (Platform.isIOS) { | ||||
result = await FlutterAlibc.openByUrl(url: url); | result = await FlutterAlibc.openByUrl(url: url); | ||||
// TradeResult result = await FlutterAlibc.openByUrl(url: ''); | |||||
Logger.debug('${result.errorCode} ${result.errorMessage} '); | |||||
} | } | ||||
if(null !=result && result.errorCode == '0'){ | |||||
Provider.of<UserInfoNotifier>(context).updateUserAuth(true); | |||||
} | |||||
Logger.log('${result.errorCode} ${result.errorMessage} '); | |||||
// if(null != result && result.errorCode == '0'){ | |||||
// Provider.of<UserInfoNotifier>(context, listen: false).updateUserAuth(true); | |||||
// } | |||||
await initAuth(context); | |||||
} | } | ||||
} | } | ||||
@@ -58,12 +53,32 @@ class TaobaoAuth { | |||||
// if (_profile != null) { | // if (_profile != null) { | ||||
// return _profile.isAuth; | // return _profile.isAuth; | ||||
// } | // } | ||||
Map<String, dynamic> data = Map<String, dynamic>.from( | |||||
await NetUtil.post('/api/v1/user/profile', method: NetMethod.GET)); | |||||
if (data['code'] == 1) { | |||||
_profile = ProfileModel.fromJson(Map<String, dynamic>.from(data['data'])); | |||||
return _profile.isAuth; | |||||
try { | |||||
Map<String, dynamic> data = Map<String, dynamic>.from(await NetUtil.post('/api/v1/user/profile', method: NetMethod.GET)); | |||||
if (data['code'] == 1) { | |||||
ProfileModel _profile = ProfileModel.fromJson(Map<String, dynamic>.from(data['data'])); | |||||
return _profile.isAuth; | |||||
} | |||||
}catch(e, s){ | |||||
Logger.error(e, s); | |||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
// 返回是否授权 | |||||
static void initAuth(BuildContext context) async { | |||||
try { | |||||
Map<String, dynamic> data = Map<String, dynamic>.from(await NetUtil.post('/api/v1/user/profile', method: NetMethod.GET)); | |||||
if (data['code'] == 1) { | |||||
ProfileModel model = ProfileModel.fromJson(Map<String, dynamic>.from(data['data'])); | |||||
if(null != model && model.isAuth){ | |||||
Provider.of<UserInfoNotifier>(context, listen: false).updateUserAuth(true); | |||||
} | |||||
} | |||||
}catch(e, s){ | |||||
Logger.error(e, s); | |||||
} | |||||
} | |||||
} | } |
@@ -1,11 +1,32 @@ | |||||
class AppUpdateModel { | class AppUpdateModel { | ||||
/// Android的第三方URL更新链接 例如:应用宝 | |||||
String appDownloadThirdpartyUrl; | String appDownloadThirdpartyUrl; | ||||
/// 更新的下载链接(Android为应用内的下载链接,IOS为商店链接) | |||||
String appDownloadUrl; | String appDownloadUrl; | ||||
/// 新版本号码 | |||||
String appVersion; | String appVersion; | ||||
/// 新版本昵称 | |||||
String appVersionName; | String appVersionName; | ||||
/// 更新内容 | |||||
String content; | |||||
/// 是否显示提示更新弹窗 | |||||
String dialog; | String dialog; | ||||
/// 是否强制更新 | |||||
String isForce; | String isForce; | ||||
/// 是否可以忽略此版本 | |||||
String isIgnore; | |||||
/// 是否优先使用第三方更新 | |||||
String isThirdparty; | String isThirdparty; | ||||
/// 提示 | |||||
String tip; | String tip; | ||||
AppUpdateModel({ | AppUpdateModel({ | ||||
@@ -17,6 +38,7 @@ class AppUpdateModel { | |||||
this.isForce, | this.isForce, | ||||
this.isThirdparty, | this.isThirdparty, | ||||
this.tip, | this.tip, | ||||
this.content, | |||||
}); | }); | ||||
AppUpdateModel.fromJson(Map<String, dynamic> json) { | AppUpdateModel.fromJson(Map<String, dynamic> json) { | ||||
@@ -26,8 +48,10 @@ class AppUpdateModel { | |||||
appVersionName = json['app_version_name']; | appVersionName = json['app_version_name']; | ||||
dialog = json['dialog']; | dialog = json['dialog']; | ||||
isForce = json['is_force']; | isForce = json['is_force']; | ||||
isIgnore = json['is_ignore']; | |||||
isThirdparty = json['is_thirdparty']; | isThirdparty = json['is_thirdparty']; | ||||
tip = json['tip']; | tip = json['tip']; | ||||
content = json['content']; | |||||
} | } | ||||
Map<String, dynamic> toJson() { | Map<String, dynamic> toJson() { | ||||
@@ -38,8 +62,10 @@ class AppUpdateModel { | |||||
data['app_version_name'] = this.appVersionName; | data['app_version_name'] = this.appVersionName; | ||||
data['dialog'] = this.dialog; | data['dialog'] = this.dialog; | ||||
data['is_force'] = this.isForce; | data['is_force'] = this.isForce; | ||||
data['is_ignore'] = this.isIgnore; | |||||
data['is_thirdparty'] = this.isThirdparty; | data['is_thirdparty'] = this.isThirdparty; | ||||
data['tip'] = this.tip; | data['tip'] = this.tip; | ||||
data['content'] = this.content; | |||||
return data; | return data; | ||||
} | } | ||||
} | } |
@@ -3,8 +3,10 @@ import 'dart:io'; | |||||
import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||
import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
import 'package:flutter_update_dialog/flutter_update_dialog.dart'; | import 'package:flutter_update_dialog/flutter_update_dialog.dart'; | ||||
// import 'package:flutter_xupdate/flutter_xupdate.dart'; | |||||
import 'package:flutter_xupdate/flutter_xupdate.dart'; | |||||
import 'package:package_info/package_info.dart'; | import 'package:package_info/package_info.dart'; | ||||
import 'package:url_launcher/url_launcher.dart'; | |||||
import 'package:zhiying_comm/util/shared_prefe_util.dart'; | |||||
import 'package:zhiying_comm/util/update/app_update_model.dart'; | import 'package:zhiying_comm/util/update/app_update_model.dart'; | ||||
import 'package:zhiying_comm/zhiying_comm.dart'; | import 'package:zhiying_comm/zhiying_comm.dart'; | ||||
import 'package:fluttertoast/fluttertoast.dart'; | import 'package:fluttertoast/fluttertoast.dart'; | ||||
@@ -15,48 +17,49 @@ import '../log/let_log.dart'; | |||||
/// App更新工具类 | /// App更新工具类 | ||||
/// | /// | ||||
class AppUpdateUtil { | class AppUpdateUtil { | ||||
static final String _IGNORE_VERSION = "xupdate_ignore_version"; | |||||
/// | /// | ||||
/// 初始化更新插件 | /// 初始化更新插件 | ||||
/// | /// | ||||
static void initXUpdate() { | static void initXUpdate() { | ||||
if (Platform.isAndroid) { | if (Platform.isAndroid) { | ||||
// FlutterXUpdate.init( | |||||
// | |||||
// ///是否输出日志 | |||||
// debug: true, | |||||
// | |||||
// ///是否使用post请求 | |||||
// isPost: false, | |||||
// | |||||
// ///post请求是否是上传json | |||||
// isPostJson: false, | |||||
// | |||||
// ///是否开启自动模式 | |||||
// isWifiOnly: false, | |||||
// | |||||
// ///是否开启自动模式 | |||||
// isAutoMode: false, | |||||
// | |||||
// ///需要设置的公共参数 | |||||
// supportSilentInstall: false, | |||||
// | |||||
// ///在下载过程中,如果点击了取消的话,是否弹出切换下载方式的重试提示弹窗 | |||||
// enableRetry: false) | |||||
// .then((value) { | |||||
// // updateMessage("初始化成功: $value"); | |||||
// Logger.log('初始化成功: $value'); | |||||
// }).catchError((error) { | |||||
// print(error); | |||||
// }); | |||||
// FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async { | |||||
// Logger.warn(message); | |||||
// // setState(() { | |||||
// // _message = "$message"; | |||||
// // }); | |||||
// }); | |||||
FlutterXUpdate.init( | |||||
///是否输出日志 | |||||
debug: true, | |||||
///是否使用post请求 | |||||
isPost: false, | |||||
///post请求是否是上传json | |||||
isPostJson: false, | |||||
///是否开启自动模式 | |||||
isWifiOnly: false, | |||||
///是否开启自动模式 | |||||
isAutoMode: false, | |||||
///需要设置的公共参数 | |||||
supportSilentInstall: false, | |||||
///在下载过程中,如果点击了取消的话,是否弹出切换下载方式的重试提示弹窗 | |||||
enableRetry: false) | |||||
.then((value) { | |||||
Logger.log('初始化成功: $value'); | |||||
}).catchError((error) { | |||||
print(error); | |||||
}); | |||||
FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async { | |||||
Logger.warn(message); | |||||
}); | |||||
FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async { | |||||
Logger.warn(message); | |||||
}); | |||||
} else { | } else { | ||||
// updateMessage("ios暂不支持XUpdate更新"); | |||||
Logger.log('ios暂不支持XUpdate更新'); | Logger.log('ios暂不支持XUpdate更新'); | ||||
} | } | ||||
} | } | ||||
@@ -64,74 +67,89 @@ class AppUpdateUtil { | |||||
/// | /// | ||||
/// 检查并且更新app | /// 检查并且更新app | ||||
/// | /// | ||||
static void updateApp(BuildContext context) async { | |||||
PackageInfo packageInfo = await PackageInfo.fromPlatform(); | |||||
Logger.log('version = ${packageInfo.version}, buildNum = ${packageInfo.buildNumber}'); | |||||
var result = await NetUtil.post('/api/v1/appcheck', params: {'app_version': packageInfo.buildNumber}, method: NetMethod.GET); | |||||
customStyle(context, onUpdate: (){ | |||||
Navigator.pop(context); | |||||
}); | |||||
// UpdateEntity updateEntity = await _checkAppUpdate(); | |||||
// // 有新版本,进行更新 | |||||
// if (!EmptyUtil.isEmpty(updateEntity) && updateEntity.hasUpdate) { | |||||
// if (Platform.isAndroid) { | |||||
// FlutterXUpdate.updateByInfo( | |||||
// updateEntity: updateEntity, | |||||
// supportBackgroundUpdate: true, | |||||
// ); | |||||
// } else if (Platform.isIOS) { | |||||
// // TODO 完成IOS更新 | |||||
// String updateUrl = updateEntity.downloadUrl; | |||||
// customStyle(context, onUpdate: (){ | |||||
// | |||||
// | |||||
// | |||||
// Navigator.pop(context); | |||||
// }); | |||||
// } | |||||
// } else { | |||||
// Fluttertoast.showToast(msg: '已经是最新版本了~'); | |||||
// } | |||||
/// @context 上下文 | |||||
/// @needToast 是否需要提示最新版本 | |||||
/// @mustShowDialog 是否必须弹窗(检查更新页面要弹窗) | |||||
/// | |||||
static void updateApp(BuildContext context, {bool needToast = false, bool mustShowDialog = false}) async { | |||||
UpdateEntity updateEntity = await _checkAppUpdate(); | |||||
// 有新版本,进行更新 | |||||
if (!EmptyUtil.isEmpty(updateEntity) && updateEntity.hasUpdate) { | |||||
if (Platform.isAndroid) { | |||||
FlutterXUpdate.updateByInfo( | |||||
updateEntity: updateEntity, | |||||
supportBackgroundUpdate: true, | |||||
enableIgnore: mustShowDialog || updateEntity.isForce, | |||||
retryContent: '更新下载速度太慢了,是否考虑切换下载方式?', | |||||
enableRetry: updateEntity.thirdParty, | |||||
overrideGlobalRetryStrategy: true, | |||||
retryUrl: updateEntity.thirdUrl, | |||||
); | |||||
} else if (Platform.isIOS) { | |||||
bool ignore = await isIgnoreVersion(updateEntity?.versionCode?.toString()); | |||||
if ((!ignore || mustShowDialog) || updateEntity.isForce || !updateEntity.isIgnorable) { | |||||
String updateUrl = updateEntity.downloadUrl; | |||||
customStyle(context, updateEntity, onUpdate: () { | |||||
// 打开第三方sdk | |||||
launch(updateUrl, forceSafariVC: true, enableJavaScript: true, forceWebView: true); | |||||
Navigator.pop(context); | |||||
}); | |||||
} | |||||
} | |||||
} else { | |||||
if (needToast) Fluttertoast.showToast(msg: '已经是最新版本了~'); | |||||
} | |||||
} | } | ||||
/// 检查是否有新版本 | /// 检查是否有新版本 | ||||
// static Future<UpdateEntity> _checkAppUpdate() async { | |||||
// try { | |||||
// PackageInfo packageInfo = await PackageInfo.fromPlatform(); | |||||
// // var result = await NetUtil.post('/api/v1/appcheck', params: {'app_version': packageInfo.version}, method: NetMethod.GET); | |||||
// | |||||
// var result = { | |||||
// 'dialog': '1', | |||||
// 'is_force': '0', | |||||
// 'app_version': '5', | |||||
// 'app_version_name': '5.0.0', | |||||
// 'tip': '\n1、优化api接口。\n2、添加使用demo演示。\n3、新增自定义更新服务API接口。\n4、优化更新提示界面。', | |||||
// 'app_download_url': 'http://imtt.dd.qq.com/16891/apk/FAD58DEFE56A938D86B123DEA4E298EB.apk?fsname=com.hairuyi.www_5.8.8_469.apk&hsr=4d5s', | |||||
// }; | |||||
// AppUpdateModel model = AppUpdateModel.fromJson(result); | |||||
// if (!EmptyUtil.isEmpty(model)) { | |||||
// // ⚠️ isIgnorable 目前只有两种状态,为强制更新和不强制更新(每次进来都会提示更新UI弹窗) | |||||
// return UpdateEntity( | |||||
// hasUpdate: model?.dialog == '1', | |||||
// isIgnorable: false, | |||||
// isForce: model?.isForce == '1', | |||||
// versionCode: int.parse(model?.appVersion ?? '1'), | |||||
// versionName: model?.appVersionName, | |||||
// downloadUrl: model?.appDownLoadUrl, | |||||
// updateContent: model?.tip, | |||||
// ); | |||||
// } | |||||
// } catch (e, s) { | |||||
// Logger.error(e, s); | |||||
// } | |||||
// return null; | |||||
// } | |||||
static void customStyle(BuildContext context, {@required VoidCallback onUpdate }) { | |||||
static Future<UpdateEntity> _checkAppUpdate() async { | |||||
try { | |||||
// var result = { | |||||
// "code": 1, | |||||
// "data": { | |||||
// "app_download_thirdparty_url": "https://android.myapp.com/myapp/detail.htm?apkName=com.hairuyi.www&ADTAG=mobile", | |||||
// "app_download_url": "http://fir.osant.cn/zhiyi", | |||||
// "app_version": "1", | |||||
// "app_version_name": "1.0.0", | |||||
// "content": "更新接口\n完善app页面\n更新站长后台", | |||||
// "dialog": "1", | |||||
// "is_force": "0", | |||||
// "is_ignore": "0", | |||||
// "is_thirdparty": "1", | |||||
// "tip": "有新版下载" | |||||
// }, | |||||
// "msg": "ok" | |||||
// }; | |||||
PackageInfo packageInfo = await PackageInfo.fromPlatform(); | |||||
var result = await NetUtil.post('/api/v1/appcheck', method: NetMethod.GET); | |||||
AppUpdateModel model = AppUpdateModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); | |||||
if (!EmptyUtil.isEmpty(model)) { | |||||
return UpdateEntity( | |||||
hasUpdate: model?.dialog == '1' || model?.isForce == '1', | |||||
isIgnorable: model?.isIgnore == '1' && model?.isForce != '1', | |||||
isForce: model?.isForce == '1', | |||||
versionCode: int.parse(model?.appVersion ?? '1'), | |||||
versionName: model?.appVersionName, | |||||
downloadUrl: model?.appDownloadUrl, | |||||
updateContent: model?.content, | |||||
tip: model?.tip, | |||||
thirdUrl: model?.appDownloadThirdpartyUrl, | |||||
thirdParty: model?.isThirdparty == '1', | |||||
); | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
// IOS 样式 | |||||
static void customStyle(BuildContext context, UpdateEntity updateEntity, {@required VoidCallback onUpdate}) { | |||||
UpdateDialog.showUpdate(context, | UpdateDialog.showUpdate(context, | ||||
width: 250, | width: 250, | ||||
title: "是否升级到4.1.4版本?", | |||||
updateContent: "新版本大小:2.0M\n1.xxxxxxx\n2.xxxxxxx\n3.xxxxxxx", | |||||
title: "是否升级到${updateEntity?.versionName ?? '1.0.0'}版本?", | |||||
updateContent: updateEntity?.updateContent ?? '', | |||||
titleTextSize: 14, | titleTextSize: 14, | ||||
contentTextSize: 12, | contentTextSize: 12, | ||||
buttonTextSize: 12, | buttonTextSize: 12, | ||||
@@ -140,11 +158,28 @@ class AppUpdateUtil { | |||||
radius: 8, | radius: 8, | ||||
themeColor: Colors.redAccent, | themeColor: Colors.redAccent, | ||||
progressBackgroundColor: Color(0x5AFFAC5D), | progressBackgroundColor: Color(0x5AFFAC5D), | ||||
isForce: false, | |||||
isForce: updateEntity?.isForce ?? false, | |||||
updateButtonText: '升级', | updateButtonText: '升级', | ||||
ignoreButtonText: '忽略此版本', | ignoreButtonText: '忽略此版本', | ||||
enableIgnore: true, onIgnore: () { | |||||
enableIgnore: updateEntity?.isIgnorable ?? false, onIgnore: () { | |||||
saveIgnoreVersion(updateEntity?.versionCode?.toString()); | |||||
Navigator.pop(context); | Navigator.pop(context); | ||||
}, onUpdate: onUpdate); | }, onUpdate: onUpdate); | ||||
} | } | ||||
// 保存忽略的版本号码 | |||||
static void saveIgnoreVersion(String newVersion) async { | |||||
if (!EmptyUtil.isEmpty(newVersion)) { | |||||
await SharedPreferencesUtil.setStringValue(_IGNORE_VERSION, newVersion); | |||||
} | |||||
} | |||||
// 是否是忽略版本 | |||||
static Future<bool> isIgnoreVersion(String newVersion) async { | |||||
String oldVersion = await SharedPreferencesUtil.getStringValue(_IGNORE_VERSION); | |||||
if (!EmptyUtil.isEmpty(oldVersion) && !EmptyUtil.isEmpty(newVersion)) { | |||||
return oldVersion == newVersion; | |||||
} | |||||
return false; | |||||
} | |||||
} | } |
@@ -33,7 +33,10 @@ dependencies: | |||||
# 京东sdk | # 京东sdk | ||||
jdsdk: ^0.0.1 | jdsdk: ^0.0.1 | ||||
# Android app更新 | # Android app更新 | ||||
# flutter_xupdate: ^1.0.0 | |||||
flutter_xupdate: | |||||
git: | |||||
ref: 1.0.1 | |||||
url: http://192.168.0.138:3000/FnuoOS_ZhiYing/flutter_xupdate.git | |||||
# app更新dialogUI(用于IOS,以便统一样式) | # app更新dialogUI(用于IOS,以便统一样式) | ||||
flutter_update_dialog: 1.0.0 | flutter_update_dialog: 1.0.0 | ||||
flutter_alibc: | flutter_alibc: | ||||