You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			244 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Dart
		
	
		
		
			
		
	
	
			244 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Dart
		
	
| 
								 
											10 months ago
										 
									 | 
							
								import 'dart:async';
							 | 
						||
| 
								 | 
							
								import 'dart:convert';
							 | 
						||
| 
								 | 
							
								import 'dart:developer';
							 | 
						||
| 
								 | 
							
								import 'dart:io';
							 | 
						||
| 
								 | 
							
								import 'package:flutter/foundation.dart';
							 | 
						||
| 
								 | 
							
								import 'package:http/http.dart';
							 | 
						||
| 
								 | 
							
								import 'package:http/io_client.dart';
							 | 
						||
| 
								 | 
							
								import 'package:hmg_qline/constants/app_constants.dart';
							 | 
						||
| 
								 | 
							
								import 'package:hmg_qline/utilities/api_exception.dart';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef FactoryConstructor<U> = U Function(dynamic);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								abstract class ApiClient {
							 | 
						||
| 
								 | 
							
								  Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
							 | 
						||
| 
								 | 
							
								      {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<Response> postJsonForResponse<T>(String url, T jsonObject, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<U> getJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<Response> getJsonForResponse<T>(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0});
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ApiClientImp implements ApiClient {
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
							 | 
						||
| 
								 | 
							
								      {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
							 | 
						||
| 
								 | 
							
								    var headers0 = {'Accept': 'application/json'};
							 | 
						||
| 
								 | 
							
								    if (headers != null && headers.isNotEmpty) {
							 | 
						||
| 
								 | 
							
								      headers0.addAll(headers);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: headers0, retryTimes: retryTimes);
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      if (!kReleaseMode) {
							 | 
						||
| 
								 | 
							
								        log("statusCode:${response.statusCode}");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      var jsonData = jsonDecode(response.body);
							 | 
						||
| 
								 | 
							
								      return factoryConstructor(jsonData);
							 | 
						||
| 
								 | 
							
								    } catch (ex) {
							 | 
						||
| 
								 | 
							
								      log(ex.toString());
							 | 
						||
| 
								 | 
							
								      log("exception:$ex");
							 | 
						||
| 
								 | 
							
								      throw APIException(APIException.badResponseFormat, arguments: ex);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Future<Response> postJsonForResponse<T>(String url, T jsonObject, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
							 | 
						||
| 
								 | 
							
								    String? requestBody;
							 | 
						||
| 
								 | 
							
								    if (jsonObject != null) {
							 | 
						||
| 
								 | 
							
								      requestBody = jsonEncode(jsonObject);
							 | 
						||
| 
								 | 
							
								      if (headers == null) {
							 | 
						||
| 
								 | 
							
								        headers = {'Content-Type': 'application/json'};
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        headers['Content-Type'] = 'application/json';
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<Response> _postForResponse(
							 | 
						||
| 
								 | 
							
								    String url,
							 | 
						||
| 
								 | 
							
								    requestBody, {
							 | 
						||
| 
								 | 
							
								    String? token,
							 | 
						||
| 
								 | 
							
								    Map<String, dynamic>? queryParameters,
							 | 
						||
| 
								 | 
							
								    Map<String, String>? headers,
							 | 
						||
| 
								 | 
							
								    int retryTimes = 0,
							 | 
						||
| 
								 | 
							
								  }) async {
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      var headers0 = <String, String>{};
							 | 
						||
| 
								 | 
							
								      if (token != null) {
							 | 
						||
| 
								 | 
							
								        headers0['Authorization'] = 'Bearer $token';
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (headers != null && headers.isNotEmpty) {
							 | 
						||
| 
								 | 
							
								        headers0.addAll(headers);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (queryParameters != null) {
							 | 
						||
| 
								 | 
							
								        var queryString = Uri(queryParameters: queryParameters).query;
							 | 
						||
| 
								 | 
							
								        url = '$url?$queryString';
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      Response response;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      response = await _post(Uri.parse(url), body: requestBody, headers: headers0).timeout(const Duration(seconds: 100));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!kReleaseMode) {
							 | 
						||
| 
								 | 
							
								        logger.d("------URL------");
							 | 
						||
| 
								 | 
							
								        logger.i(url);
							 | 
						||
| 
								 | 
							
								        logger.d("------Payload------");
							 | 
						||
| 
								 | 
							
								        logger.i(jsonDecode(requestBody));
							 | 
						||
| 
								 | 
							
								        logger.d("------Response------");
							 | 
						||
| 
								 | 
							
								        logger.i(jsonDecode(response.body));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (response.statusCode >= 200 && response.statusCode < 500) {
							 | 
						||
| 
								 | 
							
								        var jsonData = jsonDecode(response.body);
							 | 
						||
| 
								 | 
							
								        if (jsonData["StatusMessage"] != null && jsonData["StatusMessage"] == "Unauthorized user attempt to access API") {
							 | 
						||
| 
								 | 
							
								          return await _postForResponse(url, requestBody, token: '', queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return response;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIError.throwAPIException(response);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } on SocketException catch (e) {
							 | 
						||
| 
								 | 
							
								      if (retryTimes > 0) {
							 | 
						||
| 
								 | 
							
								        log('will retry after 3 seconds...');
							 | 
						||
| 
								 | 
							
								        await Future.delayed(const Duration(seconds: 3));
							 | 
						||
| 
								 | 
							
								        return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIException(APIException.other, arguments: e);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } on HttpException catch (e) {
							 | 
						||
| 
								 | 
							
								      if (retryTimes > 0) {
							 | 
						||
| 
								 | 
							
								        log('will retry after 3 seconds...');
							 | 
						||
| 
								 | 
							
								        await Future.delayed(const Duration(seconds: 3));
							 | 
						||
| 
								 | 
							
								        return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIException(APIException.other, arguments: e);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } on TimeoutException catch (e) {
							 | 
						||
| 
								 | 
							
								      throw APIException(APIException.timeout, arguments: e);
							 | 
						||
| 
								 | 
							
								    } on ClientException catch (e) {
							 | 
						||
| 
								 | 
							
								      if (retryTimes > 0) {
							 | 
						||
| 
								 | 
							
								        log('will retry after 3 seconds...');
							 | 
						||
| 
								 | 
							
								        await Future.delayed(const Duration(seconds: 3));
							 | 
						||
| 
								 | 
							
								        return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIException(APIException.other, arguments: e);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } catch (ex) {
							 | 
						||
| 
								 | 
							
								      log("exception1:$ex");
							 | 
						||
| 
								 | 
							
								      throw APIException(APIException.badResponseFormat, arguments: ex);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool _certificateCheck(X509Certificate cert, String host, int port) => true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<T> _withClient<T>(Future<T> Function(Client) fn) async {
							 | 
						||
| 
								 | 
							
								    var httpClient = HttpClient()..badCertificateCallback = _certificateCheck;
							 | 
						||
| 
								 | 
							
								    var client = IOClient(httpClient);
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      return await fn(client);
							 | 
						||
| 
								 | 
							
								    } finally {
							 | 
						||
| 
								 | 
							
								      client.close();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<Response> _post(url, {Map<String, String>? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Future<U> getJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url,
							 | 
						||
| 
								 | 
							
								      {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
							 | 
						||
| 
								 | 
							
								    var headers0 = {'Accept': 'application/json'};
							 | 
						||
| 
								 | 
							
								    if (headers != null && headers.isNotEmpty) {
							 | 
						||
| 
								 | 
							
								      headers0.addAll(headers);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    var response = await getJsonForResponse(url, token: token, queryParameters: queryParameters, headers: headers0, retryTimes: retryTimes);
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      var jsonData = jsonDecode(response.body);
							 | 
						||
| 
								 | 
							
								      return factoryConstructor(jsonData);
							 | 
						||
| 
								 | 
							
								    } catch (ex) {
							 | 
						||
| 
								 | 
							
								      log("exception:${response.body}");
							 | 
						||
| 
								 | 
							
								      throw APIException(APIException.badResponseFormat, arguments: ex);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Future<Response> getJsonForResponse<T>(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
							 | 
						||
| 
								 | 
							
								    if (headers == null) {
							 | 
						||
| 
								 | 
							
								      headers = {'Content-Type': 'application/json'};
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      headers['Content-Type'] = 'application/json';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool isFirstCall = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<Response> _getForResponse(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      var headers0 = <String, String>{};
							 | 
						||
| 
								 | 
							
								      if (token != null) {
							 | 
						||
| 
								 | 
							
								        headers0['Authorization'] = 'Bearer $token';
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (headers != null && headers.isNotEmpty) {
							 | 
						||
| 
								 | 
							
								        headers0.addAll(headers);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (queryParameters != null) {
							 | 
						||
| 
								 | 
							
								        String queryString = Uri(queryParameters: queryParameters).query;
							 | 
						||
| 
								 | 
							
								        if (isFirstCall) url = '$url?$queryString';
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!kReleaseMode) {
							 | 
						||
| 
								 | 
							
								        logger.i(url);
							 | 
						||
| 
								 | 
							
								        logger.i("$queryParameters");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      var response = await _get(Uri.parse(url), headers: headers0).timeout(const Duration(seconds: 60));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!kReleaseMode) {
							 | 
						||
| 
								 | 
							
								        logger.i(jsonDecode(response.body));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (response.statusCode >= 200 && response.statusCode < 500) {
							 | 
						||
| 
								 | 
							
								        var jsonData = jsonDecode(response.body);
							 | 
						||
| 
								 | 
							
								        if (jsonData["StatusMessage"] != null && jsonData["StatusMessage"] == "Unauthorized user attempt to access API") {
							 | 
						||
| 
								 | 
							
								          isFirstCall = false;
							 | 
						||
| 
								 | 
							
								          return await _getForResponse(url, token: '', queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return response;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIError.throwAPIException(response);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } on SocketException catch (e) {
							 | 
						||
| 
								 | 
							
								      if (retryTimes > 0) {
							 | 
						||
| 
								 | 
							
								        log('will retry after 3 seconds...');
							 | 
						||
| 
								 | 
							
								        await Future.delayed(const Duration(seconds: 3));
							 | 
						||
| 
								 | 
							
								        return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIException(APIException.other, arguments: e);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } on HttpException catch (e) {
							 | 
						||
| 
								 | 
							
								      if (retryTimes > 0) {
							 | 
						||
| 
								 | 
							
								        log('will retry after 3 seconds...');
							 | 
						||
| 
								 | 
							
								        await Future.delayed(const Duration(seconds: 3));
							 | 
						||
| 
								 | 
							
								        return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIException(APIException.other, arguments: e);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } on TimeoutException catch (e) {
							 | 
						||
| 
								 | 
							
								      throw APIException(APIException.timeout, arguments: e);
							 | 
						||
| 
								 | 
							
								    } on ClientException catch (e) {
							 | 
						||
| 
								 | 
							
								      if (retryTimes > 0) {
							 | 
						||
| 
								 | 
							
								        await Future.delayed(const Duration(seconds: 3));
							 | 
						||
| 
								 | 
							
								        return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        throw APIException(APIException.other, arguments: e);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Future<Response> _get(url, {Map<String, String>? headers}) => _withClient((client) => client.get(url, headers: headers));
							 | 
						||
| 
								 | 
							
								}
							 |