From 3cd34294c193811dee17f647ac3c39af4e2e0c46 Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Thu, 12 Oct 2023 13:32:20 +0200 Subject: [PATCH 01/13] Added additional fields for sessions request to test more payment methods --- .../lib/network/models/billing_address.dart | 33 ++++++++++ .../lib/network/models/delivery_address.dart | 33 ++++++++++ example/lib/network/models/line_item.dart | 49 ++++++++++++++ .../models/session_request_network_model.dart | 22 +++++++ .../session_response_network_model.dart | 53 +++++++++++---- .../adyen_sessions_repository.dart | 64 ++++++++++++++----- 6 files changed, 225 insertions(+), 29 deletions(-) create mode 100644 example/lib/network/models/billing_address.dart create mode 100644 example/lib/network/models/delivery_address.dart create mode 100644 example/lib/network/models/line_item.dart diff --git a/example/lib/network/models/billing_address.dart b/example/lib/network/models/billing_address.dart new file mode 100644 index 00000000..0c6e1b0e --- /dev/null +++ b/example/lib/network/models/billing_address.dart @@ -0,0 +1,33 @@ +class BillingAddress { + String? city; + String? country; + String? houseNumberOrName; + String? postalCode; + String? street; + + BillingAddress({ + this.city, + this.country, + this.houseNumberOrName, + this.postalCode, + this.street, + }); + + BillingAddress.fromJson(Map json) { + city = json['city']; + country = json['country']; + houseNumberOrName = json['houseNumberOrName']; + postalCode = json['postalCode']; + street = json['street']; + } + + Map toJson() { + final Map data = {}; + data['city'] = city; + data['country'] = country; + data['houseNumberOrName'] = houseNumberOrName; + data['postalCode'] = postalCode; + data['street'] = street; + return data; + } +} diff --git a/example/lib/network/models/delivery_address.dart b/example/lib/network/models/delivery_address.dart new file mode 100644 index 00000000..4e966ccb --- /dev/null +++ b/example/lib/network/models/delivery_address.dart @@ -0,0 +1,33 @@ +class DeliveryAddress { + String? city; + String? country; + String? houseNumberOrName; + String? postalCode; + String? street; + + DeliveryAddress({ + this.city, + this.country, + this.houseNumberOrName, + this.postalCode, + this.street, + }); + + DeliveryAddress.fromJson(Map json) { + city = json['city']; + country = json['country']; + houseNumberOrName = json['houseNumberOrName']; + postalCode = json['postalCode']; + street = json['street']; + } + + Map toJson() { + final Map data = {}; + data['city'] = city; + data['country'] = country; + data['houseNumberOrName'] = houseNumberOrName; + data['postalCode'] = postalCode; + data['street'] = street; + return data; + } +} diff --git a/example/lib/network/models/line_item.dart b/example/lib/network/models/line_item.dart new file mode 100644 index 00000000..0e4cf71a --- /dev/null +++ b/example/lib/network/models/line_item.dart @@ -0,0 +1,49 @@ +class LineItem { + int? quantity; + int? amountExcludingTax; + int? taxPercentage; + String? description; + String? id; + int? taxAmount; + int? amountIncludingTax; + String? productUrl; + String? imageUrl; + + LineItem({ + this.quantity, + this.amountExcludingTax, + this.taxPercentage, + this.description, + this.id, + this.taxAmount, + this.amountIncludingTax, + this.productUrl, + this.imageUrl, + }); + + LineItem.fromJson(Map json) { + quantity = json['quantity']; + amountExcludingTax = json['amountExcludingTax']; + taxPercentage = json['taxPercentage']; + description = json['description']; + id = json['id']; + taxAmount = json['taxAmount']; + amountIncludingTax = json['amountIncludingTax']; + productUrl = json['productUrl']; + imageUrl = json['imageUrl']; + } + + Map toJson() { + final Map data = {}; + data['quantity'] = quantity; + data['amountExcludingTax'] = amountExcludingTax; + data['taxPercentage'] = taxPercentage; + data['description'] = description; + data['id'] = id; + data['taxAmount'] = taxAmount; + data['amountIncludingTax'] = amountIncludingTax; + data['productUrl'] = productUrl; + data['imageUrl'] = imageUrl; + return data; + } +} diff --git a/example/lib/network/models/session_request_network_model.dart b/example/lib/network/models/session_request_network_model.dart index f2d62fa4..e6aeeca6 100644 --- a/example/lib/network/models/session_request_network_model.dart +++ b/example/lib/network/models/session_request_network_model.dart @@ -1,6 +1,9 @@ import 'dart:convert'; import 'package:adyen_checkout_example/network/models/amount_network_model.dart'; +import 'package:adyen_checkout_example/network/models/billing_address.dart'; +import 'package:adyen_checkout_example/network/models/delivery_address.dart'; +import 'package:adyen_checkout_example/network/models/line_item.dart'; class SessionRequestNetworkModel { final String merchantAccount; @@ -12,6 +15,12 @@ class SessionRequestNetworkModel { final String? storePaymentMethodMode; final String? recurringProcessingModel; final String? channel; + final String? telephoneNumber; + final String? dateOfBirth; + final String? socialSecurityNumber; + final DeliveryAddress? deliveryAddress; + final BillingAddress? billingAddress; + final List? lineItems; SessionRequestNetworkModel({ required this.merchantAccount, @@ -23,6 +32,12 @@ class SessionRequestNetworkModel { this.storePaymentMethodMode, this.recurringProcessingModel, this.channel, + this.telephoneNumber, + this.dateOfBirth, + this.socialSecurityNumber, + this.deliveryAddress, + this.billingAddress, + this.lineItems, }); String toRawJson() => json.encode(toJson()); @@ -38,6 +53,13 @@ class SessionRequestNetworkModel { data['storePaymentMethodMode'] = storePaymentMethodMode; data['recurringProcessingModel'] = recurringProcessingModel; data['channel'] = channel; + data['telephoneNumber'] = telephoneNumber; + data['dateOfBirth'] = dateOfBirth; + data['socialSecurityNumber'] = socialSecurityNumber; + data['billingAddress'] = billingAddress?.toJson(); + data['deliveryAddress'] = deliveryAddress?.toJson(); + data['lineItems'] = + lineItems?.map((lineItem) => lineItem.toJson()).toList(); return data; } } diff --git a/example/lib/network/models/session_response_network_model.dart b/example/lib/network/models/session_response_network_model.dart index f7923838..081b6da1 100644 --- a/example/lib/network/models/session_response_network_model.dart +++ b/example/lib/network/models/session_response_network_model.dart @@ -1,6 +1,9 @@ import 'dart:convert'; import 'package:adyen_checkout_example/network/models/amount_network_model.dart'; +import 'package:adyen_checkout_example/network/models/billing_address.dart'; +import 'package:adyen_checkout_example/network/models/delivery_address.dart'; +import 'package:adyen_checkout_example/network/models/line_item.dart'; class SessionResponseNetworkModel { final AmountNetworkModel amount; @@ -14,6 +17,12 @@ class SessionResponseNetworkModel { final String? shopperReference; final String? storePaymentMethodMode; final String? recurringProcessingModel; + final String? telephoneNumber; + final String? dateOfBirth; + final String? socialSecurityNumber; + final DeliveryAddress? deliveryAddress; + final BillingAddress? billingAddress; + final List? lineItems; SessionResponseNetworkModel({ required this.amount, @@ -27,22 +36,40 @@ class SessionResponseNetworkModel { this.shopperReference, this.storePaymentMethodMode, this.recurringProcessingModel, + this.telephoneNumber, + this.dateOfBirth, + this.socialSecurityNumber, + this.deliveryAddress, + this.billingAddress, + this.lineItems, }); factory SessionResponseNetworkModel.fromRawJson(String str) => SessionResponseNetworkModel.fromJson(json.decode(str)); - factory SessionResponseNetworkModel.fromJson(Map json) => SessionResponseNetworkModel( - amount: AmountNetworkModel.fromJson(json["amount"]), - countryCode: json["countryCode"], - expiresAt: DateTime.parse(json["expiresAt"]), - id: json["id"], - merchantAccount: json["merchantAccount"], - reference: json["reference"], - returnUrl: json["returnUrl"], - sessionData: json["sessionData"], - shopperReference: json["shopperReference"], - storePaymentMethodMode: json["storePaymentMethodMode"], - recurringProcessingModel: json["recurringProcessingModel"], - ); + factory SessionResponseNetworkModel.fromJson(Map json) => + SessionResponseNetworkModel( + amount: AmountNetworkModel.fromJson(json["amount"]), + countryCode: json["countryCode"], + expiresAt: DateTime.parse(json["expiresAt"]), + id: json["id"], + merchantAccount: json["merchantAccount"], + reference: json["reference"], + returnUrl: json["returnUrl"], + sessionData: json["sessionData"], + shopperReference: json["shopperReference"], + storePaymentMethodMode: json["storePaymentMethodMode"], + recurringProcessingModel: json["recurringProcessingModel"], + telephoneNumber: json["telephoneNumber"], + dateOfBirth: json["dateOfBirth"], + socialSecurityNumber: json["socialSecurityNumber"], + deliveryAddress: json["deliveryAddress"] != null + ? DeliveryAddress.fromJson(json["deliveryAddress"]) + : null, + billingAddress: json["billingAddress"] != null + ? BillingAddress.fromJson(json["billingAddress"]) + : null, + lineItems: List.from( + json["lineItems"].map((model) => LineItem.fromJson(model))), + ); } diff --git a/example/lib/repositories/adyen_sessions_repository.dart b/example/lib/repositories/adyen_sessions_repository.dart index 1c260af8..31c4c647 100644 --- a/example/lib/repositories/adyen_sessions_repository.dart +++ b/example/lib/repositories/adyen_sessions_repository.dart @@ -4,6 +4,9 @@ import 'dart:io'; import 'package:adyen_checkout/adyen_checkout.dart'; import 'package:adyen_checkout_example/config.dart'; import 'package:adyen_checkout_example/network/models/amount_network_model.dart'; +import 'package:adyen_checkout_example/network/models/billing_address.dart'; +import 'package:adyen_checkout_example/network/models/delivery_address.dart'; +import 'package:adyen_checkout_example/network/models/line_item.dart'; import 'package:adyen_checkout_example/network/models/payment_methods_request_network_model.dart'; import 'package:adyen_checkout_example/network/models/payment_request_network_model.dart'; import 'package:adyen_checkout_example/network/models/session_request_network_model.dart'; @@ -27,22 +30,51 @@ class AdyenSessionsRepository { String returnUrl = await determineExampleReturnUrl(); SessionRequestNetworkModel sessionRequestNetworkModel = SessionRequestNetworkModel( - merchantAccount: Config.merchantAccount, - amount: AmountNetworkModel( - currency: amount.currency, - value: amount.value, - ), - returnUrl: returnUrl, - reference: - "flutter-session-test_${DateTime.now().millisecondsSinceEpoch}", - countryCode: Config.countryCode, - shopperReference: Config.shopperReference, - storePaymentMethodMode: - StorePaymentMethodMode.askForConsent.storePaymentMethodModeString, - recurringProcessingModel: - RecurringProcessingModel.cardOnFile.recurringModelString, - channel: _determineChannel(), - ); + merchantAccount: Config.merchantAccount, + amount: AmountNetworkModel( + currency: amount.currency, + value: amount.value, + ), + returnUrl: returnUrl, + reference: + "flutter-session-test_${DateTime.now().millisecondsSinceEpoch}", + countryCode: Config.countryCode, + shopperReference: Config.shopperReference, + storePaymentMethodMode: StorePaymentMethodMode + .askForConsent.storePaymentMethodModeString, + recurringProcessingModel: + RecurringProcessingModel.cardOnFile.recurringModelString, + channel: _determineChannel(), + telephoneNumber: "+8613012345678", + dateOfBirth: "1996-09-04", + socialSecurityNumber: "0108", + deliveryAddress: DeliveryAddress( + city: "Ankeborg", + country: "SE", + houseNumberOrName: "1", + postalCode: "1234", + street: "Stargatan", + ), + billingAddress: BillingAddress( + city: "Ankeborg", + country: "SE", + houseNumberOrName: "1", + postalCode: "1234", + street: "Stargatan", + ), + lineItems: [ + LineItem( + quantity: 1, + amountExcludingTax: 331, + taxPercentage: 2100, + description: "Shoes", + id: "Item #1", + taxAmount: 69, + amountIncludingTax: 400, + productUrl: "URL_TO_PURCHASED_ITEM", + imageUrl: "URL_TO_PICTURE_OF_PURCHASED_ITEM", + ), + ]); SessionResponseNetworkModel sessionResponseNetworkModel = await _service.createSession(sessionRequestNetworkModel, environment); From 357c770c831c8b7cb0b10ce20ccae85125f6abaa Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Fri, 13 Oct 2023 13:42:22 +0200 Subject: [PATCH 02/13] Added more properties for sessions and payments requests --- .../models/payment_request_network_model.dart | 5 +++-- .../models/session_request_network_model.dart | 3 +++ .../models/session_response_network_model.dart | 3 +++ .../repositories/adyen_sessions_repository.dart | 15 ++++++++++++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/example/lib/network/models/payment_request_network_model.dart b/example/lib/network/models/payment_request_network_model.dart index 80a0f0d9..6421cd3c 100644 --- a/example/lib/network/models/payment_request_network_model.dart +++ b/example/lib/network/models/payment_request_network_model.dart @@ -1,4 +1,5 @@ import 'package:adyen_checkout_example/network/models/amount_network_model.dart'; +import 'package:adyen_checkout_example/network/models/line_item.dart'; import 'package:adyen_checkout_example/network/models/session_request_network_model.dart'; class PaymentsRequestData { @@ -12,7 +13,7 @@ class PaymentsRequestData { final bool? threeDSAuthenticationOnly; final String? shopperIP; final String? channel; - final List? lineItems; + final List? lineItems; final String? shopperEmail; final ThreeDS2RequestDataRequest? threeDS2RequestData; final RecurringProcessingModel? recurringProcessingModel; @@ -48,7 +49,7 @@ class PaymentsRequestData { "reference": reference, if (channel != null) "channel": channel, if (lineItems != null) - "lineItems": lineItems?.map((item) => item.toJson()).toList(), + "lineItems": lineItems?.map((lineItem) => lineItem.toJson()).toList(), if (shopperEmail != null) "shopperEmail": shopperEmail, if (threeDS2RequestData != null) "threeDS2RequestData": threeDS2RequestData?.toJson(), diff --git a/example/lib/network/models/session_request_network_model.dart b/example/lib/network/models/session_request_network_model.dart index e6aeeca6..ce55e10b 100644 --- a/example/lib/network/models/session_request_network_model.dart +++ b/example/lib/network/models/session_request_network_model.dart @@ -11,6 +11,7 @@ class SessionRequestNetworkModel { final String returnUrl; final String reference; final String countryCode; + final String? shopperLocale; final String? shopperReference; final String? storePaymentMethodMode; final String? recurringProcessingModel; @@ -28,6 +29,7 @@ class SessionRequestNetworkModel { required this.returnUrl, required this.reference, required this.countryCode, + this.shopperLocale, this.shopperReference, this.storePaymentMethodMode, this.recurringProcessingModel, @@ -49,6 +51,7 @@ class SessionRequestNetworkModel { data['returnUrl'] = returnUrl; data['reference'] = reference; data['countryCode'] = countryCode; + data['shopperLocale'] = shopperLocale; data['shopperReference'] = shopperReference; data['storePaymentMethodMode'] = storePaymentMethodMode; data['recurringProcessingModel'] = recurringProcessingModel; diff --git a/example/lib/network/models/session_response_network_model.dart b/example/lib/network/models/session_response_network_model.dart index 081b6da1..2b8a4f69 100644 --- a/example/lib/network/models/session_response_network_model.dart +++ b/example/lib/network/models/session_response_network_model.dart @@ -14,6 +14,7 @@ class SessionResponseNetworkModel { final String reference; final String returnUrl; final String sessionData; + final String? shopperLocale; final String? shopperReference; final String? storePaymentMethodMode; final String? recurringProcessingModel; @@ -33,6 +34,7 @@ class SessionResponseNetworkModel { required this.reference, required this.returnUrl, required this.sessionData, + this.shopperLocale, this.shopperReference, this.storePaymentMethodMode, this.recurringProcessingModel, @@ -57,6 +59,7 @@ class SessionResponseNetworkModel { reference: json["reference"], returnUrl: json["returnUrl"], sessionData: json["sessionData"], + shopperLocale: json["shopperLocale"], shopperReference: json["shopperReference"], storePaymentMethodMode: json["storePaymentMethodMode"], recurringProcessingModel: json["recurringProcessingModel"], diff --git a/example/lib/repositories/adyen_sessions_repository.dart b/example/lib/repositories/adyen_sessions_repository.dart index 31c4c647..ea65ff19 100644 --- a/example/lib/repositories/adyen_sessions_repository.dart +++ b/example/lib/repositories/adyen_sessions_repository.dart @@ -39,6 +39,7 @@ class AdyenSessionsRepository { reference: "flutter-session-test_${DateTime.now().millisecondsSinceEpoch}", countryCode: Config.countryCode, + shopperLocale: Config.shopperLocale, shopperReference: Config.shopperReference, storePaymentMethodMode: StorePaymentMethodMode .askForConsent.storePaymentMethodModeString, @@ -111,7 +112,19 @@ class AdyenSessionsRepository { threeDS2RequestData: ThreeDS2RequestDataRequest(), threeDSAuthenticationOnly: false, recurringProcessingModel: RecurringProcessingModel.cardOnFile, - lineItems: [], + lineItems: [ + LineItem( + quantity: 1, + amountExcludingTax: 331, + taxPercentage: 2100, + description: "Shoes", + id: "Item #1", + taxAmount: 69, + amountIncludingTax: 400, + productUrl: "URL_TO_PURCHASED_ITEM", + imageUrl: "URL_TO_PICTURE_OF_PURCHASED_ITEM", + ) + ], ); Map mergedJson = {}; From 7acb6f37ab4224d9a77ce1fe2731b9b81d1ac9f3 Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Fri, 13 Oct 2023 15:56:52 +0200 Subject: [PATCH 03/13] Added missing did complete handling --- ios/Classes/CheckoutPlatformApi.swift | 2 +- .../DropInAdvancedFlowDelegate.swift | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift index 5e339423..35f1a99c 100644 --- a/ios/Classes/CheckoutPlatformApi.swift +++ b/ios/Classes/CheckoutPlatformApi.swift @@ -90,7 +90,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { let dropInComponent = DropInComponent(paymentMethods: paymentMethodsWithoutGiftCards, context: adyenContext, configuration: configuration) - dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(checkoutFlutterApi: checkoutFlutterApi, component: dropInComponent) + dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(checkoutFlutterApi: checkoutFlutterApi, dropInComponent: dropInComponent) dropInComponent.delegate = dropInAdvancedFlowDelegate if dropInConfigurationDTO.isRemoveStoredPaymentMethodEnabled == true { diff --git a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift index 8068d082..9e99c9b3 100644 --- a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift +++ b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift @@ -3,11 +3,11 @@ import AdyenNetworking class DropInAdvancedFlowDelegate: DropInComponentDelegate { private let checkoutFlutterApi: CheckoutFlutterApi - private let component: DropInComponent + private let dropInComponent: DropInComponent - init(checkoutFlutterApi: CheckoutFlutterApi, component: DropInComponent) { + init(checkoutFlutterApi: CheckoutFlutterApi, dropInComponent: DropInComponent) { self.checkoutFlutterApi = checkoutFlutterApi - self.component = component + self.dropInComponent = dropInComponent } func didSubmit(_ data: PaymentComponentData, from _: PaymentComponent, in _: AnyDropInComponent) { @@ -33,9 +33,15 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { } func didComplete(from _: ActionComponent, in _: AnyDropInComponent) { - print("did complete") + let paymentResult = PaymentResultDTO(type: PaymentResultEnum.finished, result: PaymentResultModelDTO(resultCode: ResultCode.received.rawValue)) + let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult) + checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) + dropInComponent.finalizeIfNeeded(with: true, completion: { [weak self] in + guard let self = self else { return } + self.dropInComponent.viewController.dismiss(animated: true) + }) } - + func didFail(with error: Error, from _: PaymentComponent, in dropInComponent: AnyDropInComponent) { dropInComponent.viewController.presentedViewController?.dismiss(animated: true, completion: { self.sendErrorToFlutterLayer(error: error) From 26b6721c4d9c8d9fd70d266770d144ce0447b2fe Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Fri, 13 Oct 2023 16:19:05 +0200 Subject: [PATCH 04/13] Removed redundant class --- .../models/payment_request_network_model.dart | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/example/lib/network/models/payment_request_network_model.dart b/example/lib/network/models/payment_request_network_model.dart index 6421cd3c..b818afd6 100644 --- a/example/lib/network/models/payment_request_network_model.dart +++ b/example/lib/network/models/payment_request_network_model.dart @@ -76,38 +76,6 @@ class AdditionalData { } } -class Item { - final int quantity; - final int amountExcludingTax; - final int taxPercentage; - final String description; - final String id; - final int amountIncludingTax; - final String taxCategory; - - Item({ - required this.quantity, - required this.amountExcludingTax, - required this.taxPercentage, - required this.description, - required this.id, - required this.amountIncludingTax, - required this.taxCategory, - }); - - Map toJson() { - return { - 'quantity': quantity, - 'amountExcludingTax': amountExcludingTax, - 'taxPercentage': taxPercentage, - 'description': description, - 'id': id, - 'amountIncludingTax': amountIncludingTax, - 'taxCategory': taxCategory, - }; - } -} - class ThreeDS2RequestDataRequest { final String deviceChannel; final String challengeIndicator; From 2f395644a7cfa238032561408f82b8d66defd3fe Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Mon, 16 Oct 2023 11:12:51 +0200 Subject: [PATCH 05/13] Added shopperInteraction value --- .../models/payment_request_network_model.dart | 3 +++ .../models/session_request_network_model.dart | 25 +++++++++++++++++++ .../adyen_sessions_repository.dart | 4 +++ 3 files changed, 32 insertions(+) diff --git a/example/lib/network/models/payment_request_network_model.dart b/example/lib/network/models/payment_request_network_model.dart index b818afd6..73955a6c 100644 --- a/example/lib/network/models/payment_request_network_model.dart +++ b/example/lib/network/models/payment_request_network_model.dart @@ -17,6 +17,7 @@ class PaymentsRequestData { final String? shopperEmail; final ThreeDS2RequestDataRequest? threeDS2RequestData; final RecurringProcessingModel? recurringProcessingModel; + final String? shopperInteraction; PaymentsRequestData({ required this.merchantAccount, @@ -33,6 +34,7 @@ class PaymentsRequestData { this.shopperEmail, this.threeDS2RequestData, this.recurringProcessingModel, + this.shopperInteraction, }); Map toJson() { @@ -55,6 +57,7 @@ class PaymentsRequestData { "threeDS2RequestData": threeDS2RequestData?.toJson(), if (recurringProcessingModel != null) "recurringProcessingModel": recurringProcessingModel?.recurringModelString, + if (shopperInteraction != null) "shopperInteraction" : shopperInteraction }; } } diff --git a/example/lib/network/models/session_request_network_model.dart b/example/lib/network/models/session_request_network_model.dart index ce55e10b..232e31fb 100644 --- a/example/lib/network/models/session_request_network_model.dart +++ b/example/lib/network/models/session_request_network_model.dart @@ -15,6 +15,7 @@ class SessionRequestNetworkModel { final String? shopperReference; final String? storePaymentMethodMode; final String? recurringProcessingModel; + final String? shopperInteraction; final String? channel; final String? telephoneNumber; final String? dateOfBirth; @@ -33,6 +34,7 @@ class SessionRequestNetworkModel { this.shopperReference, this.storePaymentMethodMode, this.recurringProcessingModel, + this.shopperInteraction, this.channel, this.telephoneNumber, this.dateOfBirth, @@ -55,6 +57,7 @@ class SessionRequestNetworkModel { data['shopperReference'] = shopperReference; data['storePaymentMethodMode'] = storePaymentMethodMode; data['recurringProcessingModel'] = recurringProcessingModel; + data['shopperInteraction'] = shopperInteraction; data['channel'] = channel; data['telephoneNumber'] = telephoneNumber; data['dateOfBirth'] = dateOfBirth; @@ -79,6 +82,13 @@ enum RecurringProcessingModel { unscheduledCardOnFile } +enum ShopperInteractionModel { + ecommerce, + contAuth, + moto, + pos +} + extension StorePaymentMethodModeExtension on StorePaymentMethodMode { String get storePaymentMethodModeString { switch (this) { @@ -104,3 +114,18 @@ extension RecurringProcessingModelExtension on RecurringProcessingModel { } } } + +extension ShopperInteractionModelExtension on ShopperInteractionModel { + String get shopperInteractionModelString { + switch (this) { + case ShopperInteractionModel.ecommerce: + return "Ecommerce"; + case ShopperInteractionModel.contAuth: + return "ContAuth"; + case ShopperInteractionModel.moto: + return "Moto"; + case ShopperInteractionModel.pos: + return "POS"; + } + } +} diff --git a/example/lib/repositories/adyen_sessions_repository.dart b/example/lib/repositories/adyen_sessions_repository.dart index ea65ff19..1bd151a2 100644 --- a/example/lib/repositories/adyen_sessions_repository.dart +++ b/example/lib/repositories/adyen_sessions_repository.dart @@ -45,6 +45,8 @@ class AdyenSessionsRepository { .askForConsent.storePaymentMethodModeString, recurringProcessingModel: RecurringProcessingModel.cardOnFile.recurringModelString, + shopperInteraction: + ShopperInteractionModel.contAuth.shopperInteractionModelString, channel: _determineChannel(), telephoneNumber: "+8613012345678", dateOfBirth: "1996-09-04", @@ -112,6 +114,8 @@ class AdyenSessionsRepository { threeDS2RequestData: ThreeDS2RequestDataRequest(), threeDSAuthenticationOnly: false, recurringProcessingModel: RecurringProcessingModel.cardOnFile, + shopperInteraction: + ShopperInteractionModel.contAuth.shopperInteractionModelString, lineItems: [ LineItem( quantity: 1, From 9eba5671aff014329678a92f56096879b2983e99 Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Mon, 16 Oct 2023 11:14:10 +0200 Subject: [PATCH 06/13] Changed url scheme value --- example/ios/Runner/Info.plist | 2 +- example/lib/config.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 427246da..f240fd71 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -31,7 +31,7 @@ com.adyen.adyen_checkout_example CFBundleURLSchemes - ui-host + flutter-ui-host diff --git a/example/lib/config.dart b/example/lib/config.dart index 72e9ee67..90461794 100644 --- a/example/lib/config.dart +++ b/example/lib/config.dart @@ -23,7 +23,7 @@ class Config { static const Environment environment = Environment.test; static const String baseUrl = "checkout-test.adyen.com"; static const String apiVersion = "v70"; - static const String iOSReturnUrl = "ui-host://payments"; + static const String iOSReturnUrl = "flutter-ui-host://payments"; //Example data static Amount amount = Amount(currency: "EUR", value: 2100); From 4b295491b9c7207ca62cf4c97835aab210b8b6ea Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Mon, 16 Oct 2023 13:25:07 +0200 Subject: [PATCH 07/13] Set shopper interaction model to ecommerce --- example/lib/repositories/adyen_sessions_repository.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/lib/repositories/adyen_sessions_repository.dart b/example/lib/repositories/adyen_sessions_repository.dart index 1bd151a2..9a7e7e26 100644 --- a/example/lib/repositories/adyen_sessions_repository.dart +++ b/example/lib/repositories/adyen_sessions_repository.dart @@ -46,7 +46,7 @@ class AdyenSessionsRepository { recurringProcessingModel: RecurringProcessingModel.cardOnFile.recurringModelString, shopperInteraction: - ShopperInteractionModel.contAuth.shopperInteractionModelString, + ShopperInteractionModel.ecommerce.shopperInteractionModelString, channel: _determineChannel(), telephoneNumber: "+8613012345678", dateOfBirth: "1996-09-04", @@ -115,7 +115,7 @@ class AdyenSessionsRepository { threeDSAuthenticationOnly: false, recurringProcessingModel: RecurringProcessingModel.cardOnFile, shopperInteraction: - ShopperInteractionModel.contAuth.shopperInteractionModelString, + ShopperInteractionModel.ecommerce.shopperInteractionModelString, lineItems: [ LineItem( quantity: 1, From 1569dd622bbe262c5ea7704cb515d733f01bf22f Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Mon, 16 Oct 2023 13:26:20 +0200 Subject: [PATCH 08/13] Supported closing view controller e.g. an error happens while using apple pay --- .../DropInAdvancedFlowDelegate.swift | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift index 9e99c9b3..ada0aea2 100644 --- a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift +++ b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift @@ -55,14 +55,20 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { } func didFail(with error: Error, from dropInComponent: Adyen.AnyDropInComponent) { - dropInComponent.viewController.dismiss(animated: true, completion: { - switch error { - case ComponentError.cancelled: - let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: PaymentResultDTO(type: PaymentResultEnum.cancelledByUser, reason: error.localizedDescription)) - self.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) - default: - self.sendErrorToFlutterLayer(error: error) - } + dropInComponent.viewController.dismiss(animated: false) + self.dropInComponent.finalizeIfNeeded(with: false, completion: { [weak self] in + guard let self = self else { return } + self.dropInComponent.viewController.dismiss(animated: true, completion: { [weak self] in + guard let self = self else { return } + + switch error { + case ComponentError.cancelled: + let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: PaymentResultDTO(type: PaymentResultEnum.cancelledByUser, reason: error.localizedDescription)) + self.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) + default: + self.sendErrorToFlutterLayer(error: error) + } + }) }) } From 8f0b6abfcf658cace4501904e1632c0437f6c425 Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Mon, 16 Oct 2023 16:12:48 +0200 Subject: [PATCH 09/13] Moved dropin configuration mapping into dto mapper --- example/lib/main.dart | 11 +++- lib/adyen_checkout.dart | 1 + lib/src/adyen_checkout.dart | 61 +------------------ lib/src/models/drop_in_configuration.dart | 12 ---- .../stored_payment_method_configuration.dart | 11 ++++ lib/src/utils/dto_mapper.dart | 56 +++++++++-------- 6 files changed, 53 insertions(+), 99 deletions(-) create mode 100644 lib/src/models/stored_payment_method_configuration.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 3847f5c1..4cb4a8a8 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -106,6 +106,11 @@ class _MyAppState extends State { final CashAppPayConfiguration cashAppPayConfiguration = await _createCashAppPayConfiguration(); + final ApplePayConfiguration applePayConfiguration = ApplePayConfiguration( + merchantId: Config.merchantAccount, + merchantName: Config.merchantName, + ); + final DropInConfiguration dropInConfiguration = DropInConfiguration( environment: Environment.test, clientKey: Config.clientKey, @@ -115,6 +120,7 @@ class _MyAppState extends State { cardsConfiguration: cardsConfiguration, storedPaymentMethodConfiguration: storedPaymentMethodConfiguration, cashAppPayConfiguration: cashAppPayConfiguration, + applePayConfiguration: applePayConfiguration, ); return await _adyenCheckout.startPayment( @@ -129,8 +135,9 @@ class _MyAppState extends State { final String paymentMethodsResponse = await _adyenSessionRepository.fetchPaymentMethods(); - final CardsConfiguration cardsConfiguration = - CardsConfiguration(showStorePaymentField: true); + final CardsConfiguration cardsConfiguration = CardsConfiguration( + showStorePaymentField: true, + ); final ApplePayConfiguration applePayConfiguration = ApplePayConfiguration( merchantId: Config.merchantAccount, diff --git a/lib/adyen_checkout.dart b/lib/adyen_checkout.dart index 921f1045..e8b8cc26 100644 --- a/lib/adyen_checkout.dart +++ b/lib/adyen_checkout.dart @@ -20,3 +20,4 @@ export 'src/models/payment_method_configurations/cash_app_pay_configuration.dart export 'src/models/payment_method_configurations/google_pay_configuration.dart'; export 'src/models/payment_result.dart'; export 'src/models/session.dart'; +export 'src/models/stored_payment_method_configuration.dart'; diff --git a/lib/src/adyen_checkout.dart b/lib/src/adyen_checkout.dart index a3e8ea4c..c49a2385 100644 --- a/lib/src/adyen_checkout.dart +++ b/lib/src/adyen_checkout.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:adyen_checkout/adyen_checkout.dart'; import 'package:adyen_checkout/src/adyen_checkout_interface.dart'; @@ -48,36 +47,9 @@ class AdyenCheckout implements AdyenCheckoutInterface { DropInSession dropInSession) async { _adyenLogger.print("Start Drop-in session"); final dropInSessionCompleter = Completer(); - DropInConfigurationDTO dropInConfiguration = DropInConfigurationDTO( - environment: dropInSession.dropInConfiguration.environment, - clientKey: dropInSession.dropInConfiguration.clientKey, - countryCode: dropInSession.dropInConfiguration.countryCode, - amount: dropInSession.dropInConfiguration.amount.toDTO(), - shopperLocale: dropInSession.dropInConfiguration.shopperLocale ?? - Platform.localeName, - cardsConfigurationDTO: - dropInSession.dropInConfiguration.cardsConfiguration?.toDTO(), - applePayConfigurationDTO: - dropInSession.dropInConfiguration.applePayConfiguration?.toDTO(), - googlePayConfigurationDTO: - dropInSession.dropInConfiguration.googlePayConfiguration?.toDTO(), - cashAppPayConfigurationDTO: - dropInSession.dropInConfiguration.cashAppPayConfiguration?.toDTO(), - analyticsOptionsDTO: - dropInSession.dropInConfiguration.analyticsOptions?.toDTO(), - isRemoveStoredPaymentMethodEnabled: - isRemoveStoredPaymentMethodEnabled(dropInSession.dropInConfiguration), - showPreselectedStoredPaymentMethod: dropInSession - .dropInConfiguration - .storedPaymentMethodConfiguration - ?.showPreselectedStoredPaymentMethod ?? - true, - skipListWhenSinglePaymentMethod: - dropInSession.dropInConfiguration.skipListWhenSinglePaymentMethod, - ); AdyenCheckoutPlatformInterface.instance.startDropInSessionPayment( session: dropInSession.session.toDTO(), - dropInConfiguration: dropInConfiguration, + dropInConfiguration: dropInSession.dropInConfiguration.toDTO(), ); _resultApi.dropInSessionPlatformCommunicationStream = @@ -124,39 +96,10 @@ class AdyenCheckout implements AdyenCheckoutInterface { DropInAdvancedFlow dropInAdvancedFlow) async { _adyenLogger.print("Start Drop-in advanced flow"); final dropInAdvancedFlowCompleter = Completer(); - DropInConfigurationDTO dropInConfiguration = DropInConfigurationDTO( - environment: dropInAdvancedFlow.dropInConfiguration.environment, - clientKey: dropInAdvancedFlow.dropInConfiguration.clientKey, - countryCode: dropInAdvancedFlow.dropInConfiguration.countryCode, - amount: dropInAdvancedFlow.dropInConfiguration.amount.toDTO(), - shopperLocale: dropInAdvancedFlow.dropInConfiguration.shopperLocale ?? - Platform.localeName, - cardsConfigurationDTO: - dropInAdvancedFlow.dropInConfiguration.cardsConfiguration?.toDTO(), - applePayConfigurationDTO: - dropInAdvancedFlow.dropInConfiguration.applePayConfiguration?.toDTO(), - googlePayConfigurationDTO: dropInAdvancedFlow - .dropInConfiguration.googlePayConfiguration - ?.toDTO(), - cashAppPayConfigurationDTO: dropInAdvancedFlow - .dropInConfiguration.cashAppPayConfiguration - ?.toDTO(), - analyticsOptionsDTO: - dropInAdvancedFlow.dropInConfiguration.analyticsOptions?.toDTO(), - showPreselectedStoredPaymentMethod: dropInAdvancedFlow - .dropInConfiguration - .storedPaymentMethodConfiguration - ?.showPreselectedStoredPaymentMethod ?? - true, - isRemoveStoredPaymentMethodEnabled: isRemoveStoredPaymentMethodEnabled( - dropInAdvancedFlow.dropInConfiguration), - skipListWhenSinglePaymentMethod: dropInAdvancedFlow - .dropInConfiguration.skipListWhenSinglePaymentMethod, - ); AdyenCheckoutPlatformInterface.instance.startDropInAdvancedFlowPayment( paymentMethodsResponse: dropInAdvancedFlow.paymentMethodsResponse, - dropInConfiguration: dropInConfiguration, + dropInConfiguration: dropInAdvancedFlow.dropInConfiguration.toDTO(), ); _resultApi.dropInAdvancedFlowPlatformCommunicationStream = diff --git a/lib/src/models/drop_in_configuration.dart b/lib/src/models/drop_in_configuration.dart index 0eb5e13b..4e436055 100644 --- a/lib/src/models/drop_in_configuration.dart +++ b/lib/src/models/drop_in_configuration.dart @@ -30,15 +30,3 @@ class DropInConfiguration { this.skipListWhenSinglePaymentMethod = false, }); } - -class StoredPaymentMethodConfiguration { - final bool showPreselectedStoredPaymentMethod; - final bool isRemoveStoredPaymentMethodEnabled; - final Future Function(String)? deleteStoredPaymentMethodCallback; - - StoredPaymentMethodConfiguration({ - this.showPreselectedStoredPaymentMethod = true, - this.isRemoveStoredPaymentMethodEnabled = false, - this.deleteStoredPaymentMethodCallback, - }); -} diff --git a/lib/src/models/stored_payment_method_configuration.dart b/lib/src/models/stored_payment_method_configuration.dart new file mode 100644 index 00000000..13f4c07b --- /dev/null +++ b/lib/src/models/stored_payment_method_configuration.dart @@ -0,0 +1,11 @@ +class StoredPaymentMethodConfiguration { + final bool showPreselectedStoredPaymentMethod; + final bool isRemoveStoredPaymentMethodEnabled; + final Future Function(String)? deleteStoredPaymentMethodCallback; + + StoredPaymentMethodConfiguration({ + this.showPreselectedStoredPaymentMethod = true, + this.isRemoveStoredPaymentMethodEnabled = false, + this.deleteStoredPaymentMethodCallback, + }); +} \ No newline at end of file diff --git a/lib/src/utils/dto_mapper.dart b/lib/src/utils/dto_mapper.dart index eaa882e5..0a0db92c 100644 --- a/lib/src/utils/dto_mapper.dart +++ b/lib/src/utils/dto_mapper.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:adyen_checkout/adyen_checkout.dart'; import 'package:adyen_checkout/src/generated/platform_api.g.dart'; import 'package:adyen_checkout/src/models/analytics_options.dart'; @@ -9,6 +11,34 @@ extension AnalyticsOptionsMapper on AnalyticsOptions { ); } +extension DropInConfigurationMapper on DropInConfiguration { + DropInConfigurationDTO toDTO() => DropInConfigurationDTO( + environment: environment, + clientKey: clientKey, + countryCode: countryCode.toUpperCase(), + amount: amount.toDTO(), + shopperLocale: shopperLocale ?? Platform.localeName, + cardsConfigurationDTO: cardsConfiguration?.toDTO(), + applePayConfigurationDTO: applePayConfiguration?.toDTO(), + googlePayConfigurationDTO: googlePayConfiguration?.toDTO(), + cashAppPayConfigurationDTO: cashAppPayConfiguration?.toDTO(), + analyticsOptionsDTO: analyticsOptions?.toDTO(), + isRemoveStoredPaymentMethodEnabled: _isRemoveStoredPaymentMethodEnabled( + storedPaymentMethodConfiguration), + showPreselectedStoredPaymentMethod: storedPaymentMethodConfiguration + ?.showPreselectedStoredPaymentMethod ?? + true, + skipListWhenSinglePaymentMethod: skipListWhenSinglePaymentMethod, + ); + + bool _isRemoveStoredPaymentMethodEnabled( + StoredPaymentMethodConfiguration? storedPaymentMethodConfiguration) => + storedPaymentMethodConfiguration?.deleteStoredPaymentMethodCallback != + null && + storedPaymentMethodConfiguration?.isRemoveStoredPaymentMethodEnabled == + true; +} + extension CardsConfigurationMapper on CardsConfiguration { CardsConfigurationDTO toDTO() => CardsConfigurationDTO( holderNameRequired: holderNameRequired, @@ -75,29 +105,3 @@ extension OrderResponseMapper on OrderResponseDTO { orderData: orderData, ); } - -extension CardsConfigurationDTOCopy on CardsConfigurationDTO { - CardsConfigurationDTO copyWith({ - bool? holderNameRequired, - AddressMode? addressMode, - bool? showStorePaymentField, - bool? showCvcForStoredCard, - bool? showCvc, - FieldVisibility? kcpFieldVisibility, - FieldVisibility? socialSecurityNumberFieldVisibility, - List? supportedCardTypes, - }) => - CardsConfigurationDTO( - holderNameRequired: holderNameRequired ?? this.holderNameRequired, - addressMode: addressMode ?? this.addressMode, - showStorePaymentField: - showStorePaymentField ?? this.showStorePaymentField, - showCvcForStoredCard: showCvcForStoredCard ?? this.showCvcForStoredCard, - showCvc: showCvc ?? this.showCvc, - kcpFieldVisibility: kcpFieldVisibility ?? this.kcpFieldVisibility, - socialSecurityNumberFieldVisibility: - socialSecurityNumberFieldVisibility ?? - this.socialSecurityNumberFieldVisibility, - supportedCardTypes: supportedCardTypes ?? this.supportedCardTypes, - ); -} From cd654d6dd2f277fb14e6ab68a4ef7c93c5022835 Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Thu, 19 Oct 2023 16:15:54 +0200 Subject: [PATCH 10/13] Applied changes from code review --- .../network/models/amount_network_model.dart | 2 +- .../lib/network/models/delivery_address.dart | 12 ++++++++ ios/Classes/CheckoutPlatformApi.swift | 22 +++++++-------- .../DropInAdvancedFlowDelegate.swift | 28 ++++++++++--------- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/example/lib/network/models/amount_network_model.dart b/example/lib/network/models/amount_network_model.dart index 45e1fb58..83d9a581 100644 --- a/example/lib/network/models/amount_network_model.dart +++ b/example/lib/network/models/amount_network_model.dart @@ -1,5 +1,5 @@ class AmountNetworkModel { - final String? currency; + final String currency; final int value; AmountNetworkModel({ diff --git a/example/lib/network/models/delivery_address.dart b/example/lib/network/models/delivery_address.dart index 4e966ccb..e4b579b2 100644 --- a/example/lib/network/models/delivery_address.dart +++ b/example/lib/network/models/delivery_address.dart @@ -4,6 +4,9 @@ class DeliveryAddress { String? houseNumberOrName; String? postalCode; String? street; + String? firstName; + String? lastName; + String? stateOrProvince; DeliveryAddress({ this.city, @@ -11,6 +14,9 @@ class DeliveryAddress { this.houseNumberOrName, this.postalCode, this.street, + this.firstName, + this.lastName, + this.stateOrProvince }); DeliveryAddress.fromJson(Map json) { @@ -19,6 +25,9 @@ class DeliveryAddress { houseNumberOrName = json['houseNumberOrName']; postalCode = json['postalCode']; street = json['street']; + firstName = json['firstname']; + lastName = json['firstname']; + stateOrProvince = json['stateOrProvince']; } Map toJson() { @@ -28,6 +37,9 @@ class DeliveryAddress { data['houseNumberOrName'] = houseNumberOrName; data['postalCode'] = postalCode; data['street'] = street; + data['firstName'] = firstName; + data['lastName'] = lastName; + data['stateOrProvince'] = stateOrProvince; return data; } } diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift index 35f1a99c..0f686f26 100644 --- a/ios/Classes/CheckoutPlatformApi.swift +++ b/ios/Classes/CheckoutPlatformApi.swift @@ -90,7 +90,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { let dropInComponent = DropInComponent(paymentMethods: paymentMethodsWithoutGiftCards, context: adyenContext, configuration: configuration) - dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(checkoutFlutterApi: checkoutFlutterApi, dropInComponent: dropInComponent) + dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(parentViewController: viewController, checkoutFlutterApi: checkoutFlutterApi, dropInComponent: dropInComponent) dropInComponent.delegate = dropInAdvancedFlowDelegate if dropInConfigurationDTO.isRemoveStoredPaymentMethodEnabled == true { @@ -177,14 +177,14 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { } private func handleDropInResult(dropInResult: DropInResultDTO) { - switch dropInResult.dropInResultType { - case .finished: - onDropInResultFinished(dropInResult: dropInResult) - case .action: - onDropInResultAction(dropInResult: dropInResult) - case .error: - onDropInResultError(dropInResult: dropInResult) - } + switch dropInResult.dropInResultType { + case .finished: + onDropInResultFinished(dropInResult: dropInResult) + case .action: + onDropInResultAction(dropInResult: dropInResult) + case .error: + onDropInResultError(dropInResult: dropInResult) + } } private func onDropInResultFinished(dropInResult: DropInResultDTO) { @@ -212,8 +212,8 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { private func onDropInResultError(dropInResult: DropInResultDTO) { dropInComponent?.stopLoading() - - if (dropInResult.error?.dismissDropIn == true) { + + if dropInResult.error?.dismissDropIn == true { let paymentResult = PaymentResultDTO(type: PaymentResultEnum.error, reason: dropInResult.error?.errorMessage) checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) finalize(false, dropInResult.error?.errorMessage ?? "") diff --git a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift index ada0aea2..31233abb 100644 --- a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift +++ b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift @@ -2,10 +2,12 @@ import Adyen import AdyenNetworking class DropInAdvancedFlowDelegate: DropInComponentDelegate { + private let parentViewController: UIViewController private let checkoutFlutterApi: CheckoutFlutterApi private let dropInComponent: DropInComponent - init(checkoutFlutterApi: CheckoutFlutterApi, dropInComponent: DropInComponent) { + init(parentViewController: UIViewController, checkoutFlutterApi: CheckoutFlutterApi, dropInComponent: DropInComponent) { + self.parentViewController = parentViewController self.checkoutFlutterApi = checkoutFlutterApi self.dropInComponent = dropInComponent } @@ -41,7 +43,7 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { self.dropInComponent.viewController.dismiss(animated: true) }) } - + func didFail(with error: Error, from _: PaymentComponent, in dropInComponent: AnyDropInComponent) { dropInComponent.viewController.presentedViewController?.dismiss(animated: true, completion: { self.sendErrorToFlutterLayer(error: error) @@ -54,26 +56,26 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { }) } - func didFail(with error: Error, from dropInComponent: Adyen.AnyDropInComponent) { - dropInComponent.viewController.dismiss(animated: false) - self.dropInComponent.finalizeIfNeeded(with: false, completion: { [weak self] in - guard let self = self else { return } - self.dropInComponent.viewController.dismiss(animated: true, completion: { [weak self] in - guard let self = self else { return } - + func didFail(with error: Error, from _: Adyen.AnyDropInComponent) { + dropInComponent.finalizeIfNeeded(with: false, completion: { [weak self] in + self?.parentViewController.dismiss(animated: true, completion: { [weak self] in switch error { case ComponentError.cancelled: - let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: PaymentResultDTO(type: PaymentResultEnum.cancelledByUser, reason: error.localizedDescription)) - self.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) + let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, + paymentResult: PaymentResultDTO(type: PaymentResultEnum.cancelledByUser, + reason: error.localizedDescription)) + self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) default: - self.sendErrorToFlutterLayer(error: error) + self?.sendErrorToFlutterLayer(error: error) } }) }) } private func sendErrorToFlutterLayer(error: Error) { - let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: PaymentResultDTO(type: PaymentResultEnum.error, reason: error.localizedDescription)) + let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, + paymentResult: PaymentResultDTO(type: PaymentResultEnum.error, + reason: error.localizedDescription)) checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) } } From 76d26f8f1fb4a6ed5a15e02ffe56d6b85cdd08d0 Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Fri, 20 Oct 2023 10:07:02 +0200 Subject: [PATCH 11/13] Added finalized and dismiss callback instead of using view controller --- ios/Classes/CheckoutPlatformApi.swift | 17 ++++++----- .../DropInAdvancedFlowDelegate.swift | 28 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift index 0f686f26..e441db73 100644 --- a/ios/Classes/CheckoutPlatformApi.swift +++ b/ios/Classes/CheckoutPlatformApi.swift @@ -90,7 +90,9 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { let dropInComponent = DropInComponent(paymentMethods: paymentMethodsWithoutGiftCards, context: adyenContext, configuration: configuration) - dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(parentViewController: viewController, checkoutFlutterApi: checkoutFlutterApi, dropInComponent: dropInComponent) + dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(finalizeAndDismissCallback: finalizeAndDismiss, + checkoutFlutterApi: checkoutFlutterApi, + dropInComponent: dropInComponent) dropInComponent.delegate = dropInAdvancedFlowDelegate if dropInConfigurationDTO.isRemoveStoredPaymentMethodEnabled == true { @@ -133,6 +135,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { dropInSessionStoredPaymentMethodsDelegate = nil dropInAdvancedFlowDelegate = nil dropInAdvancedFlowStoredPaymentMethodsDelegate = nil + viewController = nil } private func getViewController() -> UIViewController? { @@ -206,7 +209,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { } catch { let paymentResult = PaymentResultDTO(type: PaymentResultEnum.error, reason: error.localizedDescription) checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) - finalize(false, "\(error.localizedDescription)") + finalizeAndDismiss(false) } } @@ -216,7 +219,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { if dropInResult.error?.dismissDropIn == true { let paymentResult = PaymentResultDTO(type: PaymentResultEnum.error, reason: dropInResult.error?.errorMessage) checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) - finalize(false, dropInResult.error?.errorMessage ?? "") + finalizeAndDismiss(false) } else { dropInComponent?.finalizeIfNeeded(with: false, completion: {}) let localizationParameters = (dropInComponent as? Localizable)?.localizationParameters @@ -229,10 +232,10 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { } } - private func finalize(_ success: Bool, _: String) { - dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in - guard let self = self else { return } - self.viewController?.dismiss(animated: true) + private func finalizeAndDismiss(_ success: Bool, completion: (() -> Void)? = {}) { + dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in + self?.viewController?.dismiss(animated: true) + completion?() } } diff --git a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift index 31233abb..91158c58 100644 --- a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift +++ b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift @@ -2,12 +2,12 @@ import Adyen import AdyenNetworking class DropInAdvancedFlowDelegate: DropInComponentDelegate { - private let parentViewController: UIViewController + private let finalizeAndDismissCallback: (_ success: Bool, (() -> Void)?) -> Void? private let checkoutFlutterApi: CheckoutFlutterApi private let dropInComponent: DropInComponent - init(parentViewController: UIViewController, checkoutFlutterApi: CheckoutFlutterApi, dropInComponent: DropInComponent) { - self.parentViewController = parentViewController + init(finalizeAndDismissCallback: @escaping (_ success: Bool, (() -> Void)?) -> Void, checkoutFlutterApi: CheckoutFlutterApi, dropInComponent: DropInComponent) { + self.finalizeAndDismissCallback = finalizeAndDismissCallback self.checkoutFlutterApi = checkoutFlutterApi self.dropInComponent = dropInComponent } @@ -57,18 +57,16 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { } func didFail(with error: Error, from _: Adyen.AnyDropInComponent) { - dropInComponent.finalizeIfNeeded(with: false, completion: { [weak self] in - self?.parentViewController.dismiss(animated: true, completion: { [weak self] in - switch error { - case ComponentError.cancelled: - let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, - paymentResult: PaymentResultDTO(type: PaymentResultEnum.cancelledByUser, - reason: error.localizedDescription)) - self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) - default: - self?.sendErrorToFlutterLayer(error: error) - } - }) + finalizeAndDismissCallback(false, { [weak self] in + switch error { + case ComponentError.cancelled: + let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, + paymentResult: PaymentResultDTO(type: PaymentResultEnum.cancelledByUser, + reason: error.localizedDescription)) + self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) + default: + self?.sendErrorToFlutterLayer(error: error) + } }) } From db114ad44d21b79e1b3165fd809df17b3e26ea1c Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Fri, 20 Oct 2023 10:18:50 +0200 Subject: [PATCH 12/13] Use finalize and dismiss callback for handling drop-in closing in a single place --- ios/Classes/CheckoutPlatformApi.swift | 17 ++++++++--------- .../DropInAdvancedFlowDelegate.swift | 16 +++++++--------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift index e441db73..e1ee31ab 100644 --- a/ios/Classes/CheckoutPlatformApi.swift +++ b/ios/Classes/CheckoutPlatformApi.swift @@ -193,12 +193,10 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { private func onDropInResultFinished(dropInResult: DropInResultDTO) { let resultCode = ResultCode(rawValue: dropInResult.result ?? "") let success = resultCode == .authorised || resultCode == .received || resultCode == .pending - dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in - self?.dropInComponent?.viewController.presentingViewController?.dismiss(animated: false, completion: { - let paymentResult = PaymentResultDTO(type: PaymentResultEnum.finished, result: PaymentResultModelDTO(resultCode: resultCode?.rawValue)) - self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) - }) - } + finalizeAndDismiss(true, completion: { [weak self] in + let paymentResult = PaymentResultDTO(type: PaymentResultEnum.finished, result: PaymentResultModelDTO(resultCode: resultCode?.rawValue)) + self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) + }) } private func onDropInResultAction(dropInResult: DropInResultDTO) { @@ -233,9 +231,10 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { } private func finalizeAndDismiss(_ success: Bool, completion: (() -> Void)? = {}) { - dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in - self?.viewController?.dismiss(animated: true) - completion?() + dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in + self?.viewController?.dismiss(animated: true, completion: { + completion?() + }) } } diff --git a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift index 91158c58..cd78b2a1 100644 --- a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift +++ b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift @@ -35,13 +35,11 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { } func didComplete(from _: ActionComponent, in _: AnyDropInComponent) { - let paymentResult = PaymentResultDTO(type: PaymentResultEnum.finished, result: PaymentResultModelDTO(resultCode: ResultCode.received.rawValue)) - let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult) - checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) - dropInComponent.finalizeIfNeeded(with: true, completion: { [weak self] in - guard let self = self else { return } - self.dropInComponent.viewController.dismiss(animated: true) - }) + finalizeAndDismissCallback(true) { [weak self] in + let paymentResult = PaymentResultDTO(type: PaymentResultEnum.finished, result: PaymentResultModelDTO(resultCode: ResultCode.received.rawValue)) + let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult) + self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) + } } func didFail(with error: Error, from _: PaymentComponent, in dropInComponent: AnyDropInComponent) { @@ -57,7 +55,7 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { } func didFail(with error: Error, from _: Adyen.AnyDropInComponent) { - finalizeAndDismissCallback(false, { [weak self] in + finalizeAndDismissCallback(false) { [weak self] in switch error { case ComponentError.cancelled: let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, @@ -67,7 +65,7 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { default: self?.sendErrorToFlutterLayer(error: error) } - }) + } } private func sendErrorToFlutterLayer(error: Error) { From 243d29223ed60c192d3436fcb8308cca36f7960c Mon Sep 17 00:00:00 2001 From: Robert Schulze Dieckhoff Date: Mon, 23 Oct 2023 11:01:37 +0200 Subject: [PATCH 13/13] Switched to drop-in interactor --- ios/Classes/CheckoutPlatformApi.swift | 32 ++++++++++--------- ios/Classes/DropInInteractorDelegate.swift | 4 +++ .../DropInAdvancedFlowDelegate.swift | 23 ++++++------- 3 files changed, 31 insertions(+), 28 deletions(-) create mode 100644 ios/Classes/DropInInteractorDelegate.swift diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift index e1ee31ab..838ea0e6 100644 --- a/ios/Classes/CheckoutPlatformApi.swift +++ b/ios/Classes/CheckoutPlatformApi.swift @@ -17,7 +17,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { private var session: AdyenSession? private var dropInSessionDelegate: AdyenSessionDelegate? private var dropInSessionPresentationDelegate: PresentationDelegate? - private var dropInAdvancedFlowDelegate: DropInComponentDelegate? + private var dropInAdvancedFlowDelegate: DropInAdvancedFlowDelegate? private var dropInSessionStoredPaymentMethodsDelegate: DropInSessionsStoredPaymentMethodsDelegate? private var dropInAdvancedFlowStoredPaymentMethodsDelegate: DropInAdvancedFlowStoredPaymentMethodsDelegate? @@ -90,9 +90,8 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { let dropInComponent = DropInComponent(paymentMethods: paymentMethodsWithoutGiftCards, context: adyenContext, configuration: configuration) - dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(finalizeAndDismissCallback: finalizeAndDismiss, - checkoutFlutterApi: checkoutFlutterApi, - dropInComponent: dropInComponent) + dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(checkoutFlutterApi: checkoutFlutterApi) + dropInAdvancedFlowDelegate?.dropInInteractorDelegate = self dropInComponent.delegate = dropInAdvancedFlowDelegate if dropInConfigurationDTO.isRemoveStoredPaymentMethodEnabled == true { @@ -133,6 +132,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { dropInSessionDelegate = nil dropInSessionPresentationDelegate = nil dropInSessionStoredPaymentMethodsDelegate = nil + dropInAdvancedFlowDelegate?.dropInInteractorDelegate = nil dropInAdvancedFlowDelegate = nil dropInAdvancedFlowStoredPaymentMethodsDelegate = nil viewController = nil @@ -193,7 +193,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { private func onDropInResultFinished(dropInResult: DropInResultDTO) { let resultCode = ResultCode(rawValue: dropInResult.result ?? "") let success = resultCode == .authorised || resultCode == .received || resultCode == .pending - finalizeAndDismiss(true, completion: { [weak self] in + finalizeAndDismiss(success: true, completion: { [weak self] in let paymentResult = PaymentResultDTO(type: PaymentResultEnum.finished, result: PaymentResultModelDTO(resultCode: resultCode?.rawValue)) self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) }) @@ -207,7 +207,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { } catch { let paymentResult = PaymentResultDTO(type: PaymentResultEnum.error, reason: error.localizedDescription) checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) - finalizeAndDismiss(false) + finalizeAndDismiss(success: false) {} } } @@ -217,7 +217,7 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { if dropInResult.error?.dismissDropIn == true { let paymentResult = PaymentResultDTO(type: PaymentResultEnum.error, reason: dropInResult.error?.errorMessage) checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult), completion: { _ in }) - finalizeAndDismiss(false) + finalizeAndDismiss(success: false) {} } else { dropInComponent?.finalizeIfNeeded(with: false, completion: {}) let localizationParameters = (dropInComponent as? Localizable)?.localizationParameters @@ -230,14 +230,6 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { } } - private func finalizeAndDismiss(_ success: Bool, completion: (() -> Void)? = {}) { - dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in - self?.viewController?.dismiss(animated: true, completion: { - completion?() - }) - } - } - private func removeGiftCardPaymentMethods(paymentMethods: PaymentMethods) -> PaymentMethods { let storedPaymentMethods = paymentMethods.stored.filter { !($0.type == PaymentMethodType.giftcard) } let paymentMethods = paymentMethods.regular.filter { !($0.type == PaymentMethodType.giftcard) } @@ -249,3 +241,13 @@ class CheckoutPlatformApi: CheckoutPlatformInterface { checkoutFlutterApi.onDropInSessionPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) } } + +extension CheckoutPlatformApi : DropInInteractorDelegate { + func finalizeAndDismiss(success: Bool, completion: @escaping (() -> Void)) { + dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in + self?.viewController?.dismiss(animated: true, completion: { + completion() + }) + } + } +} diff --git a/ios/Classes/DropInInteractorDelegate.swift b/ios/Classes/DropInInteractorDelegate.swift new file mode 100644 index 00000000..cf83df65 --- /dev/null +++ b/ios/Classes/DropInInteractorDelegate.swift @@ -0,0 +1,4 @@ +public protocol DropInInteractorDelegate : AnyObject { + + func finalizeAndDismiss(success: Bool, completion: @escaping (() -> Void)) +} diff --git a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift index cd78b2a1..4c9665dd 100644 --- a/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift +++ b/ios/Classes/dropInAdvancedFlow/DropInAdvancedFlowDelegate.swift @@ -2,14 +2,11 @@ import Adyen import AdyenNetworking class DropInAdvancedFlowDelegate: DropInComponentDelegate { - private let finalizeAndDismissCallback: (_ success: Bool, (() -> Void)?) -> Void? private let checkoutFlutterApi: CheckoutFlutterApi - private let dropInComponent: DropInComponent + public weak var dropInInteractorDelegate: DropInInteractorDelegate? - init(finalizeAndDismissCallback: @escaping (_ success: Bool, (() -> Void)?) -> Void, checkoutFlutterApi: CheckoutFlutterApi, dropInComponent: DropInComponent) { - self.finalizeAndDismissCallback = finalizeAndDismissCallback + init(checkoutFlutterApi: CheckoutFlutterApi) { self.checkoutFlutterApi = checkoutFlutterApi - self.dropInComponent = dropInComponent } func didSubmit(_ data: PaymentComponentData, from _: PaymentComponent, in _: AnyDropInComponent) { @@ -35,7 +32,7 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { } func didComplete(from _: ActionComponent, in _: AnyDropInComponent) { - finalizeAndDismissCallback(true) { [weak self] in + dropInInteractorDelegate?.finalizeAndDismiss(success:true) { [weak self] in let paymentResult = PaymentResultDTO(type: PaymentResultEnum.finished, result: PaymentResultModelDTO(resultCode: ResultCode.received.rawValue)) let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, paymentResult: paymentResult) self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: { _ in }) @@ -43,19 +40,19 @@ class DropInAdvancedFlowDelegate: DropInComponentDelegate { } func didFail(with error: Error, from _: PaymentComponent, in dropInComponent: AnyDropInComponent) { - dropInComponent.viewController.presentedViewController?.dismiss(animated: true, completion: { - self.sendErrorToFlutterLayer(error: error) - }) + dropInInteractorDelegate?.finalizeAndDismiss(success: false) { [weak self] in + self?.sendErrorToFlutterLayer(error: error) + } } func didFail(with error: Error, from _: ActionComponent, in dropInComponent: AnyDropInComponent) { - dropInComponent.viewController.presentedViewController?.dismiss(animated: true, completion: { - self.sendErrorToFlutterLayer(error: error) - }) + dropInInteractorDelegate?.finalizeAndDismiss(success: false) { [weak self] in + self?.sendErrorToFlutterLayer(error: error) + } } func didFail(with error: Error, from _: Adyen.AnyDropInComponent) { - finalizeAndDismissCallback(false) { [weak self] in + dropInInteractorDelegate?.finalizeAndDismiss(success: false) { [weak self] in switch error { case ComponentError.cancelled: let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result,