Connect customer quotations and payment execution to Sendico (#50)
This commit is contained in:
1 parent
5d67c25c8e
commit
7a6510d1a8
45 files changed
+2696
-45
No files matched your search
@@ -0,0 +1,130 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'package:sxchnge_auth/sxchnge_auth.dart';
|
||||
|
||||
import '../mappers/backend.dart';
|
||||
import '../models/wallet.dart';
|
||||
import '../transport/backend.dart';
|
||||
import 'contracts.dart';
|
||||
import 'http/client.dart';
|
||||
|
||||
class BackendWalletService implements WalletService {
|
||||
BackendWalletService({
|
||||
required this.baseUri,
|
||||
required this.accessToken,
|
||||
http.Client? client,
|
||||
}) : _client = client ?? createClient() {
|
||||
if (!baseUri.hasAuthority ||
|
||||
baseUri.hasQuery ||
|
||||
baseUri.hasFragment ||
|
||||
baseUri.userInfo.isNotEmpty ||
|
||||
(baseUri.scheme != 'https' &&
|
||||
!(baseUri.scheme == 'http' &&
|
||||
['localhost', '127.0.0.1'].contains(baseUri.host))))
|
||||
throw ArgumentError('Valid wallet API URL required');
|
||||
}
|
||||
final Uri baseUri;
|
||||
final String? Function() accessToken;
|
||||
final http.Client _client;
|
||||
@override
|
||||
bool get isSimulated => false;
|
||||
Future<BackendDTO> send(
|
||||
String path, {
|
||||
Map<String, Object?>? body,
|
||||
bool factor = false,
|
||||
}) async {
|
||||
final token = accessToken();
|
||||
if (token == null) throw const WalletException(WalletError.unavailable);
|
||||
final uri = baseUri.replace(
|
||||
path:
|
||||
'${baseUri.path.replaceFirst(RegExp(r"/$"), "")}/accounts/wallet$path',
|
||||
);
|
||||
final request = http.Request(body == null ? 'GET' : 'POST', uri)
|
||||
..followRedirects = false;
|
||||
request.headers.addAll({
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
if (kIsWeb) 'X-CSRF-Protection': '1',
|
||||
});
|
||||
if (body != null) request.body = jsonEncode(body);
|
||||
try {
|
||||
final response = await _client
|
||||
.send(request)
|
||||
.then(http.Response.fromStream)
|
||||
.timeout(const Duration(seconds: 40));
|
||||
if (token != accessToken())
|
||||
throw const WalletException(WalletError.unavailable);
|
||||
final dto = BackendDTO.decode(response.body);
|
||||
if (response.statusCode < 200 ||
|
||||
response.statusCode >= 300 ||
|
||||
!dto.accepted) {
|
||||
if (factor || dto.error.startsWith('factor'))
|
||||
throw FactorException(BackendMapper.factorFailure(dto));
|
||||
throw WalletException(BackendMapper.failure(dto));
|
||||
}
|
||||
return dto;
|
||||
} on FactorException {
|
||||
rethrow;
|
||||
} on WalletException {
|
||||
rethrow;
|
||||
} catch (_) {
|
||||
throw const WalletException(WalletError.unavailable);
|
||||
}
|
||||
}
|
||||
|
||||
Future<T> _mapped<T>(
|
||||
Future<BackendDTO> dto,
|
||||
T Function(BackendDTO) map,
|
||||
) async {
|
||||
try {
|
||||
return map(await dto);
|
||||
} on FactorException {
|
||||
rethrow;
|
||||
} on WalletException {
|
||||
rethrow;
|
||||
} catch (_) {
|
||||
throw const WalletException(WalletError.unavailable);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WalletSnapshot> fetch() => _mapped(send(''), BackendMapper.snapshot);
|
||||
@override
|
||||
Future<Quote> quote(TransferRequest request) => _mapped(
|
||||
send('/quote', body: BackendMapper.request(request)),
|
||||
BackendMapper.quote,
|
||||
);
|
||||
@override
|
||||
Future<WalletOperation> submit(
|
||||
String quoteId,
|
||||
String idempotencyKey, {
|
||||
String? approval,
|
||||
}) async {
|
||||
final value = await _mapped(
|
||||
send(
|
||||
'/submit',
|
||||
body: {'quoteId': quoteId, 'idempotencyKey': idempotencyKey},
|
||||
),
|
||||
BackendMapper.operation,
|
||||
);
|
||||
if (value == null) throw const WalletException(WalletError.uncertain);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WalletOperation?> findSubmission(String idempotencyKey) => _mapped(
|
||||
send('/submission', body: {'idempotencyKey': idempotencyKey}),
|
||||
BackendMapper.operation,
|
||||
);
|
||||
@override
|
||||
Future<AccountProfile> profile() =>
|
||||
_mapped(send('/profile'), BackendMapper.profile);
|
||||
@override
|
||||
Future<AccountProfile> saveLocale(String locale) async =>
|
||||
throw const WalletException(WalletError.unsupported);
|
||||
void close() => _client.close();
|
||||
}
|
||||
Reference in new issue
Block a user