diff --git a/CHANGELOG.md b/CHANGELOG.md index 50f5ec7097..fce508d1a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,10 @@ # Braintree iOS SDK Release Notes -## unreleased +## unreleased * BraintreePayPal * Fix bug to ensure that `BTPayPalVaultRequest.userAuthenticationEmail` is not sent as an empty string +* BraintreeThreeDSecure + * Return error if no `dfReferenceId` is returned in the 3D Secure flow ## 6.25.0 (2024-12-11) * BraintreePayPal diff --git a/Sources/BraintreeThreeDSecure/BTThreeDSecureClient.swift b/Sources/BraintreeThreeDSecure/BTThreeDSecureClient.swift index 75c3316b44..8de80b4c1e 100644 --- a/Sources/BraintreeThreeDSecure/BTThreeDSecureClient.swift +++ b/Sources/BraintreeThreeDSecure/BTThreeDSecureClient.swift @@ -250,9 +250,16 @@ import BraintreeCore request: request, cardinalSession: cardinalSession ) { lookupParameters in - if let dfReferenceID = lookupParameters?["dfReferenceId"] { - request.dfReferenceID = dfReferenceID + guard let dfReferenceID = lookupParameters?["dfReferenceId"], !dfReferenceID.isEmpty else { + completion( + BTThreeDSecureError.failedLookup( + [NSLocalizedDescriptionKey: "There was an error retrieving the dfReferenceId."] + ) + ) + return } + + request.dfReferenceID = dfReferenceID completion(nil) } } else { diff --git a/UnitTests/BraintreeThreeDSecureTests/BTThreeDSecureClient_Tests.swift b/UnitTests/BraintreeThreeDSecureTests/BTThreeDSecureClient_Tests.swift index 234fe29429..1f1082f3cb 100644 --- a/UnitTests/BraintreeThreeDSecureTests/BTThreeDSecureClient_Tests.swift +++ b/UnitTests/BraintreeThreeDSecureTests/BTThreeDSecureClient_Tests.swift @@ -10,7 +10,9 @@ class BTThreeDSecureClient_Tests: XCTestCase { var threeDSecureRequest = BTThreeDSecureRequest() var client: BTThreeDSecureClient! var mockThreeDSecureRequestDelegate : MockThreeDSecureRequestDelegate! - + + let mockCardinalSession = MockCardinalSession() + let mockConfiguration = BTJSON(value: [ "threeDSecure": ["cardinalAuthenticationJWT": "FAKE_JWT"], "assetsUrl": "http://assets.example.com" @@ -21,7 +23,7 @@ class BTThreeDSecureClient_Tests: XCTestCase { threeDSecureRequest.amount = 10.0 threeDSecureRequest.nonce = "fake-card-nonce" client = BTThreeDSecureClient(apiClient: mockAPIClient) - client.cardinalSession = MockCardinalSession() + client.cardinalSession = mockCardinalSession mockThreeDSecureRequestDelegate = MockThreeDSecureRequestDelegate() } @@ -689,4 +691,20 @@ class BTThreeDSecureClient_Tests: XCTestCase { waitForExpectations(timeout: 1) } + + func testPrepareLookup_whenDfReferenceIDEmpty_throwsError() { + mockAPIClient.cannedConfigurationResponseBody = mockConfiguration + mockCardinalSession.dfReferenceID = "" + + let expectation = expectation(description: "willCallCompletion") + + threeDSecureRequest.nonce = "fake-card-nonce" + + client.prepareLookup(threeDSecureRequest) { _, error in + XCTAssertEqual(error?.localizedDescription, "There was an error retrieving the dfReferenceId.") + expectation.fulfill() + } + + waitForExpectations(timeout: 1) + } } diff --git a/UnitTests/BraintreeThreeDSecureTests/MockCardinalSession.swift b/UnitTests/BraintreeThreeDSecureTests/MockCardinalSession.swift index fbbb8ec722..24d5047be4 100644 --- a/UnitTests/BraintreeThreeDSecureTests/MockCardinalSession.swift +++ b/UnitTests/BraintreeThreeDSecureTests/MockCardinalSession.swift @@ -3,7 +3,9 @@ import CardinalMobile @testable import BraintreeThreeDSecure class MockCardinalSession: CardinalSessionTestable { - + + var dfReferenceID = "fake-df-reference-id" + func configure(_ sessionConfig: CardinalSessionConfiguration) { // do nothing } @@ -13,7 +15,7 @@ class MockCardinalSession: CardinalSessionTestable { completed didCompleteHandler: @escaping CardinalSessionSetupDidCompleteHandler, validated didValidateHandler: @escaping CardinalSessionSetupDidValidateHandler ) { - didCompleteHandler("fake-df-reference-id") + didCompleteHandler(dfReferenceID) } func continueWith(transactionId: String, payload: String, validationDelegate: CardinalValidationDelegate) {