-
Notifications
You must be signed in to change notification settings - Fork 7
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
Commits on Sep 7, 2023
-
Started with integration of advanced flow on 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" +}
Configuration menu - View commit details
-
Copy full SHA for e884b15 - Browse repository at this point
Copy the full SHA e884b15View commit details -
Improved naming of payment result
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? -} - -
Configuration menu - View commit details
-
Copy full SHA for 5d3df5a - Browse repository at this point
Copy the full SHA 5d3df5aView commit details -
Refactored iOS code for a better structure
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 {
Configuration menu - View commit details
-
Copy full SHA for ae7237b - Browse repository at this point
Copy the full SHA ae7237bView commit details -
Configuration menu - View commit details
-
Copy full SHA for 6b86802 - Browse repository at this point
Copy the full SHA 6b86802View commit details -
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(); }
Configuration menu - View commit details
-
Copy full SHA for 3158301 - Browse repository at this point
Copy the full SHA 3158301View commit details -
Configuration menu - View commit details
-
Copy full SHA for 8fff601 - Browse repository at this point
Copy the full SHA 8fff601View commit details -
Configuration menu - View commit details
-
Copy full SHA for 38f4054 - Browse repository at this point
Copy the full SHA 38f4054View commit details -
Configuration menu - View commit details
-
Copy full SHA for 10e40a7 - Browse repository at this point
Copy the full SHA 10e40a7View commit details
Commits on Sep 8, 2023
-
Configuration menu - View commit details
-
Copy full SHA for e3888d8 - Browse repository at this point
Copy the full SHA e3888d8View commit details -
Configuration menu - View commit details
-
Copy full SHA for 971c6dd - Browse repository at this point
Copy the full SHA 971c6ddView commit details
Commits on Sep 12, 2023
-
Applied changes from code review and filtered out gift cards because …
…they are not supported in beta version
Configuration menu - View commit details
-
Copy full SHA for d80b04b - Browse repository at this point
Copy the full SHA d80b04bView commit details
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.