From a7768ba7cd6858e006a4a1026c2692de1faa5a91 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 10:43:37 +0100 Subject: [PATCH 01/21] swiftlint --fix --format --- .../Core/Analytics/AnalyticsStorage.swift | 1 - .../Core/BIN Data/CardValidationService.swift | 2 +- ...KlarnaComponent+SessionAuthorization.swift | 4 +- .../Managers/KlarnaTokenizationManager.swift | 2 +- .../Klarna/Models/KlarnaHelpers.swift | 64 ++++++------- .../Klarna/Models/KlarnaPaymentCategory.swift | 6 +- .../ApplePayValidationComponent.swift | 12 +-- .../Common/NativeUIValidateable.swift | 16 ++-- .../PayPal/PayPalValidationComponent.swift | 10 +-- .../NolPay/NolPayLinkedCardsComponent.swift | 10 +-- .../Managers/AssetsManager.swift | 12 +-- .../PrimerHeadlessBanksComponentWrapper.swift | 6 +- ...CheckoutComponentWithRedirectManager.swift | 6 +- .../Error Handler/PrimerValidationError.swift | 38 ++++---- ...PrimerRawCardDataTokenizationBuilder.swift | 14 +-- .../PCI/Services/API/Primer/PrimerAPI.swift | 90 +++++++++---------- .../Services/Network/URLSessionStack.swift | 2 +- .../KlarnaTokenizationViewModel.swift | 2 +- 18 files changed, 148 insertions(+), 149 deletions(-) diff --git a/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift b/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift index 2a8fa0fbc1..5cba50c168 100644 --- a/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift +++ b/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift @@ -91,7 +91,6 @@ extension Analytics { delete(events) } - func deleteAnalyticsFile() { logger.debug(message: "📚 Analytics: Deleting analytics file at \(fileURL.absoluteString)") diff --git a/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift b/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift index c4194b6b51..95c34d2259 100644 --- a/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift +++ b/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift @@ -51,7 +51,7 @@ class DefaultCardValidationService: CardValidationService, LogReporter { // Don't validate if the BIN (first eight digits) hasn't changed let bin = String(sanitizedCardNumber.prefix(Self.maximumBinLength)) if let mostRecentCardNumber = mostRecentCardNumber, - mostRecentCardNumber.prefix(Self.maximumBinLength) == bin { + mostRecentCardNumber.prefix(Self.maximumBinLength) == bin { if let cachedMetadata = metadataCache[bin] { handle(cardMetadata: cachedMetadata, forCardState: cardState) } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift index 37655f21e4..c58aa00440 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift @@ -20,11 +20,11 @@ extension PrimerHeadlessKlarnaComponent { extension PrimerHeadlessKlarnaComponent { func authorizeSession() { var isMocked = false -#if DEBUG + #if DEBUG if PrimerAPIConfiguration.current?.clientSession?.testId != nil { isMocked = true } -#endif + #endif if isMocked { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { self.finalizeSession(token: UUID().uuidString, fromAuthorization: true) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift index f7f7fb7d8a..c1c5259b48 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift @@ -13,7 +13,7 @@ protocol KlarnaTokenizationManagerProtocol { - Parameters: - customerToken: An optional `Response.Body.Klarna.CustomerToken` object containing the customer's token and session data. - `offSessionAuthorizationId`: An optional `String` representing an off-session authorization ID. This is used when the session `intent` is `checkout`. - + - Returns: A `Promise` which resolves to a `PrimerPaymentMethodTokenData` object on successful tokenization or rejects with an `Error` if the tokenization process fails. */ func tokenize(customerToken: Response.Body.Klarna.CustomerToken?, offSessionAuthorizationId: String?) -> Promise diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaHelpers.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaHelpers.swift index 5963333d0e..f23b0ce3d0 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaHelpers.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaHelpers.swift @@ -58,39 +58,39 @@ struct KlarnaHelpers { clientSession: ClientSession.APIResponse?, recurringPaymentDescription: String?, redirectUrl: String?) -> Request.Body.Klarna.CreatePaymentSession { - let sessionType = getSessionType() - let localeData = constructLocaleData(using: clientSession) - var orderItems: [Request.Body.Klarna.OrderItem]? - var totalAmount: Int? - var billingAddress: Response.Body.Klarna.BillingAddress? - var shippingAddress: Response.Body.Klarna.BillingAddress? - var description: String? - var redUrl: String? - switch sessionType { - case .oneOffPayment: - // Configure fields specific to one-off payments. - orderItems = clientSession?.order?.lineItems?.compactMap({ getOrderItem(from: $0) }) - let surcharge = getSurcharge(fees: clientSession?.order?.fees) - orderItems = addedSurchargeItem(to: orderItems ?? [], surcharge: surcharge) - totalAmount = clientSession?.order?.totalOrderAmount - billingAddress = getCustomerAddress(of: .billing, clientSession: clientSession) - shippingAddress = getCustomerAddress(of: .shipping, clientSession: clientSession) - case .recurringPayment: - // Configure fields specific to recurring payments. - description = recurringPaymentDescription - redUrl = redirectUrl - } - return Request.Body.Klarna.CreatePaymentSession( - paymentMethodConfigId: paymentMethodConfigId, - sessionType: sessionType, - localeData: localeData, - description: description, - redirectUrl: redUrl, - totalAmount: totalAmount, - orderItems: orderItems, - billingAddress: billingAddress, - shippingAddress: shippingAddress) + let sessionType = getSessionType() + let localeData = constructLocaleData(using: clientSession) + var orderItems: [Request.Body.Klarna.OrderItem]? + var totalAmount: Int? + var billingAddress: Response.Body.Klarna.BillingAddress? + var shippingAddress: Response.Body.Klarna.BillingAddress? + var description: String? + var redUrl: String? + switch sessionType { + case .oneOffPayment: + // Configure fields specific to one-off payments. + orderItems = clientSession?.order?.lineItems?.compactMap({ getOrderItem(from: $0) }) + let surcharge = getSurcharge(fees: clientSession?.order?.fees) + orderItems = addedSurchargeItem(to: orderItems ?? [], surcharge: surcharge) + totalAmount = clientSession?.order?.totalOrderAmount + billingAddress = getCustomerAddress(of: .billing, clientSession: clientSession) + shippingAddress = getCustomerAddress(of: .shipping, clientSession: clientSession) + case .recurringPayment: + // Configure fields specific to recurring payments. + description = recurringPaymentDescription + redUrl = redirectUrl } + return Request.Body.Klarna.CreatePaymentSession( + paymentMethodConfigId: paymentMethodConfigId, + sessionType: sessionType, + localeData: localeData, + description: description, + redirectUrl: redUrl, + totalAmount: totalAmount, + orderItems: orderItems, + billingAddress: billingAddress, + shippingAddress: shippingAddress) + } /// - Returns a customer's address, either billing or shipping, based on the specified type. static func getCustomerAddress(of type: AddressType, clientSession: ClientSession.APIResponse?) -> Response.Body.Klarna.BillingAddress { let billingAddress = clientSession?.customer?.billingAddress diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaPaymentCategory.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaPaymentCategory.swift index a4ef4a329f..65da850947 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaPaymentCategory.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaPaymentCategory.swift @@ -23,8 +23,8 @@ public struct KlarnaPaymentCategory: Codable { extension KlarnaPaymentCategory: Equatable { public static func == (lhs: KlarnaPaymentCategory, rhs: KlarnaPaymentCategory) -> Bool { return lhs.id == rhs.id && - lhs.name == rhs.name && - lhs.descriptiveAssetUrl == rhs.descriptiveAssetUrl && - lhs.standardAssetUrl == rhs.standardAssetUrl + lhs.name == rhs.name && + lhs.descriptiveAssetUrl == rhs.descriptiveAssetUrl && + lhs.standardAssetUrl == rhs.standardAssetUrl } } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/ApplePay/ApplePayValidationComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/ApplePay/ApplePayValidationComponent.swift index 92583cc1e7..d90bd29442 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/ApplePay/ApplePayValidationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/ApplePay/ApplePayValidationComponent.swift @@ -13,12 +13,12 @@ struct ApplePayValidationComponent: NativeUIValidateable { func validatePaymentMethod() throws { if PrimerSettings.current.paymentMethodOptions.applePayOptions == nil { let error = PrimerError.invalidValue(key: "settings.paymentMethodOptions.applePayOptions", - value: nil, - userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], - diagnosticsId: UUID().uuidString) + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) throw error } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift index 7fdea43d68..2df0dceb8e 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift @@ -37,9 +37,9 @@ extension NativeUIValidateable { guard let cats = paymentMethod.paymentMethodManagerCategories, cats.contains(.nativeUI) else { let error = PrimerError.unsupportedPaymentMethodForManager(paymentMethodType: paymentMethod.type, - category: PrimerPaymentMethodManagerCategory.nativeUI.rawValue, - userInfo: nil, - diagnosticsId: UUID().uuidString) + category: PrimerPaymentMethodManagerCategory.nativeUI.rawValue, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) throw error } @@ -48,11 +48,11 @@ extension NativeUIValidateable { if (intent == .vault && !paymentMethod.isVaultingEnabled) || (intent == .checkout && !paymentMethod.isCheckoutEnabled) { let error = PrimerError.unsupportedIntent(intent: intent, - userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], - diagnosticsId: UUID().uuidString) + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) throw error } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/PayPal/PayPalValidationComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/PayPal/PayPalValidationComponent.swift index cbc52a38b7..4e5bd93e19 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/PayPal/PayPalValidationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/PayPal/PayPalValidationComponent.swift @@ -13,11 +13,11 @@ struct PayPalValidationComponent: NativeUIValidateable { func validatePaymentMethod() throws { if PrimerSettings.current.paymentMethodOptions.urlScheme == nil { let error = PrimerError.invalidUrlScheme(urlScheme: nil, - userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], - diagnosticsId: UUID().uuidString) + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) throw error } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift index 270df8ed27..7db6859bd7 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift @@ -103,11 +103,11 @@ public class NolPayLinkedCardsComponent { case .failure(let error): continuation.resume(throwing: error) let primerError = PrimerError.underlyingErrors(errors: [error], - userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], - diagnosticsId: UUID().uuidString) + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) completion(.failure(primerError)) } } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift index 4247f8ac42..61d9b5df90 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift @@ -47,9 +47,9 @@ extension PrimerHeadlessUniversalCheckout { } guard let paymentMethodLogo = PrimerInternalAsset( - colored: baseLogoImage.colored, - light: baseLogoImage.light, - dark: baseLogoImage.dark) else { + colored: baseLogoImage.colored, + light: baseLogoImage.light, + dark: baseLogoImage.dark) else { return nil } @@ -84,9 +84,9 @@ extension PrimerHeadlessUniversalCheckout { } guard let paymentMethodLogo = PrimerInternalAsset( - colored: baseLogoImage.colored, - light: baseLogoImage.light, - dark: baseLogoImage.dark) + colored: baseLogoImage.colored, + light: baseLogoImage.light, + dark: baseLogoImage.dark) else { continue } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift index a14b8abb18..f9967e6de3 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift @@ -46,9 +46,9 @@ import Foundation guard let banksComponent = try? manager.provideBanksComponent(paymentMethodType: paymentMethodType) as? (any BanksComponent) else { return } - banksComponent.stepDelegate = self - banksComponent.errorDelegate = self - banksComponent.validationDelegate = self + banksComponent.stepDelegate = self + banksComponent.errorDelegate = self + banksComponent.validationDelegate = self self.banksComponent = banksComponent } @objc public func submit() { diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift index 7797aee5cc..7ede580d83 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift @@ -11,11 +11,11 @@ extension PrimerHeadlessUniversalCheckout { @objc public func provideComponent(paymentMethodType: String) -> PrimerHeadlessBanksComponentWrapper { PrimerHeadlessBanksComponentWrapper(manager: self, paymentMethodType: paymentMethodType) } - public func provide(paymentMethodType: String) throws -> PrimerHeadlessMainComponent? - where PrimerCollectableData: Any, PrimerHeadlessStep: Any { + public func provide(paymentMethodType: String) throws -> PrimerHeadlessMainComponent? + where PrimerCollectableData: Any, PrimerHeadlessStep: Any { try provideBanksComponent(paymentMethodType: paymentMethodType) as? PrimerHeadlessMainComponent } - + public func provideBanksComponent(paymentMethodType: String) throws -> any PrimerHeadlessMainComponent { guard let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodType), paymentMethodType == .adyenIDeal else { diff --git a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift index 927a021246..a0bcfe1c65 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift @@ -350,25 +350,25 @@ extension PrimerValidationError: Equatable { public static func == (lhs: PrimerValidationError, rhs: PrimerValidationError) -> Bool { switch (lhs, rhs) { case (.invalidCardholderName(let message1, let userInfo1, let id1), .invalidCardholderName(let message2, let userInfo2, let id2)), - (.invalidCardnumber(let message1, let userInfo1, let id1), .invalidCardnumber(let message2, let userInfo2, let id2)), - (.invalidCvv(let message1, let userInfo1, let id1), .invalidCvv(let message2, let userInfo2, let id2)), - (.invalidExpiryMonth(let message1, let userInfo1, let id1), .invalidExpiryMonth(let message2, let userInfo2, let id2)), - (.invalidExpiryYear(let message1, let userInfo1, let id1), .invalidExpiryYear(let message2, let userInfo2, let id2)), - (.invalidExpiryDate(let message1, let userInfo1, let id1), .invalidExpiryDate(let message2, let userInfo2, let id2)), - (.invalidPostalCode(let message1, let userInfo1, let id1), .invalidPostalCode(let message2, let userInfo2, let id2)), - (.invalidFirstName(let message1, let userInfo1, let id1), .invalidFirstName(let message2, let userInfo2, let id2)), - (.invalidLastName(let message1, let userInfo1, let id1), .invalidLastName(let message2, let userInfo2, let id2)), - (.invalidAddress(let message1, let userInfo1, let id1), .invalidAddress(let message2, let userInfo2, let id2)), - (.invalidState(let message1, let userInfo1, let id1), .invalidState(let message2, let userInfo2, let id2)), - (.invalidCountry(let message1, let userInfo1, let id1), .invalidCountry(let message2, let userInfo2, let id2)), - (.invalidPhoneNumber(let message1, let userInfo1, let id1), .invalidPhoneNumber(let message2, let userInfo2, let id2)), - (.invalidPhoneNumberCountryCode(let message1, let userInfo1, let id1), .invalidPhoneNumberCountryCode(let message2, let userInfo2, let id2)), - (.invalidRetailer(let message1, let userInfo1, let id1), .invalidRetailer(let message2, let userInfo2, let id2)), - (.invalidOTPCode(let message1, let userInfo1, let id1), .invalidOTPCode(let message2, let userInfo2, let id2)), - (.invalidAccountUniqueId(let message1, let userInfo1, let id1), .invalidAccountUniqueId(let message2, let userInfo2, let id2)), - (.invalidAccountRegistrationDate(let message1, let userInfo1, let id1), .invalidAccountRegistrationDate(let message2, let userInfo2, let id2)), - (.invalidAccountLastModified(let message1, let userInfo1, let id1), .invalidAccountLastModified(let message2, let userInfo2, let id2)), - (.invalidCardType(let message1, let userInfo1, let id1), .invalidCardType(let message2, let userInfo2, let id2)): + (.invalidCardnumber(let message1, let userInfo1, let id1), .invalidCardnumber(let message2, let userInfo2, let id2)), + (.invalidCvv(let message1, let userInfo1, let id1), .invalidCvv(let message2, let userInfo2, let id2)), + (.invalidExpiryMonth(let message1, let userInfo1, let id1), .invalidExpiryMonth(let message2, let userInfo2, let id2)), + (.invalidExpiryYear(let message1, let userInfo1, let id1), .invalidExpiryYear(let message2, let userInfo2, let id2)), + (.invalidExpiryDate(let message1, let userInfo1, let id1), .invalidExpiryDate(let message2, let userInfo2, let id2)), + (.invalidPostalCode(let message1, let userInfo1, let id1), .invalidPostalCode(let message2, let userInfo2, let id2)), + (.invalidFirstName(let message1, let userInfo1, let id1), .invalidFirstName(let message2, let userInfo2, let id2)), + (.invalidLastName(let message1, let userInfo1, let id1), .invalidLastName(let message2, let userInfo2, let id2)), + (.invalidAddress(let message1, let userInfo1, let id1), .invalidAddress(let message2, let userInfo2, let id2)), + (.invalidState(let message1, let userInfo1, let id1), .invalidState(let message2, let userInfo2, let id2)), + (.invalidCountry(let message1, let userInfo1, let id1), .invalidCountry(let message2, let userInfo2, let id2)), + (.invalidPhoneNumber(let message1, let userInfo1, let id1), .invalidPhoneNumber(let message2, let userInfo2, let id2)), + (.invalidPhoneNumberCountryCode(let message1, let userInfo1, let id1), .invalidPhoneNumberCountryCode(let message2, let userInfo2, let id2)), + (.invalidRetailer(let message1, let userInfo1, let id1), .invalidRetailer(let message2, let userInfo2, let id2)), + (.invalidOTPCode(let message1, let userInfo1, let id1), .invalidOTPCode(let message2, let userInfo2, let id2)), + (.invalidAccountUniqueId(let message1, let userInfo1, let id1), .invalidAccountUniqueId(let message2, let userInfo2, let id2)), + (.invalidAccountRegistrationDate(let message1, let userInfo1, let id1), .invalidAccountRegistrationDate(let message2, let userInfo2, let id2)), + (.invalidAccountLastModified(let message1, let userInfo1, let id1), .invalidAccountLastModified(let message2, let userInfo2, let id2)), + (.invalidCardType(let message1, let userInfo1, let id1), .invalidCardType(let message2, let userInfo2, let id2)): return message1 == message2 && userInfo1 == userInfo2 && id1 == id2 case (.invalidRawData(let userInfo1, let id1), .invalidRawData(let userInfo2, let id2)), (.banksNotLoaded(let userInfo1, let id1), .banksNotLoaded(let userInfo2, let id2)), diff --git a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift index df697b986d..69e102b91d 100644 --- a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift @@ -173,7 +173,7 @@ class PrimerRawCardDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProt cardNetworksMetadata.detectedCardNetworks.items.map { $0.network } != [.unknown] if didDetectNetwork && cardNetworksMetadata.detectedCardNetworks.preferred == nil, - let network = cardNetworksMetadata.detectedCardNetworks.items.first?.network { + let network = cardNetworksMetadata.detectedCardNetworks.items.first?.network { cardNetwork = network } else { return @@ -235,14 +235,14 @@ class PrimerRawCardDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProt if self.requiredInputElementTypes.contains(PrimerInputElementType.cardholderName) { if (rawData.cardholderName ?? "").isEmpty { errors.append(PrimerValidationError.invalidCardholderName( - message: "Cardholder name cannot be blank.", - userInfo: .errorUserInfoDictionary(), - diagnosticsId: UUID().uuidString)) + message: "Cardholder name cannot be blank.", + userInfo: .errorUserInfoDictionary(), + diagnosticsId: UUID().uuidString)) } else if !(rawData.cardholderName ?? "").isValidNonDecimalString { errors.append(PrimerValidationError.invalidCardholderName( - message: "Cardholder name is not valid.", - userInfo: .errorUserInfoDictionary(), - diagnosticsId: UUID().uuidString)) + message: "Cardholder name is not valid.", + userInfo: .errorUserInfoDictionary(), + diagnosticsId: UUID().uuidString)) } } diff --git a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift index 58f7c07017..02d22987ba 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift @@ -105,27 +105,27 @@ internal extension PrimerAPI { switch self { case .redirect(let clientToken, _), - .deleteVaultedPaymentMethod(let clientToken, _), - .exchangePaymentMethodToken(let clientToken, _, _), - .fetchVaultedPaymentMethods(let clientToken), - .createPayPalOrderSession(let clientToken, _), - .createPayPalBillingAgreementSession(let clientToken, _), - .confirmPayPalBillingAgreement(let clientToken, _), - .createKlarnaPaymentSession(let clientToken, _), - .createKlarnaCustomerToken(let clientToken, _), - .finalizeKlarnaPaymentSession(let clientToken, _), - .tokenizePaymentMethod(let clientToken, _), - .begin3DSRemoteAuth(let clientToken, _, _), - .continue3DSRemoteAuth(let clientToken, _, _), - .listAdyenBanks(let clientToken, _), - .listRetailOutlets(let clientToken, _), - .requestPrimerConfigurationWithActions(let clientToken, _), - .fetchPayPalExternalPayerInfo(let clientToken, _), - .createPayment(let clientToken, _), - .resumePayment(let clientToken, _, _), - .testFinalizePolling(let clientToken, _), - .listCardNetworks(let clientToken, _), - .getPhoneMetadata(let clientToken, _): + .deleteVaultedPaymentMethod(let clientToken, _), + .exchangePaymentMethodToken(let clientToken, _, _), + .fetchVaultedPaymentMethods(let clientToken), + .createPayPalOrderSession(let clientToken, _), + .createPayPalBillingAgreementSession(let clientToken, _), + .confirmPayPalBillingAgreement(let clientToken, _), + .createKlarnaPaymentSession(let clientToken, _), + .createKlarnaCustomerToken(let clientToken, _), + .finalizeKlarnaPaymentSession(let clientToken, _), + .tokenizePaymentMethod(let clientToken, _), + .begin3DSRemoteAuth(let clientToken, _, _), + .continue3DSRemoteAuth(let clientToken, _, _), + .listAdyenBanks(let clientToken, _), + .listRetailOutlets(let clientToken, _), + .requestPrimerConfigurationWithActions(let clientToken, _), + .fetchPayPalExternalPayerInfo(let clientToken, _), + .createPayment(let clientToken, _), + .resumePayment(let clientToken, _, _), + .testFinalizePolling(let clientToken, _), + .listCardNetworks(let clientToken, _), + .getPhoneMetadata(let clientToken, _): if let token = clientToken.accessToken { tmpHeaders["Primer-Client-Token"] = token } @@ -217,31 +217,31 @@ internal extension PrimerAPI { var baseURL: String? { switch self { case .createPayPalOrderSession(let clientToken, _), - .createPayPalBillingAgreementSession(let clientToken, _), - .confirmPayPalBillingAgreement(let clientToken, _), - .createKlarnaPaymentSession(let clientToken, _), - .createKlarnaCustomerToken(let clientToken, _), - .finalizeKlarnaPaymentSession(let clientToken, _), - .listAdyenBanks(let clientToken, _), - .listRetailOutlets(let clientToken, _), - .fetchPayPalExternalPayerInfo(let clientToken, _), - .testFinalizePolling(let clientToken, _), - .getNolSdkSecret(let clientToken, _): + .createPayPalBillingAgreementSession(let clientToken, _), + .confirmPayPalBillingAgreement(let clientToken, _), + .createKlarnaPaymentSession(let clientToken, _), + .createKlarnaCustomerToken(let clientToken, _), + .finalizeKlarnaPaymentSession(let clientToken, _), + .listAdyenBanks(let clientToken, _), + .listRetailOutlets(let clientToken, _), + .fetchPayPalExternalPayerInfo(let clientToken, _), + .testFinalizePolling(let clientToken, _), + .getNolSdkSecret(let clientToken, _): guard let baseURL = configuration?.coreUrl ?? clientToken.coreUrl else { return nil } return baseURL case .listCardNetworks: guard let baseURL = configuration?.binDataUrl else { return nil } return baseURL case .deleteVaultedPaymentMethod(let clientToken, _), - .fetchVaultedPaymentMethods(let clientToken), - .exchangePaymentMethodToken(let clientToken, _, _), - .tokenizePaymentMethod(let clientToken, _), - .begin3DSRemoteAuth(let clientToken, _, _), - .continue3DSRemoteAuth(let clientToken, _, _), - .createPayment(let clientToken, _), - .resumePayment(let clientToken, _, _), - .requestPrimerConfigurationWithActions(let clientToken, _), - .getPhoneMetadata(let clientToken, _): + .fetchVaultedPaymentMethods(let clientToken), + .exchangePaymentMethodToken(let clientToken, _, _), + .tokenizePaymentMethod(let clientToken, _), + .begin3DSRemoteAuth(let clientToken, _, _), + .continue3DSRemoteAuth(let clientToken, _, _), + .createPayment(let clientToken, _), + .resumePayment(let clientToken, _, _), + .requestPrimerConfigurationWithActions(let clientToken, _), + .getPhoneMetadata(let clientToken, _): guard let baseURL = configuration?.pciUrl ?? clientToken.pciUrl else { return nil } return baseURL case .fetchConfiguration(let clientToken, _): @@ -332,11 +332,11 @@ internal extension PrimerAPI { case .deleteVaultedPaymentMethod: return .delete case .redirect, - .fetchConfiguration, - .fetchVaultedPaymentMethods, - .listRetailOutlets, - .listCardNetworks, - .getPhoneMetadata: + .fetchConfiguration, + .fetchVaultedPaymentMethods, + .listRetailOutlets, + .listCardNetworks, + .getPhoneMetadata: return .get case .createPayPalOrderSession, .createPayPalBillingAgreementSession, diff --git a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift index 61fbcbf2bf..0ef841103f 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift @@ -344,7 +344,7 @@ internal extension URLSessionStack { return false } guard let baseURL = primerAPI.baseURL, let url = URL(string: baseURL), - !disallowedTrackingPaths.contains(url.path) else { + !disallowedTrackingPaths.contains(url.path) else { return false } return true diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift index 03e78c5ecc..cab9fe51f7 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift @@ -18,7 +18,7 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { #if DEBUG private var demoThirdPartySDKViewController: PrimerThirdPartySDKViewController? -#endif + #endif private var klarnaPaymentSession: Response.Body.Klarna.PaymentSession? private var klarnaCustomerTokenAPIResponse: Response.Body.Klarna.CustomerToken? private var klarnaPaymentSessionCompletion: ((_ authorizationToken: String?, _ error: Error?) -> Void)? From 4d5523d94038dcfaa0b595d9ff9f522ea6f831e4 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 11:21:59 +0100 Subject: [PATCH 02/21] Fix cyclomatic_complexity warnings and error --- Debug App/.swiftlint.yml | 2 +- .../Models/BanksTokenizationComponent.swift | 27 +++++- .../NolPay/NolPayLinkCardComponent.swift | 3 + .../NolPay/NolPayUnlinkCardComponent.swift | 3 + .../CardComponentsManager.swift | 53 ++++++----- .../RawDataManager.swift | 4 + .../Managers/VaultManager.swift | 73 ++++++++++------ ...eadlessUniversalCheckoutInputElement.swift | 4 + ...niversalCheckoutInputElementDelegate.swift | 7 +- .../Extensions & Utilities/AnyCodable.swift | 3 + .../Extensions & Utilities/AnyDecodable.swift | 2 + .../Extensions & Utilities/AnyEncodable.swift | 2 + .../ApplePayUtils.swift | 3 + .../ImageFileProcessor.swift | 2 + .../Classes/Modules/Downloader.swift | 3 + ...wCardDataRedirectTokenizationBuilder.swift | 8 +- ...PrimerRawCardDataTokenizationBuilder.swift | 6 +- .../Services/Network/URLSessionStack.swift | 73 ++++++++++------ ...rmPaymentMethodTokenizationViewModel.swift | 2 + ...rmPaymentMethodTokenizationViewModel.swift | 46 ++++++---- .../Text Fields/PrimerCVVFieldView.swift | 8 +- .../PrimerCardNumberFieldView.swift | 4 +- .../PrimerExpiryDateFieldView.swift | 7 +- .../Root/PrimerRootViewController.swift | 3 + ...rimerUniversalCheckoutViewController.swift | 4 + ...outWithVaultedPaymentMethodViewModel.swift | 87 ++++++++++++------- .../IPay88TokenizationViewModel.swift | 17 ++-- .../KlarnaTokenizationViewModel.swift | 70 ++++++++++----- ...entMethodTokenizationViewModel+Logic.swift | 65 +++++++++----- 29 files changed, 405 insertions(+), 186 deletions(-) diff --git a/Debug App/.swiftlint.yml b/Debug App/.swiftlint.yml index d70436478c..896ee0ef7d 100644 --- a/Debug App/.swiftlint.yml +++ b/Debug App/.swiftlint.yml @@ -3,7 +3,7 @@ disabled_rules: - type_body_length - function_body_length - file_length - - cyclomatic_complexity +# - cyclomatic_complexity included: - ../Sources diff --git a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift index 9b907009dc..18ef61796e 100644 --- a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift @@ -9,6 +9,8 @@ import Foundation import UIKit import SafariServices +// swiftlint:disable cyclomatic_complexity + final class BanksTokenizationComponent: NSObject, LogReporter { var config: PrimerPaymentMethod var paymentMethodType: PrimerPaymentMethodType @@ -470,7 +472,11 @@ final class BanksTokenizationComponent: NSObject, LogReporter { seal.reject(err) } } else { - let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidClientToken(userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -647,7 +653,11 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } private func tokenize(bank: AdyenBank, completion: @escaping (_ paymentMethodTokenData: PrimerPaymentMethodTokenData?, _ err: Error?) -> Void) { guard PrimerAPIConfigurationModule.decodedJWTToken != nil else { - let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidClientToken(userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, err) return @@ -1003,7 +1013,12 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { decisionHandlerHasBeenCalled = true switch paymentCreationDecision.type { case .abort(let errorMessage): - let error = PrimerError.merchantError(message: errorMessage ?? "", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let error = PrimerError.merchantError(message: errorMessage ?? "", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) seal.reject(error) case .continue: seal.fulfill() @@ -1092,7 +1107,10 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { self.didCancel = { let err = PrimerError.cancelled( paymentMethodType: self.config.type, - userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) pollingModule.cancel(withError: err) @@ -1119,3 +1137,4 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { } } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift index 8a5bf04642..233754e00d 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift @@ -5,6 +5,8 @@ // Created by Boris on 13.9.23.. // +// swiftlint:disable cyclomatic_complexity + import Foundation #if canImport(PrimerNolPaySDK) import PrimerNolPaySDK @@ -330,3 +332,4 @@ public class NolPayLinkCardComponent: PrimerHeadlessCollectDataComponent { #endif } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift index fed61e187e..0169873e6b 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift @@ -5,6 +5,8 @@ // Created by Boris on 13.9.23.. // +// swiftlint:disable cyclomatic_complexity + import Foundation #if canImport(PrimerNolPaySDK) import PrimerNolPaySDK @@ -306,3 +308,4 @@ public class NolPayUnlinkCardComponent: PrimerHeadlessCollectDataComponent { #endif } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift index 4f09a6b59a..13095271d4 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift @@ -10,10 +10,10 @@ import SafariServices public protocol PrimerHeadlessUniversalCheckoutInputData {} // swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity + @available(*, deprecated, message: "CardComponentsManager is no longer supported, please use PrimerHeadlessUniversalCheckout instead") public protocol PrimerHeadlessUniversalCheckoutCardComponentsManagerDelegate: AnyObject { - // swiftlint:enable type_name - func cardComponentsManager(_ cardComponentsManager: PrimerHeadlessUniversalCheckout.CardComponentsManager, isCardFormValid: Bool) } @@ -615,10 +615,13 @@ Make sure you call the decision handler otherwise the SDK will hang. } .done { paymentResponse -> Void in guard paymentResponse != nil else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) throw err } @@ -636,7 +639,8 @@ Make sure you call the decision handler otherwise the SDK will hang. let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -662,10 +666,12 @@ Make sure you call the decision handler otherwise the SDK will hang. return Promise { seal in if decodedJWTToken.intent == RequiredActionName.threeDSAuthentication.rawValue { guard let paymentMethodTokenData = paymentMethodTokenData else { - let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) let containerErr = PrimerError.failedToPerform3DS(paymentMethodType: self.paymentMethodType, error: err, userInfo: ["file": #file, @@ -730,7 +736,8 @@ Make sure you call the decision handler otherwise the SDK will hang. let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -791,10 +798,12 @@ Make sure you call the decision handler otherwise the SDK will hang. } } else { - let err = PrimerError.invalidValue(key: "resumeToken", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], + let err = PrimerError.invalidValue(key: "resumeToken", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) @@ -917,10 +926,12 @@ Make sure you call the decision handler otherwise the SDK will hang. case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -1272,3 +1283,5 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager: SFSafariViewCon webViewCompletion = nil } } +// swiftlint:enable type_name +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift index 20bb5ca6d0..17dcdadcc8 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift @@ -9,6 +9,7 @@ import Foundation import SafariServices // swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity @objc public protocol PrimerHeadlessUniversalCheckoutRawDataManagerDelegate { @@ -1062,3 +1063,6 @@ extension PrimerHeadlessUniversalCheckout.RawDataManager { } } } + +// swiftlint:enable type_name +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift index f2e836b7ee..a9f74dc4e6 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 13/6/23. // +// swiftlint:disable cyclomatic_complexity + import SafariServices import UIKit @@ -414,7 +416,8 @@ extension PrimerHeadlessUniversalCheckout { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -431,7 +434,8 @@ extension PrimerHeadlessUniversalCheckout { let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -452,7 +456,8 @@ extension PrimerHeadlessUniversalCheckout { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -490,10 +495,13 @@ extension PrimerHeadlessUniversalCheckout { } .done { paymentResponse -> Void in guard paymentResponse != nil else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) throw err } @@ -511,7 +519,8 @@ extension PrimerHeadlessUniversalCheckout { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -537,10 +546,12 @@ extension PrimerHeadlessUniversalCheckout { return Promise { seal in if decodedJWTToken.intent == RequiredActionName.threeDSAuthentication.rawValue { guard let paymentMethodTokenData = paymentMethodTokenData else { - let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) let containerErr = PrimerError.failedToPerform3DS(paymentMethodType: self.paymentMethodType, error: err, userInfo: ["file": #file, @@ -625,7 +636,8 @@ extension PrimerHeadlessUniversalCheckout { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -691,15 +703,19 @@ extension PrimerHeadlessUniversalCheckout { let error = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) seal.reject(error) } } else { - let err = PrimerError.invalidValue(key: "resumeToken", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "resumeToken", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -715,10 +731,12 @@ extension PrimerHeadlessUniversalCheckout { case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -958,10 +976,12 @@ extension PrimerHeadlessUniversalCheckout.VaultManager: SFSafariViewControllerDe public func safariViewControllerDidFinish(_ controller: SFSafariViewController) { if let webViewCompletion = webViewCompletion { // Cancelled - let err = PrimerError.cancelled(paymentMethodType: self.paymentMethodType, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.cancelled(paymentMethodType: self.paymentMethodType, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) webViewCompletion(nil, err) } @@ -1024,3 +1044,4 @@ extension PrimerPaymentMethodTokenData { } extension PrimerHeadlessUniversalCheckout.VaultManager: PaymentMethodTypeViaPaymentMethodTokenDataProviding {} +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift index 54f0954f5c..c26fae6f24 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 4/10/22. // +// swiftlint:disable cyclomatic_complexity + import UIKit @objc @@ -191,3 +193,5 @@ public protocol PrimerHeadlessUniversalCheckoutInputElement { var type: PrimerInputElementType { get set } var isValid: Bool { get } } + +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift index 1501b3e2a1..b02d2f112f 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 4/10/22. // +// swiftlint:disable cyclomatic_complexity + import UIKit extension PrimerHeadlessUniversalCheckout { @@ -38,7 +40,9 @@ extension PrimerHeadlessUniversalCheckout { self.inputElementDelegate?.inputElementDidBlur?(self.inputElement) } - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + func textField(_ textField: UITextField, + shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { guard let primerCheckoutComponentsTextField = textField as? PrimerInputTextField else { return false } if !string.isEmpty { // Characters aren't in the allowed character set @@ -103,3 +107,4 @@ extension PrimerHeadlessUniversalCheckout { } } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyCodable.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyCodable.swift index 633638bace..5474779494 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyCodable.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyCodable.swift @@ -6,6 +6,8 @@ // License: https://github.com/Flight-School/AnyCodable/blob/master/LICENSE.md // +// swiftlint:disable cyclomatic_complexity + import Foundation /** @@ -143,3 +145,4 @@ extension AnyCodable: Hashable { } } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift index 5df270109a..f08d0f9f0e 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift @@ -7,6 +7,7 @@ // // swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity #if canImport(Foundation) import Foundation #endif @@ -192,3 +193,4 @@ extension AnyDecodable: Hashable { } } // swiftlint:enable type_name +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift index a3a71084f5..3d22f8da87 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift @@ -11,6 +11,7 @@ import Foundation #endif // swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity /** A type-erased `Encodable` value. @@ -294,4 +295,5 @@ extension AnyEncodable: Hashable { } } } +// swiftlint:enable cyclomatic_complexity // swiftlint:enable type_name diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/ApplePayUtils.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/ApplePayUtils.swift index 32ec35a074..38c9be4254 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/ApplePayUtils.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/ApplePayUtils.swift @@ -5,6 +5,8 @@ // Created by Jack Newcombe on 07/11/2023. // +// swiftlint:disable cyclomatic_complexity + import PassKit private let paymentOptionsSettings = PrimerSettings.current.paymentMethodOptions.cardPaymentOptions @@ -60,3 +62,4 @@ final class ApplePayUtils { } } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift index 842dd0afff..0eaacc04bd 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift @@ -7,6 +7,7 @@ import Foundation +// swiftlint:disable cyclomatic_complexity class ImageFileProcessor { init() {} @@ -123,3 +124,4 @@ class ImageFileProcessor { } } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Modules/Downloader.swift b/Sources/PrimerSDK/Classes/Modules/Downloader.swift index c6a2bff103..76f09c66db 100644 --- a/Sources/PrimerSDK/Classes/Modules/Downloader.swift +++ b/Sources/PrimerSDK/Classes/Modules/Downloader.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 14/7/22. // +// swiftlint:disable cyclomatic_complexity + import Foundation internal typealias FileName = String @@ -295,3 +297,4 @@ extension Downloader: FileManagerDelegate { return true } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift index 062ac0c118..2e95e826db 100644 --- a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift @@ -7,7 +7,9 @@ import Foundation -// swiftlint:disable:next type_name +// swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity + class PrimerRawCardDataRedirectTokenizationBuilder: PrimerRawDataTokenizationBuilderProtocol { var requiredInputElementTypes: [PrimerInputElementType] @@ -37,7 +39,6 @@ class PrimerRawCardDataRedirectTokenizationBuilder: PrimerRawDataTokenizationBui } } -// swiftlint:disable:next type_name class PrimerBancontactRawCardDataRedirectTokenizationBuilder: PrimerRawDataTokenizationBuilderProtocol { var rawData: PrimerRawData? { @@ -259,3 +260,6 @@ class PrimerBancontactRawCardDataRedirectTokenizationBuilder: PrimerRawDataToken } } } + +// swiftlint:enable type_name +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift index 69e102b91d..b6e1c33181 100644 --- a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift @@ -5,6 +5,8 @@ // Created by Dario Carlomagno on 18/08/22. // +// swiftlint:disable cyclomatic_complexity + import Foundation class PrimerRawCardDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProtocol { @@ -54,7 +56,8 @@ class PrimerRawCardDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProt } DispatchQueue.main.async { - rawDataManager.delegate?.primerRawDataManager?(rawDataManager, metadataDidChange: ["cardNetwork": self.cardNetwork.rawValue]) + rawDataManager.delegate?.primerRawDataManager?(rawDataManager, + metadataDidChange: ["cardNetwork": self.cardNetwork.rawValue]) } } } @@ -293,3 +296,4 @@ class PrimerRawCardDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProt } } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift index 0ef841103f..2996147fed 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift @@ -6,6 +6,8 @@ // import Foundation +// swiftlint:disable function_body_length +// swiftlint:disable cyclomatic_complexity internal class URLSessionStack: NetworkService, LogReporter { @@ -20,8 +22,6 @@ internal class URLSessionStack: NetworkService, LogReporter { } // MARK: - Network Stack logic - - // swiftlint:disable function_body_length @discardableResult func request(_ endpoint: Endpoint, completion: @escaping ResultCallback) -> PrimerCancellable? { @@ -44,10 +44,12 @@ internal class URLSessionStack: NetworkService, LogReporter { } guard let url = url(for: endpoint) else { - let err = InternalError.invalidUrl(url: "Base URL: \(endpoint.baseURL ?? "nil") | Endpoint: \(endpoint.path)", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.invalidUrl(url: "Base URL: \(endpoint.baseURL ?? "nil") | Endpoint: \(endpoint.path)", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return nil @@ -142,7 +144,8 @@ internal class URLSessionStack: NetworkService, LogReporter { let err = InternalError.noData(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) DispatchQueue.main.async { completion(.failure(err)) } return @@ -205,10 +208,13 @@ internal class URLSessionStack: NetworkService, LogReporter { } if statusCode == 401 { - let err = InternalError.unauthorized(url: urlStr, method: endpoint.method, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.unauthorized(url: urlStr, + method: endpoint.method, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) #if DEBUG @@ -219,10 +225,13 @@ internal class URLSessionStack: NetworkService, LogReporter { DispatchQueue.main.async { completion(.failure(err)) } } else if (400...499).contains(statusCode) { - let err = InternalError.serverError(status: statusCode, response: primerErrorResponse, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.serverError(status: statusCode, + response: primerErrorResponse, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) #if DEBUG @@ -233,10 +242,13 @@ internal class URLSessionStack: NetworkService, LogReporter { DispatchQueue.main.async { completion(.failure(err)) } } else if (500...599).contains(statusCode) { - let err = InternalError.serverError(status: statusCode, response: primerErrorResponse, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.serverError(status: statusCode, + response: primerErrorResponse, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) #if DEBUG @@ -247,10 +259,13 @@ internal class URLSessionStack: NetworkService, LogReporter { DispatchQueue.main.async { completion(.failure(err)) } } else { - let err = InternalError.serverError(status: statusCode, response: primerErrorResponse, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.serverError(status: statusCode, + response: primerErrorResponse, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) resEventProperties?.errorBody = err.localizedDescription @@ -265,10 +280,12 @@ internal class URLSessionStack: NetworkService, LogReporter { } } else { - let err = InternalError.failedToDecode(message: "Failed to decode response from URL: \(urlStr)", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "Failed to decode response from URL: \(urlStr)", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) resEventProperties?.errorBody = err.localizedDescription @@ -350,3 +367,5 @@ internal extension URLSessionStack { return true } } +// swiftlint:enable function_body_length +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift index 071b9851f5..15e911c6ab 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift @@ -771,6 +771,7 @@ extension CardFormPaymentMethodTokenizationViewModel: InternalCardComponentsMana } } + // swiftlint:disable cyclomatic_complexity fileprivate func showTexfieldViewErrorIfNeeded(for primerTextFieldView: PrimerTextFieldView, isValid: Bool?) { if isValid == false { @@ -829,6 +830,7 @@ extension CardFormPaymentMethodTokenizationViewModel: InternalCardComponentsMana } } } + // swiftlint:enable cyclomatic_complexity fileprivate func enableSubmitButtonIfNeeded() { var validations = [ diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift index 135b976552..2045cdddc2 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift @@ -5,6 +5,9 @@ // Copyright © 2022 Primer API ltd. All rights reserved. // +// swiftlint:disable identifier_name +// swiftlint:disable cyclomatic_complexity + import Foundation import UIKit @@ -397,7 +400,6 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel billingAddressFields.flatMap { $0.filter { $0.isFieldHidden == false } }.map { $0.fieldView } } - // swiftlint:disable:next identifier_name internal var allVisibleBillingAddressFieldContainerViews: [[PrimerCustomFieldView]] { let allVisibleBillingAddressFields = billingAddressFields.map { $0.filter { $0.isFieldHidden == false } } return allVisibleBillingAddressFields.map { $0.map { $0.containerFieldView } } @@ -433,7 +435,6 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel /// Dictionary containing the payment method types expecting to show a view with the Payment Logo and a message /// informing the user to complete the payment outside of the current Application context - // swiftlint:disable:next identifier_name let needingExternalCompletionPaymentMethodDictionary: [PrimerPaymentMethodType: String] = [.adyenMBWay: Strings.MBWay.completeYourPayment, .adyenBlik: Strings.Blik.completeYourPayment] @@ -454,35 +455,45 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } guard decodedJWTToken.pciUrl != nil else { - let err = PrimerError.invalidValue(key: "clientToken.pciUrl", value: decodedJWTToken.pciUrl, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "clientToken.pciUrl", + value: decodedJWTToken.pciUrl, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } if PrimerInternal.shared.intent == .checkout { if AppState.current.amount == nil { - let err = PrimerError.invalidSetting(name: "amount", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidSetting(name: "amount", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } if AppState.current.currency == nil { - let err = PrimerError.invalidSetting(name: "currency", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidSetting(name: "currency", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -604,7 +615,8 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel let error = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) seal.reject(error) } } else if decodedJWTToken.intent == RequiredActionName.paymentMethodVoucher.rawValue { @@ -1024,3 +1036,5 @@ extension FormPaymentMethodTokenizationViewModel: UITextFieldDelegate { return true } } +// swiftlint:enable identifier_name +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift index 916f721966..e4a1b66759 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 5/7/21. // +// swiftlint:disable cyclomatic_complexity + import UIKit public final class PrimerCVVFieldView: PrimerTextFieldView { @@ -28,7 +30,9 @@ public final class PrimerCVVFieldView: PrimerTextFieldView { } } - public override func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + public override func textField(_ textField: UITextField, + shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { guard let primerTextField = textField as? PrimerTextField else { return true } let currentText = primerTextField.internalText ?? "" let newText = (currentText as NSString).replacingCharacters(in: range, with: string) as String @@ -90,5 +94,5 @@ public final class PrimerCVVFieldView: PrimerTextFieldView { return false } - } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift index d633bf6e81..369caa563a 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 29/6/21. // +// swiftlint:disable cyclomatic_complexity + import UIKit public final class PrimerCardNumberFieldView: PrimerTextFieldView { @@ -96,5 +98,5 @@ public final class PrimerCardNumberFieldView: PrimerTextFieldView { primerTextField.text = newText.withoutWhiteSpace.separate(every: 4, with: " ") return false } - } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift index 68e2720991..f6d4d1cd52 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 5/7/21. // +// swiftlint:disable cyclomatic_complexity + import UIKit public final class PrimerExpiryDateFieldView: PrimerTextFieldView { @@ -26,7 +28,9 @@ public final class PrimerExpiryDateFieldView: PrimerTextFieldView { } } - public override func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + public override func textField(_ textField: UITextField, + shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { guard let primerTextField = textField as? PrimerTextField else { return true } let currentText = primerTextField.internalText ?? "" var newText = (currentText as NSString).replacingCharacters(in: range, with: string) as String @@ -88,3 +92,4 @@ public final class PrimerExpiryDateFieldView: PrimerTextFieldView { return false } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift index 32a762b0d4..67f7aab4a3 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift @@ -5,6 +5,8 @@ // Copyright © 2022 Primer API ltd. All rights reserved. // +// swiftlint:disable cyclomatic_complexity + import UIKit internal class PrimerRootViewController: PrimerViewController { @@ -447,3 +449,4 @@ extension PrimerRootViewController: UIGestureRecognizerDelegate { return true } } +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift index 0cdae5f1d3..549d08a245 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 31/7/21. // +// swiftlint:disable cyclomatic_complexity + import UIKit internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { @@ -331,3 +333,5 @@ extension PrimerUniversalCheckoutViewController: ReloadDelegate { renderSelectedPaymentInstrument(insertAt: 1) } } + +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift index 580be82402..7063a8e2df 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift @@ -7,7 +7,8 @@ import Foundation -// swiftlint:disable:next type_name +// swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity class CheckoutWithVaultedPaymentMethodViewModel: LogReporter { static var apiClient: PrimerAPIClientProtocol? @@ -265,10 +266,11 @@ Make sure you call the decision handler otherwise the SDK will hang. case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], diagnosticsId: UUID().uuidString) merchantErr = err } else { @@ -298,10 +300,13 @@ Make sure you call the decision handler otherwise the SDK will hang. } else { guard let resumePaymentId = self.resumePaymentId else { - let resumePaymentIdError = PrimerError.invalidValue(key: "resumePaymentId", value: "Resume Payment ID not valid", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let resumePaymentIdError = PrimerError.invalidValue(key: "resumePaymentId", + value: "Resume Payment ID not valid", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: resumePaymentIdError) seal.reject(resumePaymentIdError) return @@ -312,10 +317,13 @@ Make sure you call the decision handler otherwise the SDK will hang. } .done { paymentResponse -> Void in guard let paymentResponse = paymentResponse else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -416,7 +424,8 @@ Make sure you call the decision handler otherwise the SDK will hang. let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -430,10 +439,12 @@ Make sure you call the decision handler otherwise the SDK will hang. case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -454,7 +465,8 @@ Make sure you call the decision handler otherwise the SDK will hang. let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -492,10 +504,13 @@ Make sure you call the decision handler otherwise the SDK will hang. } .done { paymentResponse -> Void in guard paymentResponse != nil else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) throw err } @@ -513,7 +528,8 @@ Make sure you call the decision handler otherwise the SDK will hang. let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -539,10 +555,12 @@ Make sure you call the decision handler otherwise the SDK will hang. return Promise { seal in if decodedJWTToken.intent == RequiredActionName.threeDSAuthentication.rawValue { guard let paymentMethodTokenData = self.paymentMethodTokenData else { - let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) let containerErr = PrimerError.failedToPerform3DS(paymentMethodType: self.paymentMethodType, error: err, userInfo: ["file": #file, @@ -571,10 +589,13 @@ Make sure you call the decision handler otherwise the SDK will hang. } } else { - let err = PrimerError.invalidValue(key: "resumeToken", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "resumeToken", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -657,3 +678,5 @@ Make sure you call the decision handler otherwise the SDK will hang. self.paymentMethodTokenData?.paymentInstrumentData?.paymentMethodType ?? "UNKNOWN" } } +// swiftlint:enable type_name +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift index 519d483e84..f369fca3b4 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 12/12/22. // +// swiftlint:disable cyclomatic_complexity + import Foundation import UIKit @@ -57,7 +59,8 @@ class IPay88TokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -315,10 +318,13 @@ class IPay88TokenizationViewModel: PaymentMethodTokenizationViewModel { return Promise { seal in #if canImport(PrimerIPay88MYSDK) guard let configId = config.id else { - let err = PrimerError.invalidValue(key: "configuration.id", value: config.id, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "configuration.id", + value: config.id, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -709,3 +715,4 @@ extension IPay88TokenizationViewModel: PrimerIPay88ViewControllerDelegate { } } #endif +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift index cab9fe51f7..db2803fe36 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift @@ -1,3 +1,5 @@ +// swiftlint:disable cyclomatic_complexity + import Foundation import UIKit @@ -337,7 +339,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -347,7 +350,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.missingPrimerConfiguration(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -357,10 +361,13 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { var amount = AppState.current.amount if amount == nil && PrimerInternal.shared.intent == .checkout { - let err = PrimerError.invalidSetting(name: "amount", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidSetting(name: "amount", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -371,40 +378,52 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { if case .oneOffPayment = klarnaSessionType { if amount == nil { - let err = PrimerError.invalidSetting(name: "amount", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidSetting(name: "amount", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return } if AppState.current.currency == nil { - let err = PrimerError.invalidSetting(name: "currency", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidSetting(name: "currency", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return } if (PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.lineItems ?? []).isEmpty { - let err = PrimerError.invalidValue(key: "settings.orderItems", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "settings.orderItems", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return } if !(PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.lineItems ?? []).filter({ $0.amount == nil }).isEmpty { - let err = PrimerError.invalidValue(key: "settings.orderItems.amount", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "settings.orderItems.amount", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -462,7 +481,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -520,7 +540,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return @@ -569,3 +590,4 @@ extension KlarnaTokenizationViewModel: PrimerKlarnaViewControllerDelegate { } } #endif +// swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift index 54b7604c75..1d8e1276a9 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 6/5/22. // +// swiftlint:disable cyclomatic_complexity + import Foundation import UIKit @@ -248,7 +250,8 @@ extension PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -262,10 +265,12 @@ extension PaymentMethodTokenizationViewModel { case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -286,7 +291,8 @@ extension PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -324,10 +330,13 @@ extension PaymentMethodTokenizationViewModel { } .done { paymentResponse -> Void in guard paymentResponse != nil else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) throw err } @@ -345,7 +354,8 @@ extension PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -376,10 +386,12 @@ extension PaymentMethodTokenizationViewModel { case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -408,10 +420,13 @@ extension PaymentMethodTokenizationViewModel { } else { guard let resumePaymentId = self.resumePaymentId else { - let resumePaymentIdError = PrimerError.invalidValue(key: "resumePaymentId", value: "Resume Payment ID not valid", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let resumePaymentIdError = PrimerError.invalidValue(key: "resumePaymentId", + value: "Resume Payment ID not valid", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: resumePaymentIdError) seal.reject(resumePaymentIdError) return @@ -422,10 +437,13 @@ extension PaymentMethodTokenizationViewModel { } .done { paymentResponse -> Void in guard let paymentResponse = paymentResponse else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -636,3 +654,4 @@ Make sure you call the decision handler otherwise the SDK will hang. } extension PaymentMethodTokenizationViewModel: PaymentMethodTypeViaPaymentMethodTokenDataProviding {} +// swiftlint:enable cyclomatic_complexity From c40fe5d8e514a13458c0aa79d4eb2a53356ed6c8 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 11:46:11 +0100 Subject: [PATCH 03/21] Fix all file length warnings --- Debug App/.swiftlint.yml | 2 - .../Classes/Core/3DS/3DSService.swift | 3 + .../Classes/Core/3DS/Data Models/3DS.swift | 3 + .../Classes/Core/Constants/Strings.swift | 2 + .../Models/BanksTokenizationComponent.swift | 6 +- .../CardComponentsManager.swift | 7 ++- .../RawDataManager.swift | 7 ++- .../Managers/VaultManager.swift | 2 + .../Classes/Data Models/PaymentMethod.swift | 3 + .../Data Models/PrimerConfiguration.swift | 3 + .../Classes/Modules/UserInterfaceModule.swift | 3 + .../PCI/Services/API/Primer/PrimerAPI.swift | 4 +- ...rmPaymentMethodTokenizationViewModel.swift | 62 ++++++++++++------- ...ethodTokenizationViewModel+FormViews.swift | 3 + ...rmPaymentMethodTokenizationViewModel.swift | 2 + .../InternalCardComponentsManager.swift | 4 +- .../Root/PrimerRootViewController.swift | 2 + .../ApplePayTokenizationViewModel.swift | 3 + ...outWithVaultedPaymentMethodViewModel.swift | 7 ++- .../IPay88TokenizationViewModel.swift | 2 + .../KlarnaTokenizationViewModel.swift | 2 + .../PayPalTokenizationViewModel.swift | 3 + ...entMethodTokenizationViewModel+Logic.swift | 2 + ...ctPaymentMethodTokenizationViewModel.swift | 3 + 24 files changed, 106 insertions(+), 34 deletions(-) diff --git a/Debug App/.swiftlint.yml b/Debug App/.swiftlint.yml index 896ee0ef7d..41bb193615 100644 --- a/Debug App/.swiftlint.yml +++ b/Debug App/.swiftlint.yml @@ -2,8 +2,6 @@ disabled_rules: - line_length - type_body_length - function_body_length - - file_length -# - cyclomatic_complexity included: - ../Sources diff --git a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift index 615fc34043..4c339e09d3 100644 --- a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift +++ b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 17/6/21. // +// swiftlint:disable file_length + import Foundation import UIKit @@ -733,3 +735,4 @@ internal class MockPrimer3DSCompletion: Primer3DSCompletion { var transactionStatus: String = "transactionStatus" } #endif +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift b/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift index fc58ca719e..2c6105d6d9 100644 --- a/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift +++ b/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 1/4/21. // +// swiftlint:disable file_length + import Foundation #if canImport(Primer3DS) import Primer3DS @@ -635,3 +637,4 @@ public class ThreeDS { } } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift index 24864c9b9f..0d3d071a86 100644 --- a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift +++ b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift @@ -5,6 +5,7 @@ // Copyright © 2022 Primer API ltd. All rights reserved. // +// swiftlint:disable file_length import Foundation // MARK: - Strings @@ -1037,3 +1038,4 @@ extension Strings { comment: "The title of the mocked failed flow for a Test Payment Method") } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift index 18ef61796e..b06ac606a2 100644 --- a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift @@ -5,12 +5,13 @@ // Created by Alexandra Lovin on 03.12.2023. // +// swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length + import Foundation import UIKit import SafariServices -// swiftlint:disable cyclomatic_complexity - final class BanksTokenizationComponent: NSObject, LogReporter { var config: PrimerPaymentMethod var paymentMethodType: PrimerPaymentMethodType @@ -1138,3 +1139,4 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift index 13095271d4..3836b05ed7 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift @@ -5,12 +5,14 @@ // Created by Evangelos on 9/2/22. // +// swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length + import Foundation import SafariServices public protocol PrimerHeadlessUniversalCheckoutInputData {} -// swiftlint:disable type_name -// swiftlint:disable cyclomatic_complexity @available(*, deprecated, message: "CardComponentsManager is no longer supported, please use PrimerHeadlessUniversalCheckout instead") public protocol PrimerHeadlessUniversalCheckoutCardComponentsManagerDelegate: AnyObject { @@ -1285,3 +1287,4 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager: SFSafariViewCon } // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift index 17dcdadcc8..2f40958f19 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift @@ -5,11 +5,13 @@ // Created by Evangelos on 12/7/22. // +// swiftlint:disable type_name +// swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length + import Foundation import SafariServices -// swiftlint:disable type_name -// swiftlint:disable cyclomatic_complexity @objc public protocol PrimerHeadlessUniversalCheckoutRawDataManagerDelegate { @@ -1066,3 +1068,4 @@ extension PrimerHeadlessUniversalCheckout.RawDataManager { // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift index a9f74dc4e6..6945da767a 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length import SafariServices import UIKit @@ -1045,3 +1046,4 @@ extension PrimerPaymentMethodTokenData { extension PrimerHeadlessUniversalCheckout.VaultManager: PaymentMethodTypeViaPaymentMethodTokenDataProviding {} // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift b/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift index dd539d8dd6..b954489c86 100644 --- a/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift +++ b/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift @@ -5,6 +5,8 @@ // Copyright © 2022 Primer API ltd. All rights reserved. // +// swiftlint:disable file_length + import Foundation import UIKit @@ -563,3 +565,4 @@ extension PrimerTheme { } } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift b/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift index fe14b2a9b7..6e0e615614 100644 --- a/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift +++ b/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 28/12/21. // +// swiftlint:disable file_length + import Foundation import PassKit @@ -438,3 +440,4 @@ extension Response.Body.Configuration { } } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift b/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift index f26132b297..4f12bea623 100644 --- a/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift +++ b/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift @@ -5,6 +5,8 @@ // Copyright © 2022 Primer API ltd. All rights reserved. // +// swiftlint:disable file_length + protocol UserInterfaceModuleProtocol { var paymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModelProtocol! { get } @@ -1047,3 +1049,4 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { self.paymentMethodTokenizationViewModel.submitButtonTapped() } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift index 02d22987ba..89384a6c59 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 26/2/21. // +// swiftlint:disable file_length + import Foundation enum PrimerAPI: Endpoint, Equatable { @@ -461,5 +463,5 @@ internal extension PrimerAPI { var configuration: PrimerAPIConfiguration? { PrimerAPIConfiguration.current } - } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift index 15e911c6ab..6bd6d25514 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 11/10/21. // +// swiftlint:disable file_length + import Foundation import SafariServices import UIKit @@ -330,35 +332,45 @@ class CardFormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewM let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } guard decodedJWTToken.pciUrl != nil else { - let err = PrimerError.invalidValue(key: "clientToken.pciUrl", value: decodedJWTToken.pciUrl, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "clientToken.pciUrl", + value: decodedJWTToken.pciUrl, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } if PrimerInternal.shared.intent == .checkout { if AppState.current.amount == nil { - let err = PrimerError.invalidSetting(name: "amount", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidSetting(name: "amount", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } if AppState.current.currency == nil { - let err = PrimerError.invalidSetting(name: "currency", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidSetting(name: "currency", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -505,16 +517,19 @@ class CardFormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewM let error = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) seal.reject(error) } } else if decodedJWTToken.intent == RequiredActionName.threeDSAuthentication.rawValue { guard let paymentMethodTokenData = paymentMethodTokenData else { - let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "Failed to find paymentMethod", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) let containerErr = PrimerError.failedToPerform3DS(paymentMethodType: self.paymentMethodType, error: err, userInfo: ["file": #file, @@ -918,10 +933,12 @@ extension CardFormPaymentMethodTokenizationViewModel: SFSafariViewControllerDele func safariViewControllerDidFinish(_ controller: SFSafariViewController) { if let webViewCompletion = webViewCompletion { // Cancelled - let err = PrimerError.cancelled(paymentMethodType: config.type, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.cancelled(paymentMethodType: config.type, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) webViewCompletion(nil, err) } @@ -1007,3 +1024,4 @@ private extension String { locale: nil) } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift index a4b592a19b..a7058f6139 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift @@ -5,6 +5,8 @@ // Copyright © 2022 Primer API ltd. All rights reserved. // +// swiftlint:disable file_length + import UIKit extension FormPaymentMethodTokenizationViewModel { @@ -423,3 +425,4 @@ extension FormPaymentMethodTokenizationViewModel { } } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift index 2045cdddc2..593aa93704 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift @@ -7,6 +7,7 @@ // swiftlint:disable identifier_name // swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length import Foundation import UIKit @@ -1038,3 +1039,4 @@ extension FormPaymentMethodTokenizationViewModel: UITextFieldDelegate { } // swiftlint:enable identifier_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift index f8120d6c49..a128379a34 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 6/7/21. // +// swiftlint:disable file_length + import UIKit @objc @@ -450,5 +452,5 @@ internal class MockCardComponentsManager: InternalCardComponentsManagerProtocol func tokenize() { } - } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift index 67f7aab4a3..69cfeb3136 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length import UIKit @@ -450,3 +451,4 @@ extension PrimerRootViewController: UIGestureRecognizerDelegate { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift index 5c8a974f04..93bbde3745 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift @@ -1,3 +1,5 @@ +// swiftlint:disable file_length + import Foundation import PassKit import UIKit @@ -614,3 +616,4 @@ extension ApplePayTokenizationViewModel: PKPaymentAuthorizationControllerDelegat } } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift index 7063a8e2df..4f06115b97 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift @@ -5,10 +5,12 @@ // Created by Evangelos on 9/5/22. // -import Foundation - // swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length + +import Foundation + class CheckoutWithVaultedPaymentMethodViewModel: LogReporter { static var apiClient: PrimerAPIClientProtocol? @@ -680,3 +682,4 @@ Make sure you call the decision handler otherwise the SDK will hang. } // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift index f369fca3b4..302fc15c83 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length import Foundation import UIKit @@ -716,3 +717,4 @@ extension IPay88TokenizationViewModel: PrimerIPay88ViewControllerDelegate { } #endif // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift index db2803fe36..421b351613 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift @@ -1,4 +1,5 @@ // swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length import Foundation import UIKit @@ -591,3 +592,4 @@ extension KlarnaTokenizationViewModel: PrimerKlarnaViewControllerDelegate { } #endif // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift index 153fff8613..e0da75b730 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift @@ -1,3 +1,5 @@ +// swiftlint:disable file_length + import UIKit import AuthenticationServices import SafariServices @@ -456,3 +458,4 @@ extension PayPalTokenizationViewModel: ASWebAuthenticationPresentationContextPro } } +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift index 1d8e1276a9..d14df91dd6 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable file_length import Foundation import UIKit @@ -655,3 +656,4 @@ Make sure you call the decision handler otherwise the SDK will hang. extension PaymentMethodTokenizationViewModel: PaymentMethodTypeViaPaymentMethodTokenDataProviding {} // swiftlint:enable cyclomatic_complexity +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift index 7a849181bd..fabd25f080 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 11/10/21. // +// swiftlint:disable file_length + import Foundation import SafariServices import UIKit @@ -454,3 +456,4 @@ struct PollingResponse: Decodable { } } +// swiftlint:enable file_length From 2433ce6def9d881baf2b57e1544e30482a90b5fb Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 12:19:49 +0100 Subject: [PATCH 04/21] Fix all function_body_length warnings and errors --- Debug App/.swiftlint.yml | 1 - .../Classes/Core/3DS/3DSService.swift | 2 ++ .../Models/BanksTokenizationComponent.swift | 2 ++ .../Core/Payment Services/PayPalService.swift | 22 +++++++++++++------ .../NolPay/NolPayLinkCardComponent.swift | 2 ++ .../NolPay/NolPayLinkedCardsComponent.swift | 4 +++- .../NolPay/NolPayPaymentComponent.swift | 3 +++ .../NolPay/NolPayPhoneMetadataService.swift | 7 ++++-- .../NolPay/NolPayUnlinkCardComponent.swift | 2 ++ .../CardComponentsManager.swift | 2 ++ .../RawDataManager.swift | 2 ++ ...awPhoneNumberDataTokenizationBuilder.swift | 6 ++++- ...erRawRetailerDataTokenizationBuilder.swift | 3 +++ .../Managers/VaultManager.swift | 2 ++ ...niversalCheckoutInputElementDelegate.swift | 2 ++ .../PrimerHeadlessUniversalCheckout.swift | 3 +++ .../Extensions & Utilities/AnyEncodable.swift | 2 ++ .../ImageFileProcessor.swift | 2 ++ .../Classes/Modules/Downloader.swift | 2 ++ .../Classes/Modules/ImageManager.swift | 3 +++ ...wCardDataRedirectTokenizationBuilder.swift | 2 ++ ...PrimerRawCardDataTokenizationBuilder.swift | 2 ++ ...rmPaymentMethodTokenizationViewModel.swift | 2 ++ ...rmPaymentMethodTokenizationViewModel.swift | 2 ++ .../Classes/PCI/TokenizationService.swift | 3 +++ .../InternalCardComponentsManager.swift | 2 ++ .../Text Fields/PrimerCVVFieldView.swift | 2 ++ .../PrimerCardNumberFieldView.swift | 2 ++ .../PrimerExpiryDateFieldView.swift | 2 ++ .../User Interface/PrimerUIManager.swift | 3 +++ .../Root/PrimerFormViewController.swift | 3 +++ .../Root/PrimerRootViewController.swift | 2 ++ ...rimerUniversalCheckoutViewController.swift | 2 ++ .../ApplePayTokenizationViewModel.swift | 2 ++ .../BankSelectorTokenizationViewModel.swift | 3 +++ ...outWithVaultedPaymentMethodViewModel.swift | 2 ++ .../IPay88TokenizationViewModel.swift | 2 ++ .../KlarnaTokenizationViewModel.swift | 2 ++ ...entMethodTokenizationViewModel+Logic.swift | 2 ++ .../QRCodeTokenizationViewModel.swift | 3 +++ ...ctPaymentMethodTokenizationViewModel.swift | 2 ++ .../VaultPaymentMethodViewController.swift | 3 +++ 42 files changed, 112 insertions(+), 12 deletions(-) diff --git a/Debug App/.swiftlint.yml b/Debug App/.swiftlint.yml index 41bb193615..7180fa9af2 100644 --- a/Debug App/.swiftlint.yml +++ b/Debug App/.swiftlint.yml @@ -1,7 +1,6 @@ disabled_rules: - line_length - type_body_length - - function_body_length included: - ../Sources diff --git a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift index 4c339e09d3..5a3b15119a 100644 --- a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift +++ b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift @@ -6,6 +6,7 @@ // // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import UIKit @@ -735,4 +736,5 @@ internal class MockPrimer3DSCompletion: Primer3DSCompletion { var transactionStatus: String = "transactionStatus" } #endif +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift index b06ac606a2..93fccb3e9e 100644 --- a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import UIKit @@ -1139,4 +1140,5 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift b/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift index d70ae82bec..2b8787bc9b 100644 --- a/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift +++ b/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift @@ -1,3 +1,5 @@ +// swiftlint:disable function_body_length + import Foundation internal protocol PayPalServiceProtocol { @@ -184,13 +186,16 @@ internal class PayPalService: PayPalServiceProtocol { ) let apiClient: PrimerAPIClientProtocol = PayPalService.apiClient ?? PrimerAPIClient() - apiClient.createPayPalBillingAgreementSession(clientToken: decodedJWTToken, payPalCreateBillingAgreementRequest: body) { [weak self] (result) in + apiClient.createPayPalBillingAgreementSession(clientToken: decodedJWTToken, + payPalCreateBillingAgreementRequest: body) { [weak self] (result) in switch result { case .failure(let err): - let containerErr = PrimerError.failedToCreateSession(error: err, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let containerErr = PrimerError.failedToCreateSession(error: err, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: containerErr) completion(.failure(containerErr)) case .success(let config): @@ -207,7 +212,8 @@ internal class PayPalService: PayPalServiceProtocol { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return @@ -250,7 +256,8 @@ internal class PayPalService: PayPalServiceProtocol { let containerErr = PrimerError.failedToCreateSession(error: err, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: containerErr) completion(.failure(containerErr)) case .success(let response): @@ -299,3 +306,4 @@ internal class PayPalService: PayPalServiceProtocol { } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift index 233754e00d..130bdd0c99 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import Foundation #if canImport(PrimerNolPaySDK) @@ -333,3 +334,4 @@ public class NolPayLinkCardComponent: PrimerHeadlessCollectDataComponent { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift index 7db6859bd7..86b04c32fa 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift @@ -5,6 +5,8 @@ // Created by Boris on 15.9.23.. // +// swiftlint:disable function_body_length + import Foundation #if canImport(PrimerNolPaySDK) import PrimerNolPaySDK @@ -209,5 +211,5 @@ public class NolPayLinkedCardsComponent { } } } - #endif +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift index 81d2ba71cc..81077a1b7a 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift @@ -5,6 +5,8 @@ // Created by Boris on 18.9.23.. // +// swiftlint:disable function_body_length + import Foundation #if canImport(PrimerNolPaySDK) import PrimerNolPaySDK @@ -250,3 +252,4 @@ public class NolPayPaymentComponent: PrimerHeadlessCollectDataComponent { #endif } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPhoneMetadataService.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPhoneMetadataService.swift index 1e1bf0d7b1..8cd1db7e3e 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPhoneMetadataService.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPhoneMetadataService.swift @@ -5,11 +5,12 @@ // Created by Boris on 27.10.23.. // +// swiftlint:disable function_body_length +// swiftlint:disable large_tuple + import Foundation -// swiftlint:disable large_tuple typealias PhoneMetadataCompletion = (Result<(PrimerValidationStatus, String?, String?), PrimerError>) -> Void -// swiftlint:enable large_tuple protocol NolPayPhoneMetadataProviding { func getPhoneMetadata(mobileNumber: String, completion: @escaping PhoneMetadataCompletion) @@ -93,3 +94,5 @@ struct NolPayPhoneMetadataService: NolPayPhoneMetadataProviding { } } } +// swiftlint:enable large_tuple +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift index 0169873e6b..3825119360 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import Foundation #if canImport(PrimerNolPaySDK) @@ -309,3 +310,4 @@ public class NolPayUnlinkCardComponent: PrimerHeadlessCollectDataComponent { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift index 3836b05ed7..9385e23e57 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift @@ -8,6 +8,7 @@ // swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import SafariServices @@ -1287,4 +1288,5 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager: SFSafariViewCon } // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift index 2f40958f19..40059ad012 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift @@ -8,6 +8,7 @@ // swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import SafariServices @@ -1068,4 +1069,5 @@ extension PrimerHeadlessUniversalCheckout.RawDataManager { // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift index 06a663f810..8a1d73557f 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift @@ -5,9 +5,11 @@ // Created by Dario Carlomagno on 17/08/22. // +// swiftlint:disable function_body_length +// swiftlint:disable type_name + import Foundation -// swiftlint:disable:next type_name class PrimerRawPhoneNumberDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProtocol { var rawData: PrimerRawData? { @@ -151,3 +153,5 @@ class PrimerRawPhoneNumberDataTokenizationBuilder: PrimerRawDataTokenizationBuil } } } +// swiftlint:enable type_name +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift index 4627d98eff..9b2ead876a 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift @@ -5,6 +5,8 @@ // Created by Dario Carlomagno on 18/10/22. // +// swiftlint:disable function_body_length + import Foundation class PrimerRawRetailerDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProtocol { @@ -149,3 +151,4 @@ class PrimerRawRetailerDataTokenizationBuilder: PrimerRawDataTokenizationBuilder } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift index 6945da767a..81b4cfa777 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import SafariServices import UIKit @@ -1046,4 +1047,5 @@ extension PrimerPaymentMethodTokenData { extension PrimerHeadlessUniversalCheckout.VaultManager: PaymentMethodTypeViaPaymentMethodTokenDataProviding {} // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift index b02d2f112f..1938d0cde1 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import UIKit @@ -108,3 +109,4 @@ extension PrimerHeadlessUniversalCheckout { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift index a373229c3e..dfad071ed9 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 28/1/22. // +// swiftlint:disable function_body_length + import UIKit public class PrimerHeadlessUniversalCheckout: LogReporter { @@ -281,3 +283,4 @@ Add `PrimerNolPaySDK' in your project by adding \"pod 'PrimerNolPaySDK'\" in you return paymentMethods?.compactMap({ $0.type }).filter({ !unsupportedPaymentMethodTypes.contains($0) }) } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift index 3d22f8da87..0ef3e053f6 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift @@ -12,6 +12,7 @@ import Foundation // swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length /** A type-erased `Encodable` value. @@ -297,3 +298,4 @@ extension AnyEncodable: Hashable { } // swiftlint:enable cyclomatic_complexity // swiftlint:enable type_name +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift index 0eaacc04bd..1ac120add5 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift @@ -8,6 +8,7 @@ import Foundation // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length class ImageFileProcessor { init() {} @@ -125,3 +126,4 @@ class ImageFileProcessor { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Modules/Downloader.swift b/Sources/PrimerSDK/Classes/Modules/Downloader.swift index 76f09c66db..51133bf0c5 100644 --- a/Sources/PrimerSDK/Classes/Modules/Downloader.swift +++ b/Sources/PrimerSDK/Classes/Modules/Downloader.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import Foundation @@ -298,3 +299,4 @@ extension Downloader: FileManagerDelegate { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Modules/ImageManager.swift b/Sources/PrimerSDK/Classes/Modules/ImageManager.swift index bde7725011..1ced7cbd5a 100644 --- a/Sources/PrimerSDK/Classes/Modules/ImageManager.swift +++ b/Sources/PrimerSDK/Classes/Modules/ImageManager.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 15/7/22. // +// swiftlint:disable function_body_length + import UIKit internal class ImageFile: File { @@ -235,3 +237,4 @@ internal class ImageManager: LogReporter { } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift index 2e95e826db..2121791a36 100644 --- a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift @@ -9,6 +9,7 @@ import Foundation // swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length class PrimerRawCardDataRedirectTokenizationBuilder: PrimerRawDataTokenizationBuilderProtocol { @@ -263,3 +264,4 @@ class PrimerBancontactRawCardDataRedirectTokenizationBuilder: PrimerRawDataToken // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift index b6e1c33181..b9356a2f5e 100644 --- a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataTokenizationBuilder.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import Foundation @@ -297,3 +298,4 @@ class PrimerRawCardDataTokenizationBuilder: PrimerRawDataTokenizationBuilderProt } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift index 6bd6d25514..2d4183b105 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift @@ -6,6 +6,7 @@ // // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import SafariServices @@ -1024,4 +1025,5 @@ private extension String { locale: nil) } } +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift index 593aa93704..0f7a0fabf0 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift @@ -8,6 +8,7 @@ // swiftlint:disable identifier_name // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import UIKit @@ -1039,4 +1040,5 @@ extension FormPaymentMethodTokenizationViewModel: UITextFieldDelegate { } // swiftlint:enable identifier_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift b/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift index 6d0103ba38..0fbac47c63 100644 --- a/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift +++ b/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift @@ -1,3 +1,5 @@ +// swiftlint:disable function_body_length + import Foundation internal protocol TokenizationServiceProtocol { @@ -102,3 +104,4 @@ internal class TokenizationService: TokenizationServiceProtocol, LogReporter { } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift index a128379a34..64b1b48ef9 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift @@ -6,6 +6,7 @@ // // swiftlint:disable file_length +// swiftlint:disable function_body_length import UIKit @@ -453,4 +454,5 @@ internal class MockCardComponentsManager: InternalCardComponentsManagerProtocol } } +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift index e4a1b66759..f869f58283 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import UIKit @@ -96,3 +97,4 @@ public final class PrimerCVVFieldView: PrimerTextFieldView { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift index 369caa563a..9c165e417a 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCardNumberFieldView.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import UIKit @@ -100,3 +101,4 @@ public final class PrimerCardNumberFieldView: PrimerTextFieldView { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift index f6d4d1cd52..779907d399 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import UIKit @@ -93,3 +94,4 @@ public final class PrimerExpiryDateFieldView: PrimerTextFieldView { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift b/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift index 1af00911c1..a1548f49f5 100644 --- a/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift +++ b/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 9/9/22. // +// swiftlint:disable function_body_length + import UIKit internal class PrimerUIManager { @@ -262,3 +264,4 @@ internal class PrimerUIManager { PrimerUIManager.primerRootViewController?.show(viewController: resultViewController) } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift index e38cac0569..c2ef93664a 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 27/7/21. // +// swiftlint:disable function_body_length + import UIKit class PrimerFormViewController: PrimerViewController { @@ -114,3 +116,4 @@ class PrimerFormViewController: PrimerViewController { } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift index 69cfeb3136..5cdd79bc50 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import UIKit @@ -451,4 +452,5 @@ extension PrimerRootViewController: UIGestureRecognizerDelegate { } } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift index 549d08a245..9a70722820 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift @@ -6,6 +6,7 @@ // // swiftlint:disable cyclomatic_complexity +// swiftlint:disable function_body_length import UIKit @@ -335,3 +336,4 @@ extension PrimerUniversalCheckoutViewController: ReloadDelegate { } // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift index 93bbde3745..ee46ad9c66 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift @@ -1,4 +1,5 @@ // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import PassKit @@ -616,4 +617,5 @@ extension ApplePayTokenizationViewModel: PKPaymentAuthorizationControllerDelegat } } } +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift index ff87b4116c..9b14a8d437 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift @@ -5,6 +5,8 @@ // Created by Admin on 8/11/21. // +// swiftlint:disable function_body_length + import SafariServices import UIKit @@ -380,3 +382,4 @@ extension BankSelectorTokenizationViewModel: BankSelectorTokenizationProviding { } extension BankSelectorTokenizationViewModel: WebRedirectTokenizationDelegate {} +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift index 4f06115b97..536111c3cc 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift @@ -8,6 +8,7 @@ // swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation @@ -682,4 +683,5 @@ Make sure you call the decision handler otherwise the SDK will hang. } // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift index 302fc15c83..ab11c396d7 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import UIKit @@ -717,4 +718,5 @@ extension IPay88TokenizationViewModel: PrimerIPay88ViewControllerDelegate { } #endif // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift index 421b351613..2809f6495c 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift @@ -1,5 +1,6 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import UIKit @@ -592,4 +593,5 @@ extension KlarnaTokenizationViewModel: PrimerKlarnaViewControllerDelegate { } #endif // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift index d14df91dd6..0c8a1e6d50 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable function_body_length import Foundation import UIKit @@ -656,4 +657,5 @@ Make sure you call the decision handler otherwise the SDK will hang. extension PaymentMethodTokenizationViewModel: PaymentMethodTypeViaPaymentMethodTokenDataProviding {} // swiftlint:enable cyclomatic_complexity +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift index bbacc09fe4..7b1c011ff0 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift @@ -5,6 +5,8 @@ // Copyright © 2022 Primer API ltd. All rights reserved. // +// swiftlint:disable function_body_length + import SafariServices import UIKit @@ -366,3 +368,4 @@ No events will be sent to your delegate instance. } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift index fabd25f080..916bfa9716 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift @@ -5,6 +5,7 @@ // Created by Evangelos Pittas on 11/10/21. // +// swiftlint:disable function_body_length // swiftlint:disable file_length import Foundation @@ -456,4 +457,5 @@ struct PollingResponse: Decodable { } } +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift index a572d6aafa..a8c5a5b600 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift @@ -1,3 +1,5 @@ +// swiftlint:disable function_body_length + import UIKit internal class VaultedPaymentInstrumentCell: UITableViewCell { @@ -338,3 +340,4 @@ extension VaultedPaymentInstrumentsViewController: UITableViewDataSource, UITabl tableView.reloadData() } } +// swiftlint:enable function_body_length From 3db73c964471c42628edd2027c99437e7a666993 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 12:43:13 +0100 Subject: [PATCH 05/21] Fix all type_body_length warnings and errors --- Debug App/.swiftlint.yml | 1 - .../Classes/Core/3DS/3DSService.swift | 2 + .../Classes/Core/3DS/Data Models/3DS.swift | 2 + .../Classes/Core/Constants/Strings.swift | 3 + .../Models/BanksTokenizationComponent.swift | 63 +++++++-- .../Core/Payment Services/PayPalService.swift | 2 + .../NolPay/NolPayLinkCardComponent.swift | 2 + .../CardComponentsManager.swift | 2 + .../RawDataManager.swift | 2 + .../Managers/VaultManager.swift | 2 + .../Classes/Data Models/CardNetwork.swift | 3 + .../Classes/Data Models/ClientSession.swift | 3 + .../Classes/Data Models/CountryCode.swift | 8 +- .../Classes/Data Models/PaymentMethod.swift | 2 + .../Theme/Public/PrimerThemeData.swift | 2 + .../Classes/Error Handler/PrimerError.swift | 5 + .../Error Handler/PrimerValidationError.swift | 3 + .../Classes/Modules/UserInterfaceModule.swift | 2 + .../Services/Network/URLSessionStack.swift | 2 + ...rmPaymentMethodTokenizationViewModel.swift | 2 + ...rmPaymentMethodTokenizationViewModel.swift | 2 + .../InternalCardComponentsManager.swift | 2 + .../Root/PrimerRootViewController.swift | 2 + .../ApplePayTokenizationViewModel.swift | 2 + ...outWithVaultedPaymentMethodViewModel.swift | 2 + .../IPay88TokenizationViewModel.swift | 2 + .../KlarnaTokenizationViewModel.swift | 2 + .../PayPalTokenizationViewModel.swift | 127 +++++++++++------- ...ctPaymentMethodTokenizationViewModel.swift | 2 + 29 files changed, 199 insertions(+), 57 deletions(-) diff --git a/Debug App/.swiftlint.yml b/Debug App/.swiftlint.yml index 7180fa9af2..e3699aaa35 100644 --- a/Debug App/.swiftlint.yml +++ b/Debug App/.swiftlint.yml @@ -1,6 +1,5 @@ disabled_rules: - line_length - - type_body_length included: - ../Sources diff --git a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift index 5a3b15119a..00e5bbdcbc 100644 --- a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift +++ b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift @@ -7,6 +7,7 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import UIKit @@ -737,4 +738,5 @@ internal class MockPrimer3DSCompletion: Primer3DSCompletion { } #endif // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift b/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift index 2c6105d6d9..06b913f90e 100644 --- a/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift +++ b/Sources/PrimerSDK/Classes/Core/3DS/Data Models/3DS.swift @@ -5,6 +5,7 @@ // Created by Evangelos Pittas on 1/4/21. // +// swiftlint:disable type_body_length // swiftlint:disable file_length import Foundation @@ -637,4 +638,5 @@ public class ThreeDS { } } } +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift index 0d3d071a86..ae74455166 100644 --- a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift +++ b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift @@ -6,6 +6,8 @@ // // swiftlint:disable file_length +// swiftlint:disable type_body_length + import Foundation // MARK: - Strings @@ -1038,4 +1040,5 @@ extension Strings { comment: "The title of the mocked failed flow for a Test Payment Method") } } +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift index 93fccb3e9e..5e17094589 100644 --- a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift @@ -8,6 +8,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import UIKit @@ -276,7 +277,11 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } .done { guard let decodedJWTToken = PrimerAPIConfigurationModule.decodedJWTToken else { - let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidClientToken(userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -290,7 +295,12 @@ final class BanksTokenizationComponent: NSObject, LogReporter { case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -308,7 +318,11 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } .done { guard let decodedJWTToken = PrimerAPIConfigurationModule.decodedJWTToken else { - let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidClientToken(userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -331,7 +345,10 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } else { guard let token = paymentMethodTokenData.token else { let err = PrimerError.invalidClientToken( - userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) @@ -343,7 +360,13 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } .done { paymentResponse -> Void in guard paymentResponse != nil else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) throw err } @@ -358,7 +381,11 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } .done { guard let decodedJWTToken = PrimerAPIConfigurationModule.decodedJWTToken else { - let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidClientToken(userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -577,7 +604,12 @@ final class BanksTokenizationComponent: NSObject, LogReporter { case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -606,7 +638,13 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } else { guard let resumePaymentId = self.resumePaymentId else { - let resumePaymentIdError = PrimerError.invalidValue(key: "resumePaymentId", value: "Resume Payment ID not valid", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let resumePaymentIdError = PrimerError.invalidValue(key: "resumePaymentId", + value: "Resume Payment ID not valid", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: resumePaymentIdError) seal.reject(resumePaymentIdError) return @@ -617,7 +655,13 @@ final class BanksTokenizationComponent: NSObject, LogReporter { } .done { paymentResponse -> Void in guard let paymentResponse = paymentResponse else { - let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "paymentResponse", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -1141,4 +1185,5 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { } // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift b/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift index 2b8787bc9b..a2327cf59c 100644 --- a/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift +++ b/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift @@ -1,4 +1,5 @@ // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation @@ -307,3 +308,4 @@ internal class PayPalService: PayPalServiceProtocol { } } // swiftlint:enable function_body_length +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift index 130bdd0c99..6d3af071cf 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation #if canImport(PrimerNolPaySDK) @@ -335,3 +336,4 @@ public class NolPayLinkCardComponent: PrimerHeadlessCollectDataComponent { } // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift index 9385e23e57..6a3140fbfd 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift @@ -9,6 +9,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import SafariServices @@ -1289,4 +1290,5 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager: SFSafariViewCon // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift index 40059ad012..ae5ff7d519 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift @@ -9,6 +9,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import SafariServices @@ -1070,4 +1071,5 @@ extension PrimerHeadlessUniversalCheckout.RawDataManager { // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift index 81b4cfa777..b24144ae6f 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift @@ -8,6 +8,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import SafariServices import UIKit @@ -1048,4 +1049,5 @@ extension PrimerPaymentMethodTokenData { extension PrimerHeadlessUniversalCheckout.VaultManager: PaymentMethodTypeViaPaymentMethodTokenDataProviding {} // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift b/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift index db44c884a9..34f45baec2 100644 --- a/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift +++ b/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift @@ -5,6 +5,8 @@ // Created by Evangelos Pittas on 29/6/21. // +// swiftlint:disable type_body_length + import Foundation import PassKit import UIKit @@ -374,3 +376,4 @@ extension Array: LogReporter { return Element.allCases } } +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift b/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift index 49205e1f7c..315f4de7f6 100644 --- a/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift +++ b/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 22/11/21. // +// swiftlint:disable type_body_length + import Foundation internal class ClientSession { @@ -362,3 +364,4 @@ internal extension Encodable { return dictionary } } +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift b/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift index a2b22b6ec6..bc1a4a7d8e 100644 --- a/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift +++ b/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift @@ -1,9 +1,11 @@ +// swiftlint:disable identifier_name +// swiftlint:disable type_body_length + import Foundation import UIKit // inspired by https://gist.github.com/proxpero/f7ddfd721a0d0d6159589916185d9dc9 -// swiftlint:disable identifier_name public enum CountryCode: String, Codable, CaseIterable { case af = "AF" case ax = "AX" @@ -254,7 +256,7 @@ public enum CountryCode: String, Codable, CaseIterable { case ye = "YE" case zm = "ZM" case zw = "ZW" - // swiftlint:enable identifier_name + init?(optionalRawValue: String?) { guard let rawValue = optionalRawValue else { return nil @@ -355,3 +357,5 @@ extension CountryCode { return try? jsonParser.parse([PhoneNumberCountryCode].self, from: currenciesData) }() } +// swiftlint:enable identifier_name +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift b/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift index b954489c86..34e84aa80c 100644 --- a/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift +++ b/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift @@ -6,6 +6,7 @@ // // swiftlint:disable file_length +// swiftlint:disable type_body_length import Foundation import UIKit @@ -565,4 +566,5 @@ extension PrimerTheme { } } } +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Data Models/Theme/Public/PrimerThemeData.swift b/Sources/PrimerSDK/Classes/Data Models/Theme/Public/PrimerThemeData.swift index 726374d3a3..62208538e5 100644 --- a/Sources/PrimerSDK/Classes/Data Models/Theme/Public/PrimerThemeData.swift +++ b/Sources/PrimerSDK/Classes/Data Models/Theme/Public/PrimerThemeData.swift @@ -1,3 +1,4 @@ +// swiftlint:disable type_body_length import UIKit public class PrimerThemeData { @@ -327,3 +328,4 @@ public class PrimerThemeData { } } } +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift b/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift index 1d07b089ae..bc65bef448 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift @@ -6,6 +6,8 @@ // // swiftlint:disable file_length +// swiftlint:disable type_body_length + import Foundation import UIKit @@ -522,3 +524,6 @@ on your dashboard https://dashboard.primer.io/ } } } + +// swiftlint:enable type_body_length +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift index a0bcfe1c65..871d536634 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift @@ -5,6 +5,8 @@ // Created by Boris on 19.9.23.. // +// swiftlint:disable type_body_length + import Foundation public enum PrimerValidationError: PrimerErrorProtocol, Encodable { @@ -386,3 +388,4 @@ extension PrimerValidationError: Equatable { } } } +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift b/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift index 4f12bea623..f25f6727f9 100644 --- a/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift +++ b/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift @@ -6,6 +6,7 @@ // // swiftlint:disable file_length +// swiftlint:disable type_body_length protocol UserInterfaceModuleProtocol { @@ -1049,4 +1050,5 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { self.paymentMethodTokenizationViewModel.submitButtonTapped() } } +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift index 2996147fed..1e13865a43 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift @@ -8,6 +8,7 @@ import Foundation // swiftlint:disable function_body_length // swiftlint:disable cyclomatic_complexity +// swiftlint:disable type_body_length internal class URLSessionStack: NetworkService, LogReporter { @@ -369,3 +370,4 @@ internal extension URLSessionStack { } // swiftlint:enable function_body_length // swiftlint:enable cyclomatic_complexity +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift index 2d4183b105..bf4457cc07 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift @@ -7,6 +7,7 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import SafariServices @@ -1026,4 +1027,5 @@ private extension String { } } // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift index 0f7a0fabf0..c3532df43c 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift @@ -9,6 +9,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import UIKit @@ -1041,4 +1042,5 @@ extension FormPaymentMethodTokenizationViewModel: UITextFieldDelegate { // swiftlint:enable identifier_name // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift index 64b1b48ef9..dfac9ff6ad 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift @@ -7,6 +7,7 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import UIKit @@ -455,4 +456,5 @@ internal class MockCardComponentsManager: InternalCardComponentsManagerProtocol } } // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift index 5cdd79bc50..0c9ffbc97b 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift @@ -8,6 +8,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import UIKit @@ -453,4 +454,5 @@ extension PrimerRootViewController: UIGestureRecognizerDelegate { } // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift index ee46ad9c66..2382c6baf1 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift @@ -1,5 +1,6 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import PassKit @@ -618,4 +619,5 @@ extension ApplePayTokenizationViewModel: PKPaymentAuthorizationControllerDelegat } } // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift index 536111c3cc..33b93a4a0b 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift @@ -9,6 +9,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation @@ -684,4 +685,5 @@ Make sure you call the decision handler otherwise the SDK will hang. // swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift index ab11c396d7..11f84dbe7d 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift @@ -8,6 +8,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import UIKit @@ -719,4 +720,5 @@ extension IPay88TokenizationViewModel: PrimerIPay88ViewControllerDelegate { #endif // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift index 2809f6495c..2ae555580a 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift @@ -1,6 +1,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation import UIKit @@ -594,4 +595,5 @@ extension KlarnaTokenizationViewModel: PrimerKlarnaViewControllerDelegate { #endif // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift index e0da75b730..1b10ff0edd 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift @@ -1,4 +1,6 @@ // swiftlint:disable file_length +// swiftlint:disable type_body_length +// swiftlint:disable function_body_length import UIKit import AuthenticationServices @@ -25,34 +27,44 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } guard decodedJWTToken.pciUrl != nil else { - let err = PrimerError.invalidValue(key: "decodedClientToken.pciUrl", value: decodedJWTToken.pciUrl, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "decodedClientToken.pciUrl", + value: decodedJWTToken.pciUrl, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } guard config.id != nil else { - let err = PrimerError.invalidValue(key: "configuration.id", value: config.id, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "configuration.id", + value: config.id, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } guard decodedJWTToken.coreUrl != nil else { - let err = PrimerError.invalidValue(key: "decodedClientToken.coreUrl", value: decodedJWTToken.pciUrl, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "decodedClientToken.coreUrl", + value: decodedJWTToken.pciUrl, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -188,10 +200,13 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { switch result { case .success(let res): guard let url = URL(string: res.approvalUrl) else { - let err = PrimerError.invalidValue(key: "res.approvalUrl", value: res.approvalUrl, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "res.approvalUrl", + value: res.approvalUrl, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -209,10 +224,13 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { switch result { case .success(let urlStr): guard let url = URL(string: urlStr) else { - let err = PrimerError.invalidValue(key: "billingAgreement.response.url", value: urlStr, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "billingAgreement.response.url", + value: urlStr, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -233,10 +251,13 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { private func createOAuthSession(_ url: URL) -> Promise { return Promise { seal in guard var urlScheme = PrimerSettings.current.paymentMethodOptions.urlScheme else { - let err = PrimerError.invalidValue(key: "settings.paymentMethodOptions.urlScheme", value: nil, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "settings.paymentMethodOptions.urlScheme", + value: nil, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -312,10 +333,13 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { } } else { guard let orderId = orderId else { - let err = PrimerError.invalidValue(key: "orderId", value: orderId, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "orderId", + value: orderId, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -362,20 +386,26 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { switch PrimerInternal.shared.intent { case .checkout: guard let orderId = orderId else { - let err = PrimerError.invalidValue(key: "orderId", value: orderId, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "orderId", + value: orderId, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return } guard let externalPayerInfo = externalPayerInfo else { - let err = PrimerError.invalidValue(key: "externalPayerInfo", value: orderId, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "externalPayerInfo", + value: orderId, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return @@ -391,10 +421,13 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { case .vault: guard let confirmedBillingAgreement = self.confirmBillingAgreementResponse else { - let err = PrimerError.invalidValue(key: "confirmedBillingAgreement", value: orderId, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "confirmedBillingAgreement", + value: orderId, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return @@ -430,10 +463,12 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { paypalService.confirmBillingAgreement({ result in switch result { case .failure(let err): - let contaiinerErr = PrimerError.failedToCreateSession(error: err, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let contaiinerErr = PrimerError.failedToCreateSession(error: err, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, contaiinerErr) case .success(let res): @@ -458,4 +493,6 @@ extension PayPalTokenizationViewModel: ASWebAuthenticationPresentationContextPro } } +// swiftlint:enable type_body_length +// swiftlint:enable function_body_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift index 916bfa9716..eaf6cfe3fa 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift @@ -7,6 +7,7 @@ // swiftlint:disable function_body_length // swiftlint:disable file_length +// swiftlint:disable type_body_length import Foundation import SafariServices @@ -458,4 +459,5 @@ struct PollingResponse: Decodable { } } // swiftlint:enable function_body_length +// swiftlint:enable type_body_length // swiftlint:enable file_length From 1b320e92b25364dbb1e9ad5509d79ef20ad93449 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 14:59:25 +0100 Subject: [PATCH 06/21] Alter line_length rule and update all violations --- Debug App/.swiftlint.yml | 10 +- Debug App/Tests/Unit Tests/Mocks.swift | 9 +- ...ckPaymentMethodTokenizationViewModel.swift | 3 +- .../Primer/Ideal/BankComponentTests.swift | 3 +- .../Classes/Core/3DS/3DSService.swift | 80 +++++++++------- .../Core/Analytics/AnalyticsService.swift | 4 +- .../Core/Analytics/AnalyticsStorage.swift | 3 +- .../Core/BIN Data/CardValidationService.swift | 12 ++- .../Classes/Core/Constants/Strings.swift | 2 + .../Models/BanksTokenizationComponent.swift | 87 +++++++++++++----- .../CreateResumePaymentService.swift | 10 +- .../Core/Payment Services/PayPalService.swift | 26 ++++-- .../PrimerAPIConfigurationModule.swift | 11 ++- .../Core/Payment Services/VaultService.swift | 3 +- .../Classes/Core/Primer/AppState.swift | 3 +- .../Classes/Core/Primer/Primer.swift | 18 +++- .../Classes/Core/Primer/PrimerDelegate.swift | 26 ++++-- .../Classes/Core/Primer/PrimerInternal.swift | 21 +++-- .../FormWithRedirect/Ideal/BankStep.swift | 3 +- .../Ideal/DefaultBanksComponent.swift | 7 +- .../KlarnaTokenizationComponent.swift | 19 ++-- ...KlarnaComponent+SessionAuthorization.swift | 3 +- .../PrimerHeadlessKlarnaComponent.swift | 13 ++- .../Managers/KlarnaTokenizationManager.swift | 13 ++- .../Composable/Klarna/Models/KlarnaStep.swift | 16 +++- .../Common/NativeUIValidateable.swift | 6 +- .../NolPay/NolPayLinkCardComponent.swift | 4 +- .../NolPay/NolPayLinkedCardsComponent.swift | 4 +- .../NolPay/NolPayPaymentComponent.swift | 12 ++- .../NolPay/NolPayUnlinkCardComponent.swift | 6 +- .../Managers/AssetsManager.swift | 10 +- .../CardComponentsManager.swift | 92 +++++++++++++------ .../PrimerHeadlessBanksComponentWrapper.swift | 5 +- ...CheckoutComponentWithRedirectManager.swift | 32 +++++-- ...adlessUniversalCheckoutKlarnaManager.swift | 5 +- .../RawDataManager.swift | 60 ++++++++---- ...awPhoneNumberDataTokenizationBuilder.swift | 11 ++- ...erRawRetailerDataTokenizationBuilder.swift | 7 +- .../Managers/VaultManager.swift | 91 +++++++++++------- ...niversalCheckoutInputElementDelegate.swift | 3 +- .../PrimerHeadlessUniversalCheckout.swift | 16 +++- ...erHeadlessUniversalCheckoutProtocols.swift | 5 +- .../Data Models/CardButtonViewModel.swift | 11 ++- .../Classes/Data Models/CardNetwork.swift | 23 +++-- .../Classes/Data Models/ClientSession.swift | 42 +++++++-- .../Classes/Data Models/ClientToken.swift | 6 +- .../Classes/Data Models/CountryCode.swift | 7 +- .../Data Models/Currency/CurrencyLoader.swift | 6 +- .../CurrencyNetworkServiceProtocol.swift | 3 + .../Classes/Data Models/OrderItem.swift | 6 +- .../Classes/Data Models/PaymentMethod.swift | 15 ++- .../Data Models/PrimerConfiguration.swift | 19 +++- .../Data Models/TokenizationRequestBody.swift | 5 +- .../Data Models/TokenizationResponse.swift | 14 ++- .../Classes/Data Models/VoucherValue.swift | 24 +++-- .../Data Models/_PaymentAPIModel.swift | 50 +++++----- .../Primer3DSErrorContainer.swift | 11 ++- .../Classes/Error Handler/PrimerError.swift | 59 +++++++++--- .../Error Handler/PrimerValidationError.swift | 27 ++++-- .../AlertController.swift | 4 +- .../Extensions & Utilities/AnyDecodable.swift | 3 +- .../Extensions & Utilities/AnyEncodable.swift | 7 +- .../DataExtension.swift | 4 +- .../ImageFileProcessor.swift | 5 +- .../Extensions & Utilities/PrimerButton.swift | 16 +++- .../StringExtension.swift | 25 +++-- .../Extensions & Utilities/UserAgent.swift | 10 +- .../Classes/Modules/Downloader.swift | 4 +- .../Classes/Modules/ImageManager.swift | 62 +++++++++---- .../Classes/Modules/PollingModule.swift | 3 +- .../Classes/Modules/UserInterfaceModule.swift | 34 +++++-- .../PrimerInputElements.swift | 3 +- ...wCardDataRedirectTokenizationBuilder.swift | 10 +- .../PCI/Services/API/Primer/PrimerAPI.swift | 17 +++- .../Services/Network/URLSessionStack.swift | 16 +++- ...rmPaymentMethodTokenizationViewModel.swift | 51 ++++++---- .../Fields/CardholderNameField.swift | 3 +- ...ethodTokenizationViewModel+FormViews.swift | 55 +++++++---- ...rmPaymentMethodTokenizationViewModel.swift | 23 +++-- .../Classes/PCI/TokenizationService.swift | 3 +- .../InternalCardComponentsManager.swift | 19 ++-- .../PrimerExpiryDateFieldView.swift | 6 +- .../Services/Network/PrimerAPIClient.swift | 15 ++- .../Banks/BankSelectorViewController.swift | 3 +- .../Banks/BankTableViewCell.swift | 4 +- .../Components/PrimerSearchTextField.swift | 3 +- .../CountrySelectorViewController.swift | 3 +- .../User Interface/PrimerUIManager.swift | 4 +- .../Root/PrimerFormViewController.swift | 14 ++- .../Root/PrimerLoadingViewController.swift | 5 +- .../Root/PrimerRootViewController.swift | 13 ++- ...rimerUniversalCheckoutViewController.swift | 7 +- .../ApplePayTokenizationViewModel.swift | 16 ++-- .../BankSelectorTokenizationViewModel.swift | 17 +++- ...outWithVaultedPaymentMethodViewModel.swift | 10 +- .../IPay88TokenizationViewModel.swift | 12 ++- .../KlarnaTokenizationViewModel.swift | 38 +++++--- .../NolPayTokenizationViewModel.swift | 31 +++++-- .../PayPalTokenizationViewModel.swift | 4 +- ...entMethodTokenizationViewModel+Logic.swift | 23 +++-- .../PaymentMethodTokenizationViewModel.swift | 3 +- ...stPaymentMethodTokenizationViewModel.swift | 3 +- .../QRCodeTokenizationViewModel.swift | 16 ++-- ...ctPaymentMethodTokenizationViewModel.swift | 23 +++-- .../VaultPaymentMethodViewController.swift | 6 +- 105 files changed, 1244 insertions(+), 514 deletions(-) diff --git a/Debug App/.swiftlint.yml b/Debug App/.swiftlint.yml index e3699aaa35..ee8fd2a727 100644 --- a/Debug App/.swiftlint.yml +++ b/Debug App/.swiftlint.yml @@ -1,6 +1,10 @@ -disabled_rules: - - line_length - +line_length: + warning: 150 + ignores_function_declarations: true + ignores_comments: true + ignores_interpolated_strings: true + ignores_urls: true + included: - ../Sources diff --git a/Debug App/Tests/Unit Tests/Mocks.swift b/Debug App/Tests/Unit Tests/Mocks.swift index ffbf48e4bd..2dec264402 100644 --- a/Debug App/Tests/Unit Tests/Mocks.swift +++ b/Debug App/Tests/Unit Tests/Mocks.swift @@ -215,7 +215,8 @@ class MockPrimerDelegate: PrimerDelegate { completion(nil, PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString)) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString)) return } completion(token, nil) @@ -234,7 +235,8 @@ class MockPrimerDelegate: PrimerDelegate { if authorizePaymentFails { completion(PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString)) } + "line": "\(#line)"], + diagnosticsId: UUID().uuidString)) } } func onTokenizeSuccess(_ paymentMethodToken: PrimerPaymentMethodTokenData, _ completion: @escaping (Error?) -> Void) { @@ -242,7 +244,8 @@ class MockPrimerDelegate: PrimerDelegate { if authorizePaymentFails { completion(PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString)) } + "line": "\(#line)"], + diagnosticsId: UUID().uuidString)) } } func primerDidDismiss() { diff --git a/Debug App/Tests/Unit Tests/Mocks/MockPaymentMethodTokenizationViewModel.swift b/Debug App/Tests/Unit Tests/Mocks/MockPaymentMethodTokenizationViewModel.swift index bdef3399a8..bbee68c583 100644 --- a/Debug App/Tests/Unit Tests/Mocks/MockPaymentMethodTokenizationViewModel.swift +++ b/Debug App/Tests/Unit Tests/Mocks/MockPaymentMethodTokenizationViewModel.swift @@ -252,7 +252,8 @@ class MockPaymentMethodTokenizationViewModel: NSObject, PaymentMethodTokenizatio Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in switch paymentCreationDecision.type { case .abort(let errorMessage): - let error = PrimerError.merchantError(message: errorMessage ?? "", userInfo: nil, diagnosticsId: UUID().uuidString) + let error = PrimerError.merchantError(message: errorMessage ?? "", userInfo: nil, + diagnosticsId: UUID().uuidString) seal.reject(error) case .continue: seal.fulfill() diff --git a/Debug App/Tests/Unit Tests/Primer/Ideal/BankComponentTests.swift b/Debug App/Tests/Unit Tests/Primer/Ideal/BankComponentTests.swift index 997567bf8b..154369e40a 100644 --- a/Debug App/Tests/Unit Tests/Primer/Ideal/BankComponentTests.swift +++ b/Debug App/Tests/Unit Tests/Primer/Ideal/BankComponentTests.swift @@ -267,7 +267,8 @@ private class MockBankSelectorTokenizationModel: BankSelectorTokenizationProvidi } func tokenize(bankId: String) -> Promise { return Promise { seal in - useSuccess ? seal.fulfill() : seal.reject(PrimerError.paymentFailed(paymentMethodType: paymentMethodType.rawValue, description: "payment_failed", userInfo: nil, diagnosticsId: UUID().uuidString)) + useSuccess ? seal.fulfill() : seal.reject(PrimerError.paymentFailed(paymentMethodType: paymentMethodType.rawValue, description: "payment_failed", userInfo: nil, + diagnosticsId: UUID().uuidString)) } } func handlePaymentMethodTokenData() -> Promise { diff --git a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift index 00e5bbdcbc..4c889b2d40 100644 --- a/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift +++ b/Sources/PrimerSDK/Classes/Core/3DS/3DSService.swift @@ -8,6 +8,7 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length // swiftlint:disable type_body_length +// swiftlint:disable large_tuple import Foundation import UIKit @@ -297,7 +298,9 @@ class ThreeDSService: ThreeDSServiceProtocol, LogReporter { var certs: [Primer3DSCertificate] = [] for certificate in AppState.current.apiConfiguration?.keys?.threeDSecureIoCertificates ?? [] { - let cer = ThreeDS.Cer(cardScheme: certificate.cardNetwork, rootCertificate: certificate.rootCertificate, encryptionKey: certificate.encryptionKey) + let cer = ThreeDS.Cer(cardScheme: certificate.cardNetwork, + rootCertificate: certificate.rootCertificate, + encryptionKey: certificate.encryptionKey) certs.append(cer) } @@ -384,7 +387,8 @@ class ThreeDSService: ThreeDSServiceProtocol, LogReporter { return } - let cardNetwork = CardNetwork(cardNetworkStr: paymentMethodTokenData.paymentInstrumentData?.binData?.network ?? "") + let network = paymentMethodTokenData.paymentInstrumentData?.binData?.network + let cardNetwork = CardNetwork(cardNetworkStr: network ?? "") guard let directoryServerId = cardNetwork.directoryServerId else { let uuid = UUID().uuidString @@ -461,7 +465,6 @@ class ThreeDSService: ThreeDSServiceProtocol, LogReporter { private func initialize3DSAuthorization( sdkAuthResult: SDKAuthResult, paymentMethodTokenData: PrimerPaymentMethodTokenData - // swiftlint:disable:next large_tuple ) -> Promise<(serverAuthData: ThreeDS.ServerAuthData, resumeToken: String, threeDsAppRequestorUrl: URL?)> { @@ -514,11 +517,12 @@ please set correct threeDsAppRequestorUrl in PrimerThreeDsOptions during SDK ini seal.reject(internalErr) case .challenge: - let serverAuthData = ThreeDS.ServerAuthData(acsReferenceNumber: beginAuthResponse.authentication.acsReferenceNumber, - acsSignedContent: beginAuthResponse.authentication.acsSignedContent, - acsTransactionId: beginAuthResponse.authentication.acsTransactionId, - responseCode: beginAuthResponse.authentication.responseCode.rawValue, - transactionId: beginAuthResponse.authentication.transactionId) + let authentication = beginAuthResponse.authentication + let serverAuthData = ThreeDS.ServerAuthData(acsReferenceNumber: authentication.acsReferenceNumber, + acsSignedContent: authentication.acsSignedContent, + acsTransactionId: authentication.acsTransactionId, + responseCode: authentication.responseCode.rawValue, + transactionId: authentication.transactionId) seal.fulfill((serverAuthData, beginAuthResponse.resumeToken, threeDsAppRequestorUrl)) } @@ -564,7 +568,9 @@ please set correct threeDsAppRequestorUrl in PrimerThreeDsOptions during SDK ini return } - if let windowScene = UIApplication.shared.connectedScenes.filter({ $0.activationState == .foregroundActive }).first as? UIWindowScene { + if let windowScene = UIApplication.shared.connectedScenes + .filter({ $0.activationState == .foregroundActive }) + .first as? UIWindowScene { self.threeDSSDKWindow = UIWindow(windowScene: windowScene) } else { // Not opted-in in UISceneDelegate @@ -649,32 +655,35 @@ please set correct threeDsAppRequestorUrl in PrimerThreeDsOptions during SDK ini } let apiClient: PrimerAPIClientProtocol = ThreeDSService.apiClient ?? PrimerAPIClient() - apiClient.begin3DSAuth(clientToken: decodedJWTToken, paymentMethodTokenData: paymentMethodTokenData, threeDSecureBeginAuthRequest: threeDSecureBeginAuthRequest, completion: { result in - switch result { - case .failure(let underlyingErr): - var primerErr: PrimerError - - if let primerError = underlyingErr as? PrimerError { - primerErr = primerError - } else { - primerErr = PrimerError.underlyingErrors( - errors: [underlyingErr], - userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], - diagnosticsId: UUID().uuidString) - } - - ErrorHandler.handle(error: primerErr) - - let internalErr = InternalError.failedToPerform3dsAndShouldBreak(error: primerErr) - completion(.failure(internalErr)) - - case .success(let res): - completion(.success(res)) - } - }) + apiClient.begin3DSAuth(clientToken: decodedJWTToken, + paymentMethodTokenData: paymentMethodTokenData, + threeDSecureBeginAuthRequest: threeDSecureBeginAuthRequest, + completion: { result in + switch result { + case .failure(let underlyingErr): + var primerErr: PrimerError + + if let primerError = underlyingErr as? PrimerError { + primerErr = primerError + } else { + primerErr = PrimerError.underlyingErrors( + errors: [underlyingErr], + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) + } + + ErrorHandler.handle(error: primerErr) + + let internalErr = InternalError.failedToPerform3dsAndShouldBreak(error: primerErr) + completion(.failure(internalErr)) + + case .success(let res): + completion(.success(res)) + } + }) } #endif @@ -739,4 +748,5 @@ internal class MockPrimer3DSCompletion: Primer3DSCompletion { #endif // swiftlint:enable function_body_length // swiftlint:enable type_body_length +// swiftlint:enable large_tuple // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsService.swift b/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsService.swift index c0e0aa5a67..70e744e089 100644 --- a/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsService.swift +++ b/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsService.swift @@ -179,7 +179,9 @@ extension Analytics { let events = events.filter({ $0.analyticsUrl != nil }) let urls = Set(events.compactMap { $0.analyticsUrl }).compactMap { URL(string: $0) } - let eventSets = urls.map { url in (url: url, events: events.filter { $0.analyticsUrl == url.absoluteString }) } + let eventSets = urls.map { url in + (url: url, events: events.filter { $0.analyticsUrl == url.absoluteString }) + } let promises = eventSets.map { item in sendSdkAnalyticsEvents(url: item.url, events: item.events) diff --git a/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift b/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift index 5cba50c168..488037716b 100644 --- a/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift +++ b/Sources/PrimerSDK/Classes/Core/Analytics/AnalyticsStorage.swift @@ -7,7 +7,8 @@ import Foundation -private let analyticsFileURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("analytics") +private let analyticsFileURL: URL = FileManager.default.urls(for: .documentDirectory, + in: .userDomainMask)[0].appendingPathComponent("analytics") protocol AnalyticsStorage { diff --git a/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift b/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift index 95c34d2259..ae30af0b6a 100644 --- a/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift +++ b/Sources/PrimerSDK/Classes/Core/BIN Data/CardValidationService.swift @@ -96,7 +96,8 @@ class DefaultCardValidationService: CardValidationService, LogReporter { return } - let cardMetadata = self.createValidationMetadata(networks: result.networks.map { CardNetwork(cardNetworkStr: $0.value) }, + let networks = result.networks.map { CardNetwork(cardNetworkStr: $0.value) } + let cardMetadata = self.createValidationMetadata(networks: networks, source: .remote) self.handle(cardMetadata: cardMetadata, forCardState: cardState) @@ -113,7 +114,10 @@ class DefaultCardValidationService: CardValidationService, LogReporter { source: isFallback ? .localFallback : .local) if cardState.cardNumber.count >= Self.maximumBinLength { - let logMessage = "Local validation was used where remote validation would have been preferred (max BIN length exceeded)." + let logMessage = """ +Local validation was used where remote validation \ +would have been preferred (max BIN length exceeded). +""" logger.warn(message: logMessage) let event = Analytics.Event.message( @@ -210,7 +214,9 @@ class DefaultCardValidationService: CardValidationService, LogReporter { cancellable.cancel() } - validateCardNetworksCancellable = (Self.apiClient ?? apiClient).listCardNetworks(clientToken: decodedJWTToken, bin: cardNumber) { result in + let apiClient = (Self.apiClient ?? apiClient) + validateCardNetworksCancellable = apiClient.listCardNetworks(clientToken: decodedJWTToken, + bin: cardNumber) { result in switch result { case .success(let networks): resolver.fulfill(networks) diff --git a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift index ae74455166..bf3779d6ca 100644 --- a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift +++ b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift @@ -7,6 +7,7 @@ // swiftlint:disable file_length // swiftlint:disable type_body_length +// swiftlint:disable line_length import Foundation @@ -1041,4 +1042,5 @@ extension Strings { } } // swiftlint:enable type_body_length +// swiftlint:enable line_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift index 5e17094589..f0bf04e985 100644 --- a/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/Models/BanksTokenizationComponent.swift @@ -54,7 +54,11 @@ final class BanksTokenizationComponent: NSObject, LogReporter { func validate() throws { guard let decodedJWTToken = PrimerAPIConfigurationModule.decodedJWTToken, decodedJWTToken.isValid else { - let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidClientToken(userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -62,7 +66,11 @@ final class BanksTokenizationComponent: NSObject, LogReporter { private func fetchBanks() -> Promise<[AdyenBank]> { return Promise { seal in guard let decodedJWTToken = PrimerAPIConfigurationModule.decodedJWTToken else { - let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidClientToken(userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -154,10 +162,13 @@ final class BanksTokenizationComponent: NSObject, LogReporter { if let error = err as? PrimerError { primerErr = error } else { - primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.generic(message: err.localizedDescription, + userInfo: nil, + diagnosticsId: UUID().uuidString) } - return PrimerDelegateProxy.raisePrimerDidFailWithError(primerErr, data: self.paymentCheckoutData) + return PrimerDelegateProxy.raisePrimerDidFailWithError(primerErr, + data: self.paymentCheckoutData) } .done { merchantErrorMessage in self.handleFailureFlow(errorMessage: merchantErrorMessage) @@ -174,7 +185,9 @@ final class BanksTokenizationComponent: NSObject, LogReporter { var cancelledError: PrimerError? self.didCancel = { self.isCancelled = true - cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, diagnosticsId: UUID().uuidString) + cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: cancelledError!) seal.reject(cancelledError!) self.isCancelled = false @@ -411,7 +424,8 @@ final class BanksTokenizationComponent: NSObject, LogReporter { private func handleCreatePaymentEvent(_ paymentMethodData: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.createPayment(paymentRequest: Request.Body.Payment.Create(token: paymentMethodData)) { paymentResponse, error in + let paymentRequest = Request.Body.Payment.Create(token: paymentMethodData) + createResumePaymentService.createPayment(paymentRequest: paymentRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -555,21 +569,25 @@ final class BanksTokenizationComponent: NSObject, LogReporter { PrimerUIManager.prepareRootViewController() } .done { - PrimerUIManager.primerRootViewController?.present(self.webViewController!, animated: true, completion: { - DispatchQueue.main.async { - self.handleWebViewControlllerPresentedCompletion() - seal.fulfill() - } - }) + PrimerUIManager.primerRootViewController?.present(self.webViewController!, + animated: true, + completion: { + DispatchQueue.main.async { + self.handleWebViewControlllerPresentedCompletion() + seal.fulfill() + } + }) } .catch { _ in } } else { - PrimerUIManager.primerRootViewController?.present(self.webViewController!, animated: true, completion: { - DispatchQueue.main.async { - self.handleWebViewControlllerPresentedCompletion() - seal.fulfill() - } - }) + PrimerUIManager.primerRootViewController?.present(self.webViewController!, + animated: true, + completion: { + DispatchQueue.main.async { + self.handleWebViewControlllerPresentedCompletion() + seal.fulfill() + } + }) } } } @@ -767,7 +785,9 @@ final class BanksTokenizationComponent: NSObject, LogReporter { private func handleResumePaymentEvent(_ resumePaymentId: String, resumeToken: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, paymentResumeRequest: Request.Body.Payment.Resume(token: resumeToken)) { paymentResponse, error in + let resumeRequest = Request.Body.Payment.Resume(token: resumeToken) + createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, + paymentResumeRequest: resumeRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -864,7 +884,9 @@ extension BanksTokenizationComponent: BankSelectorTokenizationProviding { return banks } return banks.filter { - $0.name.lowercased().folding(options: .diacriticInsensitive, locale: nil).contains(query.lowercased().folding(options: .diacriticInsensitive, locale: nil)) + $0.name.lowercased() + .folding(options: .diacriticInsensitive, locale: nil) + .contains(query.lowercased().folding(options: .diacriticInsensitive, locale: nil)) } } @@ -984,8 +1006,14 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { } func setup() { - NotificationCenter.default.addObserver(self, selector: #selector(self.receivedNotification(_:)), name: Notification.Name.receivedUrlSchemeRedirect, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(self.receivedNotification(_:)), name: Notification.Name.receivedUrlSchemeCancellation, object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(self.receivedNotification(_:)), + name: Notification.Name.receivedUrlSchemeRedirect, + object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(self.receivedNotification(_:)), + name: Notification.Name.receivedUrlSchemeCancellation, + object: nil) self.didFinishPayment = { _ in self.willDismissPaymentMethodUI?() @@ -1073,7 +1101,12 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] _ in if !decisionHandlerHasBeenCalled { - self?.logger.warn(message: "The 'decisionHandler' of 'primerHeadlessUniversalCheckoutWillCreatePaymentWithData' hasn't been called. Make sure you call the decision handler otherwise the SDK will hang.") + let message = + """ + The 'decisionHandler' of 'primerHeadlessUniversalCheckoutWillCreatePaymentWithData' \ + hasn't been called. Make sure you call the decision handler otherwise the SDK will hang." +""" + self?.logger.warn(message: message) } } } @@ -1107,7 +1140,9 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { var cancelledError: PrimerError? self.didCancel = { self.isCancelled = true - cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, diagnosticsId: UUID().uuidString) + cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: cancelledError!) seal.reject(cancelledError!) self.isCancelled = false @@ -1165,7 +1200,9 @@ extension BanksTokenizationComponent: PaymentMethodTokenizationModelProtocol { firstly { () -> Promise in if self.isCancelled { - let err = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.cancelled(paymentMethodType: self.config.type, + userInfo: nil, + diagnosticsId: UUID().uuidString) throw err } return pollingModule.start() diff --git a/Sources/PrimerSDK/Classes/Core/Payment Services/CreateResumePaymentService.swift b/Sources/PrimerSDK/Classes/Core/Payment Services/CreateResumePaymentService.swift index 48a886b9e4..1a005821f0 100644 --- a/Sources/PrimerSDK/Classes/Core/Payment Services/CreateResumePaymentService.swift +++ b/Sources/PrimerSDK/Classes/Core/Payment Services/CreateResumePaymentService.swift @@ -22,7 +22,8 @@ internal class CreateResumePaymentService: CreateResumePaymentServiceProtocol { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, err) return @@ -44,14 +45,17 @@ internal class CreateResumePaymentService: CreateResumePaymentServiceProtocol { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, err) return } let apiClient: PrimerAPIClientProtocol = CreateResumePaymentService.apiClient ?? PrimerAPIClient() - apiClient.resumePayment(clientToken: clientToken, paymentId: paymentId, paymentResumeRequest: paymentResumeRequest) { result in + apiClient.resumePayment(clientToken: clientToken, + paymentId: paymentId, + paymentResumeRequest: paymentResumeRequest) { result in switch result { case .failure(let error): completion(nil, error) diff --git a/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift b/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift index a2327cf59c..f3c316f60f 100644 --- a/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift +++ b/Sources/PrimerSDK/Classes/Core/Payment Services/PayPalService.swift @@ -23,15 +23,18 @@ internal class PayPalService: PayPalServiceProtocol { return nil } - guard let configId = PrimerAPIConfigurationModule.apiConfiguration?.getConfigId(for: PrimerPaymentMethodType.payPal.rawValue) else { + guard let configId = PrimerAPIConfigurationModule.apiConfiguration?.getConfigId(for: PrimerPaymentMethodType.payPal.rawValue) + else { return nil } - guard let coreURL = decodedJWTToken.coreUrl else { + guard let coreURL = decodedJWTToken.coreUrl + else { return nil } - guard let url = URL(string: "\(coreURL)\(path)") else { + guard let url = URL(string: "\(coreURL)\(path)") + else { return nil } @@ -51,10 +54,11 @@ internal class PayPalService: PayPalServiceProtocol { return } - guard let configId = PrimerAPIConfigurationModule.apiConfiguration?.getConfigId(for: PrimerPaymentMethodType.payPal.rawValue) else { + let apiConfig = PrimerAPIConfigurationModule.apiConfiguration + guard let configId = apiConfig?.getConfigId(for: PrimerPaymentMethodType.payPal.rawValue) else { let err = PrimerError.invalidValue( key: "configuration.paypal.id", - value: PrimerAPIConfigurationModule.apiConfiguration?.getConfigId(for: PrimerPaymentMethodType.payPal.rawValue), + value: apiConfig?.getConfigId(for: PrimerPaymentMethodType.payPal.rawValue), userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, @@ -126,7 +130,8 @@ internal class PayPalService: PayPalServiceProtocol { let containerErr = PrimerError.failedToCreateSession(error: err, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: containerErr) completion(.failure(containerErr)) case .success(let res): @@ -142,7 +147,8 @@ internal class PayPalService: PayPalServiceProtocol { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return @@ -251,7 +257,8 @@ internal class PayPalService: PayPalServiceProtocol { let body = Request.Body.PayPal.ConfirmBillingAgreement(paymentMethodConfigId: configId, tokenId: tokenId) let apiClient: PrimerAPIClientProtocol = PayPalService.apiClient ?? PrimerAPIClient() - apiClient.confirmPayPalBillingAgreement(clientToken: decodedJWTToken, payPalConfirmBillingAgreementRequest: body) { result in + apiClient.confirmPayPalBillingAgreement(clientToken: decodedJWTToken, + payPalConfirmBillingAgreementRequest: body) { result in switch result { case .failure(let err): let containerErr = PrimerError.failedToCreateSession(error: err, userInfo: ["file": #file, @@ -274,7 +281,8 @@ internal class PayPalService: PayPalServiceProtocol { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(.failure(err)) return diff --git a/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift b/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift index 704ac5b808..c89e24d1a4 100644 --- a/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift +++ b/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift @@ -1,3 +1,4 @@ +// swiftlint:disable type_body_length import Foundation internal typealias JWTToken = String @@ -105,7 +106,8 @@ internal class PrimerAPIConfigurationModule: PrimerAPIConfigurationModuleProtoco let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -179,7 +181,8 @@ internal class PrimerAPIConfigurationModule: PrimerAPIConfigurationModuleProtoco let error = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) throw error } @@ -249,7 +252,8 @@ internal class PrimerAPIConfigurationModule: PrimerAPIConfigurationModuleProtoco let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -309,3 +313,4 @@ internal class PrimerAPIConfigurationModule: PrimerAPIConfigurationModuleProtoco Analytics.Service.record(event: event) } } +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Core/Payment Services/VaultService.swift b/Sources/PrimerSDK/Classes/Core/Payment Services/VaultService.swift index e167e0909f..77f51558b8 100644 --- a/Sources/PrimerSDK/Classes/Core/Payment Services/VaultService.swift +++ b/Sources/PrimerSDK/Classes/Core/Payment Services/VaultService.swift @@ -18,7 +18,8 @@ internal class VaultService: VaultServiceProtocol { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return diff --git a/Sources/PrimerSDK/Classes/Core/Primer/AppState.swift b/Sources/PrimerSDK/Classes/Core/Primer/AppState.swift index 1388ec7c79..1620699f72 100644 --- a/Sources/PrimerSDK/Classes/Core/Primer/AppState.swift +++ b/Sources/PrimerSDK/Classes/Core/Primer/AppState.swift @@ -25,7 +25,8 @@ internal class AppState: AppStateProtocol { } var amount: Int? { - return PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.merchantAmount ?? PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.totalOrderAmount + return PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.merchantAmount ?? + PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.totalOrderAmount } var currency: Currency? { diff --git a/Sources/PrimerSDK/Classes/Core/Primer/Primer.swift b/Sources/PrimerSDK/Classes/Core/Primer/Primer.swift index cd2fb9c9e8..372469b11e 100644 --- a/Sources/PrimerSDK/Classes/Core/Primer/Primer.swift +++ b/Sources/PrimerSDK/Classes/Core/Primer/Primer.swift @@ -29,14 +29,18 @@ public class Primer { fileprivate init() {} - public func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + public func application(_ app: UIApplication, + open url: URL, + options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { return PrimerInternal.shared.application(app, open: url, options: options) } public func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { - return PrimerInternal.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) + return PrimerInternal.shared.application(application, + continue: userActivity, + restorationHandler: restorationHandler) } // MARK: - CONFIGURATION @@ -69,9 +73,15 @@ public class Primer { /** Show a payment method with the speicified intent (if applicable) */ - public func showPaymentMethod(_ paymentMethodType: String, intent: PrimerSessionIntent, clientToken: String, completion: ((Error?) -> Void)? = nil) { + public func showPaymentMethod(_ paymentMethodType: String, + intent: PrimerSessionIntent, + clientToken: String, + completion: ((Error?) -> Void)? = nil) { PrimerInternal.shared.sdkIntegrationType = .dropIn - PrimerInternal.shared.showPaymentMethod(paymentMethodType, withIntent: intent, andClientToken: clientToken, completion: completion) + PrimerInternal.shared.showPaymentMethod(paymentMethodType, + withIntent: intent, + andClientToken: clientToken, + completion: completion) } /** diff --git a/Sources/PrimerSDK/Classes/Core/Primer/PrimerDelegate.swift b/Sources/PrimerSDK/Classes/Core/Primer/PrimerDelegate.swift index f6ec40f713..3864638f4e 100644 --- a/Sources/PrimerSDK/Classes/Core/Primer/PrimerDelegate.swift +++ b/Sources/PrimerSDK/Classes/Core/Primer/PrimerDelegate.swift @@ -45,7 +45,9 @@ internal class PrimerDelegateProxy: LogReporter { DispatchQueue.main.async { if PrimerInternal.shared.sdkIntegrationType == .headless, (decisionHandler as ((PrimerHeadlessUniversalCheckoutResumeDecision) -> Void)?) != nil { - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidTokenizePaymentMethod?(paymentMethodTokenData, decisionHandler: decisionHandler) + let delegate = PrimerHeadlessUniversalCheckout.current.delegate + delegate?.primerHeadlessUniversalCheckoutDidTokenizePaymentMethod?(paymentMethodTokenData, + decisionHandler: decisionHandler) } else if PrimerInternal.shared.sdkIntegrationType == .dropIn, (decisionHandler as ((PrimerResumeDecision) -> Void)?) != nil { @@ -58,7 +60,8 @@ internal class PrimerDelegateProxy: LogReporter { DispatchQueue.main.async { if PrimerInternal.shared.sdkIntegrationType == .headless, (decisionHandler as ((PrimerHeadlessUniversalCheckoutResumeDecision) -> Void)?) != nil { - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidResumeWith?(resumeToken, decisionHandler: decisionHandler) + PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidResumeWith?(resumeToken, + decisionHandler: decisionHandler) } else if PrimerInternal.shared.sdkIntegrationType == .dropIn, (decisionHandler as ((PrimerResumeDecision) -> Void)?) != nil { Primer.shared.delegate?.primerDidResumeWith?(resumeToken, decisionHandler: decisionHandler) @@ -69,8 +72,10 @@ internal class PrimerDelegateProxy: LogReporter { static func primerWillCreatePaymentWithData(_ data: PrimerCheckoutPaymentMethodData, decisionHandler: @escaping (PrimerPaymentCreationDecision) -> Void) { DispatchQueue.main.async { if PrimerInternal.shared.sdkIntegrationType == .headless { - if PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutWillCreatePaymentWithData != nil { - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutWillCreatePaymentWithData?(data, decisionHandler: decisionHandler) + let delegate = PrimerHeadlessUniversalCheckout.current.delegate + if delegate?.primerHeadlessUniversalCheckoutWillCreatePaymentWithData != nil { + delegate?.primerHeadlessUniversalCheckoutWillCreatePaymentWithData?(data, + decisionHandler: decisionHandler) } else { decisionHandler(.continuePaymentCreation()) } @@ -119,7 +124,8 @@ internal class PrimerDelegateProxy: LogReporter { static func primerDidEnterResumePendingWithPaymentAdditionalInfo(_ additionalInfo: PrimerCheckoutAdditionalInfo?) { DispatchQueue.main.async { if PrimerInternal.shared.sdkIntegrationType == .headless { - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidEnterResumePendingWithPaymentAdditionalInfo?(additionalInfo) + let delegate = PrimerHeadlessUniversalCheckout.current.delegate + delegate?.primerHeadlessUniversalCheckoutDidEnterResumePendingWithPaymentAdditionalInfo?(additionalInfo) } else if PrimerInternal.shared.sdkIntegrationType == .dropIn { Primer.shared.delegate?.primerDidEnterResumePendingWithPaymentAdditionalInfo?(additionalInfo) @@ -155,7 +161,9 @@ internal class PrimerDelegateProxy: LogReporter { decisionHandler(.fail(withErrorMessage: nil)) } else { - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidFail!(withError: exposedError, checkoutData: data) + let delegate = PrimerHeadlessUniversalCheckout.current.delegate + delegate?.primerHeadlessUniversalCheckoutDidFail!(withError: exposedError, + checkoutData: data) decisionHandler(.fail(withErrorMessage: nil)) } @@ -174,7 +182,11 @@ internal class PrimerDelegateProxy: LogReporter { } else if PrimerInternal.shared.sdkIntegrationType == .dropIn { if Primer.shared.delegate?.primerDidFailWithError == nil { - logger.warn(message: "Delegate function 'primerDidFailWithError' hasn't been implemented. No custom error message will be displayed on the error screen.") + let message = """ +Delegate function 'primerDidFailWithError' hasn't been implemented.\ +No custom error message will be displayed on the error screen. +""" + logger.warn(message: message) decisionHandler(.fail(withErrorMessage: nil)) } else { diff --git a/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift b/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift index 74e9f4d7ec..de1b2f33a6 100644 --- a/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift +++ b/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift @@ -42,8 +42,12 @@ internal class PrimerInternal: LogReporter { } fileprivate init() { - NotificationCenter.default.addObserver(self, selector: #selector(onAppStateChange), name: UIApplication.willTerminateNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(onAppStateChange), name: UIApplication.willResignActiveNotification, object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(onAppStateChange), + name: UIApplication.willTerminateNotification, object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(onAppStateChange), + name: UIApplication.willResignActiveNotification, object: nil) } internal func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { @@ -151,7 +155,9 @@ internal class PrimerInternal: LogReporter { if let err = err as? PrimerError { primerErr = err } else { - primerErr = PrimerError.underlyingErrors(errors: [err], userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.underlyingErrors(errors: [err], + userInfo: nil, + diagnosticsId: UUID().uuidString) } PrimerUIManager.handleErrorBasedOnSDKSettings(primerErr) @@ -193,9 +199,10 @@ internal class PrimerInternal: LogReporter { if let err = err as? PrimerError { primerErr = err } else { - primerErr = PrimerError.underlyingErrors(errors: [err], userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.underlyingErrors(errors: [err], + userInfo: nil, + diagnosticsId: UUID().uuidString) } - PrimerUIManager.handleErrorBasedOnSDKSettings(primerErr) completion?(err) } @@ -234,7 +241,9 @@ internal class PrimerInternal: LogReporter { if let err = err as? PrimerError { primerErr = err } else { - primerErr = PrimerError.underlyingErrors(errors: [err], userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.underlyingErrors(errors: [err], + userInfo: nil, + diagnosticsId: UUID().uuidString) } PrimerUIManager.handleErrorBasedOnSDKSettings(primerErr) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/BankStep.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/BankStep.swift index 9a80d86329..224e506762 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/BankStep.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/BankStep.swift @@ -15,7 +15,8 @@ extension BanksStep: Equatable { public static func == (lhs: Self, rhs: Self) -> Bool { switch (lhs, rhs) { case (.loading, .loading): return true - case (.banksRetrieved(banks: let banks1), .banksRetrieved(banks: let banks2)): return banks1.map { $0.id } == banks2.map { $0.id } + case (.banksRetrieved(banks: let banks1), .banksRetrieved(banks: let banks2)): + return banks1.map { $0.id } == banks2.map { $0.id } default: return false } } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/DefaultBanksComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/DefaultBanksComponent.swift index d4d35726b2..981a2b9c84 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/DefaultBanksComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/FormWithRedirect/Ideal/DefaultBanksComponent.swift @@ -21,7 +21,9 @@ final class DefaultBanksComponent: BanksComponent { private let onFinished: () -> WebRedirectComponent private let tokenizationProvidingModel: BankSelectorTokenizationProviding - init(paymentMethodType: PrimerPaymentMethodType, tokenizationProvidingModel: BankSelectorTokenizationProviding, onFinished: @escaping () -> WebRedirectComponent) { + init(paymentMethodType: PrimerPaymentMethodType, + tokenizationProvidingModel: BankSelectorTokenizationProviding, + onFinished: @escaping () -> WebRedirectComponent) { self.paymentMethodType = paymentMethodType self.tokenizationProvidingModel = tokenizationProvidingModel self.onFinished = onFinished @@ -36,7 +38,8 @@ final class DefaultBanksComponent: BanksComponent { } case .bankFilterText(text: let text): let filteredBanks = tokenizationProvidingModel.filterBanks(query: text) - stepDelegate?.didReceiveStep(step: BanksStep.banksRetrieved(banks: filteredBanks.map { IssuingBank(bank: $0) })) + let banksStep = BanksStep.banksRetrieved(banks: filteredBanks.map { IssuingBank(bank: $0) }) + stepDelegate?.didReceiveStep(step: banksStep) } validateData(for: collectableData) } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift index 4faa220481..8e2f430603 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift @@ -30,7 +30,8 @@ class KlarnaTokenizationComponent: KlarnaTokenizationManager, KlarnaTokenization self.paymentMethod = paymentMethod self.apiClient = PrimerAPIConfigurationModule.apiClient ?? PrimerAPIClient() self.clientSession = PrimerAPIConfigurationModule.apiConfiguration?.clientSession - self.recurringPaymentDescription = PrimerSettings.current.paymentMethodOptions.klarnaOptions?.recurringPaymentDescription + let klarnaOptions = PrimerSettings.current.paymentMethodOptions.klarnaOptions + self.recurringPaymentDescription = klarnaOptions?.recurringPaymentDescription super.init() } } @@ -141,7 +142,9 @@ extension KlarnaTokenizationComponent { } case .recurringPayment: // Prepare the body for the Klarna Customer Token creation request - let body = prepareKlarnaCustomerTokenBody(paymentMethodConfigId: paymentMethodConfigId, sessionId: sessionId, authorizationToken: authorizationToken) + let body = prepareKlarnaCustomerTokenBody(paymentMethodConfigId: paymentMethodConfigId, + sessionId: sessionId, + authorizationToken: authorizationToken) firstly { // Create the Klarna Customer Token createKlarnaCustomerToken(with: decodedJWTToken, body: body) @@ -177,7 +180,8 @@ private extension KlarnaTokenizationComponent { /// - Sets the client session with updated primer configuration request data private func requestPrimerConfiguration(decodedJWTToken: DecodedJWTToken, request: ClientSessionUpdateRequest) -> Promise { return Promise { seal in - apiClient.requestPrimerConfigurationWithActions(clientToken: decodedJWTToken, request: request) { [weak self] result in + apiClient.requestPrimerConfigurationWithActions(clientToken: decodedJWTToken, + request: request) { [weak self] result in guard let self = self else { return } switch result { case .success(let configuration): @@ -194,7 +198,8 @@ private extension KlarnaTokenizationComponent { /// - Sets the 'paymentSessionId' with response's 'sessionId' private func createKlarnaSession(with body: Request.Body.Klarna.CreatePaymentSession, decodedJWTToken: DecodedJWTToken) -> Promise { return Promise { seal in - apiClient.createKlarnaPaymentSession(clientToken: decodedJWTToken, klarnaCreatePaymentSessionAPIRequest: body) { [weak self] result in + apiClient.createKlarnaPaymentSession(clientToken: decodedJWTToken, + klarnaCreatePaymentSessionAPIRequest: body) { [weak self] result in guard let self = self else { return } switch result { case .success(let response): @@ -219,7 +224,8 @@ extension KlarnaTokenizationComponent { /// - Request to finalize Klarna Payment Session private func finalizeKlarnaPaymentSession(with clientToken: DecodedJWTToken, body: Request.Body.Klarna.FinalizePaymentSession) -> Promise { return Promise { seal in - apiClient.finalizeKlarnaPaymentSession(clientToken: clientToken, klarnaFinalizePaymentSessionRequest: body) { (result) in + apiClient.finalizeKlarnaPaymentSession(clientToken: clientToken, + klarnaFinalizePaymentSessionRequest: body) { (result) in switch result { case .success(let response): seal.fulfill(response) @@ -240,7 +246,8 @@ extension KlarnaTokenizationComponent { /// - Request to create Klarna Customer Token private func createKlarnaCustomerToken(with clientToken: DecodedJWTToken, body: Request.Body.Klarna.CreateCustomerToken) -> Promise { return Promise { seal in - apiClient.createKlarnaCustomerToken(clientToken: clientToken, klarnaCreateCustomerTokenAPIRequest: body) { (result) in + apiClient.createKlarnaCustomerToken(clientToken: clientToken, + klarnaCreateCustomerTokenAPIRequest: body) { (result) in switch result { case .success(let response): seal.fulfill(response) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift index c58aa00440..1df6756941 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent+SessionAuthorization.swift @@ -31,7 +31,8 @@ extension PrimerHeadlessKlarnaComponent { } } else { var extraMerchantDataString: String? - if let paymentMethod = PrimerAPIConfiguration.current?.paymentMethods?.first(where: { $0.type == PrimerPaymentMethodType.klarna.rawValue }) { + if let paymentMethod = PrimerAPIConfiguration.current?.paymentMethods? + .first(where: { $0.type == PrimerPaymentMethodType.klarna.rawValue }) { if let merchantOptions = paymentMethod.options as? MerchantOptions { if let extraMerchantData = merchantOptions.extraMerchantData { extraMerchantDataString = KlarnaHelpers.getSerializedAttachmentString(from: extraMerchantData) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent.swift index 5dbc6fea43..82eb5e2901 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/PrimerHeadlessKlarnaComponent.swift @@ -35,7 +35,9 @@ class PrimerHeadlessKlarnaComponent { } /// Configures the Klarna provider and view handling component with necessary information for payment processing. func setProvider(with clientToken: String, paymentCategory: String) { - let provider: PrimerKlarnaProviding = PrimerKlarnaProvider(clientToken: clientToken, paymentCategory: paymentCategory, urlScheme: settings.paymentMethodOptions.urlScheme) + let provider: PrimerKlarnaProviding = PrimerKlarnaProvider(clientToken: clientToken, + paymentCategory: paymentCategory, + urlScheme: settings.paymentMethodOptions.urlScheme) klarnaProvider = provider } /// Validates the tokenization component, handling any errors that occur during the process. @@ -78,13 +80,15 @@ extension PrimerHeadlessKlarnaComponent: KlarnaComponent { return } guard !availableCategories.isEmpty else { - let error = PrimerValidationError.sessionNotCreated(userInfo: KlarnaHelpers.getErrorUserInfo(), diagnosticsId: UUID().uuidString) + let error = PrimerValidationError.sessionNotCreated(userInfo: KlarnaHelpers.getErrorUserInfo(), + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) validationDelegate?.didUpdate(validationStatus: .invalid(errors: [error]), for: data) return } guard availableCategories.contains(where: { $0 == category }) else { - let error = PrimerValidationError.invalidPaymentCategory(userInfo: KlarnaHelpers.getErrorUserInfo(), diagnosticsId: UUID().uuidString) + let error = PrimerValidationError.invalidPaymentCategory(userInfo: KlarnaHelpers.getErrorUserInfo(), + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) validationDelegate?.didUpdate(validationStatus: .invalid(errors: [error]), for: data) return @@ -94,7 +98,8 @@ extension PrimerHeadlessKlarnaComponent: KlarnaComponent { validationDelegate?.didUpdate(validationStatus: .valid, for: data) case .finalizePayment: guard isFinalizationRequired else { - let error = PrimerValidationError.paymentAlreadyFinalized(userInfo: KlarnaHelpers.getErrorUserInfo(), diagnosticsId: UUID().uuidString) + let error = PrimerValidationError.paymentAlreadyFinalized(userInfo: KlarnaHelpers.getErrorUserInfo(), + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) validationDelegate?.didUpdate(validationStatus: .invalid(errors: [error]), for: data) return diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift index c1c5259b48..567c7ef2d4 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Managers/KlarnaTokenizationManager.swift @@ -14,7 +14,8 @@ protocol KlarnaTokenizationManagerProtocol { - customerToken: An optional `Response.Body.Klarna.CustomerToken` object containing the customer's token and session data. - `offSessionAuthorizationId`: An optional `String` representing an off-session authorization ID. This is used when the session `intent` is `checkout`. - - Returns: A `Promise` which resolves to a `PrimerPaymentMethodTokenData` object on successful tokenization or rejects with an `Error` if the tokenization process fails. + - Returns: A `Promise` which resolves to a `PrimerPaymentMethodTokenData` + object on successful tokenization or rejects with an `Error` if the tokenization process fails. */ func tokenize(customerToken: Response.Body.Klarna.CustomerToken?, offSessionAuthorizationId: String?) -> Promise } @@ -38,9 +39,13 @@ class KlarnaTokenizationManager: KlarnaTokenizationManagerProtocol { seal.reject(error) return } - // Checks if the session type is for recurring payments. If so, it attempts to extract the customer token ID and sets 'KlarnaCustomerTokenPaymentInstrument' as a payment instrument. - // Otherwise it sets the 'customerTokenId' with 'offSessionAuthorizationId' value which is 'authToken' returned from 'primerKlarnaWrapperFinalized' KlarnaProvider delegate method and sets 'KlarnaAuthorizationPaymentInstrument' as a payment instrument. - // If the token ID is not found, it generates an error indicating an invalid value for `tokenization.customerToken` + // Checks if the session type is for recurring payments. If so, it attempts to extract the + // customer token ID and sets 'KlarnaCustomerTokenPaymentInstrument' as a payment instrument. + // Otherwise it sets the 'customerTokenId' with 'offSessionAuthorizationId' value + // which is 'authToken' returned from 'primerKlarnaWrapperFinalized' KlarnaProvider + // delegate method and sets 'KlarnaAuthorizationPaymentInstrument' as a payment instrument. + // If the token ID is not found, it generates an error indicating an invalid value + // for `tokenization.customerToken` if KlarnaHelpers.getSessionType() == .recurringPayment { guard let klarnaCustomerToken = customerToken?.customerTokenId else { let error = KlarnaHelpers.getInvalidValueError(key: "tokenization.customerToken", value: nil) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaStep.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaStep.swift index 0bdbcc048c..b5f7746cfe 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaStep.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Models/KlarnaStep.swift @@ -8,7 +8,8 @@ import Foundation import UIKit /** - * This enum is used to communicate the result of attempting to create, authorize and finalize a payment session with Klarna also handling the PaymentView. + * This enum is used to communicate the result of attempting to create, authorize and finalize a payment session + * with Klarna also handling the PaymentView. * It conforms to `PrimerHeadlessStep`. * * Cases: @@ -19,14 +20,19 @@ import UIKit * - `paymentSessionAuthorized`: Indicates that the payment session has been successfully authorized.It carries: * - `authToken` string for subsequent operations that require authorization. * - `checkoutData` for showing the checkout results, after the merchant finishes the payment. - * - `paymentSessionFinalizationRequired`: Signals that the payment session requires finalization steps to be completed by the user or the system. + * - `paymentSessionFinalizationRequired`: Signals that the payment session requires finalization steps to be + * completed by the user or the system. * * - `paymentSessionFinalized`: Indicates a successful finalization of a payment session. It caries: * - `authToken` string, which is used for further API interactions. * - * - `viewInitialized`: Indicates that the Klarna view has been initialized. This is the first step in the Klarna view handling process. - * - `viewResized(height: CGFloat)`: Represents a change in the view's height, which may occur when the Klarna view adjusts to display different content. The `height` parameter specifies the new height of the view. - * - `viewLoaded`: Indicates that the Klarna view has finished loading its initial content and is ready for interaction. The `view` parameter represents the klarna view. + * - `viewInitialized`: Indicates that the Klarna view has been initialized. This is the first step in the Klarna view + * handling process. + * - `viewResized(height: CGFloat)`: Represents a change in the view's height, which may occur + * when the Klarna view adjusts to display different content. + * The `height` parameter specifies the new height of the view. + * - `viewLoaded`: Indicates that the Klarna view has finished loading its initial content and is ready for interaction. + * The `view` parameter represents the klarna view. * - `reviewLoaded`: Indicates that the reviewed information has been loaded into the Klarna view. * - `isLoading`: Indicates that the Klarna view is still loading. */ diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift index 2df0dceb8e..0f5f65ab80 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NativeUI/Common/NativeUIValidateable.swift @@ -24,13 +24,15 @@ extension NativeUIValidateable { guard PrimerAPIConfigurationModule.decodedJWTToken != nil, PrimerAPIConfigurationModule.apiConfiguration != nil else { - let error = PrimerError.uninitializedSDKSession(userInfo: nil, diagnosticsId: UUID().uuidString) + let error = PrimerError.uninitializedSDKSession(userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) throw error } guard let paymentMethod = PrimerAPIConfigurationModule.apiConfiguration?.paymentMethods?.first(where: { $0.type == paymentMethodType }) else { - let error = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, diagnosticsId: UUID().uuidString) + let error = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) throw error } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift index 6d3af071cf..8aae61f6b5 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkCardComponent.swift @@ -278,7 +278,9 @@ public class NolPayLinkCardComponent: PrimerHeadlessCollectDataComponent { ) Analytics.Service.record(events: [sdkEvent]) - guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods?.first(where: { $0.internalPaymentMethodType == .nolPay})?.options as? MerchantOptions, + guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods? + .first(where: { $0.internalPaymentMethodType == .nolPay})? + .options as? MerchantOptions, let appId = nolPaymentMethodOption.appId else { makeAndHandleInvalidValueError(forKey: "Nol AppID") diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift index 86b04c32fa..eefb154298 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayLinkedCardsComponent.swift @@ -52,7 +52,9 @@ public class NolPayLinkedCardsComponent { } private func start(completion: @escaping (Result) -> Void) { - guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods?.first(where: { $0.internalPaymentMethodType == .nolPay})?.options as? MerchantOptions, + guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods? + .first(where: { $0.internalPaymentMethodType == .nolPay})? + .options as? MerchantOptions, let appId = nolPaymentMethodOption.appId else { let error = PrimerError.invalidValue(key: "Nol AppID", diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift index 81077a1b7a..b03f607272 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayPaymentComponent.swift @@ -134,7 +134,10 @@ public class NolPayPaymentComponent: PrimerHeadlessCollectDataComponent { return } - guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigViewModels.filter({ $0.config.type == "NOL_PAY" }).first as? NolPayTokenizationViewModel else { + guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigViewModels + .filter({ $0.config.type == "NOL_PAY" }) + .first as? NolPayTokenizationViewModel + else { return } self.tokenizationViewModel = paymentMethod @@ -195,7 +198,9 @@ public class NolPayPaymentComponent: PrimerHeadlessCollectDataComponent { ) Analytics.Service.record(events: [sdkEvent]) - guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods?.first(where: { $0.internalPaymentMethodType == .nolPay})?.options as? MerchantOptions, + guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods? + .first(where: { $0.internalPaymentMethodType == .nolPay})? + .options as? MerchantOptions, let appId = nolPaymentMethodOption.appId else { makeAndHandleInvalidValueError(forKey: "Nol AppID") @@ -206,7 +211,8 @@ public class NolPayPaymentComponent: PrimerHeadlessCollectDataComponent { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) return } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift index 3825119360..d12307a213 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/NolPay/NolPayUnlinkCardComponent.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable function_body_length +// swiftlint:disable type_body_length import Foundation #if canImport(PrimerNolPaySDK) @@ -252,7 +253,9 @@ public class NolPayUnlinkCardComponent: PrimerHeadlessCollectDataComponent { ) Analytics.Service.record(events: [sdkEvent]) - guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods?.first(where: { $0.internalPaymentMethodType == .nolPay})?.options as? MerchantOptions, + guard let nolPaymentMethodOption = PrimerAPIConfiguration.current?.paymentMethods? + .first(where: { $0.internalPaymentMethodType == .nolPay})? + .options as? MerchantOptions, let appId = nolPaymentMethodOption.appId else { makeAndHandleInvalidValueError(forKey: "Nol AppID") @@ -311,3 +314,4 @@ public class NolPayUnlinkCardComponent: PrimerHeadlessCollectDataComponent { } // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift index 61d9b5df90..5ccf7e42fd 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/AssetsManager.swift @@ -36,7 +36,9 @@ extension PrimerHeadlessUniversalCheckout { public static func getPaymentMethodAsset(for paymentMethodType: String) throws -> PrimerPaymentMethodAsset? { try verifyAPIConfig() - guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs?.first(where: { $0.type == paymentMethodType }) else { + guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs? + .first(where: { $0.type == paymentMethodType }) + else { return nil } @@ -70,7 +72,8 @@ extension PrimerHeadlessUniversalCheckout { public static func getPaymentMethodAssets() throws -> [PrimerPaymentMethodAsset] { try verifyAPIConfig() - let hucAvailablePaymentMethods = PrimerHeadlessUniversalCheckout.PaymentMethod.availablePaymentMethods.compactMap({ $0.paymentMethodType }) + let hucAvailablePaymentMethods = PrimerHeadlessUniversalCheckout.PaymentMethod.availablePaymentMethods + .compactMap({ $0.paymentMethodType }) var paymentMethodAssets: [PrimerPaymentMethodAsset] = [] @@ -113,7 +116,8 @@ extension PrimerHeadlessUniversalCheckout { private static func verifyAPIConfig() throws { if AppState.current.apiConfiguration == nil { - let err = PrimerError.uninitializedSDKSession(userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.uninitializedSDKSession(userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift index 6a3140fbfd..34475d1c3c 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift @@ -5,11 +5,11 @@ // Created by Evangelos on 9/2/22. // -// swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length // swiftlint:disable type_body_length +// swiftlint:disable type_name import Foundation import SafariServices @@ -74,8 +74,9 @@ extension PrimerHeadlessUniversalCheckout { var tmpInputElementsContainers: [Weak] = [] inputElements.forEach { element in if element.inputElementDelegate != nil { - tmpInputElementsContainers.append(Weak(value: PrimerInputElementDelegateContainer(element: element, - delegate: element.inputElementDelegate))) + let container = Weak(value: PrimerInputElementDelegateContainer(element: element, + delegate: element.inputElementDelegate)) + tmpInputElementsContainers.append(container) } } inputElements.forEach { element in @@ -283,9 +284,15 @@ extension PrimerHeadlessUniversalCheckout { private func makeCardRedirectRequestBody() -> Promise { return Promise { seal in - guard let cardnumberField = inputElements.filter({ $0.type == .cardNumber }).first as? PrimerInputTextField, - let expiryDateField = inputElements.filter({ $0.type == .expiryDate }).first as? PrimerInputTextField, - let cardholderNameField = inputElements.filter({ $0.type == .cardholderName }).first as? PrimerInputTextField + guard let cardnumberField = inputElements + .filter({ $0.type == .cardNumber }) + .first as? PrimerInputTextField, + let expiryDateField = inputElements + .filter({ $0.type == .expiryDate }) + .first as? PrimerInputTextField, + let cardholderNameField = inputElements + .filter({ $0.type == .cardholderName }) + .first as? PrimerInputTextField else { let err = PrimerError.invalidValue(key: "input-element", value: nil, @@ -320,7 +327,8 @@ extension PrimerHeadlessUniversalCheckout { let expiryArr = expiryDate.components(separatedBy: expiryDateField.type.delimiter!) let currentYearAsString = Date().yearComponentAsString - let milleniumAndCenturyOfCurrentYearAsString = currentYearAsString.prefix(upTo: currentYearAsString.index(currentYearAsString.startIndex, offsetBy: 2)) + let index = currentYearAsString.index(currentYearAsString.startIndex, offsetBy: 2) + let milleniumAndCenturyOfCurrentYearAsString = currentYearAsString.prefix(upTo: index) let expiryMonth = expiryArr[0] let expiryYear = "\(milleniumAndCenturyOfCurrentYearAsString)\(expiryArr[1])" @@ -337,9 +345,10 @@ extension PrimerHeadlessUniversalCheckout { return } + let number = (PrimerInputElementType.cardNumber.clearFormatting(value: cardNumber) as? String) let cardOffSessionPaymentInstrument = CardOffSessionPaymentInstrument(paymentMethodConfigId: configId, paymentMethodType: paymentMethodType, - number: (PrimerInputElementType.cardNumber.clearFormatting(value: cardNumber) as? String) ?? cardNumber, + number: number ?? cardNumber, expirationMonth: expiryMonth, expirationYear: expiryYear, cardholderName: cardholderName) @@ -351,9 +360,15 @@ extension PrimerHeadlessUniversalCheckout { private func makeCardRequestBody() -> Promise { return Promise { seal in - guard let cardnumberField = inputElements.filter({ $0.type == .cardNumber }).first as? PrimerInputTextField, - let expiryDateField = inputElements.filter({ $0.type == .expiryDate }).first as? PrimerInputTextField, - let cvvField = inputElements.filter({ $0.type == .cvv }).first as? PrimerInputTextField + guard let cardnumberField = inputElements + .filter({ $0.type == .cardNumber }) + .first as? PrimerInputTextField, + let expiryDateField = inputElements + .filter({ $0.type == .expiryDate }) + .first as? PrimerInputTextField, + let cvvField = inputElements + .filter({ $0.type == .cvv }) + .first as? PrimerInputTextField else { let err = PrimerError.invalidValue(key: "input-element", value: nil, @@ -388,13 +403,16 @@ extension PrimerHeadlessUniversalCheckout { let expiryArr = expiryDate.components(separatedBy: expiryDateField.type.delimiter!) let currentYearAsString = Date().yearComponentAsString - let milleniumAndCenturyOfCurrentYearAsString = currentYearAsString.prefix(upTo: currentYearAsString.index(currentYearAsString.startIndex, offsetBy: 2)) + let index = currentYearAsString.index(currentYearAsString.startIndex, offsetBy: 2) + let milleniumAndCenturyOfCurrentYearAsString = currentYearAsString.prefix(upTo: index) let expiryMonth = expiryArr[0] let expiryYear = "\(milleniumAndCenturyOfCurrentYearAsString)\(expiryArr[1])" var cardholderName: String? - if let cardholderNameField = inputElements.filter({ $0.type == .cardholderName }).first as? PrimerInputTextField { + if let cardholderNameField = inputElements + .filter({ $0.type == .cardholderName }) + .first as? PrimerInputTextField { if !cardholderNameField.isValid { let err = PrimerError.invalidValue(key: "cardholder-name", value: nil, @@ -411,8 +429,9 @@ extension PrimerHeadlessUniversalCheckout { cardholderName = cardholderNameField.internalText } + let number = (PrimerInputElementType.cardNumber.clearFormatting(value: cardNumber) as? String) let paymentInstrument = CardPaymentInstrument( - number: (PrimerInputElementType.cardNumber.clearFormatting(value: cardNumber) as? String) ?? cardNumber, + number: number ?? cardNumber, cvv: cvv, expirationMonth: expiryMonth, expirationYear: expiryYear, @@ -860,7 +879,8 @@ Make sure you call the decision handler otherwise the SDK will hang. private func handleCreatePaymentEvent(_ paymentMethodData: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.createPayment(paymentRequest: Request.Body.Payment.Create(token: paymentMethodData)) { paymentResponse, error in + let paymentRequest = Request.Body.Payment.Create(token: paymentMethodData) + createResumePaymentService.createPayment(paymentRequest: paymentRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -1010,7 +1030,9 @@ Make sure you call the decision handler otherwise the SDK will hang. return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, paymentResumeRequest: Request.Body.Payment.Resume(token: resumeToken)) { paymentResponse, error in + let resumeRequest = Request.Body.Payment.Resume(token: resumeToken) + createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, + paymentResumeRequest: resumeRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -1075,7 +1097,9 @@ Make sure you call the decision handler otherwise the SDK will hang. public func inputElementShouldFocus(_ sender: PrimerHeadlessUniversalCheckoutInputElement) -> Bool { guard let senderTextField = sender as? PrimerInputTextField else { return true } - guard let inputElementContainer = originalInputElementsContainers?.filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }).first else { return true } + guard let inputElementContainer = originalInputElementsContainers? + .filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }) + .first else { return true } if let shouldFocus = inputElementContainer.value?.delegate.inputElementShouldFocus?(sender) { return shouldFocus @@ -1086,13 +1110,17 @@ Make sure you call the decision handler otherwise the SDK will hang. public func inputElementDidFocus(_ sender: PrimerHeadlessUniversalCheckoutInputElement) { guard let senderTextField = sender as? PrimerInputTextField else { return } - guard let inputElementContainer = originalInputElementsContainers?.filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }).first else { return } + guard let inputElementContainer = originalInputElementsContainers? + .filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }) + .first else { return } inputElementContainer.value?.delegate.inputElementDidFocus?(sender) } public func inputElementShouldBlur(_ sender: PrimerHeadlessUniversalCheckoutInputElement) -> Bool { guard let senderTextField = sender as? PrimerInputTextField else { return true } - guard let inputElementContainer = originalInputElementsContainers?.filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }).first else { return true } + guard let inputElementContainer = originalInputElementsContainers? + .filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }) + .first else { return true } if let shouldBlur = inputElementContainer.value?.delegate.inputElementShouldBlur?(sender) { return shouldBlur @@ -1103,19 +1131,25 @@ Make sure you call the decision handler otherwise the SDK will hang. public func inputElementDidBlur(_ sender: PrimerHeadlessUniversalCheckoutInputElement) { guard let senderTextField = sender as? PrimerInputTextField else { return } - guard let inputElementContainer = originalInputElementsContainers?.filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }).first else { return } + guard let inputElementContainer = originalInputElementsContainers? + .filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }) + .first else { return } inputElementContainer.value?.delegate.inputElementDidBlur?(sender) } public func inputElementValueDidChange(_ sender: PrimerHeadlessUniversalCheckoutInputElement) { guard let senderTextField = sender as? PrimerInputTextField else { return } - guard let inputElementContainer = originalInputElementsContainers?.filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }).first else { return } + guard let inputElementContainer = originalInputElementsContainers? + .filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }) + .first else { return } inputElementContainer.value?.delegate.inputElementValueDidChange?(sender) } public func inputElementDidDetectType(_ sender: PrimerHeadlessUniversalCheckoutInputElement, type: Any?) { guard let senderTextField = sender as? PrimerInputTextField else { return } - guard let inputElementContainer = originalInputElementsContainers?.filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }).first else { return } + guard let inputElementContainer = originalInputElementsContainers? + .filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }) + .first else { return } if let cvvTextField = self.inputElements.filter({ $0.type == .cvv }).first as? PrimerInputTextField { cvvTextField.detectedValueType = type @@ -1126,7 +1160,9 @@ Make sure you call the decision handler otherwise the SDK will hang. public func inputElementValueIsValid(_ sender: PrimerHeadlessUniversalCheckoutInputElement, isValid: Bool) { guard let senderTextField = sender as? PrimerInputTextField else { return } - guard let inputElementContainer = originalInputElementsContainers?.filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }).first else { return } + guard let inputElementContainer = originalInputElementsContainers? + .filter({ ($0.value?.element as? PrimerInputTextField) == senderTextField }) + .first else { return } inputElementContainer.value?.delegate.inputElementValueIsValid?(sender, isValid: isValid) DispatchQueue.global(qos: .userInitiated).async { @@ -1177,7 +1213,9 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager { if let err = err as? PrimerError { primerErr = err } else { - primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.generic(message: err.localizedDescription, + userInfo: nil, + diagnosticsId: UUID().uuidString) } ErrorHandler.handle(error: primerErr) @@ -1260,7 +1298,9 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager { ErrorHandler.handle(error: err) DispatchQueue.main.async { - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidFail?(withError: err, checkoutData: self.paymentCheckoutData) + PrimerHeadlessUniversalCheckout.current.delegate? + .primerHeadlessUniversalCheckoutDidFail?(withError: err, + checkoutData: self.paymentCheckoutData) } } } @@ -1287,8 +1327,8 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager: SFSafariViewCon webViewCompletion = nil } } -// swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length // swiftlint:enable type_body_length +// swiftlint:enable type_name // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift index f9967e6de3..8da989a62e 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift @@ -5,6 +5,8 @@ // Created by Alexandra Lovin on 22.11.2023. // +// swiftlint:disable type_name + import Foundation @objc public protocol BanksComponentErrorable: AnyObject { @objc func didReceiveError(_ error: NSError) @@ -26,9 +28,7 @@ import Foundation @objc func didReceiveValidationStatus(_ status: ValidStatus) } -// swiftlint:disable type_name @objc public protocol PrimerHeadlessBanksComponentWrapperDelegate: AnyObject, PrimerHeadlessSubmitable, PrimerHeadlessStartable { - // swiftlint:enable type_name @objc var stepDelegate: BanksComponentSteppable? { get set } @objc var errorDelegate: BanksComponentErrorable? { get set } @objc var validationDelegate: BanksComponentValidatable? { get set } @@ -98,3 +98,4 @@ private extension PrimerValidationStatus { } } } +// swiftlint:enable type_name diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift index 7ede580d83..a5db979dc8 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutComponentWithRedirectManager.swift @@ -11,27 +11,42 @@ extension PrimerHeadlessUniversalCheckout { @objc public func provideComponent(paymentMethodType: String) -> PrimerHeadlessBanksComponentWrapper { PrimerHeadlessBanksComponentWrapper(manager: self, paymentMethodType: paymentMethodType) } - public func provide(paymentMethodType: String) throws -> PrimerHeadlessMainComponent? + public func provide(paymentMethodType: String) throws -> MainComponent? where PrimerCollectableData: Any, PrimerHeadlessStep: Any { - try provideBanksComponent(paymentMethodType: paymentMethodType) as? PrimerHeadlessMainComponent + try provideBanksComponent(paymentMethodType: paymentMethodType) as? MainComponent } public func provideBanksComponent(paymentMethodType: String) throws -> any PrimerHeadlessMainComponent { guard let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodType), paymentMethodType == .adyenIDeal else { - let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } guard let tokenizationModel = try getPaymentMethodTokenizationModel() as? BankSelectorTokenizationProviding else { - let err = PrimerError.generic(message: "Unable to locate a correct payment method view model", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.generic(message: "Unable to locate a correct payment method view model", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } guard let webDelegate = try getPaymentMethodTokenizationModel() as? WebRedirectTokenizationDelegate else { - let err = PrimerError.generic(message: "Unable to locate a correct payment method view model", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.generic(message: "Unable to locate a correct payment method view model", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -50,7 +65,12 @@ extension PrimerHeadlessUniversalCheckout { do { try $0.tokenizationModel?.validate() } catch { - let err = PrimerError.generic(message: "Unable to locate a valid payment method view model", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], diagnosticsId: UUID().uuidString) + let err = PrimerError.generic(message: "Unable to locate a valid payment method view model", + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift index 5a309ab862..a3c21e7255 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift @@ -14,7 +14,10 @@ extension PrimerHeadlessUniversalCheckout { public func provideKlarnaComponent(with intent: PrimerSessionIntent) throws -> (any KlarnaComponent)? { guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs?.first(where: { $0.type == "KLARNA" }) else { let err = PrimerError.generic(message: "Unable to locate a valid payment method configuration.", - userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, "line": "\(#line)"], + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift index ae5ff7d519..874a87fdbe 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift @@ -102,7 +102,8 @@ extension PrimerHeadlessUniversalCheckout { self.delegate = delegate guard PrimerPaymentMethod.getPaymentMethod(withType: paymentMethodType) != nil else { - let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -112,10 +113,14 @@ extension PrimerHeadlessUniversalCheckout { switch paymentMethodType { case PrimerPaymentMethodType.paymentCard.rawValue: - self.rawDataTokenizationBuilder = PrimerRawCardDataTokenizationBuilder(paymentMethodType: PrimerPaymentMethodType.paymentCard.rawValue) + self.rawDataTokenizationBuilder = PrimerRawCardDataTokenizationBuilder( + paymentMethodType: PrimerPaymentMethodType.paymentCard.rawValue + ) case PrimerPaymentMethodType.adyenBancontactCard.rawValue: - self.rawDataTokenizationBuilder = PrimerBancontactRawCardDataRedirectTokenizationBuilder(paymentMethodType: paymentMethodType) + self.rawDataTokenizationBuilder = PrimerBancontactRawCardDataRedirectTokenizationBuilder( + paymentMethodType: paymentMethodType + ) case PrimerPaymentMethodType.xenditOvo.rawValue, PrimerPaymentMethodType.adyenMBWay.rawValue: @@ -125,7 +130,8 @@ extension PrimerHeadlessUniversalCheckout { self.rawDataTokenizationBuilder = PrimerRawRetailerDataTokenizationBuilder(paymentMethodType: paymentMethodType) default: - let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -155,7 +161,8 @@ extension PrimerHeadlessUniversalCheckout { Analytics.Service.record(events: [sdkEvent]) guard let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodType) else { - let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, err) return @@ -186,7 +193,9 @@ extension PrimerHeadlessUniversalCheckout { Analytics.Service.record(events: [sdkEvent]) guard let rawData = rawData else { - let err = PrimerError.invalidValue(key: "rawData", value: nil, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "rawData", value: nil, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) self.isDataValid = false @@ -194,8 +203,9 @@ extension PrimerHeadlessUniversalCheckout { DispatchQueue.main.async { self.delegate?.primerRawDataManager?(self, dataIsValid: self.isDataValid, errors: [err]) } - - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidFail?(withError: err, checkoutData: self.paymentCheckoutData) + let delegate = PrimerHeadlessUniversalCheckout.current.delegate + delegate?.primerHeadlessUniversalCheckoutDidFail?(withError: err, + checkoutData: self.paymentCheckoutData) return } @@ -231,7 +241,9 @@ extension PrimerHeadlessUniversalCheckout { PrimerUIManager.dismissPrimerUI(animated: true) } .catch { error in - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidFail?(withError: error, checkoutData: self.paymentCheckoutData) + let delegate = PrimerHeadlessUniversalCheckout.current.delegate + delegate?.primerHeadlessUniversalCheckoutDidFail?(withError: error, + checkoutData: self.paymentCheckoutData) } } @@ -390,7 +402,8 @@ Make sure you call the decision handler otherwise the SDK will hang." let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -407,7 +420,8 @@ Make sure you call the decision handler otherwise the SDK will hang." let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) merchantErr = err } else { merchantErr = NSError.emptyDescriptionError @@ -428,7 +442,8 @@ Make sure you call the decision handler otherwise the SDK will hang." let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -469,7 +484,8 @@ Make sure you call the decision handler otherwise the SDK will hang." let err = PrimerError.invalidValue(key: "paymentResponse", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) throw err } @@ -487,7 +503,8 @@ Make sure you call the decision handler otherwise the SDK will hang." let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -590,7 +607,9 @@ Make sure you call the decision handler otherwise the SDK will hang." if let primerErr = err as? PrimerError { pollingModule?.cancel(withError: primerErr) } else { - let err = PrimerError.underlyingErrors(errors: [err], userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.underlyingErrors(errors: [err], + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) pollingModule?.cancel(withError: err) } @@ -642,7 +661,9 @@ Make sure you call the decision handler otherwise the SDK will hang." if let primerErr = err as? PrimerError { pollingModule?.cancel(withError: primerErr) } else { - let err = PrimerError.underlyingErrors(errors: [err], userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.underlyingErrors(errors: [err], + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) pollingModule?.cancel(withError: err) } @@ -841,7 +862,8 @@ Make sure you call the decision handler otherwise the SDK will hang." private func handleCreatePaymentEvent(_ paymentMethodData: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.createPayment(paymentRequest: Request.Body.Payment.Create(token: paymentMethodData)) { paymentResponse, error in + let paymentRequest = Request.Body.Payment.Create(token: paymentMethodData) + createResumePaymentService.createPayment(paymentRequest: paymentRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -905,7 +927,9 @@ Make sure you call the decision handler otherwise the SDK will hang." private func handleResumePaymentEvent(_ resumePaymentId: String, resumeToken: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, paymentResumeRequest: Request.Body.Payment.Resume(token: resumeToken)) { paymentResponse, error in + let resumeRequest = Request.Body.Payment.Resume(token: resumeToken) + createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, + paymentResumeRequest: resumeRequest) { paymentResponse, error in if let error = error { if let paymentResponse { diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift index 8a1d73557f..7b4bf07d98 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawPhoneNumberDataTokenizationBuilder.swift @@ -47,14 +47,18 @@ class PrimerRawPhoneNumberDataTokenizationBuilder: PrimerRawDataTokenizationBuil return Promise { seal in guard let paymentMethod = PrimerPaymentMethod.getPaymentMethod(withType: paymentMethodType), let paymentMethodId = paymentMethod.id else { - let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return } guard let rawData = data as? PrimerPhoneNumberData else { - let err = PrimerError.invalidValue(key: "rawData", value: nil, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "rawData", + value: nil, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -103,7 +107,8 @@ class PrimerRawPhoneNumberDataTokenizationBuilder: PrimerRawDataTokenizationBuil return } - if let paymentMethodType = PrimerPaymentMethodType(rawValue: self.paymentMethodType), !rawData.phoneNumber.isValidPhoneNumberForPaymentMethodType(paymentMethodType) { + if let paymentMethodType = PrimerPaymentMethodType(rawValue: self.paymentMethodType), + !rawData.phoneNumber.isValidPhoneNumberForPaymentMethodType(paymentMethodType) { errors.append(PrimerValidationError.invalidPhoneNumber( message: "Phone number is not valid.", userInfo: [ diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift index 9b2ead876a..e5599439ae 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/PrimerRawRetailerDataTokenizationBuilder.swift @@ -46,14 +46,17 @@ class PrimerRawRetailerDataTokenizationBuilder: PrimerRawDataTokenizationBuilder return Promise { seal in guard let paymentMethod = PrimerPaymentMethod.getPaymentMethod(withType: paymentMethodType), let paymentMethodId = paymentMethod.id else { - let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return } guard let rawData = data as? PrimerRetailerData else { - let err = PrimerError.invalidValue(key: "rawData", value: nil, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "rawData", value: nil, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift index b24144ae6f..6b549e15f8 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/VaultManager.swift @@ -46,7 +46,9 @@ extension PrimerHeadlessUniversalCheckout { internal func validateAdditionalDataSynchronously(vaultedPaymentMethodId: String, vaultedPaymentMethodAdditionalData: PrimerVaultedPaymentMethodAdditionalData) -> [Error]? { var errors: [Error] = [] - guard let vaultedPaymentMethod = self.vaultedPaymentMethods?.first(where: { $0.id == vaultedPaymentMethodId }) else { + guard let vaultedPaymentMethod = self.vaultedPaymentMethods? + .first(where: { $0.id == vaultedPaymentMethodId }) + else { let err = PrimerError.invalidVaultedPaymentMethodId( vaultedPaymentMethodId: vaultedPaymentMethodId, userInfo: ["file": #file, @@ -60,7 +62,8 @@ extension PrimerHeadlessUniversalCheckout { } if vaultedPaymentMethod.paymentMethodType == "PAYMENT_CARD" { - let cardNetwork = CardNetwork(cardNetworkStr: vaultedPaymentMethod.paymentInstrumentData.binData?.network ?? "") + let network = vaultedPaymentMethod.paymentInstrumentData.binData?.network ?? "" + let cardNetwork = CardNetwork(cardNetworkStr: network) if let vaultedCardAdditionalData = vaultedPaymentMethodAdditionalData as? PrimerVaultedCardAdditionalData { if vaultedCardAdditionalData.cvv.isEmpty { @@ -114,7 +117,8 @@ extension PrimerHeadlessUniversalCheckout { public func validate(vaultedPaymentMethodId: String, vaultedPaymentMethodAdditionalData: PrimerVaultedPaymentMethodAdditionalData, completion: @escaping (_ errors: [Error]?) -> Void) { DispatchQueue.global(qos: .userInteractive).async { - let errors = self.validateAdditionalDataSynchronously(vaultedPaymentMethodId: vaultedPaymentMethodId, vaultedPaymentMethodAdditionalData: vaultedPaymentMethodAdditionalData) + let errors = self.validateAdditionalDataSynchronously(vaultedPaymentMethodId: vaultedPaymentMethodId, + vaultedPaymentMethodAdditionalData: vaultedPaymentMethodAdditionalData) DispatchQueue.main.async { completion(errors) } @@ -176,7 +180,9 @@ extension PrimerHeadlessUniversalCheckout { } public func startPaymentFlow(vaultedPaymentMethodId: String, vaultedPaymentMethodAdditionalData: PrimerVaultedPaymentMethodAdditionalData? = nil) { - guard let vaultedPaymentMethod = self.vaultedPaymentMethods?.first(where: { $0.id == vaultedPaymentMethodId }) else { + guard let vaultedPaymentMethod = self.vaultedPaymentMethods? + .first(where: { $0.id == vaultedPaymentMethodId }) + else { let err = PrimerError.invalidVaultedPaymentMethodId( vaultedPaymentMethodId: vaultedPaymentMethodId, userInfo: ["file": #file, @@ -195,7 +201,8 @@ extension PrimerHeadlessUniversalCheckout { } if let vaultedPaymentMethodAdditionalData = vaultedPaymentMethodAdditionalData { - if let errors = self.validateAdditionalDataSynchronously(vaultedPaymentMethodId: vaultedPaymentMethodId, vaultedPaymentMethodAdditionalData: vaultedPaymentMethodAdditionalData) { + if let errors = self.validateAdditionalDataSynchronously(vaultedPaymentMethodId: vaultedPaymentMethodId, + vaultedPaymentMethodAdditionalData: vaultedPaymentMethodAdditionalData) { DispatchQueue.main.async { var primerError: (any PrimerErrorProtocol)? @@ -227,7 +234,8 @@ extension PrimerHeadlessUniversalCheckout { let tokenizationService: TokenizationServiceProtocol = TokenizationService() firstly { - tokenizationService.exchangePaymentMethodToken(vaultedPaymentMethod.id, vaultedPaymentMethodAdditionalData: vaultedPaymentMethodAdditionalData) + tokenizationService.exchangePaymentMethodToken(vaultedPaymentMethod.id, + vaultedPaymentMethodAdditionalData: vaultedPaymentMethodAdditionalData) } .then { paymentMethodTokenData -> Promise in self.paymentMethodTokenData = paymentMethodTokenData @@ -248,7 +256,9 @@ extension PrimerHeadlessUniversalCheckout { DispatchQueue.main.async { if PrimerSettings.current.paymentHandling == .auto { - guard let checkoutData = self.paymentCheckoutData, PrimerSettings.current.paymentHandling == .auto else { + guard let checkoutData = self.paymentCheckoutData, + PrimerSettings.current.paymentHandling == .auto + else { let err = PrimerError.generic( message: "Failed to find checkout data", userInfo: ["file": #file, @@ -257,7 +267,8 @@ extension PrimerHeadlessUniversalCheckout { "line": "\(#line)"], diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) - PrimerDelegateProxy.primerDidFailWithError(err, data: self.paymentCheckoutData) { _ in + PrimerDelegateProxy.primerDidFailWithError(err, + data: self.paymentCheckoutData) { _ in // No need to pass anything } return @@ -283,7 +294,8 @@ extension PrimerHeadlessUniversalCheckout { diagnosticsId: UUID().uuidString) } - PrimerDelegateProxy.primerDidFailWithError(primerError, data: self.paymentCheckoutData) { _ in + PrimerDelegateProxy.primerDidFailWithError(primerError, + data: self.paymentCheckoutData) { _ in // No need to pass anything } } @@ -299,7 +311,8 @@ extension PrimerHeadlessUniversalCheckout { "line": "\(#line)"], diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) - PrimerDelegateProxy.primerDidFailWithError(err, data: self.paymentCheckoutData) { _ in + PrimerDelegateProxy.primerDidFailWithError(err, + data: self.paymentCheckoutData) { _ in // No need to pass anything } return @@ -325,7 +338,8 @@ extension PrimerHeadlessUniversalCheckout { diagnosticsId: UUID().uuidString) } - PrimerDelegateProxy.primerDidFailWithError(primerError, data: self.paymentCheckoutData) { _ in + PrimerDelegateProxy.primerDidFailWithError(primerError, + data: self.paymentCheckoutData) { _ in // No need to pass anything } } @@ -333,7 +347,9 @@ extension PrimerHeadlessUniversalCheckout { } else { DispatchQueue.main.async { if PrimerSettings.current.paymentHandling == .auto { - guard let checkoutData = self.paymentCheckoutData, PrimerSettings.current.paymentHandling == .auto else { + guard let checkoutData = self.paymentCheckoutData, + PrimerSettings.current.paymentHandling == .auto + else { let err = PrimerError.generic( message: "Failed to find checkout data", userInfo: ["file": #file, @@ -382,7 +398,8 @@ extension PrimerHeadlessUniversalCheckout { guard PrimerAPIConfigurationModule.decodedJWTToken != nil, PrimerAPIConfigurationModule.apiConfiguration != nil else { - let err = PrimerError.uninitializedSDKSession(userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.uninitializedSDKSession(userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -434,10 +451,11 @@ extension PrimerHeadlessUniversalCheckout { case .fail(let message): var merchantErr: Error! if let message = message { - let err = PrimerError.merchantError(message: message, userInfo: ["file": #file, - "class": "\(Self.self)", - "function": #function, - "line": "\(#line)"], + let err = PrimerError.merchantError(message: message, + userInfo: ["file": #file, + "class": "\(Self.self)", + "function": #function, + "line": "\(#line)"], diagnosticsId: UUID().uuidString) merchantErr = err } else { @@ -625,7 +643,9 @@ extension PrimerHeadlessUniversalCheckout { if let primerErr = err as? PrimerError { pollingModule?.cancel(withError: primerErr) } else { - let err = PrimerError.underlyingErrors(errors: [err], userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.underlyingErrors(errors: [err], + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) pollingModule?.cancel(withError: err) } @@ -677,7 +697,9 @@ extension PrimerHeadlessUniversalCheckout { if let primerErr = err as? PrimerError { pollingModule?.cancel(withError: primerErr) } else { - let err = PrimerError.underlyingErrors(errors: [err], userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.underlyingErrors(errors: [err], + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) pollingModule?.cancel(withError: err) } @@ -811,7 +833,8 @@ extension PrimerHeadlessUniversalCheckout { private func handleCreatePaymentEvent(_ paymentMethodData: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.createPayment(paymentRequest: Request.Body.Payment.Create(token: paymentMethodData)) { paymentResponse, error in + let paymentRequest = Request.Body.Payment.Create(token: paymentMethodData) + createResumePaymentService.createPayment(paymentRequest: paymentRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -875,7 +898,9 @@ extension PrimerHeadlessUniversalCheckout { private func handleResumePaymentEvent(_ resumePaymentId: String, resumeToken: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, paymentResumeRequest: Request.Body.Payment.Resume(token: resumeToken)) { paymentResponse, error in + let resumeRequest = Request.Body.Payment.Resume(token: resumeToken) + createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, + paymentResumeRequest: resumeRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -953,19 +978,23 @@ extension PrimerHeadlessUniversalCheckout { PrimerUIManager.prepareRootViewController() } .done { - PrimerUIManager.primerRootViewController?.present(self.webViewController!, animated: true, completion: { - DispatchQueue.main.async { - seal.fulfill() - } - }) + PrimerUIManager.primerRootViewController?.present(self.webViewController!, + animated: true, + completion: { + DispatchQueue.main.async { + seal.fulfill() + } + }) } .catch { _ in } } else { - PrimerUIManager.primerRootViewController?.present(self.webViewController!, animated: true, completion: { - DispatchQueue.main.async { - seal.fulfill() - } - }) + PrimerUIManager.primerRootViewController?.present(self.webViewController!, + animated: true, + completion: { + DispatchQueue.main.async { + seal.fulfill() + } + }) } } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift index 1938d0cde1..611a051b70 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift @@ -47,7 +47,8 @@ extension PrimerHeadlessUniversalCheckout { guard let primerCheckoutComponentsTextField = textField as? PrimerInputTextField else { return false } if !string.isEmpty { // Characters aren't in the allowed character set - if let allowedCharacterSet = self.inputElement.type.allowedCharacterSet, string.rangeOfCharacter(from: allowedCharacterSet.inverted) != nil { + if let allowedCharacterSet = self.inputElement.type.allowedCharacterSet, + string.rangeOfCharacter(from: allowedCharacterSet.inverted) != nil { return false } } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift index dfad071ed9..ee68c8dbec 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckout.swift @@ -62,7 +62,12 @@ public class PrimerHeadlessUniversalCheckout: LogReporter { } if PrimerHeadlessUniversalCheckout.current.delegate == nil { - logger.warn(message: "PrimerHeadlessUniversalCheckout delegate has not been set, and you won't be able to receive the Payment Method Token data to create a payment.") + let message = """ + PrimerHeadlessUniversalCheckout delegate has not been set, \ + and you won't be able to receive the Payment Method Token \ + data to create a payment." + """ + logger.warn(message: message) } PrimerInternal.shared.checkoutSessionId = UUID().uuidString @@ -114,7 +119,8 @@ public class PrimerHeadlessUniversalCheckout: LogReporter { } else { DispatchQueue.main.async { let availablePaymentMethods = PrimerHeadlessUniversalCheckout.PaymentMethod.availablePaymentMethods - PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidLoadAvailablePaymentMethods?(availablePaymentMethods) + let delegate = PrimerHeadlessUniversalCheckout.current.delegate + delegate?.primerHeadlessUniversalCheckoutDidLoadAvailablePaymentMethods?(availablePaymentMethods) completion(availablePaymentMethods, nil) } } @@ -167,7 +173,8 @@ public class PrimerHeadlessUniversalCheckout: LogReporter { let err = PrimerError.missingPrimerConfiguration(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) seal.reject(err) return } @@ -176,7 +183,8 @@ public class PrimerHeadlessUniversalCheckout: LogReporter { let err = PrimerError.misconfiguredPaymentMethods(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) seal.reject(err) return } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckoutProtocols.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckoutProtocols.swift index 002337e486..997292283a 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckoutProtocols.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/PrimerHeadlessUniversalCheckoutProtocols.swift @@ -9,9 +9,10 @@ import Foundation import UIKit // swiftlint:disable type_name +// swiftlint:disable line_length + @objc public protocol PrimerHeadlessUniversalCheckoutUIDelegate { - // swiftlint:enable type_name @objc optional func primerHeadlessUniversalCheckoutUIDidStartPreparation(for paymentMethodType: String) @objc optional func primerHeadlessUniversalCheckoutUIDidShowPaymentMethod(for paymentMethodType: String) } @@ -45,3 +46,5 @@ public protocol PrimerInputElementDelegate: AnyObject { @objc optional func inputElementValueIsValid(_ sender: PrimerHeadlessUniversalCheckoutInputElement, isValid: Bool) @objc optional func inputElementDidDetectType(_ sender: PrimerHeadlessUniversalCheckoutInputElement, type: Any?) } +// swiftlint:enable type_name +// swiftlint:enable line_length diff --git a/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift b/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift index 1fef697979..fa3198f2a9 100644 --- a/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift +++ b/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift @@ -6,10 +6,15 @@ struct CardButtonViewModel { let imageName: ImageName let paymentMethodType: PaymentInstrumentType var surCharge: Int? { - guard let options = PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.paymentMethod?.options else { return nil } - guard let paymentCardOption = options.filter({ $0["type"] as? String == PrimerPaymentMethodType.paymentCard.rawValue }).first else { return nil } + let session = PrimerAPIConfigurationModule.apiConfiguration?.clientSession + guard let options = session?.paymentMethod?.options else { return nil } + guard let paymentCardOption = options + .filter({ $0["type"] as? String == PrimerPaymentMethodType.paymentCard.rawValue }) + .first else { return nil } guard let networks = paymentCardOption["networks"] as? [[String: Any]] else { return nil } - guard let tmpNetwork = networks.filter({ ($0["type"] as? String)?.lowercased() == network.lowercased() }).first else { return nil } + guard let tmpNetwork = networks.filter({ ($0["type"] as? String)? + .lowercased() == network.lowercased() }) + .first else { return nil } return tmpNetwork["surcharge"] as? Int } } diff --git a/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift b/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift index 34f45baec2..9bed503726 100644 --- a/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift +++ b/Sources/PrimerSDK/Classes/Data Models/CardNetwork.swift @@ -313,12 +313,21 @@ public enum CardNetwork: String, Codable, CaseIterable, LogReporter { } var surcharge: Int? { - guard let options = PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.paymentMethod?.options, !options.isEmpty else { return nil } + guard let options = PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.paymentMethod?.options, + !options.isEmpty else { return nil } for paymentMethodOption in options { - guard let type = paymentMethodOption["type"] as? String, type == PrimerPaymentMethodType.paymentCard.rawValue else { continue } - guard let networks = paymentMethodOption["networks"] as? [[String: Any]] else { continue } - guard let tmpNetwork = networks.filter({ $0["type"] as? String == self.rawValue.uppercased() }).first else { continue } + guard let type = paymentMethodOption["type"] as? String, + type == PrimerPaymentMethodType.paymentCard.rawValue + else { continue } + + guard let networks = paymentMethodOption["networks"] as? [[String: Any]] + else { continue } + + guard let tmpNetwork = networks + .filter({ $0["type"] as? String == self.rawValue.uppercased() }) + .first + else { continue } guard let surcharge = tmpNetwork["surcharge"] as? Int else { continue } return surcharge } @@ -359,11 +368,13 @@ public enum CardNetwork: String, Codable, CaseIterable, LogReporter { } } -extension Array: LogReporter { +extension [CardNetwork]: LogReporter { /// A list of card networks that the merchant supports static var allowedCardNetworks: Self { - guard let networkStrings = PrimerAPIConfiguration.current?.clientSession?.paymentMethod?.orderedAllowedCardNetworks else { + let session = PrimerAPIConfiguration.current?.clientSession + guard let networkStrings = session?.paymentMethod?.orderedAllowedCardNetworks + else { logger.warn(message: "Expected allowed networks to be present in client session") return [] } diff --git a/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift b/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift index 315f4de7f6..89d1b13b0f 100644 --- a/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift +++ b/Sources/PrimerSDK/Classes/Data Models/ClientSession.swift @@ -28,7 +28,8 @@ internal class ClientSession { } static func setBillingAddressActionWithParameters(_ parameters: [String: Any]) -> ClientSession.Action { - ClientSession.Action(type: .setBillingAddress, params: makeBillingAddressDictionaryRequestFromParameters(parameters)) + ClientSession.Action(type: .setBillingAddress, + params: makeBillingAddressDictionaryRequestFromParameters(parameters)) } // swiftlint:disable:next nesting @@ -107,7 +108,14 @@ internal class ClientSession { // swiftlint:disable:next nesting enum CodingKeys: String, CodingKey { - case id = "customerId", firstName, lastName, emailAddress, mobileNumber, billingAddress, shippingAddress, taxId + case id = "customerId" + case firstName + case lastName + case emailAddress + case mobileNumber + case billingAddress + case shippingAddress + case taxId } internal init(from decoder: Decoder) throws { @@ -159,7 +167,15 @@ internal class ClientSession { // swiftlint:disable:next nesting enum CodingKeys: String, CodingKey { - case id = "orderId", merchantAmount, totalOrderAmount, totalTaxAmount, countryCode, currencyCode, fees, lineItems, shippingAmount + case id = "orderId", + merchantAmount, + totalOrderAmount, + totalTaxAmount, + countryCode, + currencyCode, + fees, + lineItems, + shippingAmount } internal init( @@ -192,7 +208,8 @@ internal class ClientSession { totalTaxAmount = (try? container.decode(Int?.self, forKey: .totalTaxAmount)) ?? nil countryCode = (try? container.decode(CountryCode?.self, forKey: .countryCode)) ?? nil if let cCode = try? container.decode(String.self, forKey: .currencyCode) { - let currencyLoader = CurrencyLoader(storage: DefaultCurrencyStorage(), networkService: CurrencyNetworkService()) + let currencyLoader = CurrencyLoader(storage: DefaultCurrencyStorage(), + networkService: CurrencyNetworkService()) currencyCode = currencyLoader.getCurrency(cCode) } else { currencyCode = nil @@ -230,8 +247,10 @@ internal class ClientSession { let productType: String? func toOrderItem() throws -> OrderItem { + let applePayOptions = PrimerSettings.current.paymentMethodOptions.applePayOptions + let name = (self.description ?? applePayOptions?.merchantName) return try OrderItem( - name: (self.description ?? PrimerSettings.current.paymentMethodOptions.applePayOptions?.merchantName) ?? "Item", + name: name ?? "Item", unitAmount: self.amount, quantity: self.quantity, discountAmount: self.discountAmount, @@ -288,7 +307,8 @@ internal class ClientSession { if let tmpOptions = (try? container.decode([[String: AnyCodable]]?.self, forKey: .options)), let optionsData = try? JSONEncoder().encode(tmpOptions), - let optionsJson = (try? JSONSerialization.jsonObject(with: optionsData, options: .allowFragments)) as? [[String: Any]] { + let optionsJson = (try? JSONSerialization.jsonObject(with: optionsData, + options: .allowFragments)) as? [[String: Any]] { self.options = optionsJson } else { self.options = nil @@ -338,7 +358,8 @@ internal class ClientSession { required internal init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.clientSessionId = (try? container.decode(String?.self, forKey: .clientSessionId)) ?? nil - self.paymentMethod = (try? container.decode(ClientSession.PaymentMethod?.self, forKey: .paymentMethod)) ?? nil + self.paymentMethod = (try? container.decode(ClientSession.PaymentMethod?.self, + forKey: .paymentMethod)) ?? nil self.order = (try? container.decode(ClientSession.Order?.self, forKey: .order)) ?? nil self.customer = (try? container.decode(ClientSession.Customer?.self, forKey: .customer)) ?? nil self.testId = (try? container.decode(String?.self, forKey: .testId)) ?? nil @@ -357,8 +378,11 @@ internal class ClientSession { internal extension Encodable { func asDictionary() throws -> [String: Any] { let data = try JSONEncoder().encode(self) - guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else { - let error = NSError(domain: "EncodableError", code: 1001, userInfo: [NSLocalizedDescriptionKey: "Failed to serialize object to dictionary"]) + guard let dictionary = try JSONSerialization.jsonObject(with: data, + options: .allowFragments) as? [String: Any] else { + let error = NSError(domain: "EncodableError", + code: 1001, + userInfo: [NSLocalizedDescriptionKey: "Failed to serialize object to dictionary"]) throw error } return dictionary diff --git a/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift b/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift index 29fe9fea2a..aec33ceb61 100644 --- a/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift +++ b/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift @@ -1,3 +1,5 @@ +// swiftlint:disable function_body_length + import Foundation extension Request.Body { @@ -150,7 +152,8 @@ struct DecodedJWTToken: Codable { self.threeDSecureInitUrl = try? container.decode(String.self, forKey: .threeDSecureInitUrl) self.threeDSecureToken = try? container.decode(String.self, forKey: .threeDSecureToken) self.useThreeDsWeakValidation = try? container.decode(Bool.self, forKey: .useThreeDsWeakValidation) - self.supportedThreeDsProtocolVersions = try container.decodeIfPresent([String].self, forKey: .supportedThreeDsProtocolVersions) + self.supportedThreeDsProtocolVersions = try container.decodeIfPresent([String].self, + forKey: .supportedThreeDsProtocolVersions) self.coreUrl = try? container.decode(String.self, forKey: .coreUrl) self.pciUrl = try? container.decode(String.self, forKey: .pciUrl) self.env = try? container.decode(String.self, forKey: .env) @@ -288,3 +291,4 @@ extension DecodedJWTToken { } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift b/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift index bc1a4a7d8e..dfb9d2db77 100644 --- a/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift +++ b/Sources/PrimerSDK/Classes/Data Models/CountryCode.swift @@ -311,7 +311,8 @@ extension CountryCode { self.locale = try container.decode(String.self, forKey: .locale) self.countries = [:] - if let countriesWithMultipleOptionNames = try container.decodeIfPresent([CountryCode.RawValue: AnyCodable].self, forKey: .countries) { + if let countriesWithMultipleOptionNames = try container.decodeIfPresent([CountryCode.RawValue: AnyCodable].self, + forKey: .countries) { var updatedCountries: [CountryCode.RawValue: String] = [:] countriesWithMultipleOptionNames.forEach { if let countryNames = $0.value.value as? [String] { @@ -337,7 +338,9 @@ extension CountryCode { } private var localizedCountryName: String { - return LocalizedCountries.loadedCountriesBasedOnLocale?.countries.first { $0.key == self.rawValue }?.value ?? "N/A" + return LocalizedCountries.loadedCountriesBasedOnLocale?.countries + .first { $0.key == self.rawValue }? + .value ?? "N/A" } } diff --git a/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift b/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift index 09f5bbef0f..eca45d7911 100644 --- a/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift +++ b/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift @@ -5,6 +5,8 @@ // Created by Boris on 11.1.24.. // +// swiftlint:disable function_body_length + import Foundation var inMemoryCurrencies: [Currency]? = [] @@ -86,7 +88,8 @@ public class CurrencyLoader: LogReporter { inMemoryCurrencies = currencies self?.logger.debug(message: "Successfully updated the list of currencies.") - let sdkEvent = Analytics.Event.sdk(name: #function, params: ["message": "Successfully updated the list of currencies."]) + let sdkEvent = Analytics.Event.sdk(name: #function, + params: ["message": "Successfully updated the list of currencies."]) Analytics.Service.record(events: [sdkEvent]) completion?(nil) } catch { @@ -97,3 +100,4 @@ public class CurrencyLoader: LogReporter { } } } +// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyNetworkServiceProtocol.swift b/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyNetworkServiceProtocol.swift index 3e04eb93b8..cd29b8dd4b 100644 --- a/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyNetworkServiceProtocol.swift +++ b/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyNetworkServiceProtocol.swift @@ -5,6 +5,8 @@ // Created by Boris on 24.1.24.. // +// swiftlint:disable large_tuple + import Foundation public protocol CurrencyNetworkServiceProtocol { @@ -29,3 +31,4 @@ class MockCurrencyNetworkService: CurrencyNetworkServiceProtocol { completion(mockResponse?.0, mockResponse?.1, mockResponse?.2) } } +// swiftlint:enable large_tuple diff --git a/Sources/PrimerSDK/Classes/Data Models/OrderItem.swift b/Sources/PrimerSDK/Classes/Data Models/OrderItem.swift index e274933e61..bc05f9ff33 100644 --- a/Sources/PrimerSDK/Classes/Data Models/OrderItem.swift +++ b/Sources/PrimerSDK/Classes/Data Models/OrderItem.swift @@ -52,7 +52,8 @@ internal struct OrderItem: Codable { let err = PrimerError.generic(message: "amount should be null for pending items", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -61,7 +62,8 @@ internal struct OrderItem: Codable { let err = PrimerError.generic(message: "amount cannot be null for non-pending items", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } diff --git a/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift b/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift index 34e84aa80c..6ba8ffaa63 100644 --- a/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift +++ b/Sources/PrimerSDK/Classes/Data Models/PaymentMethod.swift @@ -289,12 +289,14 @@ class PrimerPaymentMethod: Codable, LogReporter { let container = try decoder.container(keyedBy: CodingKeys.self) id = (try? container.decode(String?.self, forKey: .id)) ?? nil - implementationType = try container.decode(PrimerPaymentMethod.ImplementationType.self, forKey: .implementationType) + implementationType = try container.decode(PrimerPaymentMethod.ImplementationType.self, + forKey: .implementationType) type = try container.decode(String.self, forKey: .type) name = try container.decode(String.self, forKey: .name) processorConfigId = (try? container.decode(String?.self, forKey: .processorConfigId)) ?? nil surcharge = (try? container.decode(Int?.self, forKey: .surcharge)) ?? nil - displayMetadata = (try? container.decode(PrimerPaymentMethod.DisplayMetadata?.self, forKey: .displayMetadata)) ?? nil + displayMetadata = (try? container.decode(PrimerPaymentMethod.DisplayMetadata?.self, + forKey: .displayMetadata)) ?? nil switch type { case "PAYMENT_CARD": @@ -410,7 +412,8 @@ extension PrimerPaymentMethod { borderColor == nil, text == nil, textColor == nil { - let err = InternalError.failedToDecode(message: "BaseColors", userInfo: nil, diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "BaseColors", userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -469,7 +472,8 @@ extension PrimerTheme { darkUrlStr = (try? container.decode(String?.self, forKey: .darkUrlStr)) ?? nil if coloredUrlStr == nil && lightUrlStr == nil && darkUrlStr == nil { - let err = InternalError.failedToDecode(message: "BaseColoredURLs", userInfo: nil, diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "BaseColoredURLs", userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -514,7 +518,8 @@ extension PrimerTheme { lightHex = (try? container.decode(String?.self, forKey: .lightHex)) ?? nil if coloredHex == nil && lightHex == nil && darkHex == nil { - let err = InternalError.failedToDecode(message: "BaseColors", userInfo: nil, diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "BaseColors", userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } diff --git a/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift b/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift index 6e0e615614..0b40890e31 100644 --- a/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift +++ b/Sources/PrimerSDK/Classes/Data Models/PrimerConfiguration.swift @@ -36,7 +36,8 @@ extension Request.URLParameters { self.requestDisplayMetadata = (try? container.decode(Bool?.self, forKey: .requestDisplayMetadata)) ?? nil if skipPaymentMethodTypes == nil && requestDisplayMetadata == nil { - throw InternalError.failedToDecode(message: "All values are nil", userInfo: nil, diagnosticsId: UUID().uuidString) + throw InternalError.failedToDecode(message: "All values are nil", userInfo: nil, + diagnosticsId: UUID().uuidString) } } @@ -44,7 +45,8 @@ extension Request.URLParameters { var container = encoder.container(keyedBy: CodingKeys.self) if skipPaymentMethodTypes == nil && requestDisplayMetadata == nil { - throw InternalError.failedToDecode(message: "All values are nil", userInfo: nil, diagnosticsId: UUID().uuidString) + throw InternalError.failedToDecode(message: "All values are nil", userInfo: nil, + diagnosticsId: UUID().uuidString) } if let skipPaymentMethodTypes = skipPaymentMethodTypes { @@ -89,10 +91,17 @@ extension Response.Body { } var hasSurchargeEnabled: Bool { - let pmSurcharge = PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.paymentMethod?.options?.first(where: { $0["surcharge"] as? Int != nil }) + let pmSurcharge = PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.paymentMethod?.options? + .first(where: { $0["surcharge"] as? Int != nil }) let options = PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.paymentMethod?.options - let cardSurcharge = options?.first(where: { (($0["networks"] as? [[String: Any]])?.first(where: { $0["surcharge"] as? Int != nil })) != nil }) + let cardSurcharge = options? + .first(where: { + (($0["networks"] as? [[String: Any]])? + .first(where: { + $0["surcharge"] as? Int != nil + })) != nil + }) return pmSurcharge != nil || cardSurcharge != nil } @@ -284,7 +293,7 @@ Add `PrimerIPay88SDK' in your project by adding \"pod 'PrimerIPay88SDK'\" in you coreUrl: String?, pciUrl: String?, binDataUrl: String?, - assetsUrl: String?, /// poghledaj u responsu kako se zove + assetsUrl: String?, clientSession: ClientSession.APIResponse?, paymentMethods: [PrimerPaymentMethod]?, primerAccountId: String?, diff --git a/Sources/PrimerSDK/Classes/Data Models/TokenizationRequestBody.swift b/Sources/PrimerSDK/Classes/Data Models/TokenizationRequestBody.swift index f021ff442d..d89b2f536b 100644 --- a/Sources/PrimerSDK/Classes/Data Models/TokenizationRequestBody.swift +++ b/Sources/PrimerSDK/Classes/Data Models/TokenizationRequestBody.swift @@ -42,7 +42,10 @@ extension Request.Body { } else if let paymentInstrument = self.paymentInstrument as? CardOffSessionPaymentInstrument { try container.encode(paymentInstrument, forKey: .paymentInstrument) } else { - let err = InternalError.invalidValue(key: "PaymentInstrument", value: self.paymentInstrument, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = InternalError.invalidValue(key: "PaymentInstrument", + value: self.paymentInstrument, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } diff --git a/Sources/PrimerSDK/Classes/Data Models/TokenizationResponse.swift b/Sources/PrimerSDK/Classes/Data Models/TokenizationResponse.swift index 729eac1d74..ca54e3a840 100644 --- a/Sources/PrimerSDK/Classes/Data Models/TokenizationResponse.swift +++ b/Sources/PrimerSDK/Classes/Data Models/TokenizationResponse.swift @@ -87,9 +87,19 @@ extension Response.Body.Tokenization { paymentMethodType: self.paymentInstrumentType) case .payPalBillingAgreement: guard let cardholder = self.paymentInstrumentData?.externalPayerInfo?.email else { return nil } - return CardButtonViewModel(network: "PayPal", cardholder: cardholder, last4: "", expiry: "", imageName: self.icon, paymentMethodType: self.paymentInstrumentType) + return CardButtonViewModel(network: "PayPal", + cardholder: cardholder, + last4: "", + expiry: "", + imageName: self.icon, + paymentMethodType: self.paymentInstrumentType) case .goCardlessMandate: - return CardButtonViewModel(network: "Bank account", cardholder: "", last4: "", expiry: "", imageName: self.icon, paymentMethodType: self.paymentInstrumentType) + return CardButtonViewModel(network: "Bank account", + cardholder: "", + last4: "", + expiry: "", + imageName: self.icon, + paymentMethodType: self.paymentInstrumentType) case .klarnaCustomerToken: return CardButtonViewModel( network: paymentInstrumentData?.sessionData?.billingAddress?.email ?? "Klarna Customer Token", diff --git a/Sources/PrimerSDK/Classes/Data Models/VoucherValue.swift b/Sources/PrimerSDK/Classes/Data Models/VoucherValue.swift index b774490440..39d0cea02d 100644 --- a/Sources/PrimerSDK/Classes/Data Models/VoucherValue.swift +++ b/Sources/PrimerSDK/Classes/Data Models/VoucherValue.swift @@ -25,12 +25,18 @@ extension VoucherValue { static var currentVoucherValues: [VoucherValue] { var currentVaucherValues = [ - VoucherValue(id: "entity", description: Strings.VoucherInfoPaymentView.entityLabelText, value: PrimerAPIConfigurationModule.decodedJWTToken?.entity), - VoucherValue(id: "reference", description: Strings.VoucherInfoPaymentView.referenceLabelText, value: PrimerAPIConfigurationModule.decodedJWTToken?.reference) + VoucherValue(id: "entity", + description: Strings.VoucherInfoPaymentView.entityLabelText, + value: PrimerAPIConfigurationModule.decodedJWTToken?.entity), + VoucherValue(id: "reference", + description: Strings.VoucherInfoPaymentView.referenceLabelText, + value: PrimerAPIConfigurationModule.decodedJWTToken?.reference) ] if let currency = AppState.current.currency, let amount = AppState.current.amount { - currentVaucherValues.append(VoucherValue(id: "amount", description: Strings.VoucherInfoPaymentView.amountLabelText, value: "\(amount.toCurrencyString(currency: currency))")) + currentVaucherValues.append(VoucherValue(id: "amount", + description: Strings.VoucherInfoPaymentView.amountLabelText, + value: "\(amount.toCurrencyString(currency: currency))")) } return currentVaucherValues @@ -51,15 +57,21 @@ extension VoucherValue { var voucherSharableValues = "" var sharableVoucherValues = [ - VoucherValue(id: "entity", description: Strings.VoucherInfoPaymentView.entityLabelText, value: PrimerAPIConfigurationModule.decodedJWTToken?.entity), - VoucherValue(id: "reference", description: Strings.VoucherInfoPaymentView.referenceLabelText, value: PrimerAPIConfigurationModule.decodedJWTToken?.reference) + VoucherValue(id: "entity", + description: Strings.VoucherInfoPaymentView.entityLabelText, + value: PrimerAPIConfigurationModule.decodedJWTToken?.entity), + VoucherValue(id: "reference", + description: Strings.VoucherInfoPaymentView.referenceLabelText, + value: PrimerAPIConfigurationModule.decodedJWTToken?.reference) ] if let expirationDate = PrimerAPIConfigurationModule.decodedJWTToken?.expiresAt { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .short - sharableVoucherValues.append(VoucherValue(id: "expirationDate", description: Strings.VoucherInfoPaymentView.expiresAt, value: formatter.string(from: expirationDate))) + sharableVoucherValues.append(VoucherValue(id: "expirationDate", + description: Strings.VoucherInfoPaymentView.expiresAt, + value: formatter.string(from: expirationDate))) } for voucherValue in sharableVoucherValues { diff --git a/Sources/PrimerSDK/Classes/Data Models/_PaymentAPIModel.swift b/Sources/PrimerSDK/Classes/Data Models/_PaymentAPIModel.swift index 1c3bd87fca..73bab5b625 100644 --- a/Sources/PrimerSDK/Classes/Data Models/_PaymentAPIModel.swift +++ b/Sources/PrimerSDK/Classes/Data Models/_PaymentAPIModel.swift @@ -12,31 +12,37 @@ import Foundation extension PrimerClientSession { internal convenience init(from apiConfiguration: PrimerAPIConfiguration) { - let lineItems = apiConfiguration.clientSession?.order?.lineItems?.compactMap { PrimerLineItem(itemId: $0.itemId, - itemDescription: $0.description, - amount: $0.amount, - discountAmount: $0.discountAmount, - quantity: $0.quantity, - taxCode: apiConfiguration.clientSession?.customer?.taxId, - taxAmount: apiConfiguration.clientSession?.order?.totalTaxAmount) } + let lineItems = apiConfiguration.clientSession?.order?.lineItems? + .compactMap { PrimerLineItem(itemId: $0.itemId, + itemDescription: $0.description, + amount: $0.amount, + discountAmount: $0.discountAmount, + quantity: $0.quantity, + taxCode: apiConfiguration.clientSession?.customer?.taxId, + taxAmount: apiConfiguration.clientSession?.order?.totalTaxAmount) } let orderDetails = PrimerOrder(countryCode: apiConfiguration.clientSession?.order?.countryCode?.rawValue) - let billingAddress = PrimerAddress(firstName: apiConfiguration.clientSession?.customer?.billingAddress?.firstName, - lastName: apiConfiguration.clientSession?.customer?.billingAddress?.lastName, - addressLine1: apiConfiguration.clientSession?.customer?.billingAddress?.addressLine1, - addressLine2: apiConfiguration.clientSession?.customer?.billingAddress?.addressLine2, - postalCode: apiConfiguration.clientSession?.customer?.billingAddress?.postalCode, city: apiConfiguration.clientSession?.customer?.billingAddress?.city, - state: apiConfiguration.clientSession?.customer?.billingAddress?.state, - countryCode: apiConfiguration.clientSession?.customer?.billingAddress?.countryCode?.rawValue) - - let shippingAddress = PrimerAddress(firstName: apiConfiguration.clientSession?.customer?.shippingAddress?.firstName, - lastName: apiConfiguration.clientSession?.customer?.shippingAddress?.lastName, - addressLine1: apiConfiguration.clientSession?.customer?.shippingAddress?.addressLine1, - addressLine2: apiConfiguration.clientSession?.customer?.shippingAddress?.addressLine2, - postalCode: apiConfiguration.clientSession?.customer?.shippingAddress?.postalCode, city: apiConfiguration.clientSession?.customer?.shippingAddress?.city, - state: apiConfiguration.clientSession?.customer?.shippingAddress?.state, - countryCode: apiConfiguration.clientSession?.customer?.shippingAddress?.countryCode?.rawValue) + let billing = apiConfiguration.clientSession?.customer?.billingAddress + let shipping = apiConfiguration.clientSession?.customer?.shippingAddress + + let billingAddress = PrimerAddress(firstName: billing?.firstName, + lastName: billing?.lastName, + addressLine1: billing?.addressLine1, + addressLine2: billing?.addressLine2, + postalCode: billing?.postalCode, + city: billing?.city, + state: billing?.state, + countryCode: billing?.countryCode?.rawValue) + + let shippingAddress = PrimerAddress(firstName: shipping?.firstName, + lastName: shipping?.lastName, + addressLine1: shipping?.addressLine1, + addressLine2: shipping?.addressLine2, + postalCode: shipping?.postalCode, + city: shipping?.city, + state: shipping?.state, + countryCode: shipping?.countryCode?.rawValue) let customer = PrimerCustomer(emailAddress: apiConfiguration.clientSession?.customer?.emailAddress, mobileNumber: apiConfiguration.clientSession?.customer?.mobileNumber, diff --git a/Sources/PrimerSDK/Classes/Error Handler/Primer3DSErrorContainer.swift b/Sources/PrimerSDK/Classes/Error Handler/Primer3DSErrorContainer.swift index f914f67a91..8d3b617e73 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/Primer3DSErrorContainer.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/Primer3DSErrorContainer.swift @@ -24,9 +24,16 @@ public enum Primer3DSErrorContainer: PrimerErrorProtocol { typealias K = AnalyticsContextKeys case missingSdkDependency(userInfo: [String: String]?, diagnosticsId: String) - case invalid3DSSdkVersion(userInfo: [String: String]?, diagnosticsId: String, invalidVersion: String?, validVersion: String) + case invalid3DSSdkVersion(userInfo: [String: String]?, + diagnosticsId: String, + invalidVersion: String?, + validVersion: String) case missing3DSConfiguration(userInfo: [String: String]?, diagnosticsId: String, missingKey: String) - case primer3DSSdkError(paymentMethodType: String?, userInfo: [String: String]?, diagnosticsId: String, initProtocolVersion: String?, errorInfo: Primer3DSErrorInfo) + case primer3DSSdkError(paymentMethodType: String?, + userInfo: [String: String]?, + diagnosticsId: String, + initProtocolVersion: String?, + errorInfo: Primer3DSErrorInfo) case underlyingError(userInfo: [String: String]?, diagnosticsId: String, error: Error) public var errorId: String { diff --git a/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift b/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift index bc65bef448..cfdd5f4097 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/PrimerError.swift @@ -37,16 +37,28 @@ public enum PrimerError: PrimerErrorProtocol { case missingPrimerDelegate(userInfo: [String: String]?, diagnosticsId: String) case missingPrimerCheckoutComponentsDelegate(userInfo: [String: String]?, diagnosticsId: String) case misconfiguredPaymentMethods(userInfo: [String: String]?, diagnosticsId: String) - case missingPrimerInputElement(inputElementType: PrimerInputElementType, userInfo: [String: String]?, diagnosticsId: String) + case missingPrimerInputElement(inputElementType: PrimerInputElementType, + userInfo: [String: String]?, + diagnosticsId: String) case cancelled(paymentMethodType: String, userInfo: [String: String]?, diagnosticsId: String) case failedToCreateSession(error: Error?, userInfo: [String: String]?, diagnosticsId: String) case failedOnWebViewFlow(error: Error?, userInfo: [String: String]?, diagnosticsId: String) case failedToImport3DS(userInfo: [String: String]?, diagnosticsId: String) - case failedToPerform3DS(paymentMethodType: String, error: Error?, userInfo: [String: String]?, diagnosticsId: String) + case failedToPerform3DS(paymentMethodType: String, + error: Error?, + userInfo: [String: String]?, + diagnosticsId: String) case invalidUrl(url: String?, userInfo: [String: String]?, diagnosticsId: String) case invalid3DSKey(userInfo: [String: String]?, diagnosticsId: String) - case invalidArchitecture(description: String, recoverSuggestion: String?, userInfo: [String: String]?, diagnosticsId: String) - case invalidClientSessionValue(name: String, value: String?, allowedValue: String?, userInfo: [String: String]?, diagnosticsId: String) + case invalidArchitecture(description: String, + recoverSuggestion: String?, + userInfo: [String: String]?, + diagnosticsId: String) + case invalidClientSessionValue(name: String, + value: String?, + allowedValue: String?, + userInfo: [String: String]?, + diagnosticsId: String) case invalidMerchantIdentifier(merchantIdentifier: String?, userInfo: [String: String]?, diagnosticsId: String) case invalidUrlScheme(urlScheme: String?, userInfo: [String: String]?, diagnosticsId: String) case invalidSetting(name: String, value: String?, userInfo: [String: String]?, diagnosticsId: String) @@ -55,15 +67,27 @@ public enum PrimerError: PrimerErrorProtocol { case unableToPresentPaymentMethod(paymentMethodType: String, userInfo: [String: String]?, diagnosticsId: String) case unsupportedIntent(intent: PrimerSessionIntent, userInfo: [String: String]?, diagnosticsId: String) case unsupportedPaymentMethod(paymentMethodType: String, userInfo: [String: String]?, diagnosticsId: String) - case unsupportedPaymentMethodForManager(paymentMethodType: String, category: String, userInfo: [String: String]?, diagnosticsId: String) + case unsupportedPaymentMethodForManager(paymentMethodType: String, + category: String, + userInfo: [String: String]?, + diagnosticsId: String) case underlyingErrors(errors: [Error], userInfo: [String: String]?, diagnosticsId: String) case missingSDK(paymentMethodType: String, sdkName: String, userInfo: [String: String]?, diagnosticsId: String) case merchantError(message: String, userInfo: [String: String]?, diagnosticsId: String) - case paymentFailed(paymentMethodType: String, description: String, userInfo: [String: String]?, diagnosticsId: String) - case failedToProcessPayment(paymentMethodType: String?, paymentId: String, status: String, userInfo: [String: String]?, diagnosticsId: String) + case paymentFailed(paymentMethodType: String, + description: String, + userInfo: [String: String]?, + diagnosticsId: String) + case failedToProcessPayment(paymentMethodType: String?, + paymentId: String, + status: String, + userInfo: [String: String]?, + diagnosticsId: String) case applePayTimedOut(userInfo: [String: String]?, diagnosticsId: String) case sdkDismissed - case invalidVaultedPaymentMethodId(vaultedPaymentMethodId: String, userInfo: [String: String]?, diagnosticsId: String) + case invalidVaultedPaymentMethodId(vaultedPaymentMethodId: String, + userInfo: [String: String]?, + diagnosticsId: String) case nolError(code: String?, message: String?, userInfo: [String: String]?, diagnosticsId: String) case klarnaWrapperError(message: String?, userInfo: [String: String]?, diagnosticsId: String) case unableToPresentApplePay(userInfo: [String: String]?, diagnosticsId: String) @@ -401,7 +425,12 @@ public enum PrimerError: PrimerErrorProtocol { case .missingPrimerConfiguration: return "Check if you have an active internet connection." case .missingPrimerDelegate: - return "Primer's delegate has not been set. Ensure that you have added Primer.shared.delegate = self on the view controller you wish to present Primer's SDK." + let message = + """ + Primer's delegate has not been set. Ensure that you have added Primer.shared.delegate = self \ + on the view controller you wish to present Primer's SDK. +""" + return message case .missingPrimerCheckoutComponentsDelegate: let message = """ @@ -455,7 +484,11 @@ on your dashboard https://dashboard.primer.io/ case .unableToMakePaymentsOnProvidedNetworks: return nil case .unableToPresentPaymentMethod: - return "Check if all necessary values have been provided on your client session. You can find the necessary values on our documentation (website)." + let message = """ +Check if all necessary values have been provided on your client session.\ + You can find the necessary values on our documentation (website). +""" + return message case .unsupportedIntent(let intent, _, _): if intent == .checkout { return "Change the intent to .vault" @@ -487,7 +520,11 @@ on your dashboard https://dashboard.primer.io/ case .klarnaWrapperError: return nil case .unableToPresentApplePay: - return "PassKit was unable to present the Apple Pay UI. Check merchantIdentifier and other parameters are set correctly for the current environment." + let message = """ +PassKit was unable to present the Apple Pay UI. Check merchantIdentifier \ +and other parameters are set correctly for the current environment. +""" + return message case .unknown: return "Contact Primer and provide them diagnostics id \(self.diagnosticsId)" } diff --git a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift index 871d536634..cad06e1fa9 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift @@ -6,6 +6,10 @@ // // swiftlint:disable type_body_length +// swiftlint:disable file_length +// swiftlint:disable identifier_name +// swiftlint:disable function_body_length + import Foundation @@ -27,8 +31,10 @@ public enum PrimerValidationError: PrimerErrorProtocol, Encodable { case invalidPhoneNumberCountryCode(message: String, userInfo: [String: String]?, diagnosticsId: String) case invalidRetailer(message: String, userInfo: [String: String]?, diagnosticsId: String) case invalidRawData(userInfo: [String: String]?, diagnosticsId: String) - // swiftlint:disable:next identifier_name - case vaultedPaymentMethodAdditionalDataMismatch(paymentMethodType: String, validVaultedPaymentMethodAdditionalDataType: String, userInfo: [String: String]?, diagnosticsId: String) + case vaultedPaymentMethodAdditionalDataMismatch(paymentMethodType: String, + validVaultedPaymentMethodAdditionalDataType: String, + userInfo: [String: String]?, + diagnosticsId: String) case invalidOTPCode(message: String, userInfo: [String: String]?, diagnosticsId: String) case invalidAccountUniqueId(message: String, userInfo: [String: String]?, diagnosticsId: String) case invalidAccountRegistrationDate(message: String, userInfo: [String: String]?, diagnosticsId: String) @@ -189,7 +195,6 @@ public enum PrimerValidationError: PrimerErrorProtocol, Encodable { return "[\(errorId)] Raw data is not valid." case .invalidRetailer(let message, _, _): return "[\(errorId)] \(message)" - // swiftlint:disable:next identifier_name case .vaultedPaymentMethodAdditionalDataMismatch(let paymentMethodType, let validVaultedPaymentMethodAdditionalDataType, _, _): return "[\(errorId)] Vaulted payment method \(paymentMethodType) needs additional data of type \(validVaultedPaymentMethodAdditionalDataType)" case .invalidPhoneNumberCountryCode(message: let message, _, _): @@ -364,11 +369,17 @@ extension PrimerValidationError: Equatable { (.invalidState(let message1, let userInfo1, let id1), .invalidState(let message2, let userInfo2, let id2)), (.invalidCountry(let message1, let userInfo1, let id1), .invalidCountry(let message2, let userInfo2, let id2)), (.invalidPhoneNumber(let message1, let userInfo1, let id1), .invalidPhoneNumber(let message2, let userInfo2, let id2)), - (.invalidPhoneNumberCountryCode(let message1, let userInfo1, let id1), .invalidPhoneNumberCountryCode(let message2, let userInfo2, let id2)), + (.invalidPhoneNumberCountryCode(let message1, let userInfo1, let id1), + .invalidPhoneNumberCountryCode(let message2, let userInfo2, let id2)), (.invalidRetailer(let message1, let userInfo1, let id1), .invalidRetailer(let message2, let userInfo2, let id2)), (.invalidOTPCode(let message1, let userInfo1, let id1), .invalidOTPCode(let message2, let userInfo2, let id2)), (.invalidAccountUniqueId(let message1, let userInfo1, let id1), .invalidAccountUniqueId(let message2, let userInfo2, let id2)), - (.invalidAccountRegistrationDate(let message1, let userInfo1, let id1), .invalidAccountRegistrationDate(let message2, let userInfo2, let id2)), + (.invalidAccountRegistrationDate(let message1, + let userInfo1, + let id1), + .invalidAccountRegistrationDate(let message2, + let userInfo2, + let id2)), (.invalidAccountLastModified(let message1, let userInfo1, let id1), .invalidAccountLastModified(let message2, let userInfo2, let id2)), (.invalidCardType(let message1, let userInfo1, let id1), .invalidCardType(let message2, let userInfo2, let id2)): return message1 == message2 && userInfo1 == userInfo2 && id1 == id2 @@ -381,7 +392,8 @@ extension PrimerValidationError: Equatable { case (.vaultedPaymentMethodAdditionalDataMismatch(let type1, let validType1, let userInfo1, let id1), .vaultedPaymentMethodAdditionalDataMismatch(let type2, let validType2, let userInfo2, let id2)): return type1 == type2 && validType1 == validType2 && userInfo1 == userInfo2 && id1 == id2 - case (.invalidBankId(let bankId1, userInfo: let userInfo1, diagnosticsId: let id1), .invalidBankId(let bankId2, userInfo: let userInfo2, diagnosticsId: let id2)): + case (.invalidBankId(let bankId1, userInfo: let userInfo1, diagnosticsId: let id1), + .invalidBankId(let bankId2, userInfo: let userInfo2, diagnosticsId: let id2)): return bankId1 == bankId2 && userInfo1 == userInfo2 && id1 == id2 default: return false @@ -389,3 +401,6 @@ extension PrimerValidationError: Equatable { } } // swiftlint:enable type_body_length +// swiftlint:enable identifier_name +// swiftlint:enable function_body_length +// swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/AlertController.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/AlertController.swift index 8f409257b2..44fbab83df 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/AlertController.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/AlertController.swift @@ -11,7 +11,9 @@ internal class AlertController: UIAlertController { private lazy var alertWindow: UIWindow = { var window: UIWindow! - if let windowScene = UIApplication.shared.connectedScenes.filter({ $0.activationState == .foregroundActive }).first as? UIWindowScene { + if let windowScene = UIApplication.shared.connectedScenes + .filter({ $0.activationState == .foregroundActive }) + .first as? UIWindowScene { window = UIWindow(windowScene: windowScene) } else { // Not opted-in in UISceneDelegate diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift index f08d0f9f0e..d4719f99d4 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyDecodable.swift @@ -78,7 +78,8 @@ extension _AnyDecodable { } else if let dictionary = try? container.decode([String: AnyDecodable].self) { self.init(dictionary.mapValues { $0.value }) } else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyDecodable value cannot be decoded") + throw DecodingError.dataCorruptedError(in: container, + debugDescription: "AnyDecodable value cannot be decoded") } } } diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift index 0ef3e053f6..1149399e79 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/AnyEncodable.swift @@ -108,7 +108,8 @@ extension _AnyEncodable { case let encodable as Encodable: try encodable.encode(to: encoder) default: - let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "AnyEncodable value cannot be encoded") + let context = EncodingError.Context(codingPath: container.codingPath, + debugDescription: "AnyEncodable value cannot be encoded") throw EncodingError.invalidValue(value, context) } } @@ -139,7 +140,9 @@ extension _AnyEncodable { case "d": try container.encode(nsnumber.doubleValue) default: - let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "NSNumber cannot be encoded because its type is not handled") + let message = "NSNumber cannot be encoded because its type is not handled" + let context = EncodingError.Context(codingPath: container.codingPath, + debugDescription: message) throw EncodingError.invalidValue(nsnumber, context) } } diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/DataExtension.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/DataExtension.swift index 27e0c447db..75b6fd6912 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/DataExtension.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/DataExtension.swift @@ -11,7 +11,9 @@ internal extension Data { var prettyPrintedJSONString: NSString? { /// NSString gives us a nice sanitized debugDescription guard let object = try? JSONSerialization.jsonObject(with: self, options: []), let data = try? JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted]), - let prettyPrintedString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) else { return nil } + let prettyPrintedString = NSString(data: data, + encoding: String.Encoding.utf8.rawValue) + else { return nil } return prettyPrintedString } diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift index 1ac120add5..6e33846140 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/ImageFileProcessor.swift @@ -104,7 +104,10 @@ class ImageFileProcessor { } .done { imageFiles in for (index, paymentMethod) in (apiConfiguration.paymentMethods ?? []).enumerated() { - let paymentMethodImageFiles = imageFiles.filter { $0.fileName.contains(paymentMethod.type.lowercased().replacingOccurrences(of: "_", with: "-")) } + let paymentMethodImageFiles = imageFiles.filter { + $0.fileName.contains(paymentMethod.type.lowercased().replacingOccurrences(of: "_", + with: "-")) + } if paymentMethodImageFiles.isEmpty { continue } diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/PrimerButton.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/PrimerButton.swift index 31e09d0464..a0e9f4c52a 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/PrimerButton.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/PrimerButton.swift @@ -92,8 +92,20 @@ import UIKit activityIndicator.color = theme?.colorStates.color(for: .selected) ?? .white self.addSubview(activityIndicator) activityIndicator.translatesAutoresizingMaskIntoConstraints = false - let xCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: activityIndicator, attribute: .centerX, multiplier: 1, constant: 0) - let yCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: activityIndicator, attribute: .centerY, multiplier: 1, constant: 0) + let xCenterConstraint = NSLayoutConstraint(item: self, + attribute: .centerX, + relatedBy: .equal, + toItem: activityIndicator, + attribute: .centerX, + multiplier: 1, + constant: 0) + let yCenterConstraint = NSLayoutConstraint(item: self, + attribute: .centerY, + relatedBy: .equal, + toItem: activityIndicator, + attribute: .centerY, + multiplier: 1, + constant: 0) self.addConstraints([xCenterConstraint, yCenterConstraint]) return activityIndicator }() diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/StringExtension.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/StringExtension.swift index 238e83c936..f70126291e 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/StringExtension.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/StringExtension.swift @@ -149,23 +149,33 @@ internal extension String { let components = self.split(separator: ".") if components.count < 2 { return nil } let segment = String(components[1]).base64IOSFormat - guard !segment.isEmpty, let data = Data(base64Encoded: segment, options: .ignoreUnknownCharacters) else { return nil } + guard !segment.isEmpty, let data = Data(base64Encoded: segment, + options: .ignoreUnknownCharacters) + else { return nil } return try? JSONParser().parse(DecodedJWTToken.self, from: data) } private var base64IOSFormat: Self { - let str = self.replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/") + let str = self.replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") let offset = str.count % 4 guard offset != 0 else { return str } - return str.padding(toLength: str.count + 4 - offset, withPad: "=", startingAt: 0) + return str.padding(toLength: str.count + 4 - offset, + withPad: "=", startingAt: 0) } var base64RFC4648Format: Self { - let str = self.replacingOccurrences(of: "+", with: "-").replacingOccurrences(of: "/", with: "_").replacingOccurrences(of: "=", with: "") + let str = self.replacingOccurrences(of: "+", + with: "-") + .replacingOccurrences(of: "/", + with: "_") + .replacingOccurrences(of: "=", + with: "") return str } - func toDate(withFormat format: String = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", timeZone: TimeZone? = nil) -> Date? { + func toDate(withFormat format: String = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", + timeZone: TimeZone? = nil) -> Date? { let dateFormatter = DateFormatter() dateFormatter.dateFormat = format dateFormatter.locale = Locale(identifier: "en_US_POSIX") @@ -278,7 +288,10 @@ internal extension String { let sanitizedInput = self.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "-", with: "") let pattern = "^\\d{7,15}$" let regex = try? NSRegularExpression(pattern: pattern, options: []) - let matches = regex?.matches(in: sanitizedInput, options: [], range: NSRange(location: 0, length: sanitizedInput.count)) + let matches = regex?.matches(in: sanitizedInput, + options: [], + range: NSRange(location: 0, + length: sanitizedInput.count)) return matches?.count ?? 0 > 0 } diff --git a/Sources/PrimerSDK/Classes/Extensions & Utilities/UserAgent.swift b/Sources/PrimerSDK/Classes/Extensions & Utilities/UserAgent.swift index 187f318d43..890bf209b0 100644 --- a/Sources/PrimerSDK/Classes/Extensions & Utilities/UserAgent.swift +++ b/Sources/PrimerSDK/Classes/Extensions & Utilities/UserAgent.swift @@ -14,7 +14,10 @@ struct UserAgent { private static func darwinVersion() -> String { var sysinfo = utsname() uname(&sysinfo) - let darwinVersion = String(bytes: Data(bytes: &sysinfo.release, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters) + let darwinVersion = String(bytes: Data(bytes: &sysinfo.release, + count: Int(_SYS_NAMELEN)), + encoding: .ascii)! + .trimmingCharacters(in: .controlCharacters) return "Darwin/\(darwinVersion)" } // eg. CFNetwork/808.3 @@ -36,7 +39,10 @@ struct UserAgent { private static func deviceName() -> String { var sysinfo = utsname() uname(&sysinfo) - return String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters) + return String(bytes: Data(bytes: &sysinfo.machine, + count: Int(_SYS_NAMELEN)), + encoding: .ascii)! + .trimmingCharacters(in: .controlCharacters) } // eg. PrimerApp/1 private static func appNameAndVersion() -> String { diff --git a/Sources/PrimerSDK/Classes/Modules/Downloader.swift b/Sources/PrimerSDK/Classes/Modules/Downloader.swift index 51133bf0c5..8a7926960a 100644 --- a/Sources/PrimerSDK/Classes/Modules/Downloader.swift +++ b/Sources/PrimerSDK/Classes/Modules/Downloader.swift @@ -22,7 +22,7 @@ internal class File: LogReporter { var tmpFilename: String = self.fileName if let fileExtension = self.fileExtension { - tmpFilename = tmpFilename + "." + fileExtension + tmpFilename += "." + fileExtension } let fileLocalUrl = documentDirectoryUrl.appendingPathComponent(tmpFilename) @@ -52,7 +52,7 @@ internal class File: LogReporter { do { var tmpFilename: String = self.fileName if let fileExtension = self.fileExtension { - tmpFilename = tmpFilename + "." + fileExtension + tmpFilename += "." + fileExtension } let fileLocalUrl = documentDirectoryUrl diff --git a/Sources/PrimerSDK/Classes/Modules/ImageManager.swift b/Sources/PrimerSDK/Classes/Modules/ImageManager.swift index 1ced7cbd5a..aa23cf20a4 100644 --- a/Sources/PrimerSDK/Classes/Modules/ImageManager.swift +++ b/Sources/PrimerSDK/Classes/Modules/ImageManager.swift @@ -43,12 +43,14 @@ internal class ImageFile: File { } else if supportedPaymentMethodType.provider == paymentMethodType { tmpPaymentMethodFileNameFirstComponent = paymentMethodType } else if paymentMethodType.starts(with: "\(supportedPaymentMethodType.provider)_") { - tmpPaymentMethodFileNameFirstComponent = paymentMethodType.replacingOccurrences(of: "\(supportedPaymentMethodType.provider)_", with: "") + tmpPaymentMethodFileNameFirstComponent = paymentMethodType.replacingOccurrences(of: "\(supportedPaymentMethodType.provider)_", + with: "") } else { return nil } - tmpPaymentMethodFileNameFirstComponent = tmpPaymentMethodFileNameFirstComponent!.lowercased().replacingOccurrences(of: "_", with: "-") + tmpPaymentMethodFileNameFirstComponent = tmpPaymentMethodFileNameFirstComponent!.lowercased().replacingOccurrences(of: "_", + with: "-") switch assetType { case .logo: @@ -67,24 +69,42 @@ internal class ImageFile: File { let paymentMethodType = ImageFile.getPaymentMethodType(fromFileName: self.fileName) ?? self.fileName if self.fileName.contains("dark") == true { - if let paymentMethodLogoFileName = ImageFile.getBundledImageFileName(forPaymentMethodType: paymentMethodType, themeMode: .dark, assetType: .logo), - let image = UIImage(named: paymentMethodLogoFileName, in: Bundle.primerResources, compatibleWith: nil) { + if let paymentMethodLogoFileName = ImageFile.getBundledImageFileName(forPaymentMethodType: paymentMethodType, + themeMode: .dark, + assetType: .logo), + let image = UIImage(named: paymentMethodLogoFileName, + in: Bundle.primerResources, + compatibleWith: nil) { return image - } else if let image = UIImage(named: self.fileName, in: Bundle.primerResources, compatibleWith: nil) { + } else if let image = UIImage(named: self.fileName, + in: Bundle.primerResources, + compatibleWith: nil) { return image } } else if self.fileName.contains("light") == true { - if let paymentMethodLogoFileName = ImageFile.getBundledImageFileName(forPaymentMethodType: paymentMethodType, themeMode: .light, assetType: .logo), - let image = UIImage(named: paymentMethodLogoFileName, in: Bundle.primerResources, compatibleWith: nil) { + if let paymentMethodLogoFileName = ImageFile.getBundledImageFileName(forPaymentMethodType: paymentMethodType, + themeMode: .light, + assetType: .logo), + let image = UIImage(named: paymentMethodLogoFileName, + in: Bundle.primerResources, + compatibleWith: nil) { return image - } else if let image = UIImage(named: self.fileName, in: Bundle.primerResources, compatibleWith: nil) { + } else if let image = UIImage(named: self.fileName, + in: Bundle.primerResources, + compatibleWith: nil) { return image } } else if self.fileName.contains("colored") == true { - if let paymentMethodLogoFileName = ImageFile.getBundledImageFileName(forPaymentMethodType: paymentMethodType, themeMode: .colored, assetType: .logo), - let image = UIImage(named: paymentMethodLogoFileName, in: Bundle.primerResources, compatibleWith: nil) { + if let paymentMethodLogoFileName = ImageFile.getBundledImageFileName(forPaymentMethodType: paymentMethodType, + themeMode: .colored, + assetType: .logo), + let image = UIImage(named: paymentMethodLogoFileName, + in: Bundle.primerResources, + compatibleWith: nil) { return image - } else if let image = UIImage(named: self.fileName, in: Bundle.primerResources, compatibleWith: nil) { + } else if let image = UIImage(named: self.fileName, + in: Bundle.primerResources, + compatibleWith: nil) { return image } } @@ -131,7 +151,9 @@ internal class ImageManager: LogReporter { } if !errors.isEmpty, errors.count == responses.count { - let err = InternalError.underlyingErrors(errors: errors, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = InternalError.underlyingErrors(errors: errors, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } else { @@ -162,11 +184,10 @@ internal class ImageManager: LogReporter { id: timingEventId ) - /// First try to download the image with the relevant caching policy. - /// Therefore, if the image is cached, it will be returned. - /// If the image download fails, check for a bundled image with the filename, - /// if it exists continue. - + // First try to download the image with the relevant caching policy. + // Therefore, if the image is cached, it will be returned. + // If the image download fails, check for a bundled image with the filename, + // if it exists continue. firstly { downloader.download(file: file) } @@ -176,7 +197,8 @@ internal class ImageManager: LogReporter { seal.fulfill(imageFile) } else { - let err = InternalError.failedToDecode(message: "image", userInfo: nil, diagnosticsId: UUID().uuidString) + let err = InternalError.failedToDecode(message: "image", userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -220,7 +242,9 @@ internal class ImageManager: LogReporter { } static func clean() { - guard let documentDirectoryUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } + guard let documentDirectoryUrl = FileManager.default.urls(for: .documentDirectory, + in: .userDomainMask).first + else { return } let documentsPath = documentDirectoryUrl.path do { diff --git a/Sources/PrimerSDK/Classes/Modules/PollingModule.swift b/Sources/PrimerSDK/Classes/Modules/PollingModule.swift index 1cdadaf8b7..5191c47e90 100644 --- a/Sources/PrimerSDK/Classes/Modules/PollingModule.swift +++ b/Sources/PrimerSDK/Classes/Modules/PollingModule.swift @@ -93,7 +93,8 @@ class PollingModule: Module { let err = PrimerError.generic(message: "Should never end up here", userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) } case .failure(let err): diff --git a/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift b/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift index f25f6727f9..bdd5b95a0d 100644 --- a/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift +++ b/Sources/PrimerSDK/Classes/Modules/UserInterfaceModule.swift @@ -47,16 +47,22 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { switch internaPaymentMethodType { case .adyenBlik: - return UIScreen.isDarkModeEnabled ? logo : UIImage(named: "blik-logo-light", in: Bundle.primerResources, compatibleWith: nil) + return UIScreen.isDarkModeEnabled ? logo : UIImage(named: "blik-logo-light", + in: Bundle.primerResources, + compatibleWith: nil) case .adyenMultibanco: - return UIScreen.isDarkModeEnabled ? logo : UIImage(named: "multibanco-logo-light", in: Bundle.primerResources, compatibleWith: nil) + return UIScreen.isDarkModeEnabled ? logo : UIImage(named: "multibanco-logo-light", + in: Bundle.primerResources, + compatibleWith: nil) default: return logo } } var icon: UIImage? { - var fileName = paymentMethodTokenizationViewModel.config.type.lowercased().replacingOccurrences(of: "_", with: "-") + var fileName = paymentMethodTokenizationViewModel.config.type + .lowercased().replacingOccurrences(of: "_", + with: "-") fileName += "-icon" switch self.themeMode { @@ -100,7 +106,9 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { } var localDisplayMetadata: PrimerPaymentMethod.DisplayMetadata? { - guard let internaPaymentMethodType = PrimerPaymentMethodType(rawValue: self.paymentMethodTokenizationViewModel.config.type) else { return nil } + let type = self.paymentMethodTokenizationViewModel.config.type + guard let internaPaymentMethodType = PrimerPaymentMethodType(rawValue: type) + else { return nil } switch internaPaymentMethodType { case .adyenAlipay: @@ -758,8 +766,13 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { return Strings.CardFormView.additionalFeesTitle default: guard let currency = AppState.current.currency else { return nil } - guard let availablePaymentMethods = PrimerAPIConfigurationModule.apiConfiguration?.paymentMethods, !availablePaymentMethods.isEmpty else { return nil } - guard let str = availablePaymentMethods.filter({ $0.type == paymentMethodTokenizationViewModel.config.type }).first?.surcharge?.toCurrencyString(currency: currency) else { return nil } + guard let availablePaymentMethods = PrimerAPIConfigurationModule.apiConfiguration?.paymentMethods, + !availablePaymentMethods.isEmpty + else { return nil } + guard let str = availablePaymentMethods + .filter({ $0.type == paymentMethodTokenizationViewModel.config.type }) + .first?.surcharge?.toCurrencyString(currency: currency) + else { return nil } return "+\(str)" } } @@ -782,7 +795,8 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { // for the a Payment Method Instrument object out of `/configuration` API response // // if let metadataButtonText = metadataButtonText { return metadataButtonText } - return PrimerInternal.shared.intent == .vault ? Strings.VaultPaymentMethodViewContent.addCard : Strings.PaymentButton.payWithCard + return PrimerInternal.shared.intent == .vault ? + Strings.VaultPaymentMethodViewContent.addCard : Strings.PaymentButton.payWithCard case PrimerPaymentMethodType.twoCtwoP.rawValue: return Strings.PaymentButton.payInInstallments @@ -919,7 +933,8 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { paymentMethodButton.clipsToBounds = true let imagePadding: CGFloat = 20 let leftPadding = UILocalizableUtil.isRightToLeftLocale ? imagePadding : 0 - let defaultRightPadding = customPaddingSettingsCard.contains(paymentMethodTokenizationViewModel.config.type) ? imagePadding : 0 + let type = paymentMethodTokenizationViewModel.config.type + let defaultRightPadding = customPaddingSettingsCard.contains(type) ? imagePadding : 0 let rightPadding = UILocalizableUtil.isRightToLeftLocale ? 0 : defaultRightPadding paymentMethodButton.imageEdgeInsets = UIEdgeInsets(top: 8, left: leftPadding, @@ -1006,7 +1021,8 @@ class UserInterfaceModule: NSObject, UserInterfaceModuleProtocol { submitButton.accessibilityIdentifier = "submit_btn" submitButton.isEnabled = isEnabled submitButton.setTitle(titleText, for: .normal) - submitButton.backgroundColor = isEnabled ? theme.mainButton.color(for: .enabled) : theme.mainButton.color(for: .disabled) + let colorState: ColorState = isEnabled ? .enabled : .disabled + submitButton.backgroundColor = theme.mainButton.color(for: colorState) submitButton.setTitleColor(theme.mainButton.text.color, for: .normal) submitButton.layer.cornerRadius = 4 submitButton.clipsToBounds = true diff --git a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerInputElements.swift b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerInputElements.swift index 84c9d1ac9c..bf0ba876c5 100644 --- a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerInputElements.swift +++ b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerInputElements.swift @@ -21,7 +21,8 @@ public class PrimerInputElementDelegateContainer { public class PrimerInputTextField: UITextField, PrimerHeadlessUniversalCheckoutInputElement { public weak var inputElementDelegate: PrimerInputElementDelegate! { didSet { - self.checkoutModulesTextFieldDelegate = PrimerHeadlessUniversalCheckout.Delegate(inputElement: self, inputElementDelegate: inputElementDelegate) + self.checkoutModulesTextFieldDelegate = PrimerHeadlessUniversalCheckout.Delegate(inputElement: self, + inputElementDelegate: inputElementDelegate) self.delegate = self.checkoutModulesTextFieldDelegate } } diff --git a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift index 2121791a36..a795ff0ed9 100644 --- a/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift +++ b/Sources/PrimerSDK/Classes/PCI/Checkout Components/PrimerRawCardDataRedirectTokenizationBuilder.swift @@ -104,7 +104,8 @@ class PrimerBancontactRawCardDataRedirectTokenizationBuilder: PrimerRawDataToken guard let paymentMethod = PrimerPaymentMethod.getPaymentMethod(withType: paymentMethodType), let configId = AppState.current.apiConfiguration?.getConfigId(for: paymentMethod.type) else { - let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.unsupportedPaymentMethod(paymentMethodType: paymentMethodType, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -113,7 +114,9 @@ class PrimerBancontactRawCardDataRedirectTokenizationBuilder: PrimerRawDataToken guard let rawData = data as? PrimerCardData, (rawData.expiryDate.split(separator: "/")).count == 2 else { - let err = PrimerError.invalidValue(key: "rawData", value: nil, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "rawData", value: nil, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -122,9 +125,10 @@ class PrimerBancontactRawCardDataRedirectTokenizationBuilder: PrimerRawDataToken let expiryMonth = String((rawData.expiryDate.split(separator: "/"))[0]) let expiryYear = String((rawData.expiryDate.split(separator: "/"))[1]) + let number = (PrimerInputElementType.cardNumber.clearFormatting(value: rawData.cardNumber) as? String) ?? rawData.cardNumber let paymentInstrument = CardOffSessionPaymentInstrument(paymentMethodConfigId: configId, paymentMethodType: paymentMethodType, - number: (PrimerInputElementType.cardNumber.clearFormatting(value: rawData.cardNumber) as? String) ?? rawData.cardNumber, + number: number, expirationMonth: expiryMonth, expirationYear: expiryYear, cardholderName: rawData.cardholderName ?? "") diff --git a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift index 89384a6c59..f055a42bd3 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift @@ -41,13 +41,18 @@ enum PrimerAPI: Endpoint, Equatable { } case redirect(clientToken: DecodedJWTToken, url: URL) - case exchangePaymentMethodToken(clientToken: DecodedJWTToken, vaultedPaymentMethodId: String, vaultedPaymentMethodAdditionalData: PrimerVaultedPaymentMethodAdditionalData?) + case exchangePaymentMethodToken(clientToken: DecodedJWTToken, + vaultedPaymentMethodId: String, + vaultedPaymentMethodAdditionalData: PrimerVaultedPaymentMethodAdditionalData?) case fetchConfiguration(clientToken: DecodedJWTToken, requestParameters: Request.URLParameters.Configuration?) case fetchVaultedPaymentMethods(clientToken: DecodedJWTToken) case deleteVaultedPaymentMethod(clientToken: DecodedJWTToken, id: String) - case createPayPalOrderSession(clientToken: DecodedJWTToken, payPalCreateOrderRequest: Request.Body.PayPal.CreateOrder) - case createPayPalBillingAgreementSession(clientToken: DecodedJWTToken, payPalCreateBillingAgreementRequest: Request.Body.PayPal.CreateBillingAgreement) - case confirmPayPalBillingAgreement(clientToken: DecodedJWTToken, payPalConfirmBillingAgreementRequest: Request.Body.PayPal.ConfirmBillingAgreement) + case createPayPalOrderSession(clientToken: DecodedJWTToken, + payPalCreateOrderRequest: Request.Body.PayPal.CreateOrder) + case createPayPalBillingAgreementSession(clientToken: DecodedJWTToken, + payPalCreateBillingAgreementRequest: Request.Body.PayPal.CreateBillingAgreement) + case confirmPayPalBillingAgreement(clientToken: DecodedJWTToken, + payPalConfirmBillingAgreementRequest: Request.Body.PayPal.ConfirmBillingAgreement) case createKlarnaPaymentSession(clientToken: DecodedJWTToken, klarnaCreatePaymentSessionAPIRequest: Request.Body.Klarna.CreatePaymentSession) case createKlarnaCustomerToken(clientToken: DecodedJWTToken, klarnaCreateCustomerTokenAPIRequest: Request.Body.Klarna.CreateCustomerToken) case finalizeKlarnaPaymentSession(clientToken: DecodedJWTToken, klarnaFinalizePaymentSessionRequest: Request.Body.Klarna.FinalizePaymentSession) @@ -58,7 +63,9 @@ enum PrimerAPI: Endpoint, Equatable { case requestPrimerConfigurationWithActions(clientToken: DecodedJWTToken, request: ClientSessionUpdateRequest) // 3DS - case begin3DSRemoteAuth(clientToken: DecodedJWTToken, paymentMethodTokenData: PrimerPaymentMethodTokenData, threeDSecureBeginAuthRequest: ThreeDS.BeginAuthRequest) + case begin3DSRemoteAuth(clientToken: DecodedJWTToken, + paymentMethodTokenData: PrimerPaymentMethodTokenData, + threeDSecureBeginAuthRequest: ThreeDS.BeginAuthRequest) case continue3DSRemoteAuth(clientToken: DecodedJWTToken, threeDSTokenId: String, continueInfo: ThreeDS.ContinueInfo) // Generic diff --git a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift index 1e13865a43..a56f58baad 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/Network/URLSessionStack.swift @@ -124,7 +124,8 @@ internal class URLSessionStack: NetworkService, LogReporter { let err = InternalError.underlyingErrors(errors: [error], userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) DispatchQueue.main.async { completion(.failure(err)) } return @@ -165,7 +166,8 @@ internal class URLSessionStack: NetworkService, LogReporter { logger.debug(message: "Analytics event sent") } else if !data.isEmpty { let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) - let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject as Any, options: .prettyPrinted) + let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject as Any, + options: .prettyPrinted) var jsonStr: String? if jsonData != nil { jsonStr = String(data: jsonData!, encoding: .utf8 ) @@ -196,12 +198,16 @@ internal class URLSessionStack: NetworkService, LogReporter { DispatchQueue.main.async { completion(.success(result)) } } } catch { - if let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments), let jsonDic = json as? [String: Any?], + if let json = try? JSONSerialization.jsonObject(with: data, + options: .allowFragments), + let jsonDic = json as? [String: Any?], let primerErrorJSON = jsonDic["error"] as? [String: Any], - let primerErrorObject = try? JSONSerialization.data(withJSONObject: primerErrorJSON, options: .fragmentsAllowed), + let primerErrorObject = try? JSONSerialization.data(withJSONObject: primerErrorJSON, + options: .fragmentsAllowed), let statusCode = (response as? HTTPURLResponse)?.statusCode { - let primerErrorResponse = try? self.parser.parse(PrimerServerErrorResponse.self, from: primerErrorObject) + let primerErrorResponse = try? self.parser.parse(PrimerServerErrorResponse.self, + from: primerErrorObject) if self.shouldReportNetworkEvents(for: endpoint) { resEventProperties?.errorBody = "\(primerErrorJSON)" diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift index bf4457cc07..67d38ef0df 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift @@ -74,8 +74,11 @@ class CardFormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewM } var isShowingBillingAddressFieldsRequired: Bool { - guard let billingAddressModule = PrimerAPIConfigurationModule.apiConfiguration?.checkoutModules?.filter({ $0.type == "BILLING_ADDRESS" }).first else { return false } - return (billingAddressModule.options as? PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions)?.postalCode == true + guard let billingAddressModule = PrimerAPIConfigurationModule.apiConfiguration?.checkoutModules? + .filter({ $0.type == "BILLING_ADDRESS" }) + .first else { return false } + let options = (billingAddressModule.options as? PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions) + return options?.postalCode == true } internal lazy var countrySelectorViewController: CountrySelectorViewController = { @@ -245,7 +248,9 @@ class CardFormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewM // MARK: All billing address fields internal var billingAddressCheckoutModuleOptions: PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions? { - return PrimerAPIConfigurationModule.apiConfiguration?.checkoutModules?.filter({ $0.type == "BILLING_ADDRESS" }).first?.options as? PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions + return PrimerAPIConfigurationModule.apiConfiguration?.checkoutModules? + .filter({ $0.type == "BILLING_ADDRESS" }) + .first?.options as? PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions } internal var billingAddressFields: [[BillingAddressField]] { @@ -604,7 +609,8 @@ class CardFormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewM let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -612,7 +618,8 @@ class CardFormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewM let err = PrimerError.invalidValue(key: "resumeToken", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -751,7 +758,8 @@ extension CardFormPaymentMethodTokenizationViewModel: InternalCardComponentsMana let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, err) } @@ -761,7 +769,8 @@ extension CardFormPaymentMethodTokenizationViewModel: InternalCardComponentsMana let err = PrimerError.underlyingErrors(errors: errors, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) self.cardComponentsManagerTokenizationCompletion?(nil, err) self.cardComponentsManagerTokenizationCompletion = nil @@ -802,21 +811,29 @@ extension CardFormPaymentMethodTokenizationViewModel: InternalCardComponentsMana } else if primerTextFieldView is PrimerCardholderNameFieldView, !primerTextFieldView.isEmpty { cardholderNameContainerView?.errorText = Strings.CardFormView.Cardholder.invalidErrorMessage } else if primerTextFieldView is PrimerPostalCodeFieldView { - postalCodeContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.PostalCode.isRequiredErrorMessage : Strings.CardFormView.PostalCode.invalidErrorMessage + postalCodeContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.PostalCode.isRequiredErrorMessage : Strings.CardFormView.PostalCode.invalidErrorMessage } else if primerTextFieldView is PrimerCountryFieldView { - countryFieldContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.CountryCode.isRequiredErrorMessage : Strings.CardFormView.CountryCode.invalidErrorMessage + countryFieldContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.CountryCode.isRequiredErrorMessage : Strings.CardFormView.CountryCode.invalidErrorMessage } else if primerTextFieldView is PrimerFirstNameFieldView { - firstNameContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.FirstName.isRequiredErrorMessage : Strings.CardFormView.FirstName.invalidErrorMessage + firstNameContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.FirstName.isRequiredErrorMessage : Strings.CardFormView.FirstName.invalidErrorMessage } else if primerTextFieldView is PrimerLastNameFieldView { - lastNameContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.LastName.isRequiredErrorMessage : Strings.CardFormView.LastName.invalidErrorMessage + lastNameContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.LastName.isRequiredErrorMessage : Strings.CardFormView.LastName.invalidErrorMessage } else if primerTextFieldView is PrimerCityFieldView { - cityContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.City.isRequiredErrorMessage : Strings.CardFormView.City.invalidErrorMessage + cityContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.City.isRequiredErrorMessage : Strings.CardFormView.City.invalidErrorMessage } else if primerTextFieldView is PrimerStateFieldView { - stateContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.State.isRequiredErrorMessage : Strings.CardFormView.State.invalidErrorMessage + stateContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.State.isRequiredErrorMessage : Strings.CardFormView.State.invalidErrorMessage } else if primerTextFieldView is PrimerAddressLine1FieldView { - addressLine1ContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.AddressLine1.isRequiredErrorMessage : Strings.CardFormView.AddressLine1.invalidErrorMessage + addressLine1ContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.AddressLine1.isRequiredErrorMessage : Strings.CardFormView.AddressLine1.invalidErrorMessage } else if primerTextFieldView is PrimerAddressLine2FieldView { - addressLine2ContainerView.errorText = primerTextFieldView.isEmpty ? Strings.CardFormView.AddressLine2.isRequiredErrorMessage : Strings.CardFormView.AddressLine2.invalidErrorMessage + addressLine2ContainerView.errorText = primerTextFieldView.isEmpty ? + Strings.CardFormView.AddressLine2.isRequiredErrorMessage : Strings.CardFormView.AddressLine2.invalidErrorMessage } } else { // We don't know for sure if the text is valid @@ -893,7 +910,9 @@ extension CardFormPaymentMethodTokenizationViewModel: PrimerTextFieldViewDelegat var network = self.cardNetwork?.rawValue.uppercased() let clientSessionActionsModule: ClientSessionActionsProtocol = ClientSessionActionsModule() - if let cardNetwork = cardNetwork, cardNetwork != .unknown, cardNumberContainerView.rightImage2 != cardNetwork.icon { + if let cardNetwork = cardNetwork, + cardNetwork != .unknown, + cardNumberContainerView.rightImage2 != cardNetwork.icon { if network == nil || network == "UNKNOWN" { network = "OTHER" } diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/Fields/CardholderNameField.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/Fields/CardholderNameField.swift index 817e64a216..c9a90b02bf 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/Fields/CardholderNameField.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/Fields/CardholderNameField.swift @@ -37,7 +37,8 @@ extension PrimerCardholderNameField { internal static var isCardholderNameFieldEnabled: Bool { let cardInfoOptions = PrimerAPIConfigurationModule.apiConfiguration?.checkoutModules? - .first(where: { $0.type == "CARD_INFORMATION" })?.options as? PrimerAPIConfiguration.CheckoutModule.CardInformationOptions + .first(where: { $0.type == "CARD_INFORMATION" })? + .options as? PrimerAPIConfiguration.CheckoutModule.CardInformationOptions // swiftlint:disable:next identifier_name if let isCardHolderNameCheckoutModuleOptionEnabled = cardInfoOptions?.cardHolderName { return isCardHolderNameCheckoutModuleOptionEnabled diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift index a7058f6139..d5240983b0 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel+FormViews.swift @@ -14,7 +14,8 @@ extension FormPaymentMethodTokenizationViewModel { // MARK: Input view func makeInputViews() -> [Input] { - guard let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type), inputPaymentMethodTypes.contains(paymentMethodType) else { return [] } + guard let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type), + inputPaymentMethodTypes.contains(paymentMethodType) else { return [] } switch paymentMethodType { case .adyenBlik: @@ -65,7 +66,9 @@ extension FormPaymentMethodTokenizationViewModel { dueAtContainerStackView.axis = .horizontal dueAtContainerStackView.spacing = 8.0 - let calendarImage = UIImage(named: "calendar", in: Bundle.primerResources, compatibleWith: nil)?.withRenderingMode(.alwaysTemplate) + let calendarImage = UIImage(named: "calendar", + in: Bundle.primerResources, + compatibleWith: nil)?.withRenderingMode(.alwaysTemplate) let calendarImageView = UIImageView(image: calendarImage) calendarImageView.tintColor = .gray600 calendarImageView.clipsToBounds = true @@ -92,15 +95,16 @@ extension FormPaymentMethodTokenizationViewModel { } // Account number + let spacing = PrimerDimensions.StackViewSpacing.default let accountNumberInfoContainerStackView = PrimerStackView() accountNumberInfoContainerStackView.axis = .vertical accountNumberInfoContainerStackView.spacing = 12.0 accountNumberInfoContainerStackView.addBackground(color: .gray100) - accountNumberInfoContainerStackView.layoutMargins = UIEdgeInsets(top: PrimerDimensions.StackViewSpacing.default, - left: PrimerDimensions.StackViewSpacing.default, - bottom: PrimerDimensions.StackViewSpacing.default, - right: PrimerDimensions.StackViewSpacing.default) + accountNumberInfoContainerStackView.layoutMargins = UIEdgeInsets(top: spacing, + left: spacing, + bottom: spacing, + right: spacing) accountNumberInfoContainerStackView.isLayoutMarginsRelativeArrangement = true accountNumberInfoContainerStackView.layer.cornerRadius = PrimerDimensions.cornerRadius @@ -116,10 +120,10 @@ extension FormPaymentMethodTokenizationViewModel { accountNumberStackView.spacing = 12.0 accountNumberStackView.heightAnchor.constraint(equalToConstant: 56.0).isActive = true accountNumberStackView.addBackground(color: .white) - accountNumberStackView.layoutMargins = UIEdgeInsets(top: PrimerDimensions.StackViewSpacing.default, - left: PrimerDimensions.StackViewSpacing.default, - bottom: PrimerDimensions.StackViewSpacing.default, - right: PrimerDimensions.StackViewSpacing.default) + accountNumberStackView.layoutMargins = UIEdgeInsets(top: spacing, + left: spacing, + bottom: spacing, + right: spacing) accountNumberStackView.layer.cornerRadius = PrimerDimensions.cornerRadius / 2 accountNumberStackView.layer.borderColor = UIColor.gray200.cgColor accountNumberStackView.layer.borderWidth = 2.0 @@ -218,7 +222,9 @@ extension FormPaymentMethodTokenizationViewModel { expiresAtContainerStackView.axis = .horizontal expiresAtContainerStackView.spacing = 8.0 - let calendarImage = UIImage(named: "calendar", in: Bundle.primerResources, compatibleWith: nil)?.withRenderingMode(.alwaysTemplate) + let calendarImage = UIImage(named: "calendar", + in: Bundle.primerResources, + compatibleWith: nil)?.withRenderingMode(.alwaysTemplate) let calendarImageView = UIImageView(image: calendarImage) calendarImageView.tintColor = .gray600 calendarImageView.clipsToBounds = true @@ -372,21 +378,27 @@ extension FormPaymentMethodTokenizationViewModel { if shouldCompletePaymentExternally { guard let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type), - let message = needingExternalCompletionPaymentMethodDictionary.first(where: { $0.key == paymentMethodType })?.value else { + let message = needingExternalCompletionPaymentMethodDictionary + .first(where: { $0.key == paymentMethodType })? + .value + else { return Promise() } let infoView = makePaymentPendingInfoView(message: message) - let paymentPendingInfoView = PrimerPaymentPendingInfoViewController(formPaymentMethodTokenizationViewModel: self, infoView: infoView) + let paymentPendingInfoView = PrimerPaymentPendingInfoViewController(formPaymentMethodTokenizationViewModel: self, + infoView: infoView) PrimerUIManager.primerRootViewController?.show(viewController: paymentPendingInfoView) return Promise() } - if let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type), inputPaymentMethodTypes.contains(paymentMethodType) { + if let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type), + inputPaymentMethodTypes.contains(paymentMethodType) { return presentInputViewController() } - if let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type), voucherPaymentMethodTypes.contains(paymentMethodType) { + if let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type), + voucherPaymentMethodTypes.contains(paymentMethodType) { return presentVoucherInfoConfirmationStepViewController() } @@ -395,7 +407,8 @@ extension FormPaymentMethodTokenizationViewModel { func presentVoucherInfoConfirmationStepViewController() -> Promise { return Promise { seal in - let pcfvc = PrimerAccountInfoPaymentViewController(navigationBarLogo: uiModule.navigationBarLogo, formPaymentMethodTokenizationViewModel: self) + let pcfvc = PrimerAccountInfoPaymentViewController(navigationBarLogo: uiModule.navigationBarLogo, + formPaymentMethodTokenizationViewModel: self) infoView = voucherConfirmationInfoView PrimerUIManager.primerRootViewController?.show(viewController: pcfvc) seal.fulfill() @@ -403,22 +416,26 @@ extension FormPaymentMethodTokenizationViewModel { } func presentVoucherInfoViewController() { + let voucherText = VoucherValue.sharableVoucherValuesText let pcfvc = PrimerVoucherInfoPaymentViewController(navigationBarLogo: uiModule.navigationBarLogo, formPaymentMethodTokenizationViewModel: self, - shouldShareVoucherInfoWithText: VoucherValue.sharableVoucherValuesText) + shouldShareVoucherInfoWithText: voucherText) infoView = voucherInfoView PrimerUIManager.primerRootViewController?.show(viewController: pcfvc) } func presentAccountInfoViewController() { - let pcfvc = PrimerAccountInfoPaymentViewController(navigationBarLogo: uiModule.navigationBarLogo, formPaymentMethodTokenizationViewModel: self) + let pcfvc = PrimerAccountInfoPaymentViewController(navigationBarLogo: uiModule.navigationBarLogo, + formPaymentMethodTokenizationViewModel: self) infoView = makeAccountInfoPaymentView() PrimerUIManager.primerRootViewController?.show(viewController: pcfvc) } func presentInputViewController() -> Promise { return Promise { seal in - let pcfvc = PrimerInputViewController(navigationBarLogo: uiModule.navigationBarLogo, formPaymentMethodTokenizationViewModel: self, inputsDistribution: .horizontal) + let pcfvc = PrimerInputViewController(navigationBarLogo: uiModule.navigationBarLogo, + formPaymentMethodTokenizationViewModel: self, + inputsDistribution: .horizontal) inputs.append(contentsOf: makeInputViews()) PrimerUIManager.primerRootViewController?.show(viewController: pcfvc) seal.fulfill() diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift index c3532df43c..a6546cc1e3 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/FormPaymentMethodTokenizationViewModel.swift @@ -384,7 +384,9 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel // MARK: All billing address fields internal var billingAddressCheckoutModuleOptions: PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions? { - return PrimerAPIConfigurationModule.apiConfiguration?.checkoutModules?.filter({ $0.type == "BILLING_ADDRESS" }).first?.options as? PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions + return PrimerAPIConfigurationModule.apiConfiguration?.checkoutModules? + .filter({ $0.type == "BILLING_ADDRESS" }) + .first?.options as? PrimerAPIConfiguration.CheckoutModule.PostalCodeOptions } internal var billingAddressFields: [[BillingAddressField]] { @@ -518,7 +520,9 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel ) Analytics.Service.record(event: event) - PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: self.uiModule.makeIconImageView(withDimension: 24.0), message: nil) + let imageView = self.uiModule.makeIconImageView(withDimension: 24.0) + PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: imageView, + message: nil) return Promise { seal in firstly { @@ -583,7 +587,8 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel decodedJWTToken.intent != nil { let paymentMethodType = PrimerPaymentMethodType(rawValue: self.config.type) - let isPaymentMethodNeedingExternalCompletion = (needingExternalCompletionPaymentMethodDictionary.first { $0.key == paymentMethodType } != nil) == true + let isPaymentMethodNeedingExternalCompletion = (needingExternalCompletionPaymentMethodDictionary + .first { $0.key == paymentMethodType } != nil) == true firstly { self.presentPaymentMethodAppropriateViewController(shouldCompletePaymentExternally: isPaymentMethodNeedingExternalCompletion) @@ -697,7 +702,8 @@ class FormPaymentMethodTokenizationViewModel: PaymentMethodTokenizationViewModel fileprivate func enableSubmitButton(_ flag: Bool) { self.uiModule.submitButton?.isEnabled = flag let theme: PrimerThemeProtocol = DependencyContainer.resolve() - self.uiModule.submitButton?.backgroundColor = flag ? theme.mainButton.color(for: .enabled) : theme.mainButton.color(for: .disabled) + let colorState: ColorState = flag ? .enabled : .disabled + self.uiModule.submitButton?.backgroundColor = theme.mainButton.color(for: colorState) } override func submitButtonTapped() { @@ -1023,9 +1029,12 @@ extension FormPaymentMethodTokenizationViewModel: UITextFieldDelegate { var countryResults: [CountryCode] = [] - for country in countries where country.country.lowercased().folding(options: .diacriticInsensitive, - locale: nil).contains(query.lowercased().folding(options: .diacriticInsensitive, - locale: nil)) == true { + for country in countries where country.country.lowercased() + .folding(options: .diacriticInsensitive, + locale: nil) + .contains(query.lowercased() + .folding(options: .diacriticInsensitive, + locale: nil)) == true { countryResults.append(country) } diff --git a/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift b/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift index 0fbac47c63..60c532e505 100644 --- a/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift +++ b/Sources/PrimerSDK/Classes/PCI/TokenizationService.swift @@ -82,7 +82,8 @@ internal class TokenizationService: TokenizationServiceProtocol, LogReporter { userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift index dfac9ff6ad..4328a96d4b 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/InternalCardComponentsManager.swift @@ -8,6 +8,7 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length // swiftlint:disable type_body_length +// swiftlint:disable large_tuple import UIKit @@ -49,11 +50,9 @@ protocol InternalCardComponentsManagerProtocol { func tokenize() } -// swiftlint:disable large_tuple typealias BillingAddressField = (fieldView: PrimerTextFieldView, containerFieldView: PrimerCustomFieldView, isFieldHidden: Bool) -// swiftlint:enable large_tuple @objc internal class InternalCardComponentsManager: NSObject, InternalCardComponentsManagerProtocol, LogReporter { @@ -233,8 +232,12 @@ internal class InternalCardComponentsManager: NSObject, InternalCardComponentsMa } if expiryDateField.expiryMonth == nil || expiryDateField.expiryYear == nil { + let message = """ +Expiry date is not valid. Valid expiry date format is 2 characters for expiry month\ +and 4 characters for expiry year separated by '/'. +""" errors.append(PrimerValidationError.invalidExpiryDate( - message: "Expiry date is not valid. Valid expiry date format is 2 characters for expiry month and 4 characters for expiry year separated by '/'.", + message: message, userInfo: [ "file": #file, "class": "\(Self.self)", @@ -299,7 +302,8 @@ internal class InternalCardComponentsManager: NSObject, InternalCardComponentsMa guard let expiryYear = self.expiryDateField.expiryYear else { return nil } let currentYearAsString = Date().yearComponentAsString - let milleniumAndCenturyOfCurrentYearAsString = currentYearAsString.prefix(upTo: currentYearAsString.index(currentYearAsString.startIndex, offsetBy: 2)) + let index = currentYearAsString.index(currentYearAsString.startIndex, offsetBy: 2) + let milleniumAndCenturyOfCurrentYearAsString = currentYearAsString.prefix(upTo: index) return "\(milleniumAndCenturyOfCurrentYearAsString)\(expiryYear)" } @@ -372,7 +376,8 @@ internal class InternalCardComponentsManager: NSObject, InternalCardComponentsMa let containerErr = PrimerError.underlyingErrors(errors: [err], userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: containerErr) self.delegate?.cardComponentsManager?(self, tokenizationFailedWith: [err]) } @@ -384,7 +389,8 @@ internal class InternalCardComponentsManager: NSObject, InternalCardComponentsMa } catch PrimerError.underlyingErrors(errors: let errors, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) { + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) { delegate?.cardComponentsManager?(self, tokenizationFailedWith: errors) setIsLoading(false) } catch { @@ -457,4 +463,5 @@ internal class MockCardComponentsManager: InternalCardComponentsManagerProtocol } // swiftlint:enable function_body_length // swiftlint:enable type_body_length +// swiftlint:enable large_tuple // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift index 779907d399..d97b95452d 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerExpiryDateFieldView.swift @@ -42,8 +42,12 @@ public final class PrimerExpiryDateFieldView: PrimerTextFieldView { if self.isValid?(newText) ?? false { validation = .valid } else { + let message = """ +Expiry date is not valid. Valid expiry date format is 2 characters for \ +expiry month and 4 characters for expiry year separated by '/'. +""" let err = PrimerValidationError.invalidExpiryDate( - message: "Expiry date is not valid. Valid expiry date format is 2 characters for expiry month and 4 characters for expiry year separated by '/'.", + message: message, userInfo: [ "file": #file, "class": "\(Self.self)", diff --git a/Sources/PrimerSDK/Classes/Services/Network/PrimerAPIClient.swift b/Sources/PrimerSDK/Classes/Services/Network/PrimerAPIClient.swift index 8b51d5d8b0..bb8ba69a78 100644 --- a/Sources/PrimerSDK/Classes/Services/Network/PrimerAPIClient.swift +++ b/Sources/PrimerSDK/Classes/Services/Network/PrimerAPIClient.swift @@ -87,14 +87,16 @@ internal class PrimerAPIClient: PrimerAPIClientProtocol { payPalCreateBillingAgreementRequest: Request.Body.PayPal.CreateBillingAgreement, completion: @escaping APICompletion) { - let endpoint = PrimerAPI.createPayPalBillingAgreementSession(clientToken: clientToken, payPalCreateBillingAgreementRequest: payPalCreateBillingAgreementRequest) + let endpoint = PrimerAPI.createPayPalBillingAgreementSession(clientToken: clientToken, + payPalCreateBillingAgreementRequest: payPalCreateBillingAgreementRequest) execute(endpoint, completion: completion) } func confirmPayPalBillingAgreement(clientToken: DecodedJWTToken, payPalConfirmBillingAgreementRequest: Request.Body.PayPal.ConfirmBillingAgreement, completion: @escaping APICompletion) { - let endpoint = PrimerAPI.confirmPayPalBillingAgreement(clientToken: clientToken, payPalConfirmBillingAgreementRequest: payPalConfirmBillingAgreementRequest) + let endpoint = PrimerAPI.confirmPayPalBillingAgreement(clientToken: clientToken, + payPalConfirmBillingAgreementRequest: payPalConfirmBillingAgreementRequest) execute(endpoint, completion: completion) } @@ -102,7 +104,8 @@ internal class PrimerAPIClient: PrimerAPIClientProtocol { clientToken: DecodedJWTToken, klarnaCreatePaymentSessionAPIRequest: Request.Body.Klarna.CreatePaymentSession, completion: @escaping APICompletion) { - let endpoint = PrimerAPI.createKlarnaPaymentSession(clientToken: clientToken, klarnaCreatePaymentSessionAPIRequest: klarnaCreatePaymentSessionAPIRequest) + let endpoint = PrimerAPI.createKlarnaPaymentSession(clientToken: clientToken, + klarnaCreatePaymentSessionAPIRequest: klarnaCreatePaymentSessionAPIRequest) execute(endpoint, completion: completion) } @@ -110,7 +113,8 @@ internal class PrimerAPIClient: PrimerAPIClientProtocol { klarnaCreateCustomerTokenAPIRequest: Request.Body.Klarna.CreateCustomerToken, completion: @escaping APICompletion) { - let endpoint = PrimerAPI.createKlarnaCustomerToken(clientToken: clientToken, klarnaCreateCustomerTokenAPIRequest: klarnaCreateCustomerTokenAPIRequest) + let endpoint = PrimerAPI.createKlarnaCustomerToken(clientToken: clientToken, + klarnaCreateCustomerTokenAPIRequest: klarnaCreateCustomerTokenAPIRequest) execute(endpoint, completion: completion) } @@ -118,7 +122,8 @@ internal class PrimerAPIClient: PrimerAPIClientProtocol { klarnaFinalizePaymentSessionRequest: Request.Body.Klarna.FinalizePaymentSession, completion: @escaping APICompletion) { - let endpoint = PrimerAPI.finalizeKlarnaPaymentSession(clientToken: clientToken, klarnaFinalizePaymentSessionRequest: klarnaFinalizePaymentSessionRequest) + let endpoint = PrimerAPI.finalizeKlarnaPaymentSession(clientToken: clientToken, + klarnaFinalizePaymentSessionRequest: klarnaFinalizePaymentSessionRequest) execute(endpoint, completion: completion) } diff --git a/Sources/PrimerSDK/Classes/User Interface/Banks/BankSelectorViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Banks/BankSelectorViewController.swift index 4ba82a9476..6cc3935481 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Banks/BankSelectorViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Banks/BankSelectorViewController.swift @@ -48,7 +48,8 @@ internal class BankSelectorViewController: PrimerFormViewController { view.backgroundColor = theme.view.backgroundColor view.translatesAutoresizingMaskIntoConstraints = false - view.heightAnchor.constraint(equalToConstant: 120+(CGFloat(viewModel.banks.count)*viewModel.tableView.rowHeight)).isActive = true + let heightValue = 120 + (CGFloat(viewModel.banks.count)*viewModel.tableView.rowHeight) + view.heightAnchor.constraint(equalToConstant: heightValue).isActive = true viewModel.tableView.isScrollEnabled = false verticalStackView.spacing = 5 diff --git a/Sources/PrimerSDK/Classes/User Interface/Banks/BankTableViewCell.swift b/Sources/PrimerSDK/Classes/User Interface/Banks/BankTableViewCell.swift index df99251555..69dbee7a95 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Banks/BankTableViewCell.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Banks/BankTableViewCell.swift @@ -80,7 +80,9 @@ fileprivate extension UIImageView { } else { self.image = placeholder URLSession.shared.dataTask(with: request, completionHandler: { (data, response, _) in - if let data = data, let response = response, ((response as? HTTPURLResponse)?.statusCode ?? 500) < 300, let image = UIImage(data: data) { + if let data = data, + let response = response, ((response as? HTTPURLResponse)?.statusCode ?? 500) < 300, + let image = UIImage(data: data) { let cachedData = CachedURLResponse(response: response, data: data) URLCache.shared.storeCachedResponse(cachedData, for: request) diff --git a/Sources/PrimerSDK/Classes/User Interface/Components/PrimerSearchTextField.swift b/Sources/PrimerSDK/Classes/User Interface/Components/PrimerSearchTextField.swift index e7076b0c2c..ad3af4c117 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Components/PrimerSearchTextField.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Components/PrimerSearchTextField.swift @@ -83,7 +83,8 @@ internal class PrimerSearchTextField: UITextField, UITextFieldDelegate { } override func rightViewRect(forBounds bounds: CGRect) -> CGRect { - let rightViewSize = CGSize(width: bounds.size.height/2, height: bounds.size.height/2) // CGSize(width: bounds.size.height - 2*Padding.vertical, height: bounds.size.height - 2*Padding.vertical) + // CGSize(width: bounds.size.height - 2*Padding.vertical, height: bounds.size.height - 2*Padding.vertical) + let rightViewSize = CGSize(width: bounds.size.height/2, height: bounds.size.height/2) return CGRect( x: bounds.origin.x + bounds.size.width - Padding.horizontal - rightViewSize.width - spacing, y: bounds.origin.y + (bounds.size.height - rightViewSize.height)/2, diff --git a/Sources/PrimerSDK/Classes/User Interface/Countries/CountrySelectorViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Countries/CountrySelectorViewController.swift index 35cc4963da..209e17912f 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Countries/CountrySelectorViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Countries/CountrySelectorViewController.swift @@ -41,7 +41,8 @@ internal class CountrySelectorViewController: PrimerFormViewController { view.backgroundColor = theme.view.backgroundColor view.translatesAutoresizingMaskIntoConstraints = false - view.heightAnchor.constraint(equalToConstant: 120+(CGFloat(countries.count)*viewModel.tableView.rowHeight)).isActive = true + let constant = 120 + (CGFloat(countries.count) * viewModel.tableView.rowHeight) + view.heightAnchor.constraint(equalToConstant: constant).isActive = true viewModel.tableView.isScrollEnabled = false verticalStackView.spacing = 5 diff --git a/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift b/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift index a1548f49f5..5739399a82 100644 --- a/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift +++ b/Sources/PrimerSDK/Classes/User Interface/PrimerUIManager.swift @@ -103,7 +103,9 @@ internal class PrimerUIManager { } if PrimerUIManager.primerWindow == nil { - if let windowScene = UIApplication.shared.connectedScenes.filter({ $0.activationState == .foregroundActive }).first as? UIWindowScene { + if let windowScene = UIApplication.shared.connectedScenes + .filter({ $0.activationState == .foregroundActive }) + .first as? UIWindowScene { PrimerUIManager.primerWindow = UIWindow(windowScene: windowScene) } else { // Not opted-in in UISceneDelegate diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift index c2ef93664a..d5ef3658e2 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerFormViewController.swift @@ -6,6 +6,7 @@ // // swiftlint:disable function_body_length +// swiftlint:disable line_length import UIKit @@ -59,11 +60,14 @@ class PrimerFormViewController: PrimerViewController { } else { // No surcharge fee - let noAdditionalFeePaymentMethodsViewModels = paymentMethodTokenizationViewModels.filter({ $0.config.hasUnknownSurcharge == false && ($0.config.surcharge ?? 0) == 0 }) + let noAdditionalFeePaymentMethodsViewModels = paymentMethodTokenizationViewModels + .filter({ $0.config.hasUnknownSurcharge == false && ($0.config.surcharge ?? 0) == 0 }) // With surcharge fee - let additionalFeePaymentMethodsViewModels = paymentMethodTokenizationViewModels.filter({ $0.config.hasUnknownSurcharge == false && ($0.config.surcharge ?? 0) != 0 }) + let additionalFeePaymentMethodsViewModels = paymentMethodTokenizationViewModels + .filter({ $0.config.hasUnknownSurcharge == false && ($0.config.surcharge ?? 0) != 0 }) // Unknown surcharge fee - let unknownFeePaymentMethodsViewModels = paymentMethodTokenizationViewModels.filter({ $0.config.hasUnknownSurcharge == true }) + let unknownFeePaymentMethodsViewModels = paymentMethodTokenizationViewModels + .filter({ $0.config.hasUnknownSurcharge == true }) if !noAdditionalFeePaymentMethodsViewModels.isEmpty, additionalFeePaymentMethodsViewModels.isEmpty, @@ -94,7 +98,8 @@ class PrimerFormViewController: PrimerViewController { if !additionalFeePaymentMethodsViewModels.isEmpty { for additionalFeePaymentMethodsViewModel in additionalFeePaymentMethodsViewModels { let title = additionalFeePaymentMethodsViewModel.uiModule.surchargeSectionText - let additionalFeesContainerView = PaymentMethodsGroupView(title: title, paymentMethodTokenizationViewModels: [additionalFeePaymentMethodsViewModel]) + let additionalFeesContainerView = PaymentMethodsGroupView(title: title, + paymentMethodTokenizationViewModels: [additionalFeePaymentMethodsViewModel]) additionalFeesContainerView.accessibilityIdentifier = "\(additionalFeePaymentMethodsViewModel.config.type.lowercased())_surcharge_group_view" additionalFeesContainerView.titleLabel?.font = UIFont.systemFont(ofSize: 16.0, weight: .bold) paymentMethodsStack.addArrangedSubview(additionalFeesContainerView) @@ -117,3 +122,4 @@ class PrimerFormViewController: PrimerViewController { } } // swiftlint:enable function_body_length +// swiftlint:enable line_length diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerLoadingViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerLoadingViewController.swift index af7a19fd16..cdb8d124dd 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerLoadingViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerLoadingViewController.swift @@ -52,7 +52,10 @@ class PrimerLoadingViewController: PrimerViewController { activityIndicatorView.accessibilityIdentifier = "Loading Indicator" activityIndicatorView.startAnimating() - resultView = PrimerResultComponentView(frame: .zero, imageView: self.imageView, message: self.message, loadingIndicator: self.activityIndicatorView) + resultView = PrimerResultComponentView(frame: .zero, + imageView: self.imageView, + message: self.message, + loadingIndicator: self.activityIndicatorView) view.addSubview(resultView) resultView.translatesAutoresizingMaskIntoConstraints = false resultView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift index 0c9ffbc97b..6084673d54 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift @@ -286,7 +286,8 @@ internal class PrimerRootViewController: PrimerViewController { cvc.mockedNavigationBar.hidesBackButton = true } else if viewController is PrimerVoucherInfoPaymentViewController { cvc.mockedNavigationBar.hidesBackButton = true - } else if let lastViewController = self.navController.viewControllers.last as? PrimerContainerViewController, lastViewController.children.first is PrimerLoadingViewController { + } else if let lastViewController = self.navController.viewControllers.last as? PrimerContainerViewController, + lastViewController.children.first is PrimerLoadingViewController { cvc.mockedNavigationBar.hidesBackButton = true } else if viewController is PrimerLoadingViewController { cvc.mockedNavigationBar.hidesBackButton = true @@ -353,8 +354,10 @@ internal class PrimerRootViewController: PrimerViewController { } internal func popViewController() { + let index = navController.viewControllers.count-2 + guard navController.viewControllers.count > 1, - let viewController = (navController.viewControllers[navController.viewControllers.count-2] as? PrimerContainerViewController)?.childViewController + let viewController = (navController.viewControllers[index] as? PrimerContainerViewController)?.childViewController else { return } @@ -363,7 +366,8 @@ internal class PrimerRootViewController: PrimerViewController { (self.navController.viewControllers.last as? PrimerContainerViewController)?.mockedNavigationBar.hidesBackButton = true } - let navigationControllerHeight: CGFloat = min(viewController.view.bounds.size.height + navController.navigationBar.bounds.height, availableScreenHeight) + let minX = viewController.view.bounds.size.height + navController.navigationBar.bounds.height + let navigationControllerHeight: CGFloat = min(minX, availableScreenHeight) childViewHeightConstraint.constant = navigationControllerHeight + bottomPadding @@ -431,7 +435,8 @@ internal class PrimerRootViewController: PrimerViewController { } internal func resetConstraint(for viewController: UIViewController) { - let navigationControllerHeight: CGFloat = min(viewController.view.bounds.size.height + self.navController.navigationBar.bounds.height, self.availableScreenHeight) + let minX = viewController.view.bounds.size.height + self.navController.navigationBar.bounds.height + let navigationControllerHeight: CGFloat = min(minX, self.availableScreenHeight) self.childViewHeightConstraint.isActive = false self.childViewHeightConstraint?.constant = navigationControllerHeight + self.bottomPadding self.childViewHeightConstraint.isActive = true diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift index 9a70722820..44c2081882 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift @@ -60,7 +60,8 @@ internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { if let error = err as? PrimerError { primerErr = error } else { - primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, + diagnosticsId: UUID().uuidString) } PrimerDelegateProxy.primerDidFailWithError(primerErr, data: nil) { errorDecision in @@ -159,7 +160,9 @@ internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { guard var amount = AppState.current.amount, let currency = AppState.current.currency else { - let err = PrimerError.invalidValue(key: "amount or currency", value: nil, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "amount or currency", value: nil, + userInfo: nil, + diagnosticsId: UUID().uuidString) firstly { PrimerDelegateProxy.raisePrimerDidFailWithError(err, data: nil) } diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift index 2382c6baf1..4008780dc1 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/ApplePayTokenizationViewModel.swift @@ -131,8 +131,8 @@ class ApplePayTokenizationViewModel: PaymentMethodTokenizationViewModel { ) Analytics.Service.record(event: event) - PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: - self.uiModule.makeIconImageView(withDimension: 24.0), + let imageView = self.uiModule.makeIconImageView(withDimension: 24.0) + PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: imageView, message: nil) return Promise { seal in @@ -153,7 +153,8 @@ class ApplePayTokenizationViewModel: PaymentMethodTokenizationViewModel { return self.awaitUserInput() } .then { () -> Promise in - return self.updateBillingAddressViaClientSessionActionWithAddressIfNeeded(self.applePayPaymentResponse.billingAddress) + let address = self.applePayPaymentResponse.billingAddress + return self.updateBillingAddressViaClientSessionActionWithAddressIfNeeded(address) } .done { seal.fulfill() @@ -251,7 +252,8 @@ class ApplePayTokenizationViewModel: PaymentMethodTokenizationViewModel { if canMakePayment { let request = PKPaymentRequest() - let isBillingContactFieldsRequired = PrimerSettings.current.paymentMethodOptions.applePayOptions?.isCaptureBillingAddressEnabled == true + let applePayOptions = PrimerSettings.current.paymentMethodOptions.applePayOptions + let isBillingContactFieldsRequired = applePayOptions?.isCaptureBillingAddressEnabled == true request.requiredBillingContactFields = isBillingContactFieldsRequired ? [.postalAddress] : [] request.currencyCode = applePayRequest.currency.code request.countryCode = applePayRequest.countryCode.rawValue @@ -279,7 +281,8 @@ class ApplePayTokenizationViewModel: PaymentMethodTokenizationViewModel { seal.reject(err) return } else { - PrimerDelegateProxy.primerHeadlessUniversalCheckoutUIDidShowPaymentMethod(for: self.config.type) + let type = self.config.type + PrimerDelegateProxy.primerHeadlessUniversalCheckoutUIDidShowPaymentMethod(for: type) self.didPresentPaymentMethodUI?() seal.fulfill() } @@ -589,7 +592,8 @@ extension ApplePayTokenizationViewModel: PKPaymentAuthorizationControllerDelegat publicKeyHash: "apple-pay-mock-public-key-hash", transactionId: "apple-pay-mock--transaction-id")) } else { - tokenPaymentData = try JSONParser().parse(ApplePayPaymentResponseTokenPaymentData.self, from: payment.token.paymentData) + tokenPaymentData = try JSONParser().parse(ApplePayPaymentResponseTokenPaymentData.self, + from: payment.token.paymentData) } let billingAddress = clientSessionBillingAddressFromApplePayBillingContact(payment.billingContact) diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift index 9b14a8d437..61eabb7275 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/BankSelectorTokenizationViewModel.swift @@ -32,7 +32,8 @@ class BankSelectorTokenizationViewModel: WebRedirectPaymentMethodTokenizationVie let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -204,7 +205,8 @@ class BankSelectorTokenizationViewModel: WebRedirectPaymentMethodTokenizationVie let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -257,7 +259,8 @@ class BankSelectorTokenizationViewModel: WebRedirectPaymentMethodTokenizationVie let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, err) return @@ -292,7 +295,8 @@ extension BankSelectorTokenizationViewModel: UITableViewDataSource, UITableViewD func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let bank = dataSource[indexPath.row] - guard let cell = tableView.dequeueReusableCell(withIdentifier: "BankTableViewCell", for: indexPath) as? BankTableViewCell + guard let cell = tableView.dequeueReusableCell(withIdentifier: "BankTableViewCell", + for: indexPath) as? BankTableViewCell else { fatalError("Unexpected cell dequed in BankSelectorTokenizationViewModel") } @@ -360,7 +364,10 @@ extension BankSelectorTokenizationViewModel: BankSelectorTokenizationProviding { return banks } return banks.filter { - $0.name.lowercased().folding(options: .diacriticInsensitive, locale: nil).contains(query.lowercased().folding(options: .diacriticInsensitive, locale: nil)) + $0.name.lowercased() + .folding(options: .diacriticInsensitive, locale: nil) + .contains(query.lowercased() + .folding(options: .diacriticInsensitive, locale: nil)) } } func tokenize(bankId: String) -> Promise { diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift index 33b93a4a0b..e793257b24 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift @@ -63,7 +63,8 @@ class CheckoutWithVaultedPaymentMethodViewModel: LogReporter { if let error = err as? PrimerError { primerErr = error } else { - primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, + diagnosticsId: UUID().uuidString) } firstly { @@ -347,7 +348,9 @@ Make sure you call the decision handler otherwise the SDK will hang. private func handleResumePaymentEvent(_ resumePaymentId: String, resumeToken: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, paymentResumeRequest: Request.Body.Payment.Resume(token: resumeToken)) { paymentResponse, error in + let resumeRequest = Request.Body.Payment.Resume(token: resumeToken) + createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, + paymentResumeRequest: resumeRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -609,7 +612,8 @@ Make sure you call the decision handler otherwise the SDK will hang. private func handleCreatePaymentEvent(_ paymentMethodData: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.createPayment(paymentRequest: Request.Body.Payment.Create(token: paymentMethodData)) { paymentResponse, error in + let paymentRequest = Request.Body.Payment.Create(token: paymentMethodData) + createResumePaymentService.createPayment(paymentRequest: paymentRequest) { paymentResponse, error in if let error = error { if let paymentResponse { diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift index 11f84dbe7d..34a346e18c 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/IPay88TokenizationViewModel.swift @@ -7,6 +7,7 @@ // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length +// swiftlint:disable line_length // swiftlint:disable function_body_length // swiftlint:disable type_body_length @@ -130,7 +131,9 @@ class IPay88TokenizationViewModel: PaymentMethodTokenizationViewModel { errors.append(err) } else { - let productsDescription = PrimerAPIConfiguration.current?.clientSession?.order?.lineItems?.compactMap({ $0.name ?? $0.description }).joined(separator: ", ") + let productsDescription = PrimerAPIConfiguration.current?.clientSession?.order?.lineItems? + .compactMap({ $0.name ?? $0.description }) + .joined(separator: ", ") if productsDescription == nil { let err = PrimerError.invalidClientSessionValue( @@ -221,7 +224,8 @@ class IPay88TokenizationViewModel: PaymentMethodTokenizationViewModel { } override func performPreTokenizationSteps() -> Promise { - PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: self.uiModule.makeIconImageView(withDimension: 24.0), message: nil) + let imageView = self.uiModule.makeIconImageView(withDimension: 24.0) + PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: imageView, message: nil) return Promise { seal in #if canImport(PrimerIPay88MYSDK) @@ -544,11 +548,12 @@ class IPay88TokenizationViewModel: PaymentMethodTokenizationViewModel { self.willPresentPaymentMethodUI?() + let delegate = PrimerHeadlessUniversalCheckout.current.uiDelegate PrimerUIManager.primerRootViewController?.present(self.primerIPay88ViewController, animated: true, completion: { DispatchQueue.main.async { - PrimerHeadlessUniversalCheckout.current.uiDelegate?.primerHeadlessUniversalCheckoutUIDidShowPaymentMethod?(for: self.config.type) + delegate?.primerHeadlessUniversalCheckoutUIDidShowPaymentMethod?(for: self.config.type) self.didPresentPaymentMethodUI?() seal.fulfill() } @@ -721,4 +726,5 @@ extension IPay88TokenizationViewModel: PrimerIPay88ViewControllerDelegate { // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length // swiftlint:enable type_body_length +// swiftlint:enable line_length // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift index 2ae555580a..86718928fe 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift @@ -34,7 +34,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -43,7 +44,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -52,7 +54,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidValue(key: "configuration.id", value: config.id, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -63,7 +66,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidSetting(name: "amount", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -73,7 +77,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidSetting(name: "amount", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -82,7 +87,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidSetting(name: "currency", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -91,7 +97,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidValue(key: "lineItems", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -100,7 +107,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidValue(key: "settings.orderItems", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -122,7 +130,9 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { ) Analytics.Service.record(event: event) - PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: self.uiModule.makeIconImageView(withDimension: 24.0), message: nil) + let imageView = self.uiModule.makeIconImageView(withDimension: 24.0) + PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: imageView, + message: nil) return Promise { seal in #if canImport(PrimerKlarnaSDK) @@ -303,14 +313,20 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { override func tokenize() -> Promise { return Promise { seal in guard let klarnaCustomerToken = self.klarnaCustomerTokenAPIResponse?.customerTokenId else { - let err = PrimerError.invalidValue(key: "tokenization.klarnaCustomerToken", value: nil, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "tokenization.klarnaCustomerToken", + value: nil, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return } guard let sessionData = self.klarnaCustomerTokenAPIResponse?.sessionData else { - let err = PrimerError.invalidValue(key: "tokenization.sessionData", value: nil, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.invalidValue(key: "tokenization.sessionData", + value: nil, + userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/NolPayTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/NolPayTokenizationViewModel.swift index 25ece1b2ef..d2904cf381 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/NolPayTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/NolPayTokenizationViewModel.swift @@ -4,6 +4,9 @@ // // Created by Boris on 28.8.23.. // + +// swiftlint:disable type_body_length + import Foundation import SafariServices import UIKit @@ -27,7 +30,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -36,7 +40,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidValue(key: "decodedClientToken.pciUrl", value: nil, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -45,7 +50,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidValue(key: "configuration.id", value: config.id, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -111,7 +117,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidValue(key: "configuration.id", value: config.id, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -162,7 +169,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let error = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) seal.reject(error) return @@ -172,7 +180,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let error = PrimerError.invalidUrl(url: self.redirectUrl?.absoluteString, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) seal.reject(error) return @@ -205,7 +214,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let error = PrimerError.invalidUrl(url: self.statusUrl?.absoluteString, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: error) seal.reject(error) return @@ -226,7 +236,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { firstly { () -> Promise in if self.isCancelled { - let err = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, + diagnosticsId: UUID().uuidString) throw err } return pollingModule.start() @@ -279,7 +290,8 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } @@ -293,3 +305,4 @@ class NolPayTokenizationViewModel: PaymentMethodTokenizationViewModel { // no-op } } +// swiftlint:enable type_body_length diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift index 1b10ff0edd..c239812868 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PayPalTokenizationViewModel.swift @@ -100,7 +100,9 @@ class PayPalTokenizationViewModel: PaymentMethodTokenizationViewModel { ) Analytics.Service.record(event: event) - PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: self.uiModule.makeIconImageView(withDimension: 24.0), message: nil) + let imageView = self.uiModule.makeIconImageView(withDimension: 24.0) + PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: imageView, + message: nil) return Promise { seal in firstly { diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift index 0c8a1e6d50..7ccf5697d3 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel+Logic.swift @@ -53,7 +53,8 @@ extension PaymentMethodTokenizationViewModel { if let error = err as? PrimerError { primerErr = error } else { - primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, + diagnosticsId: UUID().uuidString) } return PrimerDelegateProxy.raisePrimerDidFailWithError(primerErr, data: self.paymentCheckoutData) @@ -76,7 +77,9 @@ extension PaymentMethodTokenizationViewModel { self.didStartPayment?() self.didStartPayment = nil - PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: self.uiModule.makeIconImageView(withDimension: 24.0), message: nil) + let imageView = self.uiModule.makeIconImageView(withDimension: 24.0) + PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: imageView, + message: nil) firstly { self.startPaymentFlow(withPaymentMethodTokenData: self.paymentMethodTokenData!) @@ -126,10 +129,12 @@ extension PaymentMethodTokenizationViewModel { if let error = err as? PrimerError { primerErr = error } else { - primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, diagnosticsId: UUID().uuidString) + primerErr = PrimerError.generic(message: err.localizedDescription, userInfo: nil, + diagnosticsId: UUID().uuidString) } - return PrimerDelegateProxy.raisePrimerDidFailWithError(primerErr, data: self.paymentCheckoutData) + return PrimerDelegateProxy.raisePrimerDidFailWithError(primerErr, + data: self.paymentCheckoutData) } .done { merchantErrorMessage in self.handleFailureFlow(errorMessage: merchantErrorMessage) @@ -146,7 +151,8 @@ extension PaymentMethodTokenizationViewModel { var cancelledError: PrimerError? self.didCancel = { self.isCancelled = true - cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, diagnosticsId: UUID().uuidString) + cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: cancelledError!) seal.reject(cancelledError!) self.isCancelled = false @@ -511,7 +517,8 @@ Make sure you call the decision handler otherwise the SDK will hang. private func handleCreatePaymentEvent(_ paymentMethodData: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.createPayment(paymentRequest: Request.Body.Payment.Create(token: paymentMethodData)) { paymentResponse, error in + let paymentRequest = Request.Body.Payment.Create(token: paymentMethodData) + createResumePaymentService.createPayment(paymentRequest: paymentRequest) { paymentResponse, error in if let error = error { if let paymentResponse { @@ -577,7 +584,9 @@ Make sure you call the decision handler otherwise the SDK will hang. private func handleResumePaymentEvent(_ resumePaymentId: String, resumeToken: String) -> Promise { return Promise { seal in let createResumePaymentService: CreateResumePaymentServiceProtocol = CreateResumePaymentService() - createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, paymentResumeRequest: Request.Body.Payment.Resume(token: resumeToken)) { paymentResponse, error in + let resumeRequest = Request.Body.Payment.Resume(token: resumeToken) + createResumePaymentService.resumePaymentWithPaymentId(resumePaymentId, + paymentResumeRequest: resumeRequest) { paymentResponse, error in if let error = error { if let paymentResponse { diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel.swift index 60a4101c1b..f73f34e550 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PaymentMethodTokenizationViewModel.swift @@ -89,7 +89,8 @@ class PaymentMethodTokenizationViewModel: NSObject, PaymentMethodTokenizationVie var cancelledError: PrimerError? self.didCancel = { self.isCancelled = true - cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, diagnosticsId: UUID().uuidString) + cancelledError = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: cancelledError!) seal.reject(cancelledError!) self.isCancelled = false diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PrimerTestPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PrimerTestPaymentMethodTokenizationViewModel.swift index f86bdda4ff..68638a6c38 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PrimerTestPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/PrimerTestPaymentMethodTokenizationViewModel.swift @@ -275,7 +275,8 @@ extension PrimerTestPaymentMethodTokenizationViewModel { let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) completion(nil, err) return diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift index 7b1c011ff0..94d40ac813 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/QRCodeTokenizationViewModel.swift @@ -28,7 +28,8 @@ class QRCodeTokenizationViewModel: WebRedirectPaymentMethodTokenizationViewModel let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) throw err } @@ -144,7 +145,8 @@ class QRCodeTokenizationViewModel: WebRedirectPaymentMethodTokenizationViewModel let err = PrimerError.invalidValue(key: "configuration.id", value: config.id, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -200,7 +202,8 @@ class QRCodeTokenizationViewModel: WebRedirectPaymentMethodTokenizationViewModel let error = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) seal.reject(error) } } @@ -260,14 +263,15 @@ extension QRCodeTokenizationViewModel { return } + let delegate = PrimerHeadlessUniversalCheckout.current.delegate // swiftlint:disable:next identifier_name - let isHeadlessDidReceiveAdditionalInfoImplemented = PrimerHeadlessUniversalCheckout.current.delegate?.primerHeadlessUniversalCheckoutDidReceiveAdditionalInfo != nil + let isHeadlessDidReceiveAdditionalInfoImplemented = delegate?.primerHeadlessUniversalCheckoutDidReceiveAdditionalInfo != nil guard isHeadlessDidReceiveAdditionalInfoImplemented else { let message = """ -Delegate function 'primerHeadlessUniversalCheckoutDidReceiveAdditionalInfo(_ additionalInfo: PrimerCheckoutAdditionalInfo?)' hasn't been implemented. \ -No events will be sent to your delegate instance. +Delegate function 'primerHeadlessUniversalCheckoutDidReceiveAdditionalInfo(_ additionalInfo: PrimerCheckoutAdditionalInfo?)'\ + hasn't been implemented. No events will be sent to your delegate instance. """ let err = PrimerError.generic(message: message, userInfo: ["file": #file, diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift index eaf6cfe3fa..8133dcdfea 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/WebRedirectPaymentMethodTokenizationViewModel.swift @@ -70,8 +70,14 @@ class WebRedirectPaymentMethodTokenizationViewModel: PaymentMethodTokenizationVi } func setup() { - NotificationCenter.default.addObserver(self, selector: #selector(self.receivedNotification(_:)), name: Notification.Name.receivedUrlSchemeRedirect, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(self.receivedNotification(_:)), name: Notification.Name.receivedUrlSchemeCancellation, object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(self.receivedNotification(_:)), + name: Notification.Name.receivedUrlSchemeRedirect, + object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(self.receivedNotification(_:)), + name: Notification.Name.receivedUrlSchemeCancellation, + object: nil) self.didFinishPayment = { _ in self.willDismissPaymentMethodUI?() @@ -108,7 +114,9 @@ class WebRedirectPaymentMethodTokenizationViewModel: PaymentMethodTokenizationVi ) Analytics.Service.record(event: event) - PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: self.uiModule.makeIconImageView(withDimension: 24.0), message: nil) + let imageView = self.uiModule.makeIconImageView(withDimension: 24.0) + PrimerUIManager.primerRootViewController?.showLoadingScreenIfNeeded(imageView: imageView, + message: nil) return Promise { seal in firstly { @@ -257,7 +265,8 @@ class WebRedirectPaymentMethodTokenizationViewModel: PaymentMethodTokenizationVi firstly { () -> Promise in if self.isCancelled { - let err = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, diagnosticsId: UUID().uuidString) + let err = PrimerError.cancelled(paymentMethodType: self.config.type, userInfo: nil, + diagnosticsId: UUID().uuidString) throw err } return pollingModule.start() @@ -281,7 +290,8 @@ class WebRedirectPaymentMethodTokenizationViewModel: PaymentMethodTokenizationVi let err = PrimerError.invalidValue(key: "configuration.id", value: config.id, userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) return @@ -341,7 +351,8 @@ class WebRedirectPaymentMethodTokenizationViewModel: PaymentMethodTokenizationVi let err = PrimerError.invalidClientToken(userInfo: ["file": #file, "class": "\(Self.self)", "function": #function, - "line": "\(#line)"], diagnosticsId: UUID().uuidString) + "line": "\(#line)"], + diagnosticsId: UUID().uuidString) ErrorHandler.handle(error: err) seal.reject(err) } diff --git a/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift index a8c5a5b600..6af9f7734d 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift @@ -112,7 +112,8 @@ internal class VaultedPaymentInstrumentCell: UITableViewCell { cardNetworkImageView.image = paymentMethod.cardButtonViewModel?.imageName.image cardNetworkImageView.contentMode = .scaleAspectFit - checkmarkImageView.image = isDeleting ? ImageName.delete.image?.withRenderingMode(.alwaysTemplate) : ImageName.check2.image?.withRenderingMode(.alwaysTemplate) + checkmarkImageView.image = isDeleting ? + ImageName.delete.image?.withRenderingMode(.alwaysTemplate) : ImageName.check2.image?.withRenderingMode(.alwaysTemplate) checkmarkImageView.tintColor = theme.paymentMethodButton.border.color(for: .selected) checkmarkImageView.contentMode = .scaleAspectFit checkmarkImageView.isHidden = isDeleting ? false : !isEnabled @@ -265,7 +266,8 @@ extension VaultedPaymentInstrumentsViewController: UITableViewDataSource, UITabl func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let viewModel: VaultPaymentMethodViewModelProtocol = VaultPaymentMethodViewModel() let paymentMethod = viewModel.paymentMethods[indexPath.row] - guard let cell = tableView.dequeueReusableCell(withIdentifier: "VaultedPaymentInstrumentCell", for: indexPath) as? VaultedPaymentInstrumentCell + guard let cell = tableView.dequeueReusableCell(withIdentifier: "VaultedPaymentInstrumentCell", + for: indexPath) as? VaultedPaymentInstrumentCell else { fatalError() } From f51da9c47a37ce1a0d82e9fe3d7c2ad0d4463fb2 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 18:31:40 +0100 Subject: [PATCH 07/21] Trigger danger for new swiftlint comments --- .../Klarna/Components/KlarnaTokenizationComponent.swift | 3 ++- .../Classes/Error Handler/PrimerValidationError.swift | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift index 8e2f430603..7e0d09979c 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Composable/Klarna/Components/KlarnaTokenizationComponent.swift @@ -129,7 +129,8 @@ extension KlarnaTokenizationComponent { switch KlarnaHelpers.getSessionType() { case .oneOffPayment: // Prepare the body for the Klarna Finalize Payment Session request - let body = prepareKlarnaFinalizePaymentSessionBody(paymentMethodConfigId: paymentMethodConfigId, sessionId: sessionId) + let body = prepareKlarnaFinalizePaymentSessionBody(paymentMethodConfigId: paymentMethodConfigId, + sessionId: sessionId) firstly { // Finalize Klarna Payment Session finalizeKlarnaPaymentSession(with: decodedJWTToken, body: body) diff --git a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift index cad06e1fa9..d26022973d 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift @@ -10,7 +10,6 @@ // swiftlint:disable identifier_name // swiftlint:disable function_body_length - import Foundation public enum PrimerValidationError: PrimerErrorProtocol, Encodable { From 61596d7d1a82b80768f67a935b19f350f1e7250e Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 19:02:15 +0100 Subject: [PATCH 08/21] Trigger danger for new swiftlint comments --- .../Classes/Core/Primer/PrimerInternal.swift | 3 ++- ...rimerHeadlessUniversalCheckoutKlarnaManager.swift | 4 +++- ...rimerHeadlessUniversalCheckoutPaymentMethod.swift | 4 +++- .../CardFormPaymentMethodTokenizationViewModel.swift | 3 ++- .../KlarnaTokenizationViewModel.swift | 12 ++++++++---- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift b/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift index de1b2f33a6..db3fdc0d2b 100644 --- a/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift +++ b/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift @@ -146,7 +146,8 @@ internal class PrimerInternal: LogReporter { } .done { PrimerUIManager.presentPaymentUI() - let currencyLoader = CurrencyLoader(storage: DefaultCurrencyStorage(), networkService: CurrencyNetworkService()) + let currencyLoader = CurrencyLoader(storage: DefaultCurrencyStorage(), + networkService: CurrencyNetworkService()) currencyLoader.updateCurrenciesFromAPI() completion?(nil) } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift index a3c21e7255..3dd734b6ec 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift @@ -12,7 +12,8 @@ import PrimerKlarnaSDK extension PrimerHeadlessUniversalCheckout { public class KlarnaManager: NSObject { public func provideKlarnaComponent(with intent: PrimerSessionIntent) throws -> (any KlarnaComponent)? { - guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs?.first(where: { $0.type == "KLARNA" }) else { + guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs?.first(where: { $0.type == "KLARNA" }) + else { let err = PrimerError.generic(message: "Unable to locate a valid payment method configuration.", userInfo: ["file": #file, "class": "\(Self.self)", @@ -22,6 +23,7 @@ extension PrimerHeadlessUniversalCheckout { ErrorHandler.handle(error: err) throw err } + if (intent == .vault && !paymentMethod.isVaultingEnabled) || (intent == .checkout && !paymentMethod.isCheckoutEnabled) { let err = PrimerError.unsupportedIntent(intent: intent, diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift index e847850de0..1a71e62e55 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift @@ -35,7 +35,9 @@ extension PrimerHeadlessUniversalCheckout { public private(set) var requiredInputDataClass: PrimerRawData.Type? init?(paymentMethodType: String) { - guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs?.first(where: { $0.type == paymentMethodType }) else { + guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs? + .first(where: { $0.type == paymentMethodType }) + else { return nil } diff --git a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift index 67d38ef0df..8807cdbe2c 100644 --- a/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/PCI/Tokenization View Models/FormsTokenizationViewModel/CardFormPaymentMethodTokenizationViewModel.swift @@ -976,7 +976,8 @@ extension CardFormPaymentMethodTokenizationViewModel: UITableViewDataSource, UIT func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let country = dataSource[indexPath.row] - guard let cell = tableView.dequeueReusableCell(withIdentifier: CountryTableViewCell.className, for: indexPath) as? CountryTableViewCell + guard let cell = tableView.dequeueReusableCell(withIdentifier: CountryTableViewCell.className, + for: indexPath) as? CountryTableViewCell else { fatalError("Unexpected cell dequed in PrimerSDK.CardFormPaymentMethodTokenizationViewModel") } diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift index 86718928fe..39a68a63fb 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/KlarnaTokenizationViewModel.swift @@ -435,7 +435,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { return } - if !(PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.lineItems ?? []).filter({ $0.amount == nil }).isEmpty { + if !(PrimerAPIConfigurationModule.apiConfiguration?.clientSession?.order?.lineItems ?? []) + .filter({ $0.amount == nil }).isEmpty { let err = PrimerError.invalidValue(key: "settings.orderItems.amount", value: nil, userInfo: ["file": #file, @@ -481,7 +482,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let apiClient: PrimerAPIClientProtocol = PaymentMethodTokenizationViewModel.apiClient ?? PrimerAPIClient() - apiClient.createKlarnaPaymentSession(clientToken: decodedJWTToken, klarnaCreatePaymentSessionAPIRequest: body) { (result) in + apiClient.createKlarnaPaymentSession(clientToken: decodedJWTToken, + klarnaCreatePaymentSessionAPIRequest: body) { (result) in switch result { case .failure(let err): seal.reject(err) @@ -530,7 +532,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let apiClient: PrimerAPIClientProtocol = PaymentMethodTokenizationViewModel.apiClient ?? PrimerAPIClient() - apiClient.createKlarnaCustomerToken(clientToken: decodedJWTToken, klarnaCreateCustomerTokenAPIRequest: body) { (result) in + apiClient.createKlarnaCustomerToken(clientToken: decodedJWTToken, + klarnaCreateCustomerTokenAPIRequest: body) { (result) in switch result { case .failure(let err): seal.reject(err) @@ -584,7 +587,8 @@ class KlarnaTokenizationViewModel: PaymentMethodTokenizationViewModel { let apiClient: PrimerAPIClientProtocol = PaymentMethodTokenizationViewModel.apiClient ?? PrimerAPIClient() - apiClient.finalizeKlarnaPaymentSession(clientToken: decodedJWTToken, klarnaFinalizePaymentSessionRequest: body) { (result) in + apiClient.finalizeKlarnaPaymentSession(clientToken: decodedJWTToken, + klarnaFinalizePaymentSessionRequest: body) { (result) in switch result { case .failure(let err): completion(.failure(err)) From 6b635a5ba15bee6530b4c7f2d1e1db4ebeca9c40 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Tue, 19 Mar 2024 11:41:46 +0100 Subject: [PATCH 09/21] Trigger danger for new swiftlint comments --- .../PrimerAPIConfigurationModule.swift | 14 +++++++++----- .../Classes/Core/Primer/PrimerInternal.swift | 2 +- .../CardComponentsManager.swift | 5 ++--- .../PrimerHeadlessBanksComponentWrapper.swift | 3 +-- ...merHeadlessUniversalCheckoutKlarnaManager.swift | 5 +++-- .../Payment Method Managers/RawDataManager.swift | 8 ++++++-- ...imerHeadlessUniversalCheckoutInputElement.swift | 3 +-- ...lessUniversalCheckoutInputElementDelegate.swift | 3 +-- ...merHeadlessUniversalCheckoutPaymentMethod.swift | 2 +- .../Classes/Data Models/ClientToken.swift | 3 --- .../Data Models/Currency/CurrencyLoader.swift | 3 --- .../Error Handler/PrimerValidationError.swift | 2 -- 12 files changed, 25 insertions(+), 28 deletions(-) diff --git a/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift b/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift index c89e24d1a4..d562b1de9d 100644 --- a/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift +++ b/Sources/PrimerSDK/Classes/Core/Payment Services/PrimerAPIConfigurationModule.swift @@ -1,4 +1,3 @@ -// swiftlint:disable type_body_length import Foundation internal typealias JWTToken = String @@ -21,6 +20,7 @@ internal protocol PrimerAPIConfigurationModuleProtocol { func storeRequiredActionClientToken(_ newClientToken: String) -> Promise } +// swiftlint:disable type_body_length internal class PrimerAPIConfigurationModule: PrimerAPIConfigurationModuleProtocol { static var apiClient: PrimerAPIClientProtocol? @@ -114,7 +114,8 @@ internal class PrimerAPIConfigurationModule: PrimerAPIConfigurationModuleProtoco } let apiClient: PrimerAPIClientProtocol = PrimerAPIConfigurationModule.apiClient ?? PrimerAPIClient() - apiClient.requestPrimerConfigurationWithActions(clientToken: decodedJWTToken, request: actionsRequest) { result in + apiClient.requestPrimerConfigurationWithActions(clientToken: decodedJWTToken, + request: actionsRequest) { result in switch result { case .success(let configuration): PrimerAPIConfigurationModule.apiConfiguration?.clientSession = configuration.clientSession @@ -189,9 +190,12 @@ internal class PrimerAPIConfigurationModule: PrimerAPIConfigurationModuleProtoco let previousDecodedToken = PrimerAPIConfigurationModule.decodedJWTToken - currentDecodedToken.configurationUrl = currentDecodedToken.configurationUrl?.replacingOccurrences(of: "10.0.2.2:8080", with: "localhost:8080") - currentDecodedToken.coreUrl = currentDecodedToken.coreUrl?.replacingOccurrences(of: "10.0.2.2:8080", with: "localhost:8080") - currentDecodedToken.pciUrl = currentDecodedToken.pciUrl?.replacingOccurrences(of: "10.0.2.2:8080", with: "localhost:8080") + currentDecodedToken.configurationUrl = currentDecodedToken.configurationUrl?.replacingOccurrences(of: "10.0.2.2:8080", + with: "localhost:8080") + currentDecodedToken.coreUrl = currentDecodedToken.coreUrl?.replacingOccurrences(of: "10.0.2.2:8080", + with: "localhost:8080") + currentDecodedToken.pciUrl = currentDecodedToken.pciUrl?.replacingOccurrences(of: "10.0.2.2:8080", + with: "localhost:8080") if currentDecodedToken.env == nil { currentDecodedToken.env = previousDecodedToken?.env diff --git a/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift b/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift index db3fdc0d2b..6b8f7d4da3 100644 --- a/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift +++ b/Sources/PrimerSDK/Classes/Core/Primer/PrimerInternal.swift @@ -146,7 +146,7 @@ internal class PrimerInternal: LogReporter { } .done { PrimerUIManager.presentPaymentUI() - let currencyLoader = CurrencyLoader(storage: DefaultCurrencyStorage(), + let currencyLoader = CurrencyLoader(storage: DefaultCurrencyStorage(), networkService: CurrencyNetworkService()) currencyLoader.updateCurrenciesFromAPI() completion?(nil) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift index 34475d1c3c..c62db8906c 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/CardComponentsManager.swift @@ -9,18 +9,18 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length // swiftlint:disable type_body_length -// swiftlint:disable type_name import Foundation import SafariServices public protocol PrimerHeadlessUniversalCheckoutInputData {} - +// swiftlint:disable type_name @available(*, deprecated, message: "CardComponentsManager is no longer supported, please use PrimerHeadlessUniversalCheckout instead") public protocol PrimerHeadlessUniversalCheckoutCardComponentsManagerDelegate: AnyObject { func cardComponentsManager(_ cardComponentsManager: PrimerHeadlessUniversalCheckout.CardComponentsManager, isCardFormValid: Bool) } +// swiftlint:enable type_name extension PrimerHeadlessUniversalCheckout { @@ -1330,5 +1330,4 @@ extension PrimerHeadlessUniversalCheckout.CardComponentsManager: SFSafariViewCon // swiftlint:enable cyclomatic_complexity // swiftlint:enable function_body_length // swiftlint:enable type_body_length -// swiftlint:enable type_name // swiftlint:enable file_length diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift index 8da989a62e..2cca29ba88 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessBanksComponentWrapper.swift @@ -5,8 +5,6 @@ // Created by Alexandra Lovin on 22.11.2023. // -// swiftlint:disable type_name - import Foundation @objc public protocol BanksComponentErrorable: AnyObject { @objc func didReceiveError(_ error: NSError) @@ -28,6 +26,7 @@ import Foundation @objc func didReceiveValidationStatus(_ status: ValidStatus) } +// swiftlint:disable type_name @objc public protocol PrimerHeadlessBanksComponentWrapperDelegate: AnyObject, PrimerHeadlessSubmitable, PrimerHeadlessStartable { @objc var stepDelegate: BanksComponentSteppable? { get set } @objc var errorDelegate: BanksComponentErrorable? { get set } diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift index 3dd734b6ec..d51027be62 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift @@ -12,7 +12,8 @@ import PrimerKlarnaSDK extension PrimerHeadlessUniversalCheckout { public class KlarnaManager: NSObject { public func provideKlarnaComponent(with intent: PrimerSessionIntent) throws -> (any KlarnaComponent)? { - guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs?.first(where: { $0.type == "KLARNA" }) + guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs? + .first(where: { $0.type == "KLARNA" }) else { let err = PrimerError.generic(message: "Unable to locate a valid payment method configuration.", userInfo: ["file": #file, @@ -23,7 +24,7 @@ extension PrimerHeadlessUniversalCheckout { ErrorHandler.handle(error: err) throw err } - + if (intent == .vault && !paymentMethod.isVaultingEnabled) || (intent == .checkout && !paymentMethod.isCheckoutEnabled) { let err = PrimerError.unsupportedIntent(intent: intent, diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift index 874a87fdbe..0052e7f835 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift @@ -5,7 +5,6 @@ // Created by Evangelos on 12/7/22. // -// swiftlint:disable type_name // swiftlint:disable cyclomatic_complexity // swiftlint:disable file_length // swiftlint:disable function_body_length @@ -14,6 +13,7 @@ import Foundation import SafariServices +// swiftlint:disable type_name @objc public protocol PrimerHeadlessUniversalCheckoutRawDataManagerDelegate { @@ -732,7 +732,11 @@ Make sure you call the decision handler otherwise the SDK will hang." } guard let selectedRetailer = rawData as? PrimerRetailerData, - let selectedRetailerName = (initializationData as? RetailOutletsList)?.result.first(where: { $0.id == selectedRetailer.id })?.name else { + let selectedRetailerName = (initializationData as? RetailOutletsList)? + .result + .first(where: { $0.id == selectedRetailer.id })? + .name + else { let err = PrimerError.invalidValue(key: "rawData.id", value: "Invalid Retailer Identifier", userInfo: ["file": #file, diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift index c26fae6f24..9c8129149a 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElement.swift @@ -188,10 +188,9 @@ public enum PrimerInputElementType: Int { // swiftlint:disable type_name @objc public protocol PrimerHeadlessUniversalCheckoutInputElement { - // swiftlint:enable type_name var inputElementDelegate: PrimerInputElementDelegate! { get set } var type: PrimerInputElementType { get set } var isValid: Bool { get } } - +// swiftlint:enable type_name // swiftlint:enable cyclomatic_complexity diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift index 611a051b70..6da743c889 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutInputElementDelegate.swift @@ -6,7 +6,6 @@ // // swiftlint:disable cyclomatic_complexity -// swiftlint:disable function_body_length import UIKit @@ -40,7 +39,7 @@ extension PrimerHeadlessUniversalCheckout { func textFieldDidEndEditing(_ textField: UITextField) { self.inputElementDelegate?.inputElementDidBlur?(self.inputElement) } - + // swiftlint:disable function_body_length func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift index 1a71e62e55..4ac2483f86 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift @@ -36,7 +36,7 @@ extension PrimerHeadlessUniversalCheckout { init?(paymentMethodType: String) { guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs? - .first(where: { $0.type == paymentMethodType }) + .first(where: { $0.type == paymentMethodType }) else { return nil } diff --git a/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift b/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift index aec33ceb61..c1ec16468f 100644 --- a/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift +++ b/Sources/PrimerSDK/Classes/Data Models/ClientToken.swift @@ -1,5 +1,3 @@ -// swiftlint:disable function_body_length - import Foundation extension Request.Body { @@ -291,4 +289,3 @@ extension DecodedJWTToken { } } } -// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift b/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift index eca45d7911..e235fb5378 100644 --- a/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift +++ b/Sources/PrimerSDK/Classes/Data Models/Currency/CurrencyLoader.swift @@ -5,8 +5,6 @@ // Created by Boris on 11.1.24.. // -// swiftlint:disable function_body_length - import Foundation var inMemoryCurrencies: [Currency]? = [] @@ -100,4 +98,3 @@ public class CurrencyLoader: LogReporter { } } } -// swiftlint:enable function_body_length diff --git a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift index d26022973d..96bc3881f6 100644 --- a/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift +++ b/Sources/PrimerSDK/Classes/Error Handler/PrimerValidationError.swift @@ -8,7 +8,6 @@ // swiftlint:disable type_body_length // swiftlint:disable file_length // swiftlint:disable identifier_name -// swiftlint:disable function_body_length import Foundation @@ -401,5 +400,4 @@ extension PrimerValidationError: Equatable { } // swiftlint:enable type_body_length // swiftlint:enable identifier_name -// swiftlint:enable function_body_length // swiftlint:enable file_length From 036df87da100bb023fac7f852197e0788e7433b3 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Thu, 29 Feb 2024 13:29:43 +0100 Subject: [PATCH 10/21] Finish UI implementation --- .../Text Fields/PrimerCVVFieldView.swift | 21 +-- .../Text Fields/PrimerTextFieldView.swift | 4 +- .../Root/CVVRecaptureViewController.swift | 157 ++++++++++++++++++ .../Root/PrimerRootViewController.swift | 13 +- ...rimerUniversalCheckoutViewController.swift | 45 +++-- ...outWithVaultedPaymentMethodViewModel.swift | 9 +- 6 files changed, 214 insertions(+), 35 deletions(-) create mode 100644 Sources/PrimerSDK/Classes/User Interface/Root/CVVRecaptureViewController.swift diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift index f869f58283..2ee7684c64 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCVVFieldView.swift @@ -76,19 +76,16 @@ public final class PrimerCVVFieldView: PrimerTextFieldView { primerTextField.internalText = newText primerTextField.text = newText + let isValidCVVLength: Bool? + if let cvvLength = cardNetwork.validation?.code.length { + isValidCVVLength = newText.count == cvvLength + } else { + isValidCVVLength = nil + } + switch validation { - case .valid: - if let cvvLength = cardNetwork.validation?.code.length, newText.count == cvvLength { - delegate?.primerTextFieldView(self, isValid: true) - } else { - delegate?.primerTextFieldView(self, isValid: nil) - } - case .invalid: - if let cvvLength = cardNetwork.validation?.code.length, newText.count == cvvLength { - delegate?.primerTextFieldView(self, isValid: false) - } else { - delegate?.primerTextFieldView(self, isValid: nil) - } + case .valid, .invalid: + delegate?.primerTextFieldView(self, isValid: isValidCVVLength) default: delegate?.primerTextFieldView(self, isValid: nil) } diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift index c0a9bdc404..c2b67a0f56 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift @@ -12,10 +12,10 @@ import UIKit /// all have a delegate of PrimerTextFieldViewDelegate type. public protocol PrimerTextFieldViewDelegate: AnyObject { /// Will return true if valid, false if invalid, nil if it cannot be detected yet. - /// It is applied on all PrimerTextFieldViews. + /// It is applied on all PrimerTextFieldViews. func primerTextFieldView(_ primerTextFieldView: PrimerTextFieldView, isValid: Bool?) /// Will return the card network (e.g. Visa) detected, unknown if the network cannot be detected. - /// Only applies on PrimerCardNumberFieldView + /// Only applies on PrimerCardNumberFieldView func primerTextFieldView(_ primerTextFieldView: PrimerTextFieldView, didDetectCardNetwork cardNetwork: CardNetwork?) /// Will return a the validation error on the text input. func primerTextFieldView(_ primerTextFieldView: PrimerTextFieldView, validationDidFailWithError error: Error) diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecaptureViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecaptureViewController.swift new file mode 100644 index 0000000000..6d8647819f --- /dev/null +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecaptureViewController.swift @@ -0,0 +1,157 @@ +// +// CVVRecaptureViewController.swift +// PrimerSDK +// +// Created by Boris on 28.2.24.. +// + +import UIKit + +class CVVRecaptureViewController: UIViewController { + + var didSubmitCvv: ((String) -> Void)? + var cardButtonViewModel: CardButtonViewModel! + + private let theme: PrimerThemeProtocol = DependencyContainer.resolve() + private let explanationLabel = UILabel() + private let imageView = UIImageView() + private let cardNumberLabel = UILabel() + private var cvvField: PrimerCVVFieldView! + private var cvvContainerView: PrimerCustomFieldView! + private let continueButton = PrimerButton() + + override func viewDidLoad() { + super.viewDidLoad() + setupViews() + title = "Enter CVV" + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + _ = cvvField.becomeFirstResponder() + } + + // MARK: - View Setup Functions + private let padding: CGFloat = 16.0 + private let height: CGFloat = 48.0 + + private func setupViews() { + setupExplanationLabel() + setupImageView() + setupCardNumberLabel() + setupCVVContainerView() + setupContinueButton(with: "Continue") + } + + private func setupExplanationLabel() { + explanationLabel.text = "Input the 3 or 4 digit security code on your card for a secure payment." + explanationLabel.numberOfLines = 0 + explanationLabel.textColor = theme.text.body.color + explanationLabel.font = .systemFont(ofSize: CGFloat(theme.text.body.fontSize)) + view.addSubview(explanationLabel) + activateExplanationLabelConstraints() + } + + private func setupImageView() { + imageView.image = cardButtonViewModel.imageName.image + imageView.clipsToBounds = true + imageView.contentMode = .scaleAspectFit + view.addSubview(imageView) + imageView.translatesAutoresizingMaskIntoConstraints = false + activateImageViewConstraints() + } + + private func setupCardNumberLabel() { + cardNumberLabel.text = cardButtonViewModel.last4 + cardNumberLabel.textColor = theme.text.body.color + cardNumberLabel.font = .systemFont(ofSize: CGFloat(theme.text.body.fontSize), weight: .bold) + view.addSubview(cardNumberLabel) + cardNumberLabel.translatesAutoresizingMaskIntoConstraints = false + activateCardNumberLabelConstraints() + } + + private func setupCVVContainerView() { + cvvField = PrimerCVVField.cvvFieldViewWithDelegate(self) + cvvField.cardNetwork = CardNetwork(cardNetworkStr: self.cardButtonViewModel.network) + cvvField.isValid = { text in + let cardNetwork = CardNetwork(cardNetworkStr: self.cardButtonViewModel.network) + return !text.isEmpty && text.isValidCVV(cardNetwork: cardNetwork) + } + cvvContainerView = PrimerCVVField.cvvContainerViewFieldView(cvvField) + view.addSubview(cvvContainerView) + cvvContainerView.translatesAutoresizingMaskIntoConstraints = false + activateCVVContainerViewConstraints() + } + + private func setupContinueButton(with title: String) { + continueButton.layer.cornerRadius = 4 + continueButton.setTitle(title, for: .normal) + continueButton.setTitleColor(theme.mainButton.text.color, for: .normal) + continueButton.titleLabel?.font = .boldSystemFont(ofSize: 19) + continueButton.backgroundColor = theme.mainButton.color(for: .enabled) + continueButton.addTarget(self, action: #selector(continueButtonTapped), for: .touchUpInside) + continueButton.heightAnchor.constraint(equalToConstant: 48).isActive = true + continueButton.isEnabled = false + continueButton.backgroundColor = theme.mainButton.color(for: .disabled) + view.addSubview(continueButton) + continueButton.translatesAutoresizingMaskIntoConstraints = false + activateContinueButtonConstraints() + } + + private func activateExplanationLabelConstraints() { + explanationLabel.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + explanationLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: padding), + explanationLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), + explanationLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding) + ]) + } + + private func activateImageViewConstraints() { + NSLayoutConstraint.activate([ + imageView.topAnchor.constraint(equalTo: explanationLabel.bottomAnchor, constant: 24), + imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), + imageView.widthAnchor.constraint(equalToConstant: 56), + imageView.heightAnchor.constraint(equalToConstant: 40) + ]) + } + + private func activateCardNumberLabelConstraints() { + NSLayoutConstraint.activate([ + cardNumberLabel.centerYAnchor.constraint(equalTo: imageView.centerYAnchor), + cardNumberLabel.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: padding) + ]) + } + + private func activateCVVContainerViewConstraints() { + NSLayoutConstraint.activate([ + cvvContainerView.centerYAnchor.constraint(equalTo: imageView.centerYAnchor), + cvvContainerView.leadingAnchor.constraint(equalTo: cardNumberLabel.trailingAnchor, constant: 24), + cvvContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding) + ]) + } + + private func activateContinueButtonConstraints() { + NSLayoutConstraint.activate([ + continueButton.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 24), + continueButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), + continueButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding), + continueButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: padding) + ]) + } + + @objc private func continueButtonTapped() { + didSubmitCvv?(cvvField.cvv) + } +} + +extension CVVRecaptureViewController: PrimerTextFieldViewDelegate { + + func primerTextFieldView(_ primerTextFieldView: PrimerTextFieldView, isValid: Bool?) { + print(isValid!) + continueButton.isEnabled = isValid ?? true + let continueButtonColor = theme.mainButton.color(for: (isValid ?? true) ? .enabled : .disabled) + continueButton.backgroundColor = continueButtonColor + } +} diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift index 6084673d54..25b3e0280d 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerRootViewController.swift @@ -221,7 +221,7 @@ internal class PrimerRootViewController: PrimerViewController { view.layoutIfNeeded() } - internal func show(viewController: UIViewController) { + internal func show(viewController: UIViewController, animated: Bool = false) { viewController.view.translatesAutoresizingMaskIntoConstraints = false viewController.view.widthAnchor.constraint(equalToConstant: self.childView.frame.width).isActive = true viewController.view.layoutIfNeeded() @@ -253,7 +253,7 @@ internal class PrimerRootViewController: PrimerViewController { } if isPresented { - self.navController.setViewControllers([cvc], animated: false) + self.navController.setViewControllers([cvc], animated: animated) let container = PrimerViewController() container.addChild(self.navController) @@ -271,7 +271,7 @@ internal class PrimerRootViewController: PrimerViewController { container.view.bottomAnchor.constraint(equalTo: self.childView.bottomAnchor, constant: 0).isActive = true container.didMove(toParent: self) } else { - self.navController.pushViewController(viewController: cvc, animated: false) { + self.navController.pushViewController(viewController: cvc, animated: animated) { var viewControllers = self.navController.viewControllers for (index, viewController) in viewControllers.enumerated().reversed() { // If the loading screen is the last one in the stack, do not remove it yet. @@ -353,9 +353,8 @@ internal class PrimerRootViewController: PrimerViewController { } } - internal func popViewController() { + internal func popViewController(animated: Bool = false, completion: (() -> Void)? = nil) { let index = navController.viewControllers.count-2 - guard navController.viewControllers.count > 1, let viewController = (navController.viewControllers[index] as? PrimerContainerViewController)?.childViewController else { @@ -371,12 +370,12 @@ internal class PrimerRootViewController: PrimerViewController { childViewHeightConstraint.constant = navigationControllerHeight + bottomPadding - navController.popViewController(animated: false) + navController.popViewController(animated: animated) UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut) { self.view.layoutIfNeeded() } completion: { _ in - + completion?() } } diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift index 44c2081882..f0c2c45c34 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift @@ -22,6 +22,7 @@ internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { private var onClientSessionActionUpdateCompletion: ((Error?) -> Void)? private var singleUsePaymentMethod: PrimerPaymentMethodTokenData? private var resumePaymentId: String? + private var cardButtonViewModel: CardButtonViewModel! override func viewDidLoad() { super.viewDidLoad() @@ -107,6 +108,7 @@ internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { if let selectedPaymentMethod = universalCheckoutViewModel.selectedPaymentMethod, let cardButtonViewModel = selectedPaymentMethod.cardButtonViewModel { + self.cardButtonViewModel = cardButtonViewModel self.selectedPaymentMethod = selectedPaymentMethod if savedPaymentMethodStackView == nil { @@ -287,20 +289,41 @@ internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { ) Analytics.Service.record(event: viewEvent) - enableView(false) - payButton.startAnimating() - - let checkoutWithVaultedPaymentMethodVM = CheckoutWithVaultedPaymentMethodViewModel(configuration: config, - selectedPaymentMethodTokenData: selectedPaymentMethod) - firstly { - checkoutWithVaultedPaymentMethodVM.start() + // TODO: (BNI) ping @aladin + let backendFlag = true + + if backendFlag { + let cvvViewController = CVVRecaptureViewController() + cvvViewController.cardButtonViewModel = cardButtonViewModel + cvvViewController.didSubmitCvv = { cvv in + PrimerUIManager.primerRootViewController?.popViewController(animated: true, completion: { + let cvvData = PrimerVaultedCardAdditionalData(cvv: cvv) + startCheckout(withAdditionalData: cvvData) + }) + } + PrimerUIManager.primerRootViewController?.show(viewController: cvvViewController, animated: true) + } else { + startCheckout(withAdditionalData: nil) } - .ensure { - self.enableView(true) + + // Common functionality to start the checkout process + func startCheckout(withAdditionalData additionalData: PrimerVaultedCardAdditionalData?) { + payButton.startAnimating() + enableView(false) + + let checkoutWithVaultedPaymentMethodVM = CheckoutWithVaultedPaymentMethodViewModel(configuration: config, + selectedPaymentMethodTokenData: selectedPaymentMethod, + additionalData: additionalData) + firstly { + checkoutWithVaultedPaymentMethodVM.start() + } + .ensure { + self.payButton.stopAnimating() + self.enableView(true) + } + .catch { _ in } } - .catch { _ in } } - } extension PrimerUniversalCheckoutViewController { diff --git a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift index e793257b24..8c9743fbfc 100644 --- a/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/TokenizationViewModels/CheckoutWithVaultedPaymentMethodViewModel.swift @@ -22,8 +22,8 @@ class CheckoutWithVaultedPaymentMethodViewModel: LogReporter { var paymentMethodTokenData: PrimerPaymentMethodTokenData! var paymentCheckoutData: PrimerCheckoutData? var successMessage: String? - var resumePaymentId: String? + var additionalData: PrimerVaultedCardAdditionalData? // Events var didStartTokenization: (() -> Void)? @@ -35,9 +35,12 @@ class CheckoutWithVaultedPaymentMethodViewModel: LogReporter { var willDismissPaymentMethodUI: (() -> Void)? var didDismissPaymentMethodUI: (() -> Void)? - init(configuration: PrimerPaymentMethod, selectedPaymentMethodTokenData: PrimerPaymentMethodTokenData) { + init(configuration: PrimerPaymentMethod, + selectedPaymentMethodTokenData: PrimerPaymentMethodTokenData, + additionalData: PrimerVaultedCardAdditionalData?) { self.config = configuration self.selectedPaymentMethodTokenData = selectedPaymentMethodTokenData + self.additionalData = additionalData } func start() -> Promise { @@ -116,7 +119,7 @@ class CheckoutWithVaultedPaymentMethodViewModel: LogReporter { } let tokenizationService = TokenizationService() - return tokenizationService.exchangePaymentMethodToken(paymentMethodTokenId, vaultedPaymentMethodAdditionalData: nil) + return tokenizationService.exchangePaymentMethodToken(paymentMethodTokenId, vaultedPaymentMethodAdditionalData: self.additionalData) } .then { paymentMethodTokenData -> Promise in self.paymentMethodTokenData = paymentMethodTokenData From f11f9e75d9a998b87244389c150a1bec03b6f314 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Tue, 5 Mar 2024 17:50:59 +0100 Subject: [PATCH 11/21] Implement MVVM design pattern, update flow --- .../CVVRecaptureViewController.swift | 55 ++++++++++++------- .../CVVRecapture/CVVRecaptureViewModel.swift | 36 ++++++++++++ ...rimerUniversalCheckoutViewController.swift | 12 ++-- 3 files changed, 76 insertions(+), 27 deletions(-) rename Sources/PrimerSDK/Classes/User Interface/Root/{ => CVVRecapture}/CVVRecaptureViewController.swift (79%) create mode 100644 Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecaptureViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift similarity index 79% rename from Sources/PrimerSDK/Classes/User Interface/Root/CVVRecaptureViewController.swift rename to Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift index 6d8647819f..a0d2575dfc 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecaptureViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift @@ -9,9 +9,7 @@ import UIKit class CVVRecaptureViewController: UIViewController { - var didSubmitCvv: ((String) -> Void)? - var cardButtonViewModel: CardButtonViewModel! - + var viewModel: CVVRecaptureViewModel private let theme: PrimerThemeProtocol = DependencyContainer.resolve() private let explanationLabel = UILabel() private let imageView = UIImageView() @@ -20,22 +18,42 @@ class CVVRecaptureViewController: UIViewController { private var cvvContainerView: PrimerCustomFieldView! private let continueButton = PrimerButton() + // Designated initializer + init(viewModel: CVVRecaptureViewModel) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + // Required initializer for decoding + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func viewDidLoad() { super.viewDidLoad() setupViews() - title = "Enter CVV" + bindViewModel() } - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) _ = cvvField.becomeFirstResponder() } + private func bindViewModel() { + viewModel.onContinueButtonStateChange = { [weak self] isEnabled in + self?.continueButton.isEnabled = isEnabled + let continueButtonColor = isEnabled ? self?.theme.mainButton.color(for: .enabled) : self?.theme.mainButton.color(for: .disabled) + self?.continueButton.backgroundColor = continueButtonColor + } + } + // MARK: - View Setup Functions private let padding: CGFloat = 16.0 private let height: CGFloat = 48.0 - + private let defaultElementDistance: CGFloat = 24.0 private func setupViews() { + title = "Enter CVV" setupExplanationLabel() setupImageView() setupCardNumberLabel() @@ -53,7 +71,7 @@ class CVVRecaptureViewController: UIViewController { } private func setupImageView() { - imageView.image = cardButtonViewModel.imageName.image + imageView.image = viewModel.cardButtonViewModel.imageName.image imageView.clipsToBounds = true imageView.contentMode = .scaleAspectFit view.addSubview(imageView) @@ -62,7 +80,7 @@ class CVVRecaptureViewController: UIViewController { } private func setupCardNumberLabel() { - cardNumberLabel.text = cardButtonViewModel.last4 + cardNumberLabel.text = viewModel.cardButtonViewModel.last4 cardNumberLabel.textColor = theme.text.body.color cardNumberLabel.font = .systemFont(ofSize: CGFloat(theme.text.body.fontSize), weight: .bold) view.addSubview(cardNumberLabel) @@ -72,9 +90,9 @@ class CVVRecaptureViewController: UIViewController { private func setupCVVContainerView() { cvvField = PrimerCVVField.cvvFieldViewWithDelegate(self) - cvvField.cardNetwork = CardNetwork(cardNetworkStr: self.cardButtonViewModel.network) + cvvField.cardNetwork = CardNetwork(cardNetworkStr: self.viewModel.cardButtonViewModel.network) cvvField.isValid = { text in - let cardNetwork = CardNetwork(cardNetworkStr: self.cardButtonViewModel.network) + let cardNetwork = CardNetwork(cardNetworkStr: self.viewModel.cardButtonViewModel.network) return !text.isEmpty && text.isValidCVV(cardNetwork: cardNetwork) } cvvContainerView = PrimerCVVField.cvvContainerViewFieldView(cvvField) @@ -110,7 +128,7 @@ class CVVRecaptureViewController: UIViewController { private func activateImageViewConstraints() { NSLayoutConstraint.activate([ - imageView.topAnchor.constraint(equalTo: explanationLabel.bottomAnchor, constant: 24), + imageView.topAnchor.constraint(equalTo: explanationLabel.bottomAnchor, constant: defaultElementDistance), imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), imageView.widthAnchor.constraint(equalToConstant: 56), imageView.heightAnchor.constraint(equalToConstant: 40) @@ -127,14 +145,14 @@ class CVVRecaptureViewController: UIViewController { private func activateCVVContainerViewConstraints() { NSLayoutConstraint.activate([ cvvContainerView.centerYAnchor.constraint(equalTo: imageView.centerYAnchor), - cvvContainerView.leadingAnchor.constraint(equalTo: cardNumberLabel.trailingAnchor, constant: 24), + cvvContainerView.leadingAnchor.constraint(equalTo: cardNumberLabel.trailingAnchor, constant: defaultElementDistance), cvvContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding) ]) } private func activateContinueButtonConstraints() { NSLayoutConstraint.activate([ - continueButton.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 24), + continueButton.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: defaultElementDistance), continueButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), continueButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding), continueButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: padding) @@ -142,16 +160,13 @@ class CVVRecaptureViewController: UIViewController { } @objc private func continueButtonTapped() { - didSubmitCvv?(cvvField.cvv) + continueButton.startAnimating() + viewModel.continueButtonTapped(with: cvvField.cvv) } } extension CVVRecaptureViewController: PrimerTextFieldViewDelegate { - func primerTextFieldView(_ primerTextFieldView: PrimerTextFieldView, isValid: Bool?) { - print(isValid!) - continueButton.isEnabled = isValid ?? true - let continueButtonColor = theme.mainButton.color(for: (isValid ?? true) ? .enabled : .disabled) - continueButton.backgroundColor = continueButtonColor + viewModel.isValidCvv = isValid ?? true } } diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift new file mode 100644 index 0000000000..e020a7b300 --- /dev/null +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift @@ -0,0 +1,36 @@ +// +// CVVRecaptureViewModel.swift +// PrimerSDK +// +// Created by Boris on 29.2.24.. +// + +import Foundation + +class CVVRecaptureViewModel { + + var didSubmitCvv: ((String) -> Void)? + var cardButtonViewModel: CardButtonViewModel! + var onContinueButtonStateChange: ((Bool) -> Void)? + + var isValidCvv: Bool = false { + didSet { + updateContinueButtonState() + } + } + + private let theme: PrimerThemeProtocol = DependencyContainer.resolve() + + // Logic to handle continue button tap + func continueButtonTapped(with cvv: String) { + if isValidCvv { + didSubmitCvv?(cvv) + } + } + + // Update UI based on CVV validation + private func updateContinueButtonState() { + // This closure can be used by the ViewController to update the continue button's state + onContinueButtonStateChange?(isValidCvv) + } +} diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift index f0c2c45c34..ac8b53e31b 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift @@ -293,13 +293,11 @@ internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { let backendFlag = true if backendFlag { - let cvvViewController = CVVRecaptureViewController() - cvvViewController.cardButtonViewModel = cardButtonViewModel - cvvViewController.didSubmitCvv = { cvv in - PrimerUIManager.primerRootViewController?.popViewController(animated: true, completion: { - let cvvData = PrimerVaultedCardAdditionalData(cvv: cvv) - startCheckout(withAdditionalData: cvvData) - }) + let cvvViewController = CVVRecaptureViewController(viewModel: CVVRecaptureViewModel()) + cvvViewController.viewModel.cardButtonViewModel = cardButtonViewModel + cvvViewController.viewModel.didSubmitCvv = { cvv in + let cvvData = PrimerVaultedCardAdditionalData(cvv: cvv) + startCheckout(withAdditionalData: cvvData) } PrimerUIManager.primerRootViewController?.show(viewController: cvvViewController, animated: true) } else { From b88debea814558aab3e3e6c80f1b9ab2e921e6db Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Tue, 5 Mar 2024 18:28:31 +0100 Subject: [PATCH 12/21] Fix card network image rendering --- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../Classes/User Interface/Primer/CardButton.swift | 2 +- .../Root/CVVRecapture/CVVRecaptureViewController.swift | 9 ++++++--- .../Root/CVVRecapture/CVVRecaptureViewModel.swift | 8 +------- .../Vault/VaultPaymentMethodViewController.swift | 7 ++++++- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Debug App/Primer.io Debug App.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Debug App/Primer.io Debug App.xcworkspace/xcshareddata/swiftpm/Package.resolved index f45a5d3bdf..0433329029 100644 --- a/Debug App/Primer.io Debug App.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Debug App/Primer.io Debug App.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/primer-io/primer-klarna-sdk-ios", "state": { "branch": null, - "revision": "146d9ae8f7accc1ad7b64b2a455106d54914edef", - "version": "1.1.0" + "revision": "f13260c24a900f28e21bafd213c22191e6280e86", + "version": "1.0.4" } }, { diff --git a/Sources/PrimerSDK/Classes/User Interface/Primer/CardButton.swift b/Sources/PrimerSDK/Classes/User Interface/Primer/CardButton.swift index dd92cfdfe1..b849486d72 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Primer/CardButton.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Primer/CardButton.swift @@ -38,7 +38,7 @@ internal class CardButton: PrimerButton { toggleIcon() } - addCardIcon(image: model.imageName.image) + addCardIcon(image: CardNetwork(cardNetworkStr: model.network).icon) addBorder() switch model.paymentMethodType { diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift index a0d2575dfc..d97c64b07f 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift @@ -42,8 +42,9 @@ class CVVRecaptureViewController: UIViewController { private func bindViewModel() { viewModel.onContinueButtonStateChange = { [weak self] isEnabled in + if self?.continueButton.isAnimating == true { return } self?.continueButton.isEnabled = isEnabled - let continueButtonColor = isEnabled ? self?.theme.mainButton.color(for: .enabled) : self?.theme.mainButton.color(for: .disabled) + let continueButtonColor = self?.theme.mainButton.color(for: isEnabled ? .enabled : .disabled) self?.continueButton.backgroundColor = continueButtonColor } } @@ -71,7 +72,8 @@ class CVVRecaptureViewController: UIViewController { } private func setupImageView() { - imageView.image = viewModel.cardButtonViewModel.imageName.image + let networkIcon = CardNetwork(cardNetworkStr: viewModel.cardButtonViewModel.network).icon + imageView.image = networkIcon imageView.clipsToBounds = true imageView.contentMode = .scaleAspectFit view.addSubview(imageView) @@ -90,7 +92,7 @@ class CVVRecaptureViewController: UIViewController { private func setupCVVContainerView() { cvvField = PrimerCVVField.cvvFieldViewWithDelegate(self) - cvvField.cardNetwork = CardNetwork(cardNetworkStr: self.viewModel.cardButtonViewModel.network) + cvvField.cardNetwork = CardNetwork(cardNetworkStr: viewModel.cardButtonViewModel.network) cvvField.isValid = { text in let cardNetwork = CardNetwork(cardNetworkStr: self.viewModel.cardButtonViewModel.network) return !text.isEmpty && text.isValidCVV(cardNetwork: cardNetwork) @@ -161,6 +163,7 @@ class CVVRecaptureViewController: UIViewController { @objc private func continueButtonTapped() { continueButton.startAnimating() + continueButton.isEnabled = false viewModel.continueButtonTapped(with: cvvField.cvv) } } diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift index e020a7b300..b4e998e240 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift @@ -15,7 +15,7 @@ class CVVRecaptureViewModel { var isValidCvv: Bool = false { didSet { - updateContinueButtonState() + onContinueButtonStateChange?(isValidCvv) } } @@ -27,10 +27,4 @@ class CVVRecaptureViewModel { didSubmitCvv?(cvv) } } - - // Update UI based on CVV validation - private func updateContinueButtonState() { - // This closure can be used by the ViewController to update the continue button's state - onContinueButtonStateChange?(isValidCvv) - } } diff --git a/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift index 6af9f7734d..05cad32273 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Vault/VaultPaymentMethodViewController.swift @@ -109,7 +109,12 @@ internal class VaultedPaymentInstrumentCell: UITableViewCell { verticalRightStackView.distribution = .fillEqually verticalRightStackView.spacing = 0 - cardNetworkImageView.image = paymentMethod.cardButtonViewModel?.imageName.image + if let network = paymentMethod.cardButtonViewModel?.network { + let cardNetworkImage = CardNetwork(cardNetworkStr: network).icon + cardNetworkImageView.image = cardNetworkImage + } else { + cardNetworkImageView.image = paymentMethod.cardButtonViewModel?.imageName.image + } cardNetworkImageView.contentMode = .scaleAspectFit checkmarkImageView.image = isDeleting ? From 7532a936c0f879ed4c766d06810617277d4a06fa Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Wed, 13 Mar 2024 16:32:39 +0100 Subject: [PATCH 13/21] Treat Localizable.strings as textual file --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..f4ed7ca701 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.strings diff From f39f49bd9300c4ece2ec5e8eb8f93aa7d007ed2c Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Wed, 13 Mar 2024 16:36:53 +0100 Subject: [PATCH 14/21] Update wording --- .../View Controllers/Merchant Helpers/MerchantHelpers.swift | 3 --- .../Root/CVVRecapture/CVVRecaptureViewController.swift | 2 +- .../Root/CVVRecapture/CVVRecaptureViewModel.swift | 5 +++++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift b/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift index a2ce269e58..7dd2c759f5 100644 --- a/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift +++ b/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift @@ -115,7 +115,4 @@ struct MerchantMockDataManager { ], ] ] - - } - diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift index d97c64b07f..98fbec8d8c 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift @@ -63,7 +63,7 @@ class CVVRecaptureViewController: UIViewController { } private func setupExplanationLabel() { - explanationLabel.text = "Input the 3 or 4 digit security code on your card for a secure payment." + explanationLabel.text = "Input the \(viewModel.cvvLength) digit security code on your card for a secure payment." explanationLabel.numberOfLines = 0 explanationLabel.textColor = theme.text.body.color explanationLabel.font = .systemFont(ofSize: CGFloat(theme.text.body.fontSize)) diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift index b4e998e240..823f27f6d5 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift @@ -19,6 +19,11 @@ class CVVRecaptureViewModel { } } + var cvvLength: Int { + let network = CardNetwork(cardNetworkStr: cardButtonViewModel.network) + return network.validation?.code.length ?? 3 + } + private let theme: PrimerThemeProtocol = DependencyContainer.resolve() // Logic to handle continue button tap From a1918d82e24205a37ddb6268f1c5750db7e136e9 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 18 Mar 2024 15:23:01 +0100 Subject: [PATCH 15/21] Add localized strings --- .../Classes/Core/Constants/Strings.swift | 28 ++++++++++++++++++ .../CVVRecaptureViewController.swift | 7 +++-- .../Localizable/ar.lproj/Localizable.strings | Bin 21026 -> 21578 bytes .../Localizable/da.lproj/Localizable.strings | Bin 21028 -> 21580 bytes .../Localizable/de.lproj/Localizable.strings | Bin 21612 -> 22194 bytes .../Localizable/el.lproj/Localizable.strings | Bin 21824 -> 22392 bytes .../Localizable/en.lproj/Localizable.strings | Bin 22118 -> 22636 bytes .../Localizable/es.lproj/Localizable.strings | Bin 21820 -> 22388 bytes .../Localizable/fr.lproj/Localizable.strings | Bin 21986 -> 22574 bytes .../Localizable/it.lproj/Localizable.strings | Bin 21560 -> 22140 bytes .../Localizable/ms.lproj/Localizable.strings | Bin 22428 -> 22970 bytes .../Localizable/nb.lproj/Localizable.strings | Bin 21146 -> 21684 bytes .../Localizable/nl.lproj/Localizable.strings | Bin 21326 -> 21868 bytes .../Localizable/pl.lproj/Localizable.strings | Bin 21402 -> 21974 bytes .../Localizable/pt.lproj/Localizable.strings | Bin 21652 -> 22260 bytes .../Localizable/sv.lproj/Localizable.strings | Bin 21078 -> 21628 bytes .../Localizable/th.lproj/Localizable.strings | Bin 21852 -> 22382 bytes .../Localizable/tr.lproj/Localizable.strings | Bin 21054 -> 21572 bytes .../zh-CN.lproj/Localizable.strings | Bin 19636 -> 20040 bytes .../zh-HK.lproj/Localizable.strings | Bin 19636 -> 20054 bytes .../zh-TW.lproj/Localizable.strings | Bin 19638 -> 20056 bytes 21 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift index bf3779d6ca..5c8c4fdc8d 100644 --- a/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift +++ b/Sources/PrimerSDK/Classes/Core/Constants/Strings.swift @@ -936,6 +936,34 @@ extension Strings { comment: "An error message displayed when the Last Name is not correct") } } + + struct CVVRecapture { +// "primer-cvv-recapture-title" = "Enter CVV"; +// +// /* CVV recapture explanation */ +// "primer-cvv-recapture-explanation" = "Input the %d digit security code on your card for a secure payment."; + + static let title = NSLocalizedString( + "primer-cvv-recapture-title", + tableName: nil, + bundle: Bundle.primerResources, + value: "Enter CVV", + comment: "Enter CVV - CVV recapture screen title") + + static let explanation = NSLocalizedString( + "primer-cvv-recapture-explanation", + tableName: nil, + bundle: Bundle.primerResources, + value: "Input the %d digit security code on your card for a secure payment.", + comment: "Some cards have 3 or 4 digits for their CVV card") + + static let buttonTitle = NSLocalizedString( + "continue", + tableName: nil, + bundle: Bundle.primerResources, + value: "Continue", + comment: "Continue") + } } // MARK: - Apple Pay diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift index 98fbec8d8c..9811c202b9 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewController.swift @@ -54,16 +54,17 @@ class CVVRecaptureViewController: UIViewController { private let height: CGFloat = 48.0 private let defaultElementDistance: CGFloat = 24.0 private func setupViews() { - title = "Enter CVV" + title = Strings.CVVRecapture.title setupExplanationLabel() setupImageView() setupCardNumberLabel() setupCVVContainerView() - setupContinueButton(with: "Continue") + setupContinueButton(with: Strings.CVVRecapture.buttonTitle) } private func setupExplanationLabel() { - explanationLabel.text = "Input the \(viewModel.cvvLength) digit security code on your card for a secure payment." + let explanationText = String(format: Strings.CVVRecapture.explanation, viewModel.cvvLength) + explanationLabel.text = explanationText explanationLabel.numberOfLines = 0 explanationLabel.textColor = theme.text.body.color explanationLabel.font = .systemFont(ofSize: CGFloat(theme.text.body.fontSize)) diff --git a/Sources/PrimerSDK/Resources/Localizable/ar.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/ar.lproj/Localizable.strings index 909e5224e6b518f3396e66038f45d5952291cdd9..65ae7eda300f70cb1602a19f4f216ff519ef833f 100644 GIT binary patch delta 452 zcmZ{g!AiqG5QhJP{9q5>R6JDIgwQl-L%c{U9!!&x_9A-lF0lteqLfy=^%aD?fq3xf z3-|)w`V_u|2mehKMU-WCW_JGlW@aBAYp+kWXXmsLB7i{;XIchhjF96TH<)0GarrXX zD&PIJjU2aHyT9`omGgLg*=5K!6PohPX?TB<#5LM?B43GLl=G$4@_ut=_Ago0e(3dP zf=gVZfFshOwu2#$8F7aL8hBL?P1^+`rreXYkt@H+{%4f3$BZXcoZ52+4;O;D0>u)h z5@xcAyiDj!Sc8sYTg2zSaxnv83=(=$M7r6oG^tcWw&aIAVn@~yrLUW|nms@rU!QHq hu;UcyPOF~@l&VXVR}(H$HuF7es-jK$!nU}8eE_etN=Evd*78-z0cNB4g+JM;5e`FN|mCzl63b!61n6`zq+q_J-GsD*M_R}35Ov$a=W zYN_sjRgv2r)VD&fJ3nf)H&9?2&NI{mcIv*iYi{3Eiw#s>T65E}P^`I9HQ}6an!2EJ zM>N5i@^2A!mEnwdBSD?6lo9b*Gcp_Q7*9rJu1P`BfX{WmLdC$m(P&8B2Am(=*AJ=Y zdf+Z|-e-_=^})8IlS8lrUs6nt_W!pFs=g7H6=_KrYM!hHolRL<=ax1yqxaCWCPOVqi$_ RWnRmC91>>CK=YV^S^%V9aM}O> delta 9 Qcmeydj`6@M#tjak02uQGSO5S3 diff --git a/Sources/PrimerSDK/Resources/Localizable/en.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/en.lproj/Localizable.strings index d35850632d5e7905e9e6a584f9bb24681c5e893c..77267cff65c5d9e76ce2717c13f2f18c217654a6 100644 GIT binary patch delta 358 zcmaF1hVjh?#tms(rW(c&2GoJg%v6R7pdC3toAM@KloOx4PmNC4gEdeG0Mh$R?EnA( delta 9 QcmaE}f$`ZI#tms<02$H*od5s; diff --git a/Sources/PrimerSDK/Resources/Localizable/es.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/es.lproj/Localizable.strings index 57beadef3d5dcaaecc571fd4d0750fe46f6c269e..a1fbe0bb650ac625ad7e5cda6d5afc51c1992f85 100644 GIT binary patch delta 409 zcmZ{f&1%9>6oe-WrFBueQE|~4B5ne$bSeHIh&!Px-AcF#)*^|Grih4r2hUr$D1885 zsVjYe&W%zw)R|&YtMjvtnKYwOTwss<1C@GG;s5{u delta 9 Qcmeyej&aW_#tk;102r?XOaK4? diff --git a/Sources/PrimerSDK/Resources/Localizable/fr.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/fr.lproj/Localizable.strings index c5385e69505b7a3c93d6283200b8a6627f2f8cc8..00cc929d77877d829e4cda3ee6a433a82d2ae74d 100644 GIT binary patch delta 452 zcmZ{gK}rKb5Ji7>A={uKxUd}v2|+V!5d{&lQnE6efH1_43UNke#-K~j(8mxYYtJBf z1KT(?Ty>+z<0?yfh- znh`s{aalL$H{8oXHL+kuQ|1i}sqPDoL>JVNt_hFKbfpYt%g;c2swq^L{t?^%*k8<8 z-N7}5B_?wi62)$-wbA}Z6FOIB+{0nro$b~}OMQvX3-0pG^oeHfg*&G@wZ&k zoe^L;zR(OpIRaT O4Etn&KdVUk?cNtPi(ak( delta 9 QcmZ3tf$`C5#tn}`0T_M+)c^nh diff --git a/Sources/PrimerSDK/Resources/Localizable/it.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/it.lproj/Localizable.strings index 6383444c90c6cd7968612d918c16cf4e2ec61b60..3d36c5175aa52a79e69fe9eb15f99bbcff406977 100644 GIT binary patch delta 394 zcmaKoF>3-r5QX1$!AeM?LJ-#lEe=lGlOTd2l_@3I9;d=Va;x5*h<{`LM2ZwC)8_Z2 zN^g<3tAYtA%djwS-uGtr^Ud46dmrJr-h~f^2R!pAtT0222n*yWu#&G)L$2Dj>KbbV z|5eOnIjqVgyy@-z8uuvSB9VN>+A!gTIjQ`VZ)Mjk2WJwPdNNH%js!+VVN({@mB)m% zjGfqS%gHTI#NL!Wg%)o`Ey3KWim7%gW2Ge7T{0B%J-8G7RLc`~6<%TJGfq2_4LbPy fI^zh|Q8KIMqN(A delta 9 QcmeyfhH=LV#tjxB02sUkM*si- diff --git a/Sources/PrimerSDK/Resources/Localizable/ms.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/ms.lproj/Localizable.strings index af622bf77cf6ad94a98e93766cb355972dbffcbb..3cdf62a36da63bcd3adeb7d2e332b5d15820a3da 100644 GIT binary patch delta 394 zcmbQUo^jV^#tn1AC)ZhWh=wtQF(@z;F{CmiGbAz;FqANqG89cd=qEopKvzsMnV}2_ zbJMX3Vz6f5V$f&M0-6O8!7vkOg8~p&0PV;D+LSk0Fj#c* zA2k7e95w)LMN$paQNobPkPp;nZ7Ca`4P>PN&C3R=DF$MYiMe1kK$C&uDL}R9KwJW3 ztAbS)0A*8v7^DZpQUH>9P?1s~3*_(Y$rC-rC!g`=NkcVL56yo-SAboU2h;=dl@`$F gTtGF+Aon53C;{bcfmn$l1gNeEsJa+zdmhw00NeymrT_o{ delta 9 QcmdnBnQ_i~#tn1A0T$>4UH||9 diff --git a/Sources/PrimerSDK/Resources/Localizable/nb.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/nb.lproj/Localizable.strings index 8e6fc3ce235762fa3b49536ecac79486e2b517ca..e226e3a87870117bf2d7cba814b74525ab672c01 100644 GIT binary patch delta 418 zcmZ`#%SyvQ6g^!Dp=hMk(p82)7Y1rSpqNdipc|ouEQL0v4=PF8q~b2$Q0}G#T)J@Q z!q0HikMKV{Gx(w+!@TZ2ubJ|x^7>qPDF?E3506%e5MqQBIo4Ro^0FrWRaI_IPnsd_ zIojC6Ad=lhYQ`B7-GRhb0$+FiAk;N%G?)ZMXb%Z=E!VblW$szcX{-ig(58> zNJrLkTIh?YFgDZ?AEIriIAfSDEOg)z+cPnB+?XG!Z9R4@V#2-7&r|xwjd6@}e()*y E0mE!mga7~l delta 9 Qcmdn8l5y5j#tpNA02UhrI{*Lx diff --git a/Sources/PrimerSDK/Resources/Localizable/nl.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/nl.lproj/Localizable.strings index 182e7cf1592b5686399faf8567a73f2aaf65eae4..73a31abb173026ddee79e893598cf7243e459e7c 100644 GIT binary patch delta 468 zcmZ{gKTZNs5XL_m3tAG1q2NhkLn7E%5euS~g$)V)x~!W;vTN1_>^Q_bfsKW+@CshQ zlXwVzv${byn901n%*^*^=JTcT_1bv9nfO8Lpna(+;gl;VxCX<{wRb?8Tty zbV2smrE)YYHBK}G6~aB&9hID4Ty}1GS7d?%tC{mykIZHpKxQz*p5q*A-g_(tzzhC1 z>HueiEguozl^vboO`-s00!BWlorZPGwNo@~zR%H`%$(ujPiwc|)sJXg+No~61r-KZ AfB*mh delta 9 QcmaE}it*es#tnYK02sjpUH||9 diff --git a/Sources/PrimerSDK/Resources/Localizable/pl.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/pl.lproj/Localizable.strings index 529cc4aba6c55938fbd3a93ba90bdd3a4565c977..bd5da9233683dd58cd404435b6ae9ccecc128794 100644 GIT binary patch delta 450 zcmZ`#y-or_7@RE>a|xj!kz7ICT%rj?^Z|&CP(g#CvoJaDuJAO=0f!0=uRyZh#m36Q z#`mD-Wo(@9ATi-5n@x6ie!iK_zSQbl{bYUnP(HRF-brbM2myQ~NHM|4E<0y-Q9E@5 zymB?Lg(I?`?MkVK0Ya)`Xgp(JhmDH3)ppp#BfQi7g>1u};)z;ghgJ9P;0(^)tAa#yLX!TXyG~Hy@A0W;rVTRz(GP_R1At%^E{`++| M$TZhXm~rj+2VXZ^IsgCw delta 9 Qcmcb%nsL^0#tpNA0T*ZlVgLXD diff --git a/Sources/PrimerSDK/Resources/Localizable/pt.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/pt.lproj/Localizable.strings index 3d4165fa22e873eec4f28e559d4dbc94c55795a2..5eb2dd2398a72bdc60fb831afda286c060b08f95 100644 GIT binary patch delta 441 zcmZ`$u}Z^G6g^owWHu>9#Ft=~K+IMI=^z!CuEkwys)3rsG%4cJZz!+3vxCroD#gjo z5AfVP10pGpn|E){z2}_w-sau<{;;;2$w`C&3M1TdDHMn?#T{~#s8Hzr_*AEX+nZv^ z75>K&>-BY4UkqGJY46O5T3N`c7%ya@E!goO zK5N!beiiO(wLW*rzlbMP%dlYm%wF*#bK)rFS?PkfFeql(FIsVzdnkzQ>c4qiN!N_o zE2oPNiwaNr?Z$aDq{d8!bNIM~jplNVNJ0T)ARuD1r;%?EpNvC>&jn+a diff --git a/Sources/PrimerSDK/Resources/Localizable/sv.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/sv.lproj/Localizable.strings index 18be445ba2e8dc89fdd235d28f9b0fa000bb1193..00a88d047b38650fe59f00fa94329ff821196be6 100644 GIT binary patch delta 437 zcmaKou}T9$5QhJ2ueCTq#N{9g2d8B~u}ZM8(;|KJk|@zlSkGYRL+ld>7M4DZPoNKA zV`bqt8-gGz!`$xPKmY&F%*$i;`IJ2mPB-^d$*HFS;S@B|xrUmn)vZFzj<;gfSuYk^ zsQ!s+6d(FU-0$YSCBM{xa{a4_z9a8&xWdPitu8f_kMG+X^&dWX|H6rNx43UWJenOf zRNbI8CIaUKZO5NiO{odG;M?+^;)P11CC4m88S&eGhL%@h-u?o za(r7joh6eY!+AtKwB2~Jv(~pEJu9{GD^`@NWYLU`*$OeOL$cHnh_zwL*4T2fUjUj| ArT_o{ delta 9 Qcmeyfg7MlC#tmUX02y`!c>n+a diff --git a/Sources/PrimerSDK/Resources/Localizable/th.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/th.lproj/Localizable.strings index 81e4387d21e98fd7007ebd3ce347112f5f8841f3..b5657975a83b7359eee43606248b921f80057d32 100644 GIT binary patch delta 392 zcmcb!it*h##tku{vib~K3YU6vn^1idKr0IN7vV1VKw@v5N)K(ZM~9K}y=B#3YD|_zd?I92|WDUHTaA zj&7YC{N1~>sDwlAJ>S1`?%T6jyqMSFm0flk+l3OviZoZLN`-yDXxoqd-Jn*jBmF{^ z*k&)-I@2{@s9Q}?e05swKRnPx_qa~+&g|1>%MSM%k1?+Q`jWNAM^oaRD^nMzQ>v?T zeWOk2O~FEqT{{1zZs^Xakj^KSaZ2$ha2c44dVmutz4XE!7blN&N6j37<-oXw)+17H ulf$mCtho7weZa9b2RkD-q(fZvq59fj%-D~;LRJfm;MG3SJx&St1jP>uU{VzT delta 9 QcmX@If^pvx#tn8s02aOk5dZ)H diff --git a/Sources/PrimerSDK/Resources/Localizable/zh-CN.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/zh-CN.lproj/Localizable.strings index 35618eea2dacd91584ff1865fe99d7605dfc46cc..51badb04da72fecd0dc7a11d4ef55cd6b8ce5f09 100644 GIT binary patch delta 325 zcmdlolkvnH#tmD1Wc3-e7!(+s8Nz^2fuV>Yl_8lSk)eR0grSt7X!1f=`N=sNVv@-W zWk9HlF3*rUSyoltesX_mAj}LU25SZ`2E3*M?N9*X3ZN}HK)doLpXU&rETbq;kHZe2 zy-2EoI!YKa8S)wO7?gnK*aEQ<1IPu5!CZbVWeNxhjGhH#tmD102cKGWB>pF diff --git a/Sources/PrimerSDK/Resources/Localizable/zh-HK.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/zh-HK.lproj/Localizable.strings index b204678468349fe6972d2a413ad4a95c1378000d..78830543b561287b8fef11e67f4b63e555be6409 100644 GIT binary patch delta 357 zcmdlolkwUd#tmD14D}hb7!(+s8Nz^2fuV>Yl_8lSk)eR0grOA7Q(!0tih#sZ8S;QC zN+usPR+LO;C<8)WO!bo;9mL%&`cnfDW_Ctr1n#L&Vz6f5Vjyf=DnkX(_8g!a@+K!r zi%-5F$5W5fHlPcT)C2XDFk~|11Kp_vbg3;6D=~oF^3Y$SG%=XVucb_ZL6so|DDLZD zkqU7a&wrx{J{=(T4L`eVCIeJ=g3Ky02O63O431QwMlGNhxPZncgRKEs2a!QoSX0+i H2QdTy)9FpY delta 9 QcmcaMhjGhH#tmD102gxvasU7T diff --git a/Sources/PrimerSDK/Resources/Localizable/zh-TW.lproj/Localizable.strings b/Sources/PrimerSDK/Resources/Localizable/zh-TW.lproj/Localizable.strings index 9bb83fff2b7566d654381124b23eac73c6ea4ec4..aff2ec1eb4cc425d032e8f20fbba2e94de0568a8 100644 GIT binary patch delta 343 zcmdlslkvtJ#tqwiWc3-e7!(+s8Nz^2fuV>Yl_8lSk)eR0grSt7XtJQI@Z=k=Jd;}# zB*e=Y${2LfRWPJZeyAbtZqc6_h%luyIwNpTg%X1`0~Z5c^MST00C5G-z8s*fd6PGa zh)%vB$5)>Wv;kJoMKnO$_GpYbjG;P-RE~ ziu?Lkq(a=q^WSKKPX~y7!_O|8$pF=zAhSx$frjP*0|4YaEua^;fW{_+tpQmFkwI8k KQ`b`mF$4erHcaIJ delta 9 QcmcaHhjH6X#tqwi02h@6cmMzZ From 36ec886d929f75284c831a7561822eeff84f7a5d Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Tue, 19 Mar 2024 19:33:10 +0100 Subject: [PATCH 16/21] reset .swiftlint.yml --- Debug App/.swiftlint.yml | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Debug App/.swiftlint.yml b/Debug App/.swiftlint.yml index ee8fd2a727..f1a2941192 100644 --- a/Debug App/.swiftlint.yml +++ b/Debug App/.swiftlint.yml @@ -1,10 +1,22 @@ -line_length: - warning: 150 - ignores_function_declarations: true - ignores_comments: true - ignores_interpolated_strings: true - ignores_urls: true - +#line_length: +# warning: 150 +# ignores_function_declarations: true +# ignores_comments: true +# ignores_interpolated_strings: true +# ignores_urls: true +# +#included: +# - ../Sources +# +#excluded: +# - ../Sources/PrimerSDK/Classes/Third Party/PromiseKit +disabled_rules: + - line_length + - type_body_length + - function_body_length + - file_length +# - cyclomatic_complexity + included: - ../Sources From e955d4694e040951a416d500777fecc46ba53957 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Tue, 19 Mar 2024 20:25:29 +0100 Subject: [PATCH 17/21] Add UNIT tests --- .../project.pbxproj | 8 +- .../Primer/CVVRecaptureViewModelTests.swift | 123 ++++++++++++++++++ .../Data Models/CardButtonViewModel.swift | 18 ++- .../CVVRecapture/CVVRecaptureViewModel.swift | 2 +- 4 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 Debug App/Tests/Unit Tests/Primer/CVVRecaptureViewModelTests.swift diff --git a/Debug App/Primer.io Debug App.xcodeproj/project.pbxproj b/Debug App/Primer.io Debug App.xcodeproj/project.pbxproj index 408ff55fb4..7f2d712aef 100644 --- a/Debug App/Primer.io Debug App.xcodeproj/project.pbxproj +++ b/Debug App/Primer.io Debug App.xcodeproj/project.pbxproj @@ -95,6 +95,7 @@ A1536BAD2AEBEC3A0087DDC0 /* NolPayPhoneMetadataServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1536BAC2AEBEC3A0087DDC0 /* NolPayPhoneMetadataServiceTests.swift */; }; A1536BAF2AEC0A6D0087DDC0 /* NolTestsMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1536BAE2AEC0A6D0087DDC0 /* NolTestsMocks.swift */; }; A1585C752ACDAA700014F0B9 /* NolPayLinkedCardsComponentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1585C742ACDAA700014F0B9 /* NolPayLinkedCardsComponentTests.swift */; }; + A19CB17B2BAA129900DB4326 /* CVVRecaptureViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19CB17A2BAA129900DB4326 /* CVVRecaptureViewModelTests.swift */; }; A19EF5632B20E22E00A72F60 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = A19EF5622B20E22E00A72F60 /* .swiftlint.yml */; }; A1A3D0F32AD5585A00F7D8C9 /* NolPayUnlinkCardComponentTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A3D0F22AD5585A00F7D8C9 /* NolPayUnlinkCardComponentTest.swift */; }; A1A3D0F52AD56BE300F7D8C9 /* NolPayPaymentComponentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A3D0F42AD56BE300F7D8C9 /* NolPayPaymentComponentTests.swift */; }; @@ -129,7 +130,7 @@ E6F85ECD80B64754E7A6D35E /* RawDataManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C7C082270CF1C6B7810F9B3 /* RawDataManagerTests.swift */; }; EA7FAA4F8476BD3711D628CB /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B18D7E7738BF86467B0F1465 /* Images.xcassets */; }; F02F496FD20B5291C044F62C /* MerchantResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E3C8FE62D22147335F2455 /* MerchantResultViewController.swift */; }; - F03699592AC2E63700E4179D /* BuildFile in Sources */ = {isa = PBXBuildFile; }; + F03699592AC2E63700E4179D /* (null) in Sources */ = {isa = PBXBuildFile; }; F08F63D82B9B5A7C006EF9A9 /* SessionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F08F63D72B9B5A7C006EF9A9 /* SessionConfiguration.swift */; }; F08F63DA2B9B5BC5006EF9A9 /* AppetizeConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F08F63D92B9B5BC5006EF9A9 /* AppetizeConfigProvider.swift */; }; F08F63DC2B9F27B0006EF9A9 /* MetadataParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F08F63DB2B9F27B0006EF9A9 /* MetadataParser.swift */; }; @@ -284,6 +285,7 @@ A1536BAE2AEC0A6D0087DDC0 /* NolTestsMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NolTestsMocks.swift; sourceTree = ""; }; A1585C742ACDAA700014F0B9 /* NolPayLinkedCardsComponentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NolPayLinkedCardsComponentTests.swift; sourceTree = ""; }; A1604A656AF654D7422A2A5E /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Main.strings; sourceTree = ""; }; + A19CB17A2BAA129900DB4326 /* CVVRecaptureViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CVVRecaptureViewModelTests.swift; sourceTree = ""; }; A19EF5622B20E22E00A72F60 /* .swiftlint.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; A1A3D0F22AD5585A00F7D8C9 /* NolPayUnlinkCardComponentTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NolPayUnlinkCardComponentTest.swift; sourceTree = ""; }; A1A3D0F42AD56BE300F7D8C9 /* NolPayPaymentComponentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NolPayPaymentComponentTests.swift; sourceTree = ""; }; @@ -509,6 +511,7 @@ EEB1E1B37192BF739461AFF1 /* PrimerRawCardDataManagerTests.swift */, B266F9E1651BD20E45DCCF68 /* PrimerRawRetailerDataTests.swift */, 049A055F2B4C191D002CEEBA /* NativeUIManagerTests.swift */, + A19CB17A2BAA129900DB4326 /* CVVRecaptureViewModelTests.swift */, ); path = Primer; sourceTree = ""; @@ -1091,6 +1094,7 @@ 3BB02CA24B6B3EF458326B7D /* Networking.swift in Sources */, 25FA73D4BBA89962663B5378 /* Mocks.swift in Sources */, 2E0D85B7343377F1319902AD /* MockPaymentMethodTokenizationViewModel.swift in Sources */, + A19CB17B2BAA129900DB4326 /* CVVRecaptureViewModelTests.swift in Sources */, E11F473D2B0694C50091C31F /* PrimerHeadlessFormWithRedirectManagerTests.swift in Sources */, 161D4BE3FFD5E4A60F4461F0 /* CreateResumePaymentService.swift in Sources */, C6D7F7ECFD35B3DC3AFD6CB2 /* PayPalService.swift in Sources */, @@ -1099,7 +1103,7 @@ 583EBAA90902121CEA479416 /* VaultService.swift in Sources */, 961B5D18058EF4CFCD0185AE /* MockVaultCheckoutViewModel.swift in Sources */, 622A605DDEA98D981670B53F /* DropInUI_TokenizationViewModelTests.swift in Sources */, - F03699592AC2E63700E4179D /* BuildFile in Sources */, + F03699592AC2E63700E4179D /* (null) in Sources */, 208CA849F3187C2DA63CC17B /* HUC_TokenizationViewModelTests.swift in Sources */, 213196DEDF2A3A84037ED884 /* PollingModuleTests.swift in Sources */, 04F6EF742AE6A06200115D05 /* AnalyticsEventsTests.swift in Sources */, diff --git a/Debug App/Tests/Unit Tests/Primer/CVVRecaptureViewModelTests.swift b/Debug App/Tests/Unit Tests/Primer/CVVRecaptureViewModelTests.swift new file mode 100644 index 0000000000..96b9e73927 --- /dev/null +++ b/Debug App/Tests/Unit Tests/Primer/CVVRecaptureViewModelTests.swift @@ -0,0 +1,123 @@ +// +// CVVRecaptureViewModelTests.swift +// Debug App Tests +// +// Created by Boris on 19.3.24.. +// Copyright © 2024 Primer API Ltd. All rights reserved. +// + +import XCTest +@testable import PrimerSDK + +// Mock Classes +struct MockCardButtonViewModel: CardButtonViewModelProtocol { + var cardholder: String + + var last4: String + + var expiry: String + + var imageName: PrimerSDK.ImageName + + var paymentMethodType: PrimerSDK.PaymentInstrumentType + + var surCharge: Int? + + var network: String +} + +// Unit Tests for CVVRecaptureViewModel +class CVVRecaptureViewModelTests: XCTestCase { + + var viewModel: CVVRecaptureViewModel! + var mockCardButtonViewModel: MockCardButtonViewModel! + + override func setUp() { + super.setUp() + mockCardButtonViewModel = MockCardButtonViewModel(cardholder: "John Doe", + last4: "4444", + expiry: "13/05", + imageName: ImageName.genericCard, + paymentMethodType: PaymentInstrumentType.paymentCard, + network: "VISA") + viewModel = CVVRecaptureViewModel() + viewModel.cardButtonViewModel = mockCardButtonViewModel + } + + override func tearDown() { + viewModel = nil + mockCardButtonViewModel = nil + super.tearDown() + } + + // Test for CVV Length Calculation + func testCvvLengthForKnownNetwork() { + // Setup for a known network with specific CVV length + // e.g., mockCardButtonViewModel.network = "Visa" + let expectedLength = 3 // Adjust based on expected CVV length for the mocked network + XCTAssertEqual(viewModel.cvvLength, expectedLength, "CVV length should match the expected value for the given network") + } + + // Test Continue Button State Change on isValidCvv Update + func testContinueButtonStateChangeOnIsValidCvvUpdate() { + let expectation = XCTestExpectation(description: "onContinueButtonStateChange closure is called") + + viewModel.onContinueButtonStateChange = { isEnabled in + XCTAssertTrue(isEnabled, "Continue button should be enabled when isValidCvv is true") + expectation.fulfill() + } + + viewModel.isValidCvv = true + + wait(for: [expectation], timeout: 1.0) + } + + // Test Continue Button Tapped Action with Valid CVV + func testContinueButtonTappedWithValidCvv() { + let cvv = "123" + viewModel.isValidCvv = true + + let expectation = XCTestExpectation(description: "didSubmitCvv closure is called") + + viewModel.didSubmitCvv = { submittedCvv in + XCTAssertEqual(submittedCvv, cvv, "Submitted CVV should match the input CVV") + expectation.fulfill() + } + + viewModel.continueButtonTapped(with: cvv) + + wait(for: [expectation], timeout: 1.0) + } + + // Test Continue Button Tapped Action with Invalid CVV + func testContinueButtonTappedWithInvalidCvv() { + let cvv = "123" + viewModel.isValidCvv = false // Simulate an invalid CVV + + var didCallSubmitCvv = false + viewModel.didSubmitCvv = { _ in + didCallSubmitCvv = true + } + + viewModel.continueButtonTapped(with: cvv) + + XCTAssertFalse(didCallSubmitCvv, "didSubmitCvv should not be called when CVV is invalid") + } + + // Test for invalid CVV inputs + func testContinueButtonTappedWithInvalidCvvInputs() { + let invalidCvvs = ["", "abc", "1234"] // Examples of invalid CVVs + + for cvv in invalidCvvs { + var didCallSubmitCvv = false + viewModel.didSubmitCvv = { _ in + didCallSubmitCvv = true + } + + viewModel.continueButtonTapped(with: cvv) + + // Check that didSubmitCvv was not called for invalid CVV inputs + XCTAssertFalse(didCallSubmitCvv, "didSubmitCvv should not be called for invalid CVV input: \(cvv)") + } + } +} diff --git a/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift b/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift index fa3198f2a9..0242f8f675 100644 --- a/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift +++ b/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift @@ -1,6 +1,16 @@ import Foundation -struct CardButtonViewModel { +protocol CardButtonViewModelProtocol { + var network: String { get } + var cardholder: String { get } + var last4: String { get } + var expiry: String { get } + var imageName: ImageName { get } + var paymentMethodType: PaymentInstrumentType { get } + var surCharge: Int? { get } +} + +struct CardButtonViewModel: CardButtonViewModelProtocol { let network, cardholder, last4, expiry: String let imageName: ImageName @@ -12,9 +22,9 @@ struct CardButtonViewModel { .filter({ $0["type"] as? String == PrimerPaymentMethodType.paymentCard.rawValue }) .first else { return nil } guard let networks = paymentCardOption["networks"] as? [[String: Any]] else { return nil } - guard let tmpNetwork = networks.filter({ ($0["type"] as? String)? - .lowercased() == network.lowercased() }) - .first else { return nil } + guard let tmpNetwork = networks + .filter({ ($0["type"] as? String)?.lowercased() == network.lowercased() }) + .first else { return nil } return tmpNetwork["surcharge"] as? Int } } diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift index 823f27f6d5..3077dd5bf1 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/CVVRecapture/CVVRecaptureViewModel.swift @@ -10,7 +10,7 @@ import Foundation class CVVRecaptureViewModel { var didSubmitCvv: ((String) -> Void)? - var cardButtonViewModel: CardButtonViewModel! + var cardButtonViewModel: CardButtonViewModelProtocol! var onContinueButtonStateChange: ((Bool) -> Void)? var isValidCvv: Bool = false { From 311f739cacc49d8e59595f35810e5169d25128e9 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Tue, 19 Mar 2024 20:33:18 +0100 Subject: [PATCH 18/21] Handle backend flag for CVV recapture --- Debug App/Podfile.lock | 8 +++--- .../Base.lproj/Main.storyboard | 25 +++++++++++++---- .../Sources/Model/CreateClientToken.swift | 28 +++++++++++++++---- Debug App/Sources/Network/Networking.swift | 1 + .../Merchant Helpers/MerchantHelpers.swift | 27 ++++++++++-------- ...hantSessionAndSettingsViewController.swift | 19 ++++++++++--- ...adlessUniversalCheckoutKlarnaManager.swift | 2 +- .../RawDataManager.swift | 6 ++-- .../Data Models/CardButtonViewModel.swift | 4 +-- .../PaymentMethodConfigurationOptions.swift | 1 + .../PCI/Services/API/Primer/PrimerAPI.swift | 3 +- ...rimerUniversalCheckoutViewController.swift | 6 ++-- 12 files changed, 88 insertions(+), 42 deletions(-) diff --git a/Debug App/Podfile.lock b/Debug App/Podfile.lock index ba271780a1..5b7a1c6386 100644 --- a/Debug App/Podfile.lock +++ b/Debug App/Podfile.lock @@ -4,9 +4,9 @@ PODS: - PrimerIPay88MYSDK (0.1.7) - PrimerKlarnaSDK (1.1.0) - PrimerNolPaySDK (1.0.1) - - PrimerSDK (2.23.0): - - PrimerSDK/Core (= 2.23.0) - - PrimerSDK/Core (2.23.0) + - PrimerSDK (2.24.0): + - PrimerSDK/Core (= 2.24.0) + - PrimerSDK/Core (2.24.0) DEPENDENCIES: - IQKeyboardManagerSwift @@ -34,7 +34,7 @@ SPEC CHECKSUMS: PrimerIPay88MYSDK: 436ee0be7e2c97e4e81456ccddee20175e9e3c4d PrimerKlarnaSDK: 83e9a1357a7247bf8fa2836fc945cf97644d601d PrimerNolPaySDK: 08b140ed39b378a0b33b4f8746544a402175c0cc - PrimerSDK: 9b45df1943c73057fd375500b333b9d33b1cfc1f + PrimerSDK: af09c3d815cda8b5dc815cb91b2a693e55c52677 PODFILE CHECKSUM: 0338ba968079466f92e90a37e90d263807adbb7f diff --git a/Debug App/Resources/Localized Views/Base.lproj/Main.storyboard b/Debug App/Resources/Localized Views/Base.lproj/Main.storyboard index 554b1f7039..56f7ae8ea6 100644 --- a/Debug App/Resources/Localized Views/Base.lproj/Main.storyboard +++ b/Debug App/Resources/Localized Views/Base.lproj/Main.storyboard @@ -177,7 +177,7 @@ - + @@ -380,7 +380,7 @@ - + + + + + + + + + + - + - + - + @@ -1154,6 +1168,7 @@ + diff --git a/Debug App/Sources/Model/CreateClientToken.swift b/Debug App/Sources/Model/CreateClientToken.swift index 06eec25b96..8139e640ef 100644 --- a/Debug App/Sources/Model/CreateClientToken.swift +++ b/Debug App/Sources/Model/CreateClientToken.swift @@ -320,7 +320,7 @@ struct ClientSessionRequestBody { struct PaymentMethod: Codable { let vaultOnSuccess: Bool? - let options: PaymentMethodOptionGroup? + var options: PaymentMethodOptionGroup? let descriptor: String? let paymentType: String? @@ -348,14 +348,19 @@ struct ClientSessionRequestBody { struct PaymentMethodOptionGroup: Codable { var KLARNA: PaymentMethodOption? - + var PAYMENT_CARD: PaymentMethodOption? + var dictionaryValue: [String: Any]? { var dic: [String: Any] = [:] if let KLARNA = KLARNA { dic["KLARNA"] = KLARNA.dictionaryValue } - + + if let PAYMENT_CARD = PAYMENT_CARD { + dic["PAYMENT_CARD"] = PAYMENT_CARD.dictionaryValue + } + return dic.keys.count == 0 ? nil : dic } } @@ -364,15 +369,20 @@ struct ClientSessionRequestBody { var surcharge: SurchargeOption? var instalmentDuration: String? var extraMerchantData: [String: Any]? + var captureVaultedCardCvv: Bool? enum CodingKeys: CodingKey { - case surcharge, instalmentDuration, extraMerchantData + case surcharge, instalmentDuration, extraMerchantData, captureVaultedCardCvv } - init(surcharge: SurchargeOption?, instalmentDuration: String?, extraMerchantData: [String: Any]?) { + init(surcharge: SurchargeOption?, + instalmentDuration: String?, + extraMerchantData: [String: Any]?, + captureVaultedCardCvv: Bool?) { self.surcharge = surcharge self.instalmentDuration = instalmentDuration self.extraMerchantData = extraMerchantData + self.captureVaultedCardCvv = captureVaultedCardCvv } func encode(to encoder: Encoder) throws { @@ -404,6 +414,8 @@ struct ClientSessionRequestBody { } else { extraMerchantData = nil } + + captureVaultedCardCvv = try container.decodeIfPresent(Bool.self, forKey: .captureVaultedCardCvv) ?? false } var dictionaryValue: [String: Any]? { @@ -420,7 +432,11 @@ struct ClientSessionRequestBody { if let extraMerchantData = extraMerchantData { dic["extraMerchantData"] = extraMerchantData } - + + if let captureVaultedCardCvv = captureVaultedCardCvv { + dic["captureVaultedCardCvv"] = captureVaultedCardCvv + } + return dic.keys.count == 0 ? nil : dic } } diff --git a/Debug App/Sources/Network/Networking.swift b/Debug App/Sources/Network/Networking.swift index 886fd1a640..379e0ba4f4 100644 --- a/Debug App/Sources/Network/Networking.swift +++ b/Debug App/Sources/Network/Networking.swift @@ -92,6 +92,7 @@ class Networking { if let apiVersion = apiVersion { request.addValue(apiVersion.rawValue, forHTTPHeaderField: "x-api-version") request.addValue("IOS", forHTTPHeaderField: "Client") + request.addValue("chkt-2307-cvv-recapture-flag", forHTTPHeaderField: "x-primer-branch") } let headerDescriptions = request.allHTTPHeaderFields?.map { key, value in diff --git a/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift b/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift index 7dd2c759f5..f3179454c9 100644 --- a/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift +++ b/Debug App/Sources/View Controllers/Merchant Helpers/MerchantHelpers.swift @@ -10,7 +10,7 @@ import UIKit import PrimerSDK struct MerchantMockDataManager { - + enum SessionType { case generic case oneTimePayment @@ -78,26 +78,29 @@ struct MerchantMockDataManager { return sessionType == .generic ? genericPaymentMethod : klarnaPaymentMethod } - static var genericPaymentMethod = ClientSessionRequestBody.PaymentMethod( - vaultOnSuccess: false, - options: nil, - descriptor: nil, - paymentType: nil - ) - + static var genericPaymentMethod: ClientSessionRequestBody.PaymentMethod { + return ClientSessionRequestBody.PaymentMethod( + vaultOnSuccess: false, + options: nil, + descriptor: nil, + paymentType: nil + ) + } + static var klarnaPaymentMethod = ClientSessionRequestBody.PaymentMethod( vaultOnSuccess: nil, - options: paymentOptions, + options: klarnaPaymentOptions, descriptor: "test-descriptor", paymentType: nil ) - static var paymentOptions = ClientSessionRequestBody.PaymentMethod.PaymentMethodOptionGroup( + static var klarnaPaymentOptions = ClientSessionRequestBody.PaymentMethod.PaymentMethodOptionGroup( KLARNA: ClientSessionRequestBody.PaymentMethod.PaymentMethodOption( surcharge: ClientSessionRequestBody.PaymentMethod.SurchargeOption(amount: 140), instalmentDuration: "test", - extraMerchantData: extraMerchantData)) - + extraMerchantData: extraMerchantData, + captureVaultedCardCvv: false)) + static var extraMerchantData: [String: Any] = [ "subscription": [ [ diff --git a/Debug App/Sources/View Controllers/MerchantSessionAndSettingsViewController.swift b/Debug App/Sources/View Controllers/MerchantSessionAndSettingsViewController.swift index b2a1bf47dc..2dc1edce15 100644 --- a/Debug App/Sources/View Controllers/MerchantSessionAndSettingsViewController.swift +++ b/Debug App/Sources/View Controllers/MerchantSessionAndSettingsViewController.swift @@ -69,7 +69,8 @@ class MerchantSessionAndSettingsViewController: UIViewController { @IBOutlet weak var disableSuccessScreenSwitch: UISwitch! @IBOutlet weak var disableErrorScreenSwitch: UISwitch! @IBOutlet weak var disableInitScreenSwitch: UISwitch! - + @IBOutlet weak var enableCVVRecaptureFlowSwitch: UISwitch! + // MARK: Order Inputs @IBOutlet weak var currencyTextField: UITextField! @@ -135,7 +136,7 @@ class MerchantSessionAndSettingsViewController: UIViewController { var selectedPaymentHandling: PrimerPaymentHandling = .auto var clientSession = MerchantMockDataManager.getClientSession(sessionType: .generic) - + var selectedTestScenario: Test.Scenario? var selectedTestFlow: Test.Flow? var selectedTest3DSScenario: Test.Params.ThreeDS.Scenario? @@ -416,7 +417,15 @@ class MerchantSessionAndSettingsViewController: UIViewController { } clientSession.paymentMethod = MerchantMockDataManager.getPaymentMethod(sessionType: paymentSessionType) - + if paymentSessionType == .generic && enableCVVRecaptureFlowSwitch.isOn { + let option = ClientSessionRequestBody.PaymentMethod.PaymentMethodOption(surcharge: nil, + instalmentDuration: nil, + extraMerchantData: nil, + captureVaultedCardCvv: enableCVVRecaptureFlowSwitch.isOn) + + let optionGroup = ClientSessionRequestBody.PaymentMethod.PaymentMethodOptionGroup(PAYMENT_CARD: option) + clientSession.paymentMethod?.options = optionGroup + } if let metadata = metadataTextField.text, !metadata.isEmpty { clientSession.metadata = MetadataParser().parse(metadata) } @@ -424,7 +433,9 @@ class MerchantSessionAndSettingsViewController: UIViewController { func populateSessionSettingsFields() { clientSession = MerchantMockDataManager.getClientSession(sessionType: paymentSessionType) - + + enableCVVRecaptureFlowSwitch.isOn = clientSession.paymentMethod?.options?.PAYMENT_CARD?.captureVaultedCardCvv == true + currencyTextField.text = clientSession.currencyCode?.code countryCodeTextField.text = clientSession.order?.countryCode?.rawValue orderIdTextField.text = clientSession.orderId diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift index d51027be62..25c6636212 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/PrimerHeadlessUniversalCheckoutKlarnaManager.swift @@ -13,7 +13,7 @@ extension PrimerHeadlessUniversalCheckout { public class KlarnaManager: NSObject { public func provideKlarnaComponent(with intent: PrimerSessionIntent) throws -> (any KlarnaComponent)? { guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs? - .first(where: { $0.type == "KLARNA" }) + .first(where: { $0.type == "KLARNA" }) else { let err = PrimerError.generic(message: "Unable to locate a valid payment method configuration.", userInfo: ["file": #file, diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift index 0052e7f835..f00deef1b3 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Managers/Payment Method Managers/RawDataManager.swift @@ -733,9 +733,9 @@ Make sure you call the decision handler otherwise the SDK will hang." guard let selectedRetailer = rawData as? PrimerRetailerData, let selectedRetailerName = (initializationData as? RetailOutletsList)? - .result - .first(where: { $0.id == selectedRetailer.id })? - .name + .result + .first(where: { $0.id == selectedRetailer.id })? + .name else { let err = PrimerError.invalidValue(key: "rawData.id", value: "Invalid Retailer Identifier", diff --git a/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift b/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift index 0242f8f675..7432fa5f99 100644 --- a/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift +++ b/Sources/PrimerSDK/Classes/Data Models/CardButtonViewModel.swift @@ -23,8 +23,8 @@ struct CardButtonViewModel: CardButtonViewModelProtocol { .first else { return nil } guard let networks = paymentCardOption["networks"] as? [[String: Any]] else { return nil } guard let tmpNetwork = networks - .filter({ ($0["type"] as? String)?.lowercased() == network.lowercased() }) - .first else { return nil } + .filter({ ($0["type"] as? String)?.lowercased() == network.lowercased() }) + .first else { return nil } return tmpNetwork["surcharge"] as? Int } } diff --git a/Sources/PrimerSDK/Classes/Data Models/PaymentMethodConfigurationOptions.swift b/Sources/PrimerSDK/Classes/Data Models/PaymentMethodConfigurationOptions.swift index 35f54cb2c0..d25d82712c 100644 --- a/Sources/PrimerSDK/Classes/Data Models/PaymentMethodConfigurationOptions.swift +++ b/Sources/PrimerSDK/Classes/Data Models/PaymentMethodConfigurationOptions.swift @@ -21,6 +21,7 @@ struct CardOptions: PaymentMethodOptions { let threeDSecureInitUrl: String? let threeDSecureProvider: String let processorConfigId: String? + let captureVaultedCardCvv: Bool? } struct MerchantOptions: PaymentMethodOptions { diff --git a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift index f055a42bd3..f210a21e61 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift @@ -98,7 +98,8 @@ internal extension PrimerAPI { static let headers: [String: String] = [ "Content-Type": "application/json", "Primer-SDK-Version": VersionUtils.releaseVersionNumber ?? "n/a", - "Primer-SDK-Client": PrimerSource.sdkSourceType.sourceType + "Primer-SDK-Client": PrimerSource.sdkSourceType.sourceType, + "x-primer-branch": "chkt-2307-cvv-recapture-flag" ] var headers: [String: String]? { diff --git a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift index ac8b53e31b..f74c24fc34 100644 --- a/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift +++ b/Sources/PrimerSDK/Classes/User Interface/Root/PrimerUniversalCheckoutViewController.swift @@ -289,10 +289,8 @@ internal class PrimerUniversalCheckoutViewController: PrimerFormViewController { ) Analytics.Service.record(event: viewEvent) - // TODO: (BNI) ping @aladin - let backendFlag = true - - if backendFlag { + if let captureVaultedCardCvv = (config.options as? CardOptions)?.captureVaultedCardCvv, + captureVaultedCardCvv == true { let cvvViewController = CVVRecaptureViewController(viewModel: CVVRecaptureViewModel()) cvvViewController.viewModel.cardButtonViewModel = cardButtonViewModel cvvViewController.viewModel.didSubmitCvv = { cvv in From b62bf05427431b32b791c0ccd9acdedf29a431ec Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 25 Mar 2024 10:40:21 +0100 Subject: [PATCH 19/21] Remove testing headers --- Debug App/Sources/Network/Networking.swift | 1 - .../PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Debug App/Sources/Network/Networking.swift b/Debug App/Sources/Network/Networking.swift index 379e0ba4f4..886fd1a640 100644 --- a/Debug App/Sources/Network/Networking.swift +++ b/Debug App/Sources/Network/Networking.swift @@ -92,7 +92,6 @@ class Networking { if let apiVersion = apiVersion { request.addValue(apiVersion.rawValue, forHTTPHeaderField: "x-api-version") request.addValue("IOS", forHTTPHeaderField: "Client") - request.addValue("chkt-2307-cvv-recapture-flag", forHTTPHeaderField: "x-primer-branch") } let headerDescriptions = request.allHTTPHeaderFields?.map { key, value in diff --git a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift index f210a21e61..f055a42bd3 100644 --- a/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift +++ b/Sources/PrimerSDK/Classes/PCI/Services/API/Primer/PrimerAPI.swift @@ -98,8 +98,7 @@ internal extension PrimerAPI { static let headers: [String: String] = [ "Content-Type": "application/json", "Primer-SDK-Version": VersionUtils.releaseVersionNumber ?? "n/a", - "Primer-SDK-Client": PrimerSource.sdkSourceType.sourceType, - "x-primer-branch": "chkt-2307-cvv-recapture-flag" + "Primer-SDK-Client": PrimerSource.sdkSourceType.sourceType ] var headers: [String: String]? { From 8f61ef36d25c3bf6b76f137796154be4917af9b4 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 25 Mar 2024 13:13:02 +0100 Subject: [PATCH 20/21] Refactor function to multiple smaller ones --- .../Text Fields/PrimerCustomTextField.swift | 153 ++++++++++++++++++ .../Text Fields/PrimerTextFieldView.swift | 112 +------------ 2 files changed, 155 insertions(+), 110 deletions(-) create mode 100644 Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCustomTextField.swift diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCustomTextField.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCustomTextField.swift new file mode 100644 index 0000000000..3e2e6ab713 --- /dev/null +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerCustomTextField.swift @@ -0,0 +1,153 @@ +// +// PrimerCustomTextField.swift +// PrimerSDK +// +// Created by Boris on 25.3.24.. +// + +import UIKit + +class PrimerCustomFieldView: UIView { + + var fieldView: PrimerTextFieldView! + override var tintColor: UIColor! { + didSet { + topPlaceholderLabel.textColor = tintColor + bottomLine.backgroundColor = tintColor + } + } + var placeholderText: String? + var rightImage1: UIImage? { + didSet { + rightImageView1Container.isHidden = rightImage1 == nil + rightImageView1.image = rightImage1 + } + } + var rightImage1TintColor: UIColor? { + didSet { + rightImageView1.tintColor = rightImage1TintColor + } + } + var rightImage2: UIImage? { + didSet { + rightImageView2.isHidden = rightImage2 == nil + rightImageView2.image = rightImage2 + } + } + var rightImage2TintColor: UIColor? { + didSet { + rightImageView2.tintColor = rightImage2TintColor + } + } + var errorText: String? { + didSet { + errorLabel.text = errorText ?? "" + } + } + + private var verticalStackView: UIStackView = UIStackView() + private let errorLabel = UILabel() + private let topPlaceholderLabel = UILabel() + private let rightImageView1Container = UIView() + private let rightImageView1 = UIImageView() // As in the one furthest right + private let rightImageView2Container = UIView() + private let rightImageView2 = UIImageView() + private let bottomLine = UIView() + private var theme: PrimerThemeProtocol = DependencyContainer.resolve() + + func setup() { + setupVerticalStackView() + setupTopPlaceholderLabel() + setupTextFieldStackView() + setupBottomLine() + setupErrorLabel() + constrainVerticalStackView() + } + + private func setupVerticalStackView() { + addSubview(verticalStackView) + verticalStackView.alignment = .fill + verticalStackView.axis = .vertical + } + + private func setupTopPlaceholderLabel() { + topPlaceholderLabel.font = UIFont.systemFont(ofSize: 10.0, weight: .medium) + topPlaceholderLabel.text = placeholderText + topPlaceholderLabel.textColor = theme.text.system.color + verticalStackView.addArrangedSubview(topPlaceholderLabel) + } + + private func setupTextFieldStackView() { + let textFieldStackView = createTextFieldStackView() + + setupRightImageView2Container(in: textFieldStackView) + setupRightImageView1Container(in: textFieldStackView) + + verticalStackView.addArrangedSubview(textFieldStackView) + } + + private func createTextFieldStackView() -> UIStackView { + let textFieldStackView = UIStackView() + textFieldStackView.alignment = .fill + textFieldStackView.axis = .horizontal + textFieldStackView.addArrangedSubview(fieldView) + textFieldStackView.spacing = 6 + return textFieldStackView + } + + private func setupRightImageView2Container(in stackView: UIStackView) { + rightImageView2.contentMode = .scaleAspectFit + + stackView.addArrangedSubview(rightImageView2Container) + rightImageView2Container.translatesAutoresizingMaskIntoConstraints = false + rightImageView2Container.addSubview(rightImageView2) + rightImageView2.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + rightImageView2.topAnchor.constraint(equalTo: rightImageView2Container.topAnchor, constant: 6), + rightImageView2.bottomAnchor.constraint(equalTo: rightImageView2Container.bottomAnchor, constant: -6), + rightImageView2.leadingAnchor.constraint(equalTo: rightImageView2Container.leadingAnchor), + rightImageView2.trailingAnchor.constraint(equalTo: rightImageView2Container.trailingAnchor), + rightImageView2.widthAnchor.constraint(equalTo: rightImageView2Container.heightAnchor) + ]) + } + + private func setupRightImageView1Container(in stackView: UIStackView) { + rightImageView1.contentMode = .scaleAspectFit + + stackView.addArrangedSubview(rightImageView1Container) + rightImageView1Container.translatesAutoresizingMaskIntoConstraints = false + rightImageView1Container.addSubview(rightImageView1) + rightImageView1.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + rightImageView1.topAnchor.constraint(equalTo: rightImageView1Container.topAnchor, constant: 10), + rightImageView1.bottomAnchor.constraint(equalTo: rightImageView1Container.bottomAnchor, constant: -10), + rightImageView1.leadingAnchor.constraint(equalTo: rightImageView1Container.leadingAnchor), + rightImageView1.trailingAnchor.constraint(equalTo: rightImageView1Container.trailingAnchor), + rightImageView1.widthAnchor.constraint(equalTo: rightImageView1Container.heightAnchor) + ]) + } + + private func setupBottomLine() { + bottomLine.backgroundColor = theme.colors.primary + bottomLine.heightAnchor.constraint(equalToConstant: 1).isActive = true + verticalStackView.addArrangedSubview(bottomLine) + } + + private func setupErrorLabel() { + errorLabel.textColor = theme.text.error.color + errorLabel.heightAnchor.constraint(equalToConstant: 12.0).isActive = true + errorLabel.font = UIFont.systemFont(ofSize: 10.0, weight: .medium) + errorLabel.text = nil + verticalStackView.addArrangedSubview(errorLabel) + } + + private func constrainVerticalStackView() { + verticalStackView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + verticalStackView.topAnchor.constraint(equalTo: topAnchor), + verticalStackView.leadingAnchor.constraint(equalTo: leadingAnchor), + verticalStackView.trailingAnchor.constraint(equalTo: trailingAnchor), + verticalStackView.bottomAnchor.constraint(equalTo: bottomAnchor) + ]) + } +} diff --git a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift index c2b67a0f56..386dd26045 100644 --- a/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift +++ b/Sources/PrimerSDK/Classes/PCI/User Interface/Text Fields/PrimerTextFieldView.swift @@ -5,6 +5,7 @@ // Created by Evangelos Pittas on 29/6/21. // +// swiftlint:disable function_body_length import UIKit /// The PrimerTextFieldViewDelegate protocol can be used to retrieve information about the text input. @@ -241,115 +242,6 @@ public class PrimerTextFieldView: PrimerNibView, UITextFieldDelegate { } -class PrimerCustomFieldView: UIView { - - var fieldView: PrimerTextFieldView! - override var tintColor: UIColor! { - didSet { - topPlaceholderLabel.textColor = tintColor - bottomLine.backgroundColor = tintColor - } - } - var placeholderText: String? - var rightImage1: UIImage? { - didSet { - rightImageView1Container.isHidden = rightImage1 == nil - rightImageView1.image = rightImage1 - } - } - var rightImage1TintColor: UIColor? { - didSet { - rightImageView1.tintColor = rightImage1TintColor - } - } - var rightImage2: UIImage? { - didSet { - rightImageView2.isHidden = rightImage2 == nil - rightImageView2.image = rightImage2 - } - } - var rightImage2TintColor: UIColor? { - didSet { - rightImageView2.tintColor = rightImage2TintColor - } - } - var errorText: String? { - didSet { - errorLabel.text = errorText ?? "" - } - } - - private var verticalStackView: UIStackView = UIStackView() - private let errorLabel = UILabel() - private let topPlaceholderLabel = UILabel() - private let rightImageView1Container = UIView() - private let rightImageView1 = UIImageView() // As in the one furthest right - private let rightImageView2Container = UIView() - private let rightImageView2 = UIImageView() - private let bottomLine = UIView() - private var theme: PrimerThemeProtocol = DependencyContainer.resolve() - - func setup() { - addSubview(verticalStackView) - verticalStackView.alignment = .fill - verticalStackView.axis = .vertical - - topPlaceholderLabel.font = UIFont.systemFont(ofSize: 10.0, weight: .medium) - topPlaceholderLabel.text = placeholderText - topPlaceholderLabel.textColor = theme.text.system.color - verticalStackView.addArrangedSubview(topPlaceholderLabel) - - rightImageView1.contentMode = .scaleAspectFit - rightImageView2.contentMode = .scaleAspectFit - - let textFieldStackView = UIStackView() - textFieldStackView.alignment = .fill - textFieldStackView.axis = .horizontal - textFieldStackView.addArrangedSubview(fieldView) - textFieldStackView.addArrangedSubview(rightImageView2) - textFieldStackView.spacing = 6 - - textFieldStackView.addArrangedSubview(rightImageView2Container) - rightImageView2Container.translatesAutoresizingMaskIntoConstraints = false - rightImageView2Container.addSubview(rightImageView2) - rightImageView2.translatesAutoresizingMaskIntoConstraints = false - rightImageView2.topAnchor.constraint(equalTo: rightImageView2Container.topAnchor, constant: 6).isActive = true - rightImageView2.bottomAnchor.constraint(equalTo: rightImageView2Container.bottomAnchor, constant: -6).isActive = true - rightImageView2.leadingAnchor.constraint(equalTo: rightImageView2Container.leadingAnchor, constant: 0).isActive = true - rightImageView2.trailingAnchor.constraint(equalTo: rightImageView2Container.trailingAnchor, constant: 0).isActive = true - rightImageView2.widthAnchor.constraint(equalTo: rightImageView2Container.heightAnchor, multiplier: 1.0).isActive = true - - textFieldStackView.addArrangedSubview(rightImageView1Container) - rightImageView1Container.translatesAutoresizingMaskIntoConstraints = false - rightImageView1Container.addSubview(rightImageView1) - rightImageView1.translatesAutoresizingMaskIntoConstraints = false - rightImageView1.topAnchor.constraint(equalTo: rightImageView1Container.topAnchor, constant: 10).isActive = true - rightImageView1.bottomAnchor.constraint(equalTo: rightImageView1Container.bottomAnchor, constant: -10).isActive = true - rightImageView1.leadingAnchor.constraint(equalTo: rightImageView1Container.leadingAnchor, constant: 0).isActive = true - rightImageView1.trailingAnchor.constraint(equalTo: rightImageView1Container.trailingAnchor, constant: 0).isActive = true - rightImageView1.widthAnchor.constraint(equalTo: rightImageView1.heightAnchor, multiplier: 1.0).isActive = true - - bottomLine.backgroundColor = theme.colors.primary - bottomLine.heightAnchor.constraint(equalToConstant: 1).isActive = true - verticalStackView.addArrangedSubview(textFieldStackView) - verticalStackView.addArrangedSubview(bottomLine) - - errorLabel.textColor = theme.text.error.color - errorLabel.heightAnchor.constraint(equalToConstant: 12.0).isActive = true - errorLabel.font = UIFont.systemFont(ofSize: 10.0, weight: .medium) - errorLabel.text = nil - - verticalStackView.addArrangedSubview(errorLabel) - - verticalStackView.translatesAutoresizingMaskIntoConstraints = false - verticalStackView.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true - verticalStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0).isActive = true - verticalStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0).isActive = true - verticalStackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true - } - -} - internal class PaddedImageView: PrimerImageView { internal private(set) var insets: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) @@ -378,5 +270,5 @@ internal class PaddedImageView: PrimerImageView { required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } - } +// swiftlint:enable function_body_length From c838977ec9e1c494788621bc365d10a1233c8778 Mon Sep 17 00:00:00 2001 From: Boris Nikolic Date: Mon, 25 Mar 2024 15:35:27 +0100 Subject: [PATCH 21/21] Make the CVV recapture flag available on Headless --- ...adlessUniversalCheckoutPaymentMethod.swift | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift index 4ac2483f86..cf4a513f3f 100644 --- a/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift +++ b/Sources/PrimerSDK/Classes/Core/PrimerHeadlessUniversalCheckout/Models/PrimerHeadlessUniversalCheckoutPaymentMethod.swift @@ -5,6 +5,8 @@ // Created by Evangelos on 27/9/22. // +// swiftlint:disable nesting + import Foundation import PassKit @@ -12,6 +14,17 @@ extension PrimerHeadlessUniversalCheckout { public class PaymentMethod: NSObject { + /// To enhance your experience and provide consistent functionality across our services, + /// some features are available in both our Headless and Drop-In interfaces. + /// While Drop-In automatically utilizes these features through predefined settings, + /// the Headless interface offers you the flexibility to enable these features manually. + /// This is made possible through the introduction of the "PrimerAvailablePaymentMethodsOptions". + /// This option allows you to customize your Headless setup by enabling specific features + /// that align with the capabilities available in the Drop-In interface. + public struct PrimerAvailablePaymentMethodsOptions { + let captureVaultedCardCvv: Bool? + } + static var availablePaymentMethods: [PrimerHeadlessUniversalCheckout.PaymentMethod] { var availablePaymentMethods = PrimerAPIConfiguration.paymentMethodConfigs? .compactMap({ $0.type }) @@ -33,6 +46,7 @@ extension PrimerHeadlessUniversalCheckout { public private(set) var supportedPrimerSessionIntents: [PrimerSessionIntent] = [] public private(set) var paymentMethodManagerCategories: [PrimerPaymentMethodManagerCategory] public private(set) var requiredInputDataClass: PrimerRawData.Type? + public private(set) var options: PrimerHeadlessUniversalCheckout.PaymentMethod.PrimerAvailablePaymentMethodsOptions init?(paymentMethodType: String) { guard let paymentMethod = PrimerAPIConfiguration.paymentMethodConfigs? @@ -54,14 +68,17 @@ extension PrimerHeadlessUniversalCheckout { guard let paymentMethodManagerCategories = paymentMethod.paymentMethodManagerCategories else { return nil } - self.paymentMethodManagerCategories = paymentMethodManagerCategories if PrimerPaymentMethodType.paymentCard.rawValue == paymentMethodType { requiredInputDataClass = PrimerCardData.self } + let captureVaultedCardCvv = (paymentMethod.options as? CardOptions)?.captureVaultedCardCvv ?? false + options = PrimerAvailablePaymentMethodsOptions(captureVaultedCardCvv: captureVaultedCardCvv) + super.init() } } } +// swiftlint:enable nesting