import 'dart:convert';
import 'package:adyen_checkout/adyen_checkout.dart';
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:payment_plugin/domain/models/payment_configurations.dart';
import 'package:payment_plugin/domain/models/payment_method.dart';
import 'package:payment_plugin/domain/models/stored_payment_method.dart';
import 'package:payment_plugin/data/remote/api/api_client.dart';
import 'package:payment_plugin/common/constants.dart';
import 'package:payment_plugin/utils/json.dart';
class AdyenRepository {
final ApiClient _api;
/// Creates an AdyenRepository with a Dio instance from the main app
///
/// [dio] - The Dio instance from your main app (with all configured interceptors, baseUrl, etc.)
///
/// Example:
/// ```dart
/// final repo = AdyenRepository(
/// dio: yourConfiguredDioInstance,
/// );
/// ```
AdyenRepository({required Dio dio}) : _api = ApiClient(dio);
Future<Iterable<StoredPaymentMethod>> getCards() async {
final cards = await _api.getPaymentMethods();
return cards.storedPaymentMethods ?? [];
}
Future<void> removeCard(String cardId) async {
try {
await _api.removePaymentMethod(cardId);
} catch (e) {
throw Exception(e);
}
}
Future<dynamic> addCard(PaymentMethod paymentMethod) async {
final response = await _api.storePaymentMethod(paymentMethod);
return response;
}
Future<dynamic> createAdyenSessionForConcierge(int orderId) async {
final data = {"OrderId": orderId, "ReturnUrl": "comwell://"};
return _api.createAdyenSessionForConcierge(data);
}
Future<Json?> postPaymentsDetails(Json body, String apiKey) async {
final contentType = "application/json";
final Map<String, dynamic> data = {
"shopperReference": "Test reference",
"amount": {"value:": 0, "currency": "DKK"},
"countryCode": "DK",
"merchantAccount": "ComwellHotelsECOM",
"returnUrl": "comwell://",
"reference": "flutter-test_${DateTime.now().millisecondsSinceEpoch}",
"channel": "iOS",
};
data.addAll(body);
data.remove("storePaymentMethod");
final response = await _api.postPaymentsDetails(data, contentType, apiKey);
return response;
}
Future<Json> submitPayment(
Json paymentResult,
String shopperReference,
String merchantAccount,
String apiKey,
) async {
final Map<String, dynamic> data = {
"shopperReference": shopperReference,
"amount": {"value:": 0, "currency": "DKK"},
"countryCode": "DK",
"merchantAccount": merchantAccount,
"returnUrl": "comwell://",
"reference": "flutter-test_${DateTime.now().millisecondsSinceEpoch}",
"channel": "iOS",
};
data.addAll(paymentResult);
data.remove("storePaymentMethod");
debugPrint("Data: $data");
final response = await _api.submitPayment(data, apiKey, "application/json");
return response;
}
Future<PaymentConfigurations?> sessionCheckout(
String hotelCode,
String bookingId,
bool usePoints,
) async {
final body = {
"hotelCode": hotelCode,
"bookingConfirmationNumber": bookingId,
"returnUrl": returnUrl,
"usePoints": usePoints,
};
final json = jsonEncode(body);
final response = await _api.createAdyenSession(json) as Map<String, dynamic>;
final clientKey = response["clientKey"] as String;
final sessionResponse = response["sessionResponse"];
final payedWithPoints = response["isFullyPaidWithPoints"] as bool;
if (payedWithPoints) {
return null;
}
final id = sessionResponse["id"] as String;
final sessionData = sessionResponse["sessionData"] as String;
final availablePaymentMethods =
await _api.listAvailablePaymentMethods() as Map<String, dynamic>;
final scheme = _findPaymentMethod(availablePaymentMethods, "scheme");
final googlePay = _findPaymentMethod(availablePaymentMethods, "googlePay");
final applePay = _findPaymentMethod(availablePaymentMethods, "applePay");
// Use the server response amount for consistency across all payment methods
final serverAmount = Amount(value: sessionResponse["amount"]["value"] as int, currency: "DKK");
final session = await AdyenCheckout.session.create(
sessionId: id,
sessionData: sessionData,
configuration: dropInConfiguration(serverAmount, clientKey, false),
);
return PaymentConfigurations(
sessionCheckout: session,
googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
dropInConfiguration: dropInConfiguration(serverAmount, clientKey, false),
cardComponentConfiguration: cardComponentConfiguration(serverAmount, clientKey),
applePayConfiguration: _applePayComponentConfiguration(clientKey, serverAmount, false),
isFullyPaidWithPoints: payedWithPoints,
availablePaymentMethods: [scheme!, googlePay!, applePay!],
);
}
Future<PaymentConfigurations> createSession(
String sessionId,
String clientKey,
String sessionData,
) async {
final amount = Amount(value: 123, currency: "DKK");
final session = await AdyenCheckout.session.create(
sessionData: sessionData,
sessionId: sessionId,
configuration: dropInConfiguration(amount, clientKey, false),
);
final availablePaymentMethods =
await _api.listAvailablePaymentMethods() as Map<String, dynamic>;
final scheme = _findPaymentMethod(availablePaymentMethods, "scheme");
final googlePay = _findPaymentMethod(availablePaymentMethods, "googlePay");
final applePay = _findPaymentMethod(availablePaymentMethods, "applePay");
return PaymentConfigurations(
sessionCheckout: session,
dropInConfiguration: dropInConfiguration(amount, clientKey, false),
googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
cardComponentConfiguration: cardComponentConfiguration(amount, clientKey),
applePayConfiguration: _applePayComponentConfiguration(clientKey, amount, false),
isFullyPaidWithPoints: false,
availablePaymentMethods: [scheme!, googlePay!, applePay!],
);
}
Future<PaymentConfigurations?> fetchSessionForAddingCard() async {
final body = {"returnUrl": returnUrl};
final json = jsonEncode(body);
final response = await _api.createAdyenSessionForCards(json) as Map<String, dynamic>;
final availablePaymentMethods =
await _api.listAvailablePaymentMethods() as Map<String, dynamic>;
final clientKey = response["clientKey"] as String;
final sessionResponse = response["sessionResponse"];
final id = sessionResponse["id"] as String;
final sessionData = sessionResponse["sessionData"] as String;
final scheme = _findPaymentMethod(availablePaymentMethods, "scheme");
final googlePay = _findPaymentMethod(availablePaymentMethods, "googlePay");
final applePay = _findPaymentMethod(availablePaymentMethods, "applePay");
final session = await AdyenCheckout.session.create(
sessionId: id,
sessionData: sessionData,
configuration: cardComponentConfiguration(Amount(value: 0, currency: "DKK"), clientKey),
);
return PaymentConfigurations(
sessionCheckout: session,
availablePaymentMethods: [scheme!, googlePay!, applePay!],
googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
dropInConfiguration: dropInConfiguration(Amount(value: 0, currency: "DKK"), clientKey, true),
cardComponentConfiguration: cardComponentConfiguration(
Amount(value: 0, currency: "DKK"),
clientKey,
),
applePayConfiguration: _applePayComponentConfiguration(
clientKey,
Amount(value: 0, currency: "DKK"),
true,
),
isFullyPaidWithPoints: false,
);
}
CardComponentConfiguration cardComponentConfiguration(Amount amount, String clientKey) {
return CardComponentConfiguration(
environment: Environment.test,
amount: amount,
cardConfiguration: const CardConfiguration(showStorePaymentField: false),
clientKey: clientKey,
countryCode: "DK",
);
}
DropInConfiguration dropInConfiguration(Amount amount, String clientKey, bool addCard) {
return DropInConfiguration(
environment: Environment.test,
clientKey: clientKey,
countryCode: "DK",
skipListWhenSinglePaymentMethod: true,
googlePayConfiguration: _googlePayConfiguration,
applePayConfiguration: _getApplePlayConfig(amount, addCard),
cardConfiguration: const CardConfiguration(showStorePaymentField: false),
paymentMethodNames: {"scheme": "Credit card"},
);
}
GooglePayConfiguration get _googlePayConfiguration =>
const GooglePayConfiguration(googlePayEnvironment: GooglePayEnvironment.test);
GooglePayComponentConfiguration _getGooglePayComponentConfig(String clientKey) {
return GooglePayComponentConfiguration(
environment: Environment.test,
countryCode: "DK",
clientKey: clientKey,
googlePayConfiguration: _googlePayConfiguration,
);
}
ApplePayComponentConfiguration _applePayComponentConfiguration(
String clientKey,
Amount amount,
bool addCard,
) {
return ApplePayComponentConfiguration(
environment: Environment.test,
countryCode: "DK",
clientKey: clientKey,
applePayConfiguration: _getApplePlayConfig(amount, addCard),
);
}
ApplePayConfiguration _getApplePlayConfig(Amount amount, bool addCard) {
return ApplePayConfiguration(
merchantId: merchantId,
merchantName: merchantName,
allowOnboarding: true,
allowShippingContactEditing: true,
applePaySummaryItems: [
ApplePaySummaryItem(
label: addCard ? "add_card".tr() : "total".tr(),
amount: Amount(value: amount.value, currency: amount.currency),
type: ApplePaySummaryItemType.definite,
),
],
);
}
static final Iterable<StoredPaymentMethod> mockStoredPaymentData = [1, 2, 3, 4].map(
(i) => StoredPaymentMethod(
expiryMonth: "12",
expiryYear: "2035",
holderName: "holder name",
id: "id $i",
lastFour: "$i$i$i$i",
brand: "visa",
),
);
}
Map<String, dynamic>? _findPaymentMethod(Map<String, dynamic> pmResponse, String type) {
final list =
(pmResponse['paymentMethods'] as List?)?.cast<Map<String, dynamic>>() ??
const <Map<String, dynamic>>[];
for (final m in list) {
final t = (m['type'] as String?)?.toLowerCase();
if (t == type.toLowerCase()) {
return m; // e.g. 'scheme', 'applepay', 'googlepay'
}
}
return null;
}