Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add dropin advanced flow ios #32

Merged
merged 11 commits into from
Sep 13, 2023

Conversation

Robert-SD
Copy link
Collaborator

Summary

Added drop in advanced flow for iOS

diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift
index 49d9dfe..4d4a355 100644
--- a/ios/Classes/CheckoutPlatformApi.swift
+++ b/ios/Classes/CheckoutPlatformApi.swift
@@ -1,16 +1,10 @@
-//
-//  CheckoutApi.swift
-//  adyen_checkout
-//
-//  Created by Robert Schulze Dieckhoff on 07/08/2023.
-//

 import Foundation
 @_spi(AdyenInternal)
 import Adyen
+@_spi(AdyenInternal)
 import AdyenNetworking

-
 //Todo Add config:
 // 1) Add Info.plist for adding photo library usage description
 // 2) Add url scheme
@@ -21,7 +15,8 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
     private var session: AdyenSession?
     private var dropInComponent: DropInComponent?
     private var viewController : UIViewController?
-
+    private let jsonDecoder = JSONDecoder()
+
     init(checkoutFlutterApi: CheckoutFlutterApi) {
         self.checkoutFlutterApi = checkoutFlutterApi
     }
@@ -43,8 +38,7 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
                     switch result {
                     case let .success(session):
                         self?.session = session
-                        let paymentMethods = session.sessionContext.paymentMethods
-                        let dropInConfiguration = self?.createDropInConfiguration(paymentMethods: paymentMethods)
+                        let dropInConfiguration = self?.createDropInConfiguration()
                         let dropInComponent = DropInComponent(paymentMethods: session.sessionContext.paymentMethods,
                                                               context: adyenContext,
                                                               configuration: dropInConfiguration!)
@@ -66,7 +60,19 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {

     func startDropInAdvancedFlowPayment(dropInConfiguration: DropInConfiguration, paymentMethodsResponse: String) {
-
+        do {
+            viewController = UIApplication.shared.adyen.mainKeyWindow?.rootViewController
+            let adyenContext = try createAdyenContext(dropInConfiguration: dropInConfiguration)
+            let paymentMethods = try jsonDecoder.decode(PaymentMethods.self, from:Data(paymentMethodsResponse.utf8))
+            let configuration = createDropInConfiguration()
+            let dropInComponent = DropInComponent(paymentMethods: paymentMethods,context: adyenContext,configuration: configuration)
+            dropInComponent.delegate = self
+            dropInComponent.storedPaymentMethodsDelegate = self
+            self.dropInComponent = dropInComponent
+            viewController?.present(dropInComponent.viewController, animated: true)
+        } catch let error {
+            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)), completion: {})
+        }
     }

     func getReturnUrl(completion: @escaping (Result<String, Error>) -> Void) {
@@ -74,11 +80,13 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
     }

     func onPaymentsResult(paymentsResult: DropInResult) throws {
-
+        print(paymentsResult)
+        handleResponse(result: paymentsResult)
     }
-
+
     func onPaymentsDetailsResult(paymentsDetailsResult: DropInResult) throws {
-
+        print(paymentsDetailsResult)
+        handleResponse(result: paymentsDetailsResult)
     }

     private func createAdyenContext(dropInConfiguration: DropInConfiguration) throws  -> AdyenContext  {
@@ -109,11 +117,43 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
         }
     }

-    private func createDropInConfiguration(paymentMethods: PaymentMethods) -> DropInComponent.Configuration {
+    private func createDropInConfiguration() -> DropInComponent.Configuration {
         let dropInConfiguration = DropInComponent.Configuration()
         return dropInConfiguration
     }

+    private func handleResponse(result: [String : Any?]) {
+        do {
+            if let action = result["action"] {
+                let jsonData = try JSONSerialization.data(withJSONObject: action, options: [])
+                let decoder = JSONDecoder()
+                let result = try decoder.decode(Action.self, from: jsonData)
+                self.dropInComponent?.handle(result)
+            } else if result.keys.contains("resultCode") {
+
+                let resultCode = ResultCode(rawValue: result["resultCode"] as! String)
+
+                let success = resultCode == .authorised || resultCode == .received || resultCode == .pending
+                self.dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in
+                    print("dismiss")
+
+                    self?.dropInComponent?.viewController.dismiss(animated: false)
+                    self?.dropInComponent?.viewController.dismiss(animated: false)
+                }
+            }
+        } catch let error {
+            print(error)
+        }
+
+    }
+
+
+    private func finalize(_ success: Bool, _ message: String) {
+        dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in
+            guard let self = self else { return }
+            self.viewController?.dismiss(animated: true)
+        }
+    }
 }

 extension CheckoutPlatformApi: AdyenSessionDelegate {
@@ -142,3 +182,70 @@ extension CheckoutPlatformApi: PresentationDelegate {
         //This is required later when integrating components
     }
 }
+
+
+//AdvancedFlow
+extension CheckoutPlatformApi: DropInComponentDelegate {
+
+    func didSubmit(_ data: PaymentComponentData, from component: PaymentComponent, in dropInComponent: AnyDropInComponent) {
+        do {
+            let componentData = PaymentComponentDataResponse(amount: data.amount, paymentMethod: data.paymentMethod.encodable, storePaymentMethod: data.storePaymentMethod, order: data.order, amountToPay: data.order?.remainingAmount, installments: data.installments, shopperName: data.shopperName, emailAddress: data.emailAddress, telephoneNumber: data.telephoneNumber, browserInfo: data.browserInfo, checkoutAttemptId: data.checkoutAttemptId, billingAddress: data.billingAddress, deliveryAddress: data.deliveryAddress, socialSecurityNumber: data.socialSecurityNumber, delegatedAuthenticationData: data.delegatedAuthenticationData)
+
+            let json = try JSONEncoder().encode(componentData)
+            let jsonString = String(data: json, encoding: .utf8)
+            //TODO discuss to use an actual class instead of json
+            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel:PlatformCommunicationModel(type: PlatformCommunicationType.paymentComponent, data:jsonString ), completion: {})
+        } catch let error {
+            print(error.localizedDescription)
+        }
+    }
+
+    func didFail(with error: Error, from component: PaymentComponent, in dropInComponent: AnyDropInComponent) {
+        print(error)
+        self.dropInComponent?.viewController.dismiss(animated: true)
+    }
+
+    func didProvide(_ data: ActionComponentData, from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
+        print("did provide")
+        do {
+            let actionComponentData = ActionComponentDataModel(details: data.details.encodable, paymentData: data.paymentData)
+            let json = try JSONEncoder().encode(actionComponentData)
+            let jsonString = String(data: json, encoding: .utf8)
+            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel:PlatformCommunicationModel(type: PlatformCommunicationType.additionalDetails, data:jsonString ), completion: {})
+        } catch let error {
+            print(error.localizedDescription)
+        }
+    }
+
+    func didComplete(from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
+        print("did complete")
+    }
+
+    func didFail(with error: Error, from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
+        print(error)
+        self.dropInComponent?.viewController.dismiss(animated: true)
+    }
+
+    internal func didCancel(component: PaymentComponent, from dropInComponent: AnyDropInComponent) {
+        // Handle the event when the user closes a PresentableComponent.
+        print("User did close: \(component.paymentMethod.name)")
+        self.dropInComponent?.viewController.dismiss(animated: true)
+    }
+
+    internal func didFail(with error: Error, from dropInComponent: AnyDropInComponent) {
+        print(error)
+        self.dropInComponent?.viewController.dismiss(animated: true)
+    }
+
+    private func handleAction(action: Action) {
+        print("has action")
+        self.dropInComponent?.handle(action)
+    }
+
+}
+
+extension CheckoutPlatformApi: StoredPaymentMethodsDelegate {
+    internal func disable(storedPaymentMethod: StoredPaymentMethod, completion: @escaping (Bool) -> Void) {
+        print("stored disabled")
+    }
+}
diff --git a/ios/Classes/models/ActionComponentDataModel.swift b/ios/Classes/models/ActionComponentDataModel.swift
new file mode 100644
index 0000000..367c273
--- /dev/null
+++ b/ios/Classes/models/ActionComponentDataModel.swift
@@ -0,0 +1,16 @@
+//
+//  ActionComponentDataModel.swift
+//  adyen_checkout
+//
+//  Created by Robert Schulze Dieckhoff on 30/08/2023.
+//
+
+import Foundation
+import Adyen
+
+struct ActionComponentDataModel : Encodable {
+
+     let details: AnyEncodable
+
+     let paymentData: String?
+}
diff --git a/ios/Classes/models/PaymentComponentDataResponse.swift b/ios/Classes/models/PaymentComponentDataResponse.swift
new file mode 100644
index 0000000..3ca8a86
--- /dev/null
+++ b/ios/Classes/models/PaymentComponentDataResponse.swift
@@ -0,0 +1,55 @@
+import Foundation
+@_spi(AdyenInternal)
+import Adyen
+
+
+struct PaymentComponentDataResponse : Encodable {
+
+    let amount: Adyen.Amount?
+
+    let paymentMethod: AnyEncodable?
+
+    let storePaymentMethod: Bool?
+
+    let order: PartialPaymentOrder?
+
+    @available(*, deprecated, message: "This property is deprecated. Use the amount property if needed.")
+    let amountToPay: Adyen.Amount?
+
+    let installments: Installments?
+
+    let supportNativeRedirect: Bool = true
+
+    let shopperName: ShopperName?
+
+    let emailAddress: String?
+
+    let telephoneNumber: String?
+
+    let browserInfo: BrowserInfo?
+
+    let checkoutAttemptId: String?
+
+    let billingAddress: PostalAddress?
+
+    let deliveryAddress: PostalAddress?
+
+    let socialSecurityNumber: String?
+
+    let delegatedAuthenticationData: DelegatedAuthenticationData?
+
+
+
+
+    enum CodingKeys: String, CodingKey {
+        case amount, paymentMethod, storePaymentMethod, order, amountToPay, installments, supportNativeRedirect,shopperName,emailAddress, telephoneNumber, browserInfo, checkoutAttemptId, billingAddress, deliveryAddress, socialSecurityNumber, delegatedAuthenticationData
+    }
+}
+
+
+struct PaymentMethodDetailsModel: Details, Encodable {
+
+    var checkoutAttemptId: String?
+}
+
+
diff --git a/ios/Classes/models/ResultCode.swift b/ios/Classes/models/ResultCode.swift
new file mode 100644
index 0000000..7d1c6ce
--- /dev/null
+++ b/ios/Classes/models/ResultCode.swift
@@ -0,0 +1,21 @@
+//
+//  ResultCode.swift
+//  adyen_checkout
+//
+//  Created by Robert Schulze Dieckhoff on 30/08/2023.
+//
+
+import Foundation
+
+enum ResultCode: String, Decodable {
+    case authorised = "Authorised"
+    case refused = "Refused"
+    case pending = "Pending"
+    case cancelled = "Cancelled"
+    case error = "Error"
+    case received = "Received"
+    case redirectShopper = "RedirectShopper"
+    case identifyShopper = "IdentifyShopper"
+    case challengeShopper = "ChallengeShopper"
+    case presentToShopper = "PresentToShopper"
+}
diff --git a/ios/Classes/models/ActionComponentDataModel.swift b/ios/Classes/models/ActionComponentDataModel.swift
index 367c273..e5ffda0 100644
--- a/ios/Classes/models/ActionComponentDataModel.swift
+++ b/ios/Classes/models/ActionComponentDataModel.swift
@@ -1,10 +1,3 @@
-//
-//  ActionComponentDataModel.swift
-//  adyen_checkout
-//
-//  Created by Robert Schulze Dieckhoff on 30/08/2023.
-//
-
 import Foundation
 import Adyen

diff --git a/ios/Classes/models/PaymentComponentDataResponse.swift b/ios/Classes/models/PaymentComponentDataResponse.swift
index 3ca8a86..d2e13b0 100644
--- a/ios/Classes/models/PaymentComponentDataResponse.swift
+++ b/ios/Classes/models/PaymentComponentDataResponse.swift
@@ -2,7 +2,6 @@ import Foundation
 @_spi(AdyenInternal)
 import Adyen

-
 struct PaymentComponentDataResponse : Encodable {

     let amount: Adyen.Amount?
@@ -10,7 +9,7 @@ struct PaymentComponentDataResponse : Encodable {
     let paymentMethod: AnyEncodable?

     let storePaymentMethod: Bool?
-
+
     let order: PartialPaymentOrder?

     @available(*, deprecated, message: "This property is deprecated. Use the amount property if needed.")
@@ -21,13 +20,13 @@ struct PaymentComponentDataResponse : Encodable {
     let supportNativeRedirect: Bool = true

     let shopperName: ShopperName?
-
+
     let emailAddress: String?

     let telephoneNumber: String?

     let browserInfo: BrowserInfo?
-
+
     let checkoutAttemptId: String?

     let billingAddress: PostalAddress?
@@ -37,19 +36,8 @@ struct PaymentComponentDataResponse : Encodable {
     let socialSecurityNumber: String?

     let delegatedAuthenticationData: DelegatedAuthenticationData?
-
-
-

     enum CodingKeys: String, CodingKey {
         case amount, paymentMethod, storePaymentMethod, order, amountToPay, installments, supportNativeRedirect,shopperName,emailAddress, telephoneNumber, browserInfo, checkoutAttemptId, billingAddress, deliveryAddress, socialSecurityNumber, delegatedAuthenticationData
     }
 }
-
-
-struct PaymentMethodDetailsModel: Details, Encodable {
-
-    var checkoutAttemptId: String?
-}
-
-
diff --git a/example/lib/network/service.dart b/example/lib/network/service.dart
index cb0dac1..430dc35 100644
--- a/example/lib/network/service.dart
+++ b/example/lib/network/service.dart
@@ -39,7 +39,8 @@ class Service {
     return jsonDecode(response.body);
   }

-  Future<Map<String, dynamic>> postPaymentsDetails(Map<String, dynamic> body) async {
+  Future<Map<String, dynamic>> postPaymentsDetails(
+      Map<String, dynamic> body) async {
     final response = await http.post(
       Uri.https(Config.baseUrl, "/${Config.apiVersion}/payments/details"),
       headers: _createHeaders(),
diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift
index 4d4a355..e21152f 100644
--- a/ios/Classes/CheckoutPlatformApi.swift
+++ b/ios/Classes/CheckoutPlatformApi.swift
@@ -1,4 +1,3 @@
-
 import Foundation
 @_spi(AdyenInternal)
 import Adyen
@@ -11,12 +10,16 @@ import AdyenNetworking
 // 3) Add AppDelegate redirect

 class CheckoutPlatformApi : CheckoutPlatformInterface {
+    var dropInComponent: DropInComponent?
+    private let jsonDecoder = JSONDecoder()
     private let checkoutFlutterApi: CheckoutFlutterApi
-    private var session: AdyenSession?
-    private var dropInComponent: DropInComponent?
     private var viewController : UIViewController?
-    private let jsonDecoder = JSONDecoder()
-
+    private var session: AdyenSession?
+    private var dropInSessionsDelegate : AdyenSessionDelegate?
+    private var dropInSessionsPresentationDelegate : PresentationDelegate?
+    private var dropInAdvancedFlowDelegate : DropInComponentDelegate?
+    private var storedPaymentMethodsDelegate : StoredPaymentMethodsDelegate?
+
     init(checkoutFlutterApi: CheckoutFlutterApi) {
         self.checkoutFlutterApi = checkoutFlutterApi
     }
@@ -28,50 +31,55 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {

     func startDropInSessionPayment(dropInConfiguration: DropInConfiguration, session: Session) {
         do {
-            viewController = UIApplication.shared.adyen.mainKeyWindow?.rootViewController
+            guard let viewController = UIApplication.shared.adyen.mainKeyWindow?.rootViewController else {
+                return
+            }
+
+            self.viewController = viewController
+            dropInSessionsDelegate = DropInSessionsDelegate(viewController: viewController, checkoutFlutterApi: checkoutFlutterApi)
+            dropInSessionsPresentationDelegate = DropInSessionsPresentationDelegate()
             let adyenContext = try createAdyenContext(dropInConfiguration: dropInConfiguration)
-            let configuration = AdyenSession.Configuration(sessionIdentifier: session.id,
-                                                           initialSessionData: session.sessionData,
-                                                           context: adyenContext)
-            DispatchQueue.main.async {
-                AdyenSession.initialize(with: configuration, delegate: self, presentationDelegate: self) { [weak self] result in
-                    switch result {
-                    case let .success(session):
-                        self?.session = session
-                        let dropInConfiguration = self?.createDropInConfiguration()
-                        let dropInComponent = DropInComponent(paymentMethods: session.sessionContext.paymentMethods,
-                                                              context: adyenContext,
-                                                              configuration: dropInConfiguration!)
-                        dropInComponent.delegate = session
-                        dropInComponent.partialPaymentDelegate = session
-                        self?.dropInComponent = dropInComponent
-                        self?.viewController?.present(dropInComponent.viewController, animated: true)
-                    case let .failure(error):
-                        print("Native sdk error: \(error.localizedDescription)")
-                        self?.checkoutFlutterApi.onDropInSessionResult(sessionPaymentResult: PaymentResult(type: PaymentResultEnum.error, reason: error.localizedDescription)) {}
-                    }
+            let configuration = AdyenSession.Configuration(sessionIdentifier: session.id, initialSessionData: session.sessionData, context: adyenContext)
+            AdyenSession.initialize(with: configuration, delegate: self.dropInSessionsDelegate!, presentationDelegate: self.dropInSessionsPresentationDelegate!) { [weak self] result in
+                switch result {
+                case let .success(session):
+                    self?.session = session
+                    let dropInConfiguration = self?.createDropInConfiguration()
+                    let dropInComponent = DropInComponent(paymentMethods: session.sessionContext.paymentMethods, context: adyenContext, configuration: dropInConfiguration!)
+                    dropInComponent.delegate = session
+                    dropInComponent.partialPaymentDelegate = session
+                    self?.dropInComponent = dropInComponent
+                    self?.viewController?.present(dropInComponent.viewController, animated: true)
+                case let .failure(error):
+                    self?.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)) {}
                 }
             }
         } catch let error {
-            print("Native sdk error: \(error.localizedDescription)")
-            checkoutFlutterApi.onDropInSessionResult(sessionPaymentResult: PaymentResult(type: PaymentResultEnum.error, reason: error.localizedDescription)) {}
+            checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)) {}
         }
     }

     func startDropInAdvancedFlowPayment(dropInConfiguration: DropInConfiguration, paymentMethodsResponse: String) {
         do {
-            viewController = UIApplication.shared.adyen.mainKeyWindow?.rootViewController
+            guard let viewController = UIApplication.shared.adyen.mainKeyWindow?.rootViewController else {
+                return
+            }
+
+            self.viewController = viewController
             let adyenContext = try createAdyenContext(dropInConfiguration: dropInConfiguration)
             let paymentMethods = try jsonDecoder.decode(PaymentMethods.self, from:Data(paymentMethodsResponse.utf8))
             let configuration = createDropInConfiguration()
             let dropInComponent = DropInComponent(paymentMethods: paymentMethods,context: adyenContext,configuration: configuration)
-            dropInComponent.delegate = self
-            dropInComponent.storedPaymentMethodsDelegate = self
+            dropInAdvancedFlowDelegate = DropInAdvancedFlowDelegate(checkoutFlutterApi: checkoutFlutterApi, component: dropInComponent)
+            storedPaymentMethodsDelegate = DropInAdvancedFlowStoredPaymentMethodsDelegate()
+            dropInComponent.delegate = dropInAdvancedFlowDelegate
+            dropInComponent.storedPaymentMethodsDelegate = storedPaymentMethodsDelegate
             self.dropInComponent = dropInComponent
-            viewController?.present(dropInComponent.viewController, animated: true)
+            self.viewController?.present(dropInComponent.viewController, animated: true)
         } catch let error {
-            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)), completion: {})
+            let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription))
+            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: {})
         }
     }

@@ -79,13 +87,11 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
         completion(Result.success(""))
     }

-    func onPaymentsResult(paymentsResult: DropInResult) throws {
-        print(paymentsResult)
+    func onPaymentsResult(paymentsResult: DropInResult) {
         handleResponse(result: paymentsResult)
     }

-    func onPaymentsDetailsResult(paymentsDetailsResult: DropInResult) throws {
-        print(paymentsDetailsResult)
+    func onPaymentsDetailsResult(paymentsDetailsResult: DropInResult) {
         handleResponse(result: paymentsDetailsResult)
     }

@@ -124,30 +130,26 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {

     private func handleResponse(result: [String : Any?]) {
         do {
-            if let action = result["action"] {
-                let jsonData = try JSONSerialization.data(withJSONObject: action, options: [])
-                let decoder = JSONDecoder()
-                let result = try decoder.decode(Action.self, from: jsonData)
+            if (result.keys.contains("action")) {
+                let action = result["action"]
+                let jsonData = try JSONSerialization.data(withJSONObject: action as! [String: Any], options: [])
+                let result = try JSONDecoder().decode(Action.self, from: jsonData)
                 self.dropInComponent?.handle(result)
-            } else if result.keys.contains("resultCode") {
-
+            } else if (result.keys.contains("resultCode")) {
                 let resultCode = ResultCode(rawValue: result["resultCode"] as! String)
-
                 let success = resultCode == .authorised || resultCode == .received || resultCode == .pending
                 self.dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in
-                    print("dismiss")
-
-                    self?.dropInComponent?.viewController.dismiss(animated: false)
-                    self?.dropInComponent?.viewController.dismiss(animated: false)
+                    self?.dropInComponent?.viewController.presentingViewController?.dismiss(animated: false, completion: {
+                        let dropInResult = DropInResult(type: DropInResultEnum.finished, result: PaymentResult(resultCode: resultCode?.rawValue))
+                        self?.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: dropInResult), completion: {})
+                    })
                 }
             }
         } catch let error {
             print(error)
         }
-
     }

-
     private func finalize(_ success: Bool, _ message: String) {
         dropInComponent?.finalizeIfNeeded(with: success) { [weak self] in
             guard let self = self else { return }
@@ -155,97 +157,3 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
         }
     }
 }
-
-extension CheckoutPlatformApi: AdyenSessionDelegate {
-    func didComplete(with resultCode: SessionPaymentResultCode, component: Component, session: AdyenSession) {
-        self.viewController?.dismiss(animated: false, completion: {
-            self.checkoutFlutterApi.onDropInSessionResult(sessionPaymentResult: PaymentResult(
-                type: PaymentResultEnum.finished,
-                result: SessionPaymentResultModel(sessionId: session.sessionContext.identifier, sessionData: session.sessionContext.data, resultCode: resultCode.rawValue)), completion: {})
-        })
-    }
-
-    func didFail(with error: Error, from component: Component, session: AdyenSession) {
-        self.viewController?.dismiss(animated: true)
-        print("Native sdk error: \(error.localizedDescription)")
-        checkoutFlutterApi.onDropInSessionResult(sessionPaymentResult: PaymentResult(type: PaymentResultEnum.cancelledByUser, reason: error.localizedDescription)) {}
-    }
-
-    func didOpenExternalApplication(component: ActionComponent, session: AdyenSession) {
-        print("external")
-    }
-}
-
-extension CheckoutPlatformApi: PresentationDelegate {
-    func present(component: PresentableComponent) {
-        print("presentable component")
-        //This is required later when integrating components
-    }
-}
-
-
-//AdvancedFlow
-extension CheckoutPlatformApi: DropInComponentDelegate {
-
-    func didSubmit(_ data: PaymentComponentData, from component: PaymentComponent, in dropInComponent: AnyDropInComponent) {
-        do {
-            let componentData = PaymentComponentDataResponse(amount: data.amount, paymentMethod: data.paymentMethod.encodable, storePaymentMethod: data.storePaymentMethod, order: data.order, amountToPay: data.order?.remainingAmount, installments: data.installments, shopperName: data.shopperName, emailAddress: data.emailAddress, telephoneNumber: data.telephoneNumber, browserInfo: data.browserInfo, checkoutAttemptId: data.checkoutAttemptId, billingAddress: data.billingAddress, deliveryAddress: data.deliveryAddress, socialSecurityNumber: data.socialSecurityNumber, delegatedAuthenticationData: data.delegatedAuthenticationData)
-
-            let json = try JSONEncoder().encode(componentData)
-            let jsonString = String(data: json, encoding: .utf8)
-            //TODO discuss to use an actual class instead of json
-            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel:PlatformCommunicationModel(type: PlatformCommunicationType.paymentComponent, data:jsonString ), completion: {})
-        } catch let error {
-            print(error.localizedDescription)
-        }
-    }
-
-    func didFail(with error: Error, from component: PaymentComponent, in dropInComponent: AnyDropInComponent) {
-        print(error)
-        self.dropInComponent?.viewController.dismiss(animated: true)
-    }
-
-    func didProvide(_ data: ActionComponentData, from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
-        print("did provide")
-        do {
-            let actionComponentData = ActionComponentDataModel(details: data.details.encodable, paymentData: data.paymentData)
-            let json = try JSONEncoder().encode(actionComponentData)
-            let jsonString = String(data: json, encoding: .utf8)
-            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel:PlatformCommunicationModel(type: PlatformCommunicationType.additionalDetails, data:jsonString ), completion: {})
-        } catch let error {
-            print(error.localizedDescription)
-        }
-    }
-
-    func didComplete(from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
-        print("did complete")
-    }
-
-    func didFail(with error: Error, from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
-        print(error)
-        self.dropInComponent?.viewController.dismiss(animated: true)
-    }
-
-    internal func didCancel(component: PaymentComponent, from dropInComponent: AnyDropInComponent) {
-        // Handle the event when the user closes a PresentableComponent.
-        print("User did close: \(component.paymentMethod.name)")
-        self.dropInComponent?.viewController.dismiss(animated: true)
-    }
-
-    internal func didFail(with error: Error, from dropInComponent: AnyDropInComponent) {
-        print(error)
-        self.dropInComponent?.viewController.dismiss(animated: true)
-    }
-
-    private func handleAction(action: Action) {
-        print("has action")
-        self.dropInComponent?.handle(action)
-    }
-
-}
-
-extension CheckoutPlatformApi: StoredPaymentMethodsDelegate {
-    internal func disable(storedPaymentMethod: StoredPaymentMethod, completion: @escaping (Bool) -> Void) {
-        print("stored disabled")
-    }
-}
diff --git a/ios/Classes/dropInSessions/DropInSessionsDelegate.swift b/ios/Classes/dropInSessions/DropInSessionsDelegate.swift
new file mode 100644
index 0000000..f59bae1
--- /dev/null
+++ b/ios/Classes/dropInSessions/DropInSessionsDelegate.swift
@@ -0,0 +1,34 @@
+import Adyen
+import AdyenNetworking
+
+class DropInSessionsDelegate : AdyenSessionDelegate {
+    private let viewController : UIViewController?
+    private let checkoutFlutterApi: CheckoutFlutterApi
+
+    init(viewController: UIViewController, checkoutFlutterApi: CheckoutFlutterApi) {
+        self.viewController = viewController
+        self.checkoutFlutterApi = checkoutFlutterApi
+    }
+
+    func didComplete(with resultCode: SessionPaymentResultCode, component: Component, session: AdyenSession) {
+        viewController?.dismiss(animated: false, completion: {
+            let paymentResult = PaymentResult(sessionId: session.sessionContext.identifier, sessionData: session.sessionContext.data, resultCode: resultCode.rawValue)
+            self.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.finished,result: paymentResult), completion: {})
+        })
+    }
+
+    func didFail(with error: Error, from component: Component, session: AdyenSession) {
+        viewController?.dismiss(animated: true, completion: {
+            switch (error) {
+            case ComponentError.cancelled:
+                self.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.cancelledByUser, reason: error.localizedDescription)) {}
+            default:
+                self.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)) {}
+            }
+        })
+    }
+
+    func didOpenExternalApplication(component: ActionComponent, session: AdyenSession) {
+        print("external")
+    }
+}
diff --git a/ios/Classes/dropInSessions/DropInSessionsPresentationDelegate.swift b/ios/Classes/dropInSessions/DropInSessionsPresentationDelegate.swift
new file mode 100644
index 0000000..74a5eb4
--- /dev/null
+++ b/ios/Classes/dropInSessions/DropInSessionsPresentationDelegate.swift
@@ -0,0 +1,8 @@
+import Adyen
+
+class DropInSessionsPresentationDelegate : PresentationDelegate {
+    func present(component: PresentableComponent) {
+        print("presentable component")
+        //This is required later when integrating components
+    }
+}
diff --git a/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowDelegate.swift
new file mode 100644
index 0000000..b8baac3
--- /dev/null
+++ b/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowDelegate.swift
@@ -0,0 +1,68 @@
+import Adyen
+import AdyenNetworking
+
+class DropInAdvancedFlowDelegate : DropInComponentDelegate {
+    private let checkoutFlutterApi : CheckoutFlutterApi
+    private let component: DropInComponent
+
+    init(checkoutFlutterApi : CheckoutFlutterApi, component: DropInComponent) {
+        self.checkoutFlutterApi = checkoutFlutterApi
+        self.component = component
+    }
+
+    func didSubmit(_ data: PaymentComponentData, from component: PaymentComponent, in dropInComponent: AnyDropInComponent) {
+        do {
+            let paymentComponentData = PaymentComponentDataResponse(amount: data.amount, paymentMethod: data.paymentMethod.encodable, storePaymentMethod: data.storePaymentMethod, order: data.order, amountToPay: data.order?.remainingAmount, installments: data.installments, shopperName: data.shopperName, emailAddress: data.emailAddress, telephoneNumber: data.telephoneNumber, browserInfo: data.browserInfo, checkoutAttemptId: data.checkoutAttemptId, billingAddress: data.billingAddress, deliveryAddress: data.deliveryAddress, socialSecurityNumber: data.socialSecurityNumber, delegatedAuthenticationData: data.delegatedAuthenticationData)
+            let json = try JSONEncoder().encode(paymentComponentData)
+            let jsonString = String(data: json, encoding: .utf8)
+            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel:PlatformCommunicationModel(type: PlatformCommunicationType.paymentComponent, data:jsonString ), completion: {})
+        } catch let error {
+            self.sendErrorToFlutterLayer(error: error)
+        }
+    }
+
+    func didProvide(_ data: ActionComponentData, from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
+        do {
+            let actionComponentData = ActionComponentDataModel(details: data.details.encodable, paymentData: data.paymentData)
+            let json = try JSONEncoder().encode(actionComponentData)
+            let jsonString = String(data: json, encoding: .utf8)
+            checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel:PlatformCommunicationModel(type: PlatformCommunicationType.additionalDetails, data:jsonString ), completion: {})
+        } catch let error {
+            self.sendErrorToFlutterLayer(error: error)
+        }
+    }
+
+    func didComplete(from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
+        print("did complete")
+    }
+
+    func didFail(with error: Error, from component: PaymentComponent, in dropInComponent: AnyDropInComponent) {
+        dropInComponent.viewController.presentedViewController?.dismiss(animated: true, completion: {
+            self.sendErrorToFlutterLayer(error: error)
+        })
+    }
+
+    func didFail(with error: Error, from component: ActionComponent, in dropInComponent: AnyDropInComponent) {
+        dropInComponent.viewController.presentedViewController?.dismiss(animated: true, completion: {
+            self.sendErrorToFlutterLayer(error: error)
+        })
+    }
+
+    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, dropInResult: DropInResult(type: DropInResultEnum.cancelledByUser, reason: error.localizedDescription))
+                self.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: {})
+            default:
+                self.sendErrorToFlutterLayer(error: error)
+            }
+        })
+    }
+
+    private func sendErrorToFlutterLayer(error: Error) {
+        print(error.localizedDescription)
+        let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription))
+        checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: {})
+    }
+}
diff --git a/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowStoredPaymentMethodsDelegate.swift b/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowStoredPaymentMethodsDelegate.swift
new file mode 100644
index 0000000..aaa0e13
--- /dev/null
+++ b/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowStoredPaymentMethodsDelegate.swift
@@ -0,0 +1,7 @@
+import Adyen
+
+class DropInAdvancedFlowStoredPaymentMethodsDelegate : StoredPaymentMethodsDelegate {
+    internal func disable(storedPaymentMethod: StoredPaymentMethod, completion: @escaping (Bool) -> Void) {
+        print("stored disabled")
+    }
+}
diff --git a/ios/Classes/models/ActionComponentDataModel.swift b/ios/Classes/dropinAdvancedFlow/models/ActionComponentDataModel.swift
similarity index 55%
rename from ios/Classes/models/ActionComponentDataModel.swift
rename to ios/Classes/dropinAdvancedFlow/models/ActionComponentDataModel.swift
index e5ffda0..4c001ba 100644
--- a/ios/Classes/models/ActionComponentDataModel.swift
+++ b/ios/Classes/dropinAdvancedFlow/models/ActionComponentDataModel.swift
@@ -1,3 +1,10 @@
+//
+//  ActionComponentDataModel.swift
+//  adyen_checkout
+//
+//  Created by Robert Schulze Dieckhoff on 01/09/2023.
+//
+
 import Foundation
 import Adyen

diff --git a/ios/Classes/models/PaymentComponentDataResponse.swift b/ios/Classes/dropinAdvancedFlow/models/PaymentComponentDataResponse.swift
similarity index 100%
rename from ios/Classes/models/PaymentComponentDataResponse.swift
rename to ios/Classes/dropinAdvancedFlow/models/PaymentComponentDataResponse.swift
diff --git a/ios/Classes/models/ResultCode.swift b/ios/Classes/dropinAdvancedFlow/models/ResultCode.swift
similarity index 80%
rename from ios/Classes/models/ResultCode.swift
rename to ios/Classes/dropinAdvancedFlow/models/ResultCode.swift
index 7d1c6ce..3c562b0 100644
--- a/ios/Classes/models/ResultCode.swift
+++ b/ios/Classes/dropinAdvancedFlow/models/ResultCode.swift
@@ -1,10 +1,3 @@
-//
-//  ResultCode.swift
-//  adyen_checkout
-//
-//  Created by Robert Schulze Dieckhoff on 30/08/2023.
-//
-
 import Foundation

 enum ResultCode: String, Decodable {
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 2a443aa..bc2e104 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -126,12 +126,18 @@ class _MyAppState extends State<MyApp> {
   }

   _dialogBuilder(BuildContext context, PaymentResult dropInResult) {
+    String message = "";
+    if (dropInResult.result != null) {
+      message = "Result code: ${dropInResult.result?.resultCode}";
+    } else {
+      message = "Error: ${dropInResult.errorReason}";
+    }
     return showDialog(
       context: context,
       builder: (BuildContext context) {
         return AlertDialog(
           title: Text(dropInResult.type.name),
-          content: Text("Result code: ${dropInResult.result?.resultCode}"),
+          content: Text(message),
           actions: <Widget>[
             TextButton(
               style: TextButton.styleFrom(
diff --git a/ios/Classes/CheckoutPlatformApi.swift b/ios/Classes/CheckoutPlatformApi.swift
index 385ba9b..c065d73 100644
--- a/ios/Classes/CheckoutPlatformApi.swift
+++ b/ios/Classes/CheckoutPlatformApi.swift
@@ -51,11 +51,11 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
                     self?.dropInComponent = dropInComponent
                     self?.viewController?.present(dropInComponent.viewController, animated: true)
                 case let .failure(error):
-                    self?.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)) {}
+                    self?.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, errorReason: error.localizedDescription)) {}
                 }
             }
         } catch let error {
-            checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)) {}
+            checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, errorReason: error.localizedDescription)) {}
         }
     }

@@ -78,7 +78,7 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
             self.dropInComponent = dropInComponent
             self.viewController?.present(dropInComponent.viewController, animated: true)
         } catch let error {
-            let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription))
+            let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, errorReason: error.localizedDescription))
             checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: {})
         }
     }
@@ -94,7 +94,7 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
     func onPaymentsDetailsResult(paymentsDetailsResult: DropInResult) {
         handleResponse(result: paymentsDetailsResult)
     }
-
+
     private func createAdyenContext(dropInConfiguration: DropInConfiguration) throws  -> AdyenContext  {
         let apiContext = try APIContext(environment: mapToEnvironment(environment: dropInConfiguration.environment), clientKey: dropInConfiguration.clientKey)
         let value: Int = Int(dropInConfiguration.amount.value)
@@ -145,7 +145,7 @@ class CheckoutPlatformApi : CheckoutPlatformInterface {
                     })
                 }
             } else {
-                let dropInResult = DropInResult(type: DropInResultEnum.error, reason: "\(result)")
+                let dropInResult = DropInResult(type: DropInResultEnum.error, errorReason: "\(String(describing: result["message"]!!))")
                 self.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: dropInResult), completion: {})
                 self.finalize(false, "\(result)")
             }
diff --git a/ios/Classes/dropInSessions/DropInSessionsDelegate.swift b/ios/Classes/dropInSessions/DropInSessionsDelegate.swift
index f59bae1..ff51117 100644
--- a/ios/Classes/dropInSessions/DropInSessionsDelegate.swift
+++ b/ios/Classes/dropInSessions/DropInSessionsDelegate.swift
@@ -21,9 +21,9 @@ class DropInSessionsDelegate : AdyenSessionDelegate {
         viewController?.dismiss(animated: true, completion: {
             switch (error) {
             case ComponentError.cancelled:
-                self.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.cancelledByUser, reason: error.localizedDescription)) {}
+                self.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.cancelledByUser, errorReason: error.localizedDescription)) {}
             default:
-                self.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription)) {}
+                self.checkoutFlutterApi.onDropInSessionResult(sessionDropInResult: DropInResult(type: DropInResultEnum.error, errorReason: error.localizedDescription)) {}
             }
         })
     }
diff --git a/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowDelegate.swift b/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowDelegate.swift
index b8baac3..aa14ac6 100644
--- a/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowDelegate.swift
+++ b/ios/Classes/dropinAdvancedFlow/DropInAdvancedFlowDelegate.swift
@@ -52,7 +52,7 @@ class DropInAdvancedFlowDelegate : DropInComponentDelegate {
         dropInComponent.viewController.dismiss(animated: true, completion: {
             switch (error) {
             case ComponentError.cancelled:
-                let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.cancelledByUser, reason: error.localizedDescription))
+                let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.cancelledByUser, errorReason: error.localizedDescription))
                 self.checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: {})
             default:
                 self.sendErrorToFlutterLayer(error: error)
@@ -62,7 +62,7 @@ class DropInAdvancedFlowDelegate : DropInComponentDelegate {

     private func sendErrorToFlutterLayer(error: Error) {
         print(error.localizedDescription)
-        let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, reason: error.localizedDescription))
+        let platformCommunicationModel = PlatformCommunicationModel(type: PlatformCommunicationType.result, dropInResult: DropInResult(type: DropInResultEnum.error, errorReason: error.localizedDescription))
         checkoutFlutterApi.onDropInAdvancedFlowPlatformCommunication(platformCommunicationModel: platformCommunicationModel, completion: {})
     }
 }
diff --git a/lib/src/platform/adyen_checkout_api.dart b/lib/src/platform/adyen_checkout_api.dart
index 4632fc7..a282882 100644
--- a/lib/src/platform/adyen_checkout_api.dart
+++ b/lib/src/platform/adyen_checkout_api.dart
@@ -37,7 +37,4 @@ class AdyenCheckoutApi implements AdyenCheckoutPlatformInterface {
   @OverRide
   void onPaymentsDetailsResult(DropInResult paymentsDetailsResult) =>
       checkoutApi.onPaymentsDetailsResult(paymentsDetailsResult);
-
-  @OverRide
-  void hide() => checkoutApi.hide();
 }
@Robert-SD Robert-SD force-pushed the feature/add_dropin_advanced_flow_ios branch from d044208 to 10e40a7 Compare September 7, 2023 14:47
ios/Classes/CheckoutPlatformApi.swift Outdated Show resolved Hide resolved
ios/Classes/CheckoutPlatformApi.swift Outdated Show resolved Hide resolved
ios/Classes/CheckoutPlatformApi.swift Outdated Show resolved Hide resolved
ios/Classes/CheckoutPlatformApi.swift Show resolved Hide resolved
ios/Classes/CheckoutPlatformApi.swift Outdated Show resolved Hide resolved
ios/Classes/CheckoutPlatformApi.swift Show resolved Hide resolved
@Robert-SD Robert-SD merged commit fc2d52a into main Sep 13, 2023
1 check passed
@Robert-SD Robert-SD deleted the feature/add_dropin_advanced_flow_ios branch September 13, 2023 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants