From c3733af1079011dd8878316ae4d6e68601a02a3d Mon Sep 17 00:00:00 2001 From: "Ivaylo Hadzhiev (emerchantpay)" Date: Mon, 29 Jul 2024 15:09:16 +0300 Subject: [PATCH] 1.5.1 --- .../project.pbxproj | 6 +- .../Controller/HomeTableViewController.swift | 6 +- .../TransactionDetailsViewController.swift | 5 +- .../iOS Example/Sources/Model/InputData.swift | 55 +++++++++++++------ .../iOS Example/Tests/InputDataTests.swift | 28 ++++++++-- .../iOS Example/Tests/PickerDataTests.swift | 25 ++++++++- GenesisSwift.podspec | 2 +- GenesisSwift.xcodeproj/project.pbxproj | 6 +- GenesisSwift/Models/KlarnaItem.swift | 2 +- GenesisSwift/Models/PaymentAddress.swift | 3 +- GenesisSwift/Models/PaymentRequest.swift | 14 ++--- .../Models/PaymentTransactionType.swift | 5 +- GenesisSwift/Models/Reminder.swift | 3 +- .../Protocols/String+Conversion.swift | 18 +++--- .../Validation/RequiredParameters.swift | 8 +-- .../RequiredParametersValidator.swift | 18 +++--- .../DynamicDescriptorParamsTests.swift | 10 ++++ GenesisSwiftTests/PaymentAddressTests.swift | 5 ++ GenesisSwiftTests/PaymentRequestTests.swift | 40 +++++++++++++- .../PaymentTransactionTypeTest.swift | 10 ++++ GenesisSwiftTests/RiskParamsTests.swift | 7 +++ GenesisSwiftTests/StringTests.swift | 2 + README.md | 24 ++++---- 23 files changed, 211 insertions(+), 91 deletions(-) diff --git a/GenesisSwift Example/GenesisSwift Example.xcodeproj/project.pbxproj b/GenesisSwift Example/GenesisSwift Example.xcodeproj/project.pbxproj index c2b31a3..9bf97d6 100644 --- a/GenesisSwift Example/GenesisSwift Example.xcodeproj/project.pbxproj +++ b/GenesisSwift Example/GenesisSwift Example.xcodeproj/project.pbxproj @@ -509,6 +509,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 1.5.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -564,6 +565,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 1.5.1; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -597,7 +599,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.5.0; + MARKETING_VERSION = 1.5.1; PRODUCT_BUNDLE_IDENTIFIER = com.emerchantpay.inapppayments; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -629,7 +631,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.5.0; + MARKETING_VERSION = 1.5.1; PRODUCT_BUNDLE_IDENTIFIER = com.emerchantpay.inapppayments; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/GenesisSwift Example/iOS Example/Sources/Controller/HomeTableViewController.swift b/GenesisSwift Example/iOS Example/Sources/Controller/HomeTableViewController.swift index 3a3ff4e..3a392c3 100644 --- a/GenesisSwift Example/iOS Example/Sources/Controller/HomeTableViewController.swift +++ b/GenesisSwift Example/iOS Example/Sources/Controller/HomeTableViewController.swift @@ -58,14 +58,14 @@ private extension HomeTableViewController { } @IBAction func privacyPolicyButtonPressed() { - openURLString(urlString: "https://www.genesissupport247.com/privacy-policy/") + openURLString("https://www.genesissupport247.com/privacy-policy/") } @IBAction func termsAndConditionsButtonPressed() { - openURLString(urlString: "https://www.genesissupport247.com/terms-conditions/") + openURLString("https://www.genesissupport247.com/terms-conditions/") } - func openURLString(urlString: String) { + func openURLString(_ urlString: String) { if let url = URL(string: urlString), UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url) } else { diff --git a/GenesisSwift Example/iOS Example/Sources/Controller/TransactionDetailsViewController.swift b/GenesisSwift Example/iOS Example/Sources/Controller/TransactionDetailsViewController.swift index 6a3f570..23bc832 100644 --- a/GenesisSwift Example/iOS Example/Sources/Controller/TransactionDetailsViewController.swift +++ b/GenesisSwift Example/iOS Example/Sources/Controller/TransactionDetailsViewController.swift @@ -156,8 +156,9 @@ extension TransactionDetailsViewController: GenesisDelegate { } func genesisDidEndWithSuccess(userInfo: [AnyHashable: Any]) { - let uniqueId = userInfo[GenesisInfoKeys.uniqueId]! - presentAlertWithTitle("Success", andMessage: "Success transaction: \(uniqueId)") + if let uniqueId = userInfo[GenesisInfoKeys.uniqueId] { + presentAlertWithTitle("Success", andMessage: "Success transaction: \(uniqueId)") + } } func genesisDidEndWithFailure(userInfo: [AnyHashable: Any], errorCode: GenesisError) { diff --git a/GenesisSwift Example/iOS Example/Sources/Model/InputData.swift b/GenesisSwift Example/iOS Example/Sources/Model/InputData.swift index 0c1e756..d837d09 100644 --- a/GenesisSwift Example/iOS Example/Sources/Model/InputData.swift +++ b/GenesisSwift Example/iOS Example/Sources/Model/InputData.swift @@ -201,13 +201,11 @@ public final class InputData: NSObject { value: Date().dateBySubstracting(2, from: .year)!.iso8601Date, regex: Regex.date) private(set) lazy var recurringType = PickerData(title: Titles.recurringType.rawValue, - value: RecurringType.TypeValues.initial.rawValue, - items: RecurringType.TypeValues.allCases - .map { EnumPickerItem($0.rawValue) }) + value: RecurringTypePickerValues.notAvailable.rawValue, + items: RecurringTypePickerValues.allCases.map { EnumPickerItem($0.rawValue) }) private(set) lazy var recurringCategory = PickerData(title: Titles.recurringCategory.rawValue, - value: RecurringCategory.CategoryValues.subscription.rawValue, - items: RecurringCategory.CategoryValues.allCases - .map { EnumPickerItem($0.rawValue) }) + value: RecurringCategoryPickerValues.notAvailable.rawValue, + items: RecurringCategoryPickerValues.allCases.map { EnumPickerItem($0.rawValue) }) private var defaultObjects: [ObjectDataProtocol] { var all: [ObjectDataProtocol] = [transactionId, amount, currency, usage, customerEmail, customerPhone, @@ -405,6 +403,29 @@ extension InputData { case automatic case manual } + + enum RecurringTypePickerValues: String, CaseIterable { + case notAvailable = "N/A" + case initial + case managed + case subsequent + + var recurringType: RecurringType? { + guard let type = RecurringType.TypeValues(rawValue: rawValue) else { return nil } + return RecurringType(type: type) + } + } + + enum RecurringCategoryPickerValues: String, CaseIterable { + case notAvailable = "N/A" + case subscription + case standingOrder = "standing_order" + + var recurringCategory: RecurringCategory? { + guard let category = RecurringCategory.CategoryValues(rawValue: rawValue) else { return nil } + return RecurringCategory(category: category) + } + } } private extension InputData { @@ -525,13 +546,19 @@ extension InputData { } var recurringTypeValue: RecurringType? { - let recurringType = RecurringType(type: RecurringType.TypeValues(rawValue: recurringType.value) ?? .initial) - - return [.authorize, .authorize3d, .sale, .sale3d].contains(transactionName) ? recurringType : nil + if [.authorize, .authorize3d, .sale, .sale3d].contains(transactionName) { + return RecurringTypePickerValues(rawValue: recurringType.value)?.recurringType + } else { + return nil + } } - var recurringCategoryValue: RecurringCategory { - RecurringCategory(category: RecurringCategory.CategoryValues(rawValue: recurringCategory.value) ?? .subscription) + var recurringCategoryValue: RecurringCategory? { + if [.initRecurringSale, .initRecurringSale3d].contains(transactionName) { + return RecurringCategoryPickerValues(rawValue: recurringCategory.value)?.recurringCategory + } else { + return nil + } } var lifetimeValue: Int { @@ -568,8 +595,8 @@ extension InputData { transactionTypes: [paymentTransactionType], notificationUrl: notificationUrl.value) paymentRequest.usage = usage.value - paymentRequest.lifetime = lifetimeValue + paymentRequest.recurringCategory = recurringCategoryValue if let payLaterValue, payLaterValue { paymentRequest.payLater = payLaterValue @@ -580,10 +607,6 @@ extension InputData { paymentRequest.threeDSV2Params = threeDSParams } - if paymentRequest.requiresRecurringCategory { - paymentRequest.recurringCategory = recurringCategoryValue - } - if paymentRequest.requiresPaymentSubtype { paymentRequest.paymentSubtype = paymentSubtypeValue } diff --git a/GenesisSwift Example/iOS Example/Tests/InputDataTests.swift b/GenesisSwift Example/iOS Example/Tests/InputDataTests.swift index bc977cf..c55535c 100644 --- a/GenesisSwift Example/iOS Example/Tests/InputDataTests.swift +++ b/GenesisSwift Example/iOS Example/Tests/InputDataTests.swift @@ -96,28 +96,38 @@ extension InputDataTests { XCTAssertTrue(data.supportsRecurringType) var request = data.createPaymentRequest() for type in request.transactionTypes { - XCTAssertNotNil(type.recurringType) + XCTAssertNil(type.recurringType) // not set explicitly + } + data.recurringType.value = InputData.RecurringTypePickerValues.initial.rawValue + request = data.createPaymentRequest() + for type in request.transactionTypes { + XCTAssertNotNil(type.recurringType) // set explicitly } data = InputData(transactionName: .sale3d) XCTAssertTrue(data.supportsRecurringType) request = data.createPaymentRequest() for type in request.transactionTypes { - XCTAssertNotNil(type.recurringType) + XCTAssertNil(type.recurringType) // not set explicitly + } + data.recurringType.value = InputData.RecurringTypePickerValues.subsequent.rawValue + request = data.createPaymentRequest() + for type in request.transactionTypes { + XCTAssertNotNil(type.recurringType) // set explicitly } data = InputData(transactionName: .authorize) XCTAssertTrue(data.supportsRecurringType) request = data.createPaymentRequest() for type in request.transactionTypes { - XCTAssertNotNil(type.recurringType) + XCTAssertNil(type.recurringType) // not set explicitly } data = InputData(transactionName: .authorize3d) XCTAssertTrue(data.supportsRecurringType) request = data.createPaymentRequest() for type in request.transactionTypes { - XCTAssertNotNil(type.recurringType) + XCTAssertNil(type.recurringType) // not set explicitly } data = InputData(transactionName: .initRecurringSale) @@ -147,12 +157,18 @@ extension InputDataTests { var data = InputData(transactionName: .initRecurringSale) XCTAssertTrue(data.supportsRecurringCategory) var request = data.createPaymentRequest() - XCTAssertNotNil(request.recurringCategory) + XCTAssertNil(request.recurringCategory) // not set explicitly + data.recurringCategory.value = InputData.RecurringCategoryPickerValues.subscription.rawValue + request = data.createPaymentRequest() + XCTAssertNotNil(request.recurringCategory) // set explicitly data = InputData(transactionName: .initRecurringSale3d) XCTAssertTrue(data.supportsRecurringCategory) request = data.createPaymentRequest() - XCTAssertNotNil(request.recurringCategory) + XCTAssertNil(request.recurringCategory) // not set explicitly + data.recurringCategory.value = InputData.RecurringCategoryPickerValues.standingOrder.rawValue + request = data.createPaymentRequest() + XCTAssertNotNil(request.recurringCategory) // set explicitly data = InputData(transactionName: .sale) XCTAssertFalse(data.supportsRecurringCategory) diff --git a/GenesisSwift Example/iOS Example/Tests/PickerDataTests.swift b/GenesisSwift Example/iOS Example/Tests/PickerDataTests.swift index d26c433..fe2c8be 100644 --- a/GenesisSwift Example/iOS Example/Tests/PickerDataTests.swift +++ b/GenesisSwift Example/iOS Example/Tests/PickerDataTests.swift @@ -8,9 +8,18 @@ import XCTest @testable import GenesisSwift class PickerDataTests: XCTestCase { - private var sut: PickerData! + override func tearDown() { + super.tearDown() + sut = nil + } +} + +// MARK: - Tests + +extension PickerDataTests { + func testPickerData() { let item1 = IsoCountryInfo(name: "item1.name", numeric: "item1.numeric", alpha2: "item1.alpha2", alpha3: "item1.alpha3", calling: "item1.calling", currency: "item1.currency", continent: "item1.continent") @@ -28,4 +37,18 @@ class PickerDataTests: XCTestCase { XCTAssertEqual(sut.items[1].pickerTitle, item2.name.rawValue) XCTAssertEqual(sut.items[1].pickerValue, item2.name.rawValue) } + + func testRecurringParamsConversion() { + + XCTAssertNil(InputData.RecurringTypePickerValues.notAvailable.recurringType) + XCTAssertEqual(InputData.RecurringTypePickerValues.initial.recurringType?.type, RecurringType.TypeValues.initial) + XCTAssertEqual(InputData.RecurringTypePickerValues.managed.recurringType?.type, RecurringType.TypeValues.managed) + XCTAssertEqual(InputData.RecurringTypePickerValues.subsequent.recurringType?.type, RecurringType.TypeValues.subsequent) + + XCTAssertNil(InputData.RecurringCategoryPickerValues.notAvailable.recurringCategory) + XCTAssertEqual(InputData.RecurringCategoryPickerValues.standingOrder.recurringCategory?.category, + RecurringCategory.CategoryValues.standingOrder) + XCTAssertEqual(InputData.RecurringCategoryPickerValues.subscription.recurringCategory?.category, + RecurringCategory.CategoryValues.subscription) + } } diff --git a/GenesisSwift.podspec b/GenesisSwift.podspec index e3e9f54..c9e9040 100755 --- a/GenesisSwift.podspec +++ b/GenesisSwift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "GenesisSwift" - s.version = "1.5.0" + s.version = "1.5.1" s.summary = "iOS Genesis Payment Gateway" s.description = "The iOS Genesis Payment Gateway Swift SDK." s.homepage = "https://github.com/GenesisGateway/ios_sdk.git" diff --git a/GenesisSwift.xcodeproj/project.pbxproj b/GenesisSwift.xcodeproj/project.pbxproj index 0d3e7b6..3cec8ab 100644 --- a/GenesisSwift.xcodeproj/project.pbxproj +++ b/GenesisSwift.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 53; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -669,7 +669,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.5.0; + MARKETING_VERSION = 1.5.1; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; ONLY_ACTIVE_ARCH = NO; @@ -707,7 +707,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.5.0; + MARKETING_VERSION = 1.5.1; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; OTHER_LDFLAGS = ""; diff --git a/GenesisSwift/Models/KlarnaItem.swift b/GenesisSwift/Models/KlarnaItem.swift index 1fbef14..ed84d65 100644 --- a/GenesisSwift/Models/KlarnaItem.swift +++ b/GenesisSwift/Models/KlarnaItem.swift @@ -97,7 +97,7 @@ extension KlarnaItem: ValidateInputDataProtocol { public func isValidData() throws { let requiredParameters = RequiredParameters.requiredParametersForKlarnaItem() let validator = RequiredParametersValidator(withRequiredParameters: requiredParameters) - try validator.isValidKlarnaItem(item: self) + try validator.validateKlarnaItem(self) } } diff --git a/GenesisSwift/Models/PaymentAddress.swift b/GenesisSwift/Models/PaymentAddress.swift index b402ae6..3f05632 100644 --- a/GenesisSwift/Models/PaymentAddress.swift +++ b/GenesisSwift/Models/PaymentAddress.swift @@ -73,8 +73,7 @@ extension PaymentAddress: ValidateInputDataProtocol { public func isValidData() throws { let requiredParameters = RequiredParameters.requiredParametersForAddress() let validator = RequiredParametersValidator(withRequiredParameters: requiredParameters) - - try validator.isValidAddress(address: self) + try validator.validateAddress(self) } } diff --git a/GenesisSwift/Models/PaymentRequest.swift b/GenesisSwift/Models/PaymentRequest.swift index 6051cc8..8015067 100644 --- a/GenesisSwift/Models/PaymentRequest.swift +++ b/GenesisSwift/Models/PaymentRequest.swift @@ -57,15 +57,15 @@ public final class PaymentRequest { } public var requiresRecurringType: Bool { - // the request requires RecurringType if any of its specified types require it - let requiredTypes: Set = [.sale, .sale3d, .authorize, .authorize3d] - return isParameterRequired(for: requiredTypes) + // .sale, .sale3d, .authorize & .authorize3d may contain a recurring type parameter, but it is not required + // retain for backward compatibility and future requirements' changes + false } public var requiresRecurringCategory: Bool { - // the request requires RecurringCategory if any of its specified types require it - let requiredTypes: Set = [.initRecurringSale, .initRecurringSale3d] - return isParameterRequired(for: requiredTypes) + // .initRecurringSale & .initRecurringSale3d may contain a recurring category parameter, but it is not required + // retain for backward compatibility and future requirements' changes + false } public var requiresPaymentSubtype: Bool { @@ -263,7 +263,7 @@ extension PaymentRequest: ValidateInputDataProtocol { let requiredParameters = RequiredParameters.requiredParametersForRequest(paymentRequest: self) let validator = RequiredParametersValidator(withRequiredParameters: requiredParameters) - try validator.isValidRequest(request: self) + try validator.validateRequest(self) } } diff --git a/GenesisSwift/Models/PaymentTransactionType.swift b/GenesisSwift/Models/PaymentTransactionType.swift index e213aee..c6bea94 100644 --- a/GenesisSwift/Models/PaymentTransactionType.swift +++ b/GenesisSwift/Models/PaymentTransactionType.swift @@ -132,10 +132,9 @@ public final class PaymentTransactionType { extension PaymentTransactionType: ValidateInputDataProtocol { public func isValidData() throws { - let requiredParameters = RequiredParameters.requiredParametersForTransactionType(transactionType: self) + let requiredParameters = RequiredParameters.requiredParametersForTransactionType(self) let validator = RequiredParametersValidator(withRequiredParameters: requiredParameters) - - try validator.isValidTransactionType(transactionType: self) + try validator.validateTransactionType(self) } } diff --git a/GenesisSwift/Models/Reminder.swift b/GenesisSwift/Models/Reminder.swift index 2570c76..10caef3 100644 --- a/GenesisSwift/Models/Reminder.swift +++ b/GenesisSwift/Models/Reminder.swift @@ -65,7 +65,6 @@ extension Reminder: ValidateInputDataProtocol { public func isValidData() throws { let requiredParamters = RequiredParameters.requiredParametersForReminder() let validator = RequiredParametersValidator(withRequiredParameters: requiredParamters) - - try validator.isValidReminder(reminder: self) + try validator.validateReminder(self) } } diff --git a/GenesisSwift/Protocols/String+Conversion.swift b/GenesisSwift/Protocols/String+Conversion.swift index ada8c28..81495f7 100644 --- a/GenesisSwift/Protocols/String+Conversion.swift +++ b/GenesisSwift/Protocols/String+Conversion.swift @@ -8,19 +8,15 @@ import Foundation public extension String { func explicitConvertionToDecimal() -> Decimal? { - struct StaticFormatter { - static let formatter: NumberFormatter = { - let tmpFormatter = NumberFormatter() - tmpFormatter.generatesDecimalNumbers = true - tmpFormatter.numberStyle = NumberFormatter.Style.decimal - return tmpFormatter + enum StaticFormatter { + static let decimalFormatter: NumberFormatter = { + let formatter = NumberFormatter() + formatter.generatesDecimalNumbers = true + formatter.numberStyle = .decimal + return formatter }() } - if let decimalNumber = StaticFormatter.formatter.number(from: self) as? Decimal { - return decimalNumber - } - - return nil + return StaticFormatter.decimalFormatter.number(from: self) as? Decimal } } diff --git a/GenesisSwift/Validation/RequiredParameters.swift b/GenesisSwift/Validation/RequiredParameters.swift index 0df7362..2c074e1 100644 --- a/GenesisSwift/Validation/RequiredParameters.swift +++ b/GenesisSwift/Validation/RequiredParameters.swift @@ -107,7 +107,7 @@ enum RequiredParameters { return Array(set) } - static func requiredParametersForTransactionType(transactionType: PaymentTransactionType) -> [String] { + static func requiredParametersForTransactionType(_ transactionType: PaymentTransactionType) -> [String] { switch transactionType.name { case .ppro: return [PropertyKeys.ProductNameKey, @@ -122,8 +122,6 @@ enum RequiredParameters { return [PropertyKeys.OrderTaxAmountKey, PropertyKeys.CustomerGenderKey, PropertyKeys.ItemsKey] - case .authorize, .authorize3d, .sale, .sale3d: - return [PropertyKeys.RecurringTypeKey] default: return [] } @@ -151,10 +149,6 @@ enum RequiredParameters { requiredParameters.append(PropertyKeys.ThreeDSV2ParamsKey) } - if [.initRecurringSale, .initRecurringSale3d].contains(transactionName) { - requiredParameters.append(PropertyKeys.RecurringCategoryKey) - } - if [.applePay].contains(transactionName) { requiredParameters.append(contentsOf: [PropertyKeys.PaymentSubtypeKey]) } diff --git a/GenesisSwift/Validation/RequiredParametersValidator.swift b/GenesisSwift/Validation/RequiredParametersValidator.swift index 2f08e9b..1165e1e 100644 --- a/GenesisSwift/Validation/RequiredParametersValidator.swift +++ b/GenesisSwift/Validation/RequiredParametersValidator.swift @@ -18,7 +18,7 @@ class RequiredParametersValidator { self.parameters = parameters } - func isValidRequest(request: PaymentRequest) throws { + func validateRequest(_ request: PaymentRequest) throws { path = "PaymentRequest" resetArrays() @@ -31,7 +31,7 @@ class RequiredParametersValidator { try throwErrorIfExists() } - func isValidAddress(address: PaymentAddress) throws { + func validateAddress(_ address: PaymentAddress) throws { path = "PaymentAddress" resetArrays() @@ -46,7 +46,7 @@ class RequiredParametersValidator { try throwErrorIfExists() } - func isValidTransactionType(transactionType: PaymentTransactionType) throws { + func validateTransactionType(_ transactionType: PaymentTransactionType) throws { path = "PaymentTransactionTypes[\(transactionType.name)]" resetArrays() @@ -57,7 +57,7 @@ class RequiredParametersValidator { try throwErrorIfExists() } - func isValidKlarnaItem(item: KlarnaItem) throws { + func validateKlarnaItem(_ item: KlarnaItem) throws { path = "items" resetArrays() @@ -68,7 +68,7 @@ class RequiredParametersValidator { try throwErrorIfExists() } - func isValidReminder(reminder: Reminder) throws { + func validateReminder(_ reminder: Reminder) throws { path = "reminder" resetArrays() @@ -120,7 +120,7 @@ class RequiredParametersValidator { return !transactionsNames.isDisjoint(with: transactionTypes.map { $0.name }) } - private func isURLParameter(parameter: String) -> Bool { + private func isURLParameter(_ parameter: String) -> Bool { parameter == PropertyKeys.NotificationUrlKey || parameter == PropertyKeys.ReturnSuccessUrlKey || parameter == PropertyKeys.ReturnFailureUrlKey || @@ -131,7 +131,7 @@ class RequiredParametersValidator { Ranges.monthInMinutes.contains(interval) } - private func isValidUrlString(string: String) -> Bool { + private func isValidURLString(_ string: String) -> Bool { guard !string.isEmpty, let url = URL(string: string), let scheme = url.scheme, !scheme.isEmpty, let host = url.host, !host.isEmpty else { return false } @@ -142,8 +142,8 @@ class RequiredParametersValidator { private func isValidValue(_ value: AnyObject, forParameter parameter: String) throws { let regex = ParametersRegex.regexForKey(parameter) - if isURLParameter(parameter: parameter) { - guard let url = value as? String, isValidUrlString(string: url) else { + if isURLParameter(parameter) { + guard let url = value as? String, isValidURLString(url) else { throw GenesisValidationError.wrongValueForParameter(parameter, parameter) } } else if parameter == PropertyKeys.ThreeDSV2ParamsKey { diff --git a/GenesisSwiftTests/DynamicDescriptorParamsTests.swift b/GenesisSwiftTests/DynamicDescriptorParamsTests.swift index f0a10b3..7bbc91d 100644 --- a/GenesisSwiftTests/DynamicDescriptorParamsTests.swift +++ b/GenesisSwiftTests/DynamicDescriptorParamsTests.swift @@ -10,6 +10,16 @@ final class DynamicDescriptorParamsTests: XCTestCase { private var sut: DynamicDescriptorParams! + override func tearDown() { + super.tearDown() + sut = nil + } +} + +// MARK: - Tests + +extension DynamicDescriptorParamsTests { + func testFullNames() { sut = DynamicDescriptorParams(merchantName: "fixed.name", merchantCity: "fixed.city", subMerchantId: nil) XCTAssertEqual(sut.merchantName, "fixed.name") diff --git a/GenesisSwiftTests/PaymentAddressTests.swift b/GenesisSwiftTests/PaymentAddressTests.swift index da1a5d7..82f7d87 100644 --- a/GenesisSwiftTests/PaymentAddressTests.swift +++ b/GenesisSwiftTests/PaymentAddressTests.swift @@ -8,6 +8,11 @@ import XCTest final class PaymentAddressTests: XCTestCase { private var sut: PaymentAddress! + + override func tearDown() { + super.tearDown() + sut = nil + } } // MARK: - Tests diff --git a/GenesisSwiftTests/PaymentRequestTests.swift b/GenesisSwiftTests/PaymentRequestTests.swift index 7ab2bdc..4e00109 100644 --- a/GenesisSwiftTests/PaymentRequestTests.swift +++ b/GenesisSwiftTests/PaymentRequestTests.swift @@ -535,6 +535,44 @@ extension PaymentRequestTests { let xml = sut.toXmlString() XCTAssertEqual("subscription", xmlValue(inTag: "recurring_category", from: xml)) } + + func testOptionalRecurringParameters() { + + sut.customerEmail = "customer@mail.com" + sut.notificationUrl = "https://google.com" + + // test the optionality of both recurringType & recurringCategory (regardless of transaction type) + + sut.transactionTypes = [PaymentTransactionType(name: .initRecurringSale)] + sut.transactionTypes.first?.recurringType = nil + sut.recurringCategory = nil + XCTAssertNoThrow(try sut.isValidData()) + XCTAssertFalse(sut.requiresRecurringCategory) + XCTAssertFalse(sut.requiresRecurringType) + var xml = sut.toXmlString() + XCTAssertNil(xmlValue(inTag: "recurring_category", from: xml)) + XCTAssertNil(xmlValue(inTag: "recurring_type", from: xml)) + + sut.transactionTypes = [PaymentTransactionType(name: .sale)] + sut.transactionTypes.first?.recurringType = nil + sut.recurringCategory = nil + XCTAssertNoThrow(try sut.isValidData()) + XCTAssertFalse(sut.requiresRecurringCategory) + XCTAssertFalse(sut.requiresRecurringType) + xml = sut.toXmlString() + XCTAssertNil(xmlValue(inTag: "recurring_category", from: xml)) + XCTAssertNil(xmlValue(inTag: "recurring_type", from: xml)) + + sut.transactionTypes = [PaymentTransactionType(name: .sale)] + sut.transactionTypes.first?.recurringType = RecurringType(type: .subsequent) + sut.recurringCategory = nil + XCTAssertNoThrow(try sut.isValidData()) + XCTAssertFalse(sut.requiresRecurringCategory) + XCTAssertFalse(sut.requiresRecurringType) + xml = sut.toXmlString() + XCTAssertNil(xmlValue(inTag: "recurring_category", from: xml)) + XCTAssertEqual("subsequent", xmlValue(inTag: "recurring_type", from: xml)) + } } private extension PaymentRequestTests { @@ -619,10 +657,8 @@ private extension PaymentRequestTests { } func xmlValue(inTag tag: String, from xml: String) -> String? { - let startTag = "<\(tag)>" let endTag = "" - return valueBetween(start: startTag, end: endTag, in: xml) } } diff --git a/GenesisSwiftTests/PaymentTransactionTypeTest.swift b/GenesisSwiftTests/PaymentTransactionTypeTest.swift index 43cf11f..ad2da3d 100644 --- a/GenesisSwiftTests/PaymentTransactionTypeTest.swift +++ b/GenesisSwiftTests/PaymentTransactionTypeTest.swift @@ -10,6 +10,16 @@ final class PaymentTransactionTypeTest: XCTestCase { private var sut: PaymentTransactionType! + override func tearDown() { + super.tearDown() + sut = nil + } +} + +// MARK: - Tests + +extension PaymentTransactionTypeTest { + func testProperties() { let transactionName = TransactionName(rawValue: "sale")! sut = PaymentTransactionType(name: transactionName) diff --git a/GenesisSwiftTests/RiskParamsTests.swift b/GenesisSwiftTests/RiskParamsTests.swift index 59e94af..f37f39a 100644 --- a/GenesisSwiftTests/RiskParamsTests.swift +++ b/GenesisSwiftTests/RiskParamsTests.swift @@ -8,8 +8,15 @@ import XCTest final class RiskParamsTests: XCTestCase { private var sut: RiskParams! + + override func tearDown() { + super.tearDown() + sut = nil + } } +// MARK: - Tests + extension RiskParamsTests { func testFullParams() { diff --git a/GenesisSwiftTests/StringTests.swift b/GenesisSwiftTests/StringTests.swift index ef92656..565a34b 100644 --- a/GenesisSwiftTests/StringTests.swift +++ b/GenesisSwiftTests/StringTests.swift @@ -9,6 +9,8 @@ import XCTest final class StringTests: XCTestCase { } +// MARK: - Tests + extension StringTests { func testConvertionToDecimal() { diff --git a/README.md b/README.md index d629c4c..1f6a723 100755 --- a/README.md +++ b/README.md @@ -12,12 +12,12 @@ ## Requirements -- iOS 12.0+ -- Xcode 10.0+ +- iOS 12+ +- Xcode 12+ ## Installation -GenesisSwift requires Swift 5, so make sure you have at least [Xcode 10](https://developer.apple.com/xcode/downloads/). +GenesisSwift requires Swift 5, so make sure you have at least [Xcode 12](https://developer.apple.com/xcode/downloads/). ### CocoaPods @@ -92,15 +92,13 @@ let genesis = Genesis(withConfiguration: configuration, paymentRequest: paymentR //Push to navigation controller genesis.push(toNavigationController: navigationController!, animated: true) -//Present to modal view +//or present to modal view genesis.present(toViewController: self, animated: true) -//Use genesis.genesisViewController() and show how you want -guard let genesisViewController = genesis.genesisViewController() else { - return +//or use genesis.genesisViewController() to show it +if let genesisViewController = genesis.genesisViewController() { + show(genesisViewController, sender: nil) } -show(genesisViewController, sender: nil) - ... @@ -268,7 +266,7 @@ paymentRequest.threeDSV2Params = threeDSV2Params Check input data ```swift -//This will check all setted data +// Validate all of the configured data per request do { try paymentRequest.isValidData() } catch { @@ -290,7 +288,7 @@ do { } ``` -## Required parameters for transaction types +## Additional parameters for transaction types - ApplePay @@ -313,7 +311,7 @@ authorizeTransactionType.recurringType = RecurringType(type: .initial) let saleTransactionType = PaymentTransactionType(name: .sale) saleTransactionType.recurringType = RecurringType(type: .subsequent) -// recurringType is required for Authorize, Authorize3d, Sale, Sale3d transaction types +// recurringType can be set for Authorize, Authorize3d, Sale, and Sale3d transaction types (or can be omitted depending on the use case) paymentRequest.transactionTypes = [authorizeTransactionType, saleTransactionType] ``` @@ -325,7 +323,7 @@ let recurringCategory = RecurringCategory(category: .subscription) paymentRequest.transactionTypes = paymentTransactionTypes -// recurringCategory is required for Init Recurring Sale, Init Recurring Sale3d +// recurringCategory can be set for Init Recurring Sale and Init Recurring Sale3d transaction types (or can be omitted depending on the use case) paymentRequest.recurringCategory = recurringCategory ```