178 lines
6.4 KiB
Dart
178 lines
6.4 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:dio/dio.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:guru_app/account/account_data_store.dart';
|
|
import 'package:guru_app/account/model/user.dart';
|
|
import 'package:guru_app/guru_app.dart';
|
|
import 'package:guru_app/property/app_property.dart';
|
|
import 'package:guru_utils/auth/auth_credential_manager.dart';
|
|
import 'package:guru_utils/device/device_info.dart';
|
|
import 'package:guru_utils/device/device_utils.dart';
|
|
import 'package:retrofit/retrofit.dart';
|
|
import 'custom_transformer.dart';
|
|
import 'data/orders/orders_model.dart';
|
|
|
|
/// Created by Haoyi on 6/3/21
|
|
part 'modules/guru_api_extension.dart';
|
|
|
|
part 'guru_api.g.dart';
|
|
|
|
abstract class DioBuilder {
|
|
Dio build();
|
|
}
|
|
|
|
class GuruDioBuilder extends DioBuilder {
|
|
final AccountDataStore accountDataStore;
|
|
|
|
GuruDioBuilder() : accountDataStore = AccountDataStore.instance;
|
|
|
|
Options toOptions(RequestOptions ro) {
|
|
return Options(
|
|
method: ro.method,
|
|
sendTimeout: ro.sendTimeout,
|
|
receiveTimeout: ro.receiveTimeout,
|
|
extra: ro.extra,
|
|
headers: ro.headers,
|
|
responseType: ro.responseType,
|
|
contentType: ro.contentType,
|
|
validateStatus: ro.validateStatus,
|
|
receiveDataWhenStatusError: ro.receiveDataWhenStatusError,
|
|
followRedirects: ro.followRedirects,
|
|
maxRedirects: ro.maxRedirects,
|
|
requestEncoder: ro.requestEncoder,
|
|
responseDecoder: ro.responseDecoder,
|
|
listFormat: ro.listFormat);
|
|
}
|
|
|
|
@override
|
|
Dio build() {
|
|
Dio dio = Dio()
|
|
..transformer = CustomTransformer()
|
|
..options.connectTimeout = Duration(milliseconds: GuruApp.instance.appSpec.deployment.apiConnectTimeout)
|
|
..options.receiveTimeout = Duration(milliseconds: GuruApp.instance.appSpec.deployment.apiReceiveTimeout);
|
|
|
|
dio.interceptors.add(InterceptorsWrapper(
|
|
onRequest: (RequestOptions options, RequestInterceptorHandler handler) async {
|
|
DeviceInfo? deviceInfo = accountDataStore.currentDevice;
|
|
final deviceId = await AppProperty.getInstance().getDeviceId();
|
|
deviceInfo ??=
|
|
await DeviceUtils.buildDeviceInfo(deviceId: deviceId, firebasePushToken: "", uid: "");
|
|
final token = accountDataStore.saasToken;
|
|
options.headers
|
|
.addAll({"X-APP-ID": GuruApp.instance.details.saasAppId, "X-ACCESS-TOKEN": token ?? ''});
|
|
options.headers.addAll({"X-DEVICE-INFO": Uri.encodeFull(deviceInfo.toXDeviceInfo())});
|
|
handler.next(options);
|
|
}, onResponse: (Response response, ResponseInterceptorHandler handler) {
|
|
// Log.v("### onResponse ${response.data}");
|
|
response.data = response.data["data"] ?? response.data;
|
|
handler.next(response);
|
|
}, onError: (DioError err, ErrorInterceptorHandler handler) async {
|
|
final token = accountDataStore.saasToken;
|
|
final response = err.response;
|
|
Log.v("### onError ${err.toString()}");
|
|
if (response != null && token != null && response.statusCode == 401) {
|
|
// dio.lock();
|
|
try {
|
|
Log.v("accountDataStore.refreshAuth()");
|
|
await accountDataStore.refreshAuth(); //获取新token
|
|
} catch (e) {
|
|
// Log.v("[NETWORK]: RefreshToken Failed.");
|
|
handler.reject(err);
|
|
} finally {
|
|
// dio.unlock();
|
|
}
|
|
final options = err.requestOptions.copyWith();
|
|
options.headers["X-ACCESS-TOKEN"] = accountDataStore.saasToken;
|
|
try {
|
|
final response = await dio.request(options.path,
|
|
data: options.data,
|
|
queryParameters: options.queryParameters,
|
|
cancelToken: options.cancelToken,
|
|
onReceiveProgress: options.onReceiveProgress,
|
|
options: toOptions(options));
|
|
handler.resolve(response);
|
|
} catch (error, stacktrace) {
|
|
Log.v("re-request error:$error $stacktrace");
|
|
handler.reject(err);
|
|
}
|
|
} else {
|
|
handler.reject(err);
|
|
}
|
|
}));
|
|
dio.interceptors
|
|
.add(LogInterceptor(requestBody: true, responseBody: true, logPrint: platformLogPrint));
|
|
return dio;
|
|
}
|
|
}
|
|
|
|
@RestApi()
|
|
abstract class GuruApiMethods {
|
|
factory GuruApiMethods(Dio dio, {String baseUrl}) = _GuruApiMethods;
|
|
|
|
static GuruApiMethods create(GuruDioBuilder dioBuilder, String baseUrl) {
|
|
return GuruApiMethods(dioBuilder.build(), baseUrl: baseUrl);
|
|
}
|
|
|
|
// 上报 Device, 初次或者 token 更新后
|
|
@POST("/device/api/v1/devices")
|
|
Future reportDevice(@Body() DeviceInfo body);
|
|
|
|
// Auth
|
|
@POST("/auth/api/v1/tokens/provider/secret")
|
|
Future<GuruUser> signInWithAnonymous(@Body() AnonymousLoginReqBody body);
|
|
|
|
@POST("/auth/api/v1/tokens/provider/facebook-gaming")
|
|
Future<GuruUser> signInWithFacebook(@Body() FacebookLoginReqBody body);
|
|
|
|
@POST("/auth/api/v1/tokens/provider/google")
|
|
Future<GuruUser> signInWithGoogle(@Body() GoogleLoginReqBody body);
|
|
|
|
@POST("/auth/api/v1/tokens/provider/apple")
|
|
Future<GuruUser> signInWithApple(@Body() AppleLoginReqBody body);
|
|
|
|
@POST("/auth/api/v1/bindings/provider/facebook-gaming")
|
|
Future<GuruUser> associateWithFacebook(@Body() FacebookLoginReqBody body);
|
|
|
|
@POST("/auth/api/v1/bindings/provider/google")
|
|
Future<GuruUser> associateWithGoogle(@Body() GoogleLoginReqBody body);
|
|
|
|
@POST("/auth/api/v1/bindings/provider/apple")
|
|
Future<GuruUser> associateWithApple(@Body() AppleLoginReqBody body);
|
|
|
|
@POST("/auth/api/v1/renewals/token")
|
|
Future<GuruUser> refreshSaasToken();
|
|
|
|
@POST("/auth/api/v1/renewals/firebase")
|
|
Future<FirebaseTokenData> renewFirebaseToken();
|
|
|
|
@POST("/order/api/v1/orders/ios")
|
|
Future<OrdersResponse> iOSOrdersReport(@Body() OrdersReport body);
|
|
|
|
@POST("/order/api/v1/orders/android")
|
|
Future<OrdersResponse> androidOrdersReport(@Body() OrdersReport body);
|
|
}
|
|
|
|
class GuruApi {
|
|
static const String _saasApiDevHost = "https://dev.saas.castbox.fm";
|
|
static const String _saasApiReleaseHost = "https://saas.castbox.fm";
|
|
|
|
static bool useReleaseApi = kReleaseMode;
|
|
|
|
static final GuruApi _releaseApi =
|
|
GuruApi._(GuruApiMethods.create(GuruDioBuilder(), _saasApiReleaseHost));
|
|
static final GuruApi _debugApi =
|
|
GuruApi._(GuruApiMethods.create(GuruDioBuilder(), _saasApiDevHost));
|
|
|
|
final GuruApiMethods _methods;
|
|
|
|
static GuruApi get instance => useReleaseApi ? _releaseApi : _debugApi;
|
|
|
|
static String get saasApiHost => useReleaseApi ? _saasApiReleaseHost : _saasApiDevHost;
|
|
|
|
GuruApiMethods get methods => _methods;
|
|
|
|
GuruApi._(this._methods);
|
|
}
|