-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor ADYServiceAdaptor to ThreeDSServicable (#2023)
# Summary A refactor for the ADYServiceAdaptor to make it easily swappable if necessary. # Ticket <ticket> DSP-1866 </ticket>
- Loading branch information
Showing
25 changed files
with
827 additions
and
367 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
AdyenActions/Components/3DS2/3DS2 SDK Adapters/ChallengeParameters.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// | ||
// Copyright (c) 2025 Adyen N.V. | ||
// | ||
// This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
// | ||
|
||
import Foundation | ||
|
||
internal struct ChallengeParameters { | ||
internal let challengeToken: ThreeDS2Component.ChallengeToken | ||
internal let threeDSRequestorAppURL: URL? | ||
} |
17 changes: 17 additions & 0 deletions
17
AdyenActions/Components/3DS2/3DS2 SDK Adapters/FingerprintServiceParameters.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// Copyright (c) 2025 Adyen N.V. | ||
// | ||
// This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
// | ||
|
||
import class Adyen3DS2.ADYAppearanceConfiguration | ||
import Foundation | ||
|
||
internal struct FingerprintServiceParameters { | ||
internal let directoryServerIdentifier: String | ||
internal let directoryServerPublicKey: String | ||
internal let directoryServerRootCertificates: String | ||
internal let deviceExcludedParameters: [String: Any]? | ||
internal let appearanceConfiguration: Adyen3DS2.ADYAppearanceConfiguration | ||
internal let threeDSMessageVersion: String | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
113 changes: 113 additions & 0 deletions
113
AdyenActions/Components/3DS2/3DS2 SDK Adapters/LegacySDK/ThreeDSServiceLegacy.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// | ||
// Copyright (c) 2025 Adyen N.V. | ||
// | ||
// This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
// | ||
|
||
import Adyen3DS2 | ||
import Foundation | ||
@_spi(AdyenInternal) import Adyen | ||
|
||
/// This is a wrapper class for the Objective C 3ds2 sdk. | ||
/// This translates simple non specific sdk bound types such as | ||
/// `FingerprintServiceParameters` & `ChallengeParameters` to sdk specific types and performs actions. | ||
internal final class ThreeDSServiceLegacy: ThreeDSServiceable { | ||
private var service: AnyADYService | ||
private var transaction: AnyADYTransaction? | ||
|
||
internal init( | ||
service: AnyADYService = ADYServiceAdapter() | ||
) { | ||
self.service = service | ||
} | ||
|
||
internal func performFingerprint( | ||
parameters: FingerprintServiceParameters, | ||
completionHandler: @escaping (Result<AnyAuthenticationRequestParameters, ThreeDSServiceFingerprintError>) -> Void | ||
) { | ||
let serviceParameters = ADYServiceParameters( | ||
directoryServerIdentifier: parameters.directoryServerIdentifier, | ||
directoryServerPublicKey: parameters.directoryServerPublicKey, | ||
directoryServerRootCertificates: parameters.directoryServerRootCertificates | ||
) | ||
service.service( | ||
with: serviceParameters, | ||
appearanceConfiguration: parameters.appearanceConfiguration | ||
) { [weak self] service in | ||
guard let self else { return } | ||
do { | ||
let transaction = try service.transaction(withMessageVersion: parameters.threeDSMessageVersion) | ||
self.transaction = transaction | ||
completionHandler(.success(transaction.authenticationParameters)) | ||
|
||
} catch { | ||
completionHandler( | ||
.failure(.fingerprintingError( | ||
errorPayload: self.opaqueErrorObject(error: error) | ||
)) | ||
) | ||
} | ||
} | ||
} | ||
|
||
internal func performChallenge( | ||
with parameters: ChallengeParameters, | ||
completionHandler: @escaping (Result<AnyChallengeResult, ThreeDSServiceChallengeError>) -> Void | ||
) { | ||
let challengeParameters = ADYChallengeParameters( | ||
serverTransactionIdentifier: parameters.challengeToken.serverTransactionIdentifier, | ||
threeDSRequestorAppURL: parameters.threeDSRequestorAppURL, | ||
acsTransactionIdentifier: parameters.challengeToken.acsTransactionIdentifier, | ||
acsReferenceNumber: parameters.challengeToken.acsReferenceNumber, | ||
acsSignedContent: parameters.challengeToken.acsSignedContent | ||
) | ||
|
||
guard let transaction else { | ||
return completionHandler(.failure(.transactionNotInitialized( | ||
errorPayload: opaqueErrorObject(error: ThreeDSServiceChallengeError.transactionNotInitialized(errorPayload: "")) | ||
))) | ||
} | ||
|
||
transaction.performChallenge( | ||
with: challengeParameters | ||
) { [weak self] challengeResult, error in | ||
guard let self else { return } | ||
|
||
guard let result = challengeResult else { | ||
guard let error else { | ||
completionHandler(.failure(.errorAndResultAreNil( | ||
errorPayload: opaqueErrorObject(error: UnknownError.resultAndErrorAreNil) | ||
))) | ||
return | ||
} | ||
|
||
if isCancelled(error: error) { | ||
return completionHandler(.failure(.cancelled( | ||
errorPayload: opaqueErrorObject(error: error) | ||
))) | ||
} else { | ||
return completionHandler(.failure(.challengeError( | ||
errorPayload: opaqueErrorObject(error: error) | ||
))) | ||
} | ||
} | ||
completionHandler(.success(result)) | ||
} | ||
} | ||
|
||
private func isCancelled(error: Error) -> Bool { | ||
let error: NSError = error as NSError | ||
return (error.code == Int(ADYRuntimeErrorCode.challengeCancelled.rawValue)) && (error.domain == ADYRuntimeErrorDomain) | ||
} | ||
|
||
internal func opaqueErrorObject(error: any Error) -> String { | ||
(error as NSError).base64Representation() | ||
} | ||
|
||
internal func resetTransaction() { | ||
self.transaction = nil | ||
} | ||
} | ||
|
||
extension Adyen3DS2.ADYAuthenticationRequestParameters: AnyAuthenticationRequestParameters {} | ||
extension Adyen3DS2.ADYChallengeResult: AnyChallengeResult {} |
19 changes: 19 additions & 0 deletions
19
AdyenActions/Components/3DS2/3DS2 SDK Adapters/ThreeDSServiceChallengeError.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// Copyright (c) 2025 Adyen N.V. | ||
// | ||
// This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Errors that could happen during a challenge | ||
internal enum ThreeDSServiceChallengeError: Error { | ||
/// The transaction was not initialized during fingerprinting. | ||
case transactionNotInitialized(errorPayload: String) | ||
/// Edge case which should never occur. | ||
case errorAndResultAreNil(errorPayload: String) | ||
/// The challenge has been cancelled. | ||
case cancelled(errorPayload: String) | ||
/// The sdk faced an error performing the challenge. | ||
case challengeError(errorPayload: String) | ||
} |
13 changes: 13 additions & 0 deletions
13
AdyenActions/Components/3DS2/3DS2 SDK Adapters/ThreeDSServiceFingerprintError.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// Copyright (c) 2025 Adyen N.V. | ||
// | ||
// This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Errors that could happen during fingerprinting | ||
internal enum ThreeDSServiceFingerprintError: Error { | ||
/// The sdk faced an error performing fingerprinting. | ||
case fingerprintingError(errorPayload: String) | ||
} |
23 changes: 23 additions & 0 deletions
23
AdyenActions/Components/3DS2/3DS2 SDK Adapters/ThreeDSServiceable.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// | ||
// Copyright (c) 2025 Adyen N.V. | ||
// | ||
// This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
// | ||
|
||
import Foundation | ||
@_spi(AdyenInternal) import Adyen | ||
|
||
/// This protocol abstracts the SDK logic away. | ||
/// The 3DS2 SDK performs 2 tasks - fingerprint & challenge. | ||
/// Additionally we provide a way to reset the transaction. | ||
internal protocol ThreeDSServiceable { | ||
func performFingerprint( | ||
parameters: FingerprintServiceParameters, | ||
completionHandler: @escaping (Result<AnyAuthenticationRequestParameters, ThreeDSServiceFingerprintError>) -> Void | ||
) | ||
func performChallenge( | ||
with parameters: ChallengeParameters, | ||
completionHandler: @escaping (Result<AnyChallengeResult, ThreeDSServiceChallengeError>) -> Void | ||
) | ||
func resetTransaction() | ||
} |
13 changes: 13 additions & 0 deletions
13
AdyenActions/Components/3DS2/3DS2 SDK Adapters/UnknownError+ThreeDSServiceable.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// Copyright (c) 2025 Adyen N.V. | ||
// | ||
// This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
// | ||
|
||
@_spi(AdyenInternal) import Adyen | ||
|
||
extension UnknownError { | ||
internal static let transactionNotInitialized = UnknownError(errorDescription: "Transaction not initialized") | ||
internal static let serviceIsNil = UnknownError(errorDescription: "ADYService is nil.") | ||
internal static let resultAndErrorAreNil = UnknownError(errorDescription: "Both error and result are nil, this should never happen.") | ||
} |
Oops, something went wrong.