Skip to content

Commit

Permalink
2.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
adyen-git-manager committed Nov 1, 2018
1 parent cc48081 commit 8043c67
Show file tree
Hide file tree
Showing 181 changed files with 10,093 additions and 1,439 deletions.
5 changes: 5 additions & 0 deletions Adyen.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ Pod::Spec.new do |s|
plugin.frameworks = 'SystemConfiguration', 'CoreTelephony'
end

s.subspec 'OpenInvoice' do |plugin|
plugin.source_files = 'AdyenOpenInvoice/**/*.swift'
plugin.dependency 'Adyen/Core'
end

end
344 changes: 309 additions & 35 deletions Adyen.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

80 changes: 80 additions & 0 deletions Adyen.xcodeproj/xcshareddata/xcschemes/AdyenOpenInvoice.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1000"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E9CD42A82180908600C30D2A"
BuildableName = "AdyenOpenInvoice.framework"
BlueprintName = "AdyenOpenInvoice"
ReferencedContainer = "container:Adyen.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E9CD42A82180908600C30D2A"
BuildableName = "AdyenOpenInvoice.framework"
BlueprintName = "AdyenOpenInvoice"
ReferencedContainer = "container:Adyen.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E9CD42A82180908600C30D2A"
BuildableName = "AdyenOpenInvoice.framework"
BlueprintName = "AdyenOpenInvoice"
ReferencedContainer = "container:Adyen.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
2 changes: 1 addition & 1 deletion Adyen/Core/Models/PaymentDetail.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public struct PaymentDetail: Decodable {
public var value: String?

/// The type of input requested.
public internal(set) var inputType: InputType
public var inputType: InputType

/// A boolean value indicating whether filling this payment detail is optional.
public let isOptional: Bool
Expand Down
39 changes: 35 additions & 4 deletions Adyen/Core/Networking/APIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import AdyenInternal
import Foundation

/// Performs requests to the API.
internal final class APIClient {
/// :nodoc:
public final class APIClient {

public init() {}

// MARK: - Networking

Expand All @@ -17,7 +20,7 @@ internal final class APIClient {
/// - Parameters:
/// - request: The request to perform.
/// - completion: The completion handler to invoke when a response has been received.
internal func perform<R: Request>(_ request: R, completion: @escaping Completion<Result<R.ResponseType>>) {
public func perform<R: Request>(_ request: R, completion: @escaping Completion<Result<R.ResponseType>>) {
var urlRequest = URLRequest(url: request.url)
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = [
Expand Down Expand Up @@ -53,14 +56,42 @@ internal final class APIClient {
}

/// A request that can be sent using an APIClient.
internal protocol Request: Encodable {
/// :nodoc:
public protocol Request: Encodable {
/// The type of response expected from the request.
associatedtype ResponseType: Response

/// The payment session.
var paymentSession: PaymentSession { get }

/// The payment method for which to initiate a payment.
var paymentMethod: PaymentMethod { get }

/// The URL to which the request should be made.
var url: URL { get }

}

/// The response to a request sent using an APIClient.
internal protocol Response: Decodable {}
/// :nodoc:
public protocol Response: Decodable {}

/// :nodoc:
public extension Request {

/// Encodes the payment data for the request.
///
/// - Parameter encoder: The encoder to encode the payment data with.
public func encodePaymentData(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encode(paymentSession.paymentData, forKey: .paymentData)
try container.encode(paymentMethod.paymentMethodData, forKey: .paymentMethodData)
}

}

private enum CodingKeys: String, CodingKey {
case paymentData
case paymentMethodData
}
15 changes: 6 additions & 9 deletions Adyen/Core/Networking/PaymentInitiationRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ internal struct PaymentInitiationRequest: Request {
typealias ResponseType = PaymentInitiationResponse

/// The payment session.
internal var paymentSession: PaymentSession
var paymentSession: PaymentSession

/// The payment method for which to initiate a payment.
internal var paymentMethod: PaymentMethod
var paymentMethod: PaymentMethod

/// The payment details.
internal var paymentDetails: [PaymentDetail]
internal var paymentDetails: [PaymentDetail] = []

/// The URL to which the request should be made.
internal var url: URL {
Expand All @@ -27,17 +27,14 @@ internal struct PaymentInitiationRequest: Request {

// MARK: - Encoding

internal func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
func encode(to encoder: Encoder) throws {
try encodePaymentData(to: encoder)

try container.encode(paymentSession.paymentData, forKey: .paymentData)
try container.encode(paymentMethod.paymentMethodData, forKey: .paymentMethodData)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(paymentDetails.serialized, forKey: .paymentDetails)
}

private enum CodingKeys: String, CodingKey {
case paymentData
case paymentMethodData
case paymentDetails
}

Expand Down
10 changes: 1 addition & 9 deletions Adyen/Core/Networking/StoredPaymentMethodDeletionRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,7 @@ internal struct StoredPaymentMethodDeletionRequest: Request {
// MARK: - Encoding

internal func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encode(paymentSession.paymentData, forKey: .paymentData)
try container.encode(paymentMethod.paymentMethodData, forKey: .paymentMethodData)
}

private enum CodingKeys: String, CodingKey {
case paymentData
case paymentMethodData
try encodePaymentData(to: encoder)
}

}
36 changes: 13 additions & 23 deletions Adyen/Core/Payment Controller/PaymentController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,15 @@ public final class PaymentController {

private func decode(paymentSessionResponse: String) {
do {
paymentSession = try PaymentSession.decode(from: paymentSessionResponse)
filterUnavailablePaymentMethods()
var paymentSession = try PaymentSession.decode(from: paymentSessionResponse)

let pluginManager = PluginManager(paymentSession: paymentSession)
self.pluginManager = pluginManager

let availablePaymentMethods = pluginManager.availablePaymentMethods(for: paymentSession.paymentMethods)
paymentSession.paymentMethods = availablePaymentMethods
self.paymentSession = paymentSession

requestPaymentMethodSelection()
} catch {
finish(with: error)
Expand Down Expand Up @@ -193,26 +200,9 @@ public final class PaymentController {
PaymentControllerDelegateProxy(delegate: self.delegate)
}()

private func filterUnavailablePaymentMethods() {
guard var paymentSession = paymentSession else {
return
}

let pluginManager = PluginManager(paymentSession: paymentSession)

func isPaymentMethodAvailable(_ paymentMethod: PaymentMethod) -> Bool {
guard let plugin = pluginManager.plugin(for: paymentMethod) else {
return true
}

return plugin.isDeviceSupported
}

var paymentMethods = paymentSession.paymentMethods
paymentMethods.preferred = paymentMethods.preferred.filter(isPaymentMethodAvailable(_:))
paymentMethods.other = paymentMethods.other.filter(isPaymentMethodAvailable(_:))

self.paymentSession?.paymentMethods = paymentMethods
}
// MARK: - Plugin Manager

/// The plugin manager used for the payment. Available after the payment session has been loaded.
internal var pluginManager: PluginManager?

}
31 changes: 10 additions & 21 deletions Adyen/Core/Plugins/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,22 @@ import UIKit

/// Instances conforming to the Plugin protocol provide native logic for payment methods.
/// :nodoc:
open class Plugin: NSObject {
public protocol Plugin: AnyObject {

// MARK: - Internal
var paymentSession: PaymentSession { get }
var paymentMethod: PaymentMethod { get }

public required init(paymentMethod: PaymentMethod, paymentSession: PaymentSession, appearance: Appearance) {
self.paymentMethod = paymentMethod
self.paymentSession = paymentSession
self.appearance = appearance
}
init(paymentSession: PaymentSession, paymentMethod: PaymentMethod)

public let paymentMethod: PaymentMethod
public let paymentSession: PaymentSession
public let appearance: Appearance
open var additionalPaymentDetails: AdditionalPaymentDetails?
var isDeviceSupported: Bool { get }

open var showsDisclosureIndicator: Bool {
return false
}
}

/// :nodoc:
public extension Plugin {

open var isDeviceSupported: Bool {
public var isDeviceSupported: Bool {
return true
}

open func present(using navigationController: UINavigationController, completion: @escaping Completion<[PaymentDetail]>) {}

open func finish(with result: Result<PaymentResult>, completion: @escaping () -> Void) {
completion()
}

}
26 changes: 25 additions & 1 deletion Adyen/Core/Plugins/PluginManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal final class PluginManager {
return nil
}

let plugin = pluginClass.init(paymentMethod: paymentMethod, paymentSession: paymentSession, appearance: Appearance.shared)
let plugin = pluginClass.init(paymentSession: paymentSession, paymentMethod: paymentMethod)

plugins[paymentMethod.paymentMethodData] = plugin

Expand All @@ -60,6 +60,8 @@ internal final class PluginManager {
classNames = ["AdyenApplePay.ApplePayPlugin", "Adyen.ApplePayPlugin"]
case "card":
classNames = ["AdyenCard.CardPlugin", "Adyen.CardPlugin"]
case "klarna", "afterpay_default":
classNames = ["AdyenOpenInvoice.OpenInvoicePlugin", "Adyen.OpenInvoicePlugin"]
case "bcmc":
classNames = ["AdyenCard.CardPlugin", "Adyen.CardPlugin"]
case "sepadirectdebit":
Expand All @@ -76,4 +78,26 @@ internal final class PluginManager {
return classNames
}

// MARK: - Filtering Payment Methods

/// Returns the available payment methods for a collection of payment methods.
///
/// - Parameter paymentMethods: The payment methods to filter for available payment methods.
/// - Returns: A subset of the given payment methods, containing only available payment methods.
internal func availablePaymentMethods(for paymentMethods: SectionedPaymentMethods) -> SectionedPaymentMethods {
func isPaymentMethodAvailable(_ paymentMethod: PaymentMethod) -> Bool {
guard let plugin = self.plugin(for: paymentMethod) else {
return true
}

return plugin.isDeviceSupported
}

var paymentMethods = paymentMethods
paymentMethods.preferred = paymentMethods.preferred.filter(isPaymentMethodAvailable(_:))
paymentMethods.other = paymentMethods.other.filter(isPaymentMethodAvailable(_:))

return paymentMethods
}

}
4 changes: 4 additions & 0 deletions Adyen/Core/Utilities/Validator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
// This file is open source and available under the MIT license. See the LICENSE file for more info.
//

/// :nodoc:
public protocol Validator {
func isValid(_ string: String) -> Bool
func isMaxLength(_ string: String) -> Bool
func format(_ string: String) -> String
func sanitize(_ string: String) -> String
}

/// :nodoc:
public extension Validator {
func isValid(_ string: String) -> Bool {
return true
Expand All @@ -29,8 +31,10 @@ public extension Validator {
}
}

/// :nodoc:
public protocol NumericValidator: Validator {}

/// :nodoc:
public extension NumericValidator {
func sanitize(_ string: String) -> String {
let allowedCharacters = CharacterSet.decimalDigits
Expand Down
Loading

0 comments on commit 8043c67

Please sign in to comment.