diff --git a/Sources/ProcessOut/Sources/Repositories/CustomerTokens/HttpCustomerTokensRepository.swift b/Sources/ProcessOut/Sources/Repositories/CustomerTokens/HttpCustomerTokensRepository.swift index 282b41d83..050d05ccf 100644 --- a/Sources/ProcessOut/Sources/Repositories/CustomerTokens/HttpCustomerTokensRepository.swift +++ b/Sources/ProcessOut/Sources/Repositories/CustomerTokens/HttpCustomerTokensRepository.swift @@ -39,6 +39,7 @@ final class HttpCustomerTokensRepository: CustomerTokensRepository { } let httpRequest = HttpConnectorRequest.post( path: "/customers/\(request.customerId)/tokens", + body: request, includesDeviceMetadata: true, requiresPrivateKey: true ) diff --git a/Sources/ProcessOut/Sources/Repositories/CustomerTokens/Requests/POCreateCustomerTokenRequest.swift b/Sources/ProcessOut/Sources/Repositories/CustomerTokens/Requests/POCreateCustomerTokenRequest.swift index fefade7b6..49335b94c 100644 --- a/Sources/ProcessOut/Sources/Repositories/CustomerTokens/Requests/POCreateCustomerTokenRequest.swift +++ b/Sources/ProcessOut/Sources/Repositories/CustomerTokens/Requests/POCreateCustomerTokenRequest.swift @@ -8,16 +8,17 @@ import Foundation @_spi(PO) -public struct POCreateCustomerTokenRequest { +public struct POCreateCustomerTokenRequest: Encodable { /// Customer id to associate created token with. - public let customerId: String + @POImmutableExcludedCodable + public var customerId: String /// Flag if you wish to verify the customer token by making zero value transaction. Applicable for cards only. public let verify: Bool public init(customerId: String, verify: Bool = false) { - self.customerId = customerId + self._customerId = .init(value: customerId) self.verify = verify } } diff --git a/Tests/ProcessOutTests/Sources/Integration/CustomerTokensServiceTests.swift b/Tests/ProcessOutTests/Sources/Integration/CustomerTokensServiceTests.swift index 8ed4c5247..23cfbee4d 100644 --- a/Tests/ProcessOutTests/Sources/Integration/CustomerTokensServiceTests.swift +++ b/Tests/ProcessOutTests/Sources/Integration/CustomerTokensServiceTests.swift @@ -38,11 +38,10 @@ import XCTest let card = try await cardsService.tokenize( request: .init(number: "4242424242424242", expMonth: 12, expYear: 40, cvc: "737") ) - let token = try await sut.createCustomerToken( - request: POCreateCustomerTokenRequest(customerId: Constants.customerId) - ) let request = POAssignCustomerTokenRequest( - customerId: Constants.customerId, tokenId: token.id, source: card.id, verify: false + customerId: Constants.customerId, + tokenId: try await createToken(verify: false).id, + source: card.id ) // When @@ -52,8 +51,39 @@ import XCTest XCTAssertEqual(updatedToken.cardId, card.id) } + func test_assignCustomerToken_whenVerifyIsSetToTrue_triggers3DS() async throws { + // Given + let card = try await cardsService.tokenize( + request: .init(number: "4000000000000101", expMonth: 12, expYear: 40, cvc: "737") + ) + let request = POAssignCustomerTokenRequest( + customerId: Constants.customerId, + tokenId: try await createToken(verify: true).id, + source: card.id, + verify: true, + enableThreeDS2: true + ) + let threeDSService = Mock3DSService() + threeDSService.authenticationRequestFromClosure = { _, completion in + completion(.failure(.init(code: .cancelled))) + } + + // When + _ = try? await sut.assignCustomerToken(request: request, threeDSService: threeDSService) + + // Then + XCTAssertEqual(threeDSService.authenticationRequestCallsCount, 1) + } + // MARK: - Private Properties private var sut: POCustomerTokensService! private var cardsService: POCardsService! + + // MARK: - Private Methods + + private func createToken(verify: Bool) async throws -> POCustomerToken { + let request = POCreateCustomerTokenRequest(customerId: Constants.customerId, verify: verify) + return try await sut.createCustomerToken(request: request) + } } diff --git a/Tests/ProcessOutTests/Sources/Mocks/3DS/Mock3DSService.swift b/Tests/ProcessOutTests/Sources/Mocks/3DS/Mock3DSService.swift index 084ae779a..7c0d28854 100644 --- a/Tests/ProcessOutTests/Sources/Mocks/3DS/Mock3DSService.swift +++ b/Tests/ProcessOutTests/Sources/Mocks/3DS/Mock3DSService.swift @@ -26,17 +26,17 @@ final class Mock3DSService: PO3DSService { completion: @escaping (Result) -> Void ) { authenticationRequestCallsCount += 1 - authenticationRequestFromClosure(configuration, completion) + authenticationRequestFromClosure?(configuration, completion) } func handle(challenge: PO3DS2Challenge, completion: @escaping (Result) -> Void) { handleChallengeCallsCount += 1 - handleChallengeFromClosure(challenge, completion) + handleChallengeFromClosure?(challenge, completion) } func handle(redirect: PO3DSRedirect, completion: @escaping (Result) -> Void) { handleRedirectCallsCount += 1 - handleRedirectFromClosure(redirect, completion) + handleRedirectFromClosure?(redirect, completion) } }