From 6f8379483712dedbc5b004309159a7738954de3f Mon Sep 17 00:00:00 2001 From: Javier Su Date: Fri, 17 Sep 2021 15:26:04 +0800 Subject: [PATCH] fix: SDK not sending card CVN when creating authentication --- Xendit.podspec | 2 +- Xendit/XDTCards.swift | 36 +++++++++++++++++++++++++----------- Xendit/Xendit.swift | 10 +++++----- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Xendit.podspec b/Xendit.podspec index c6b8481..395b792 100755 --- a/Xendit.podspec +++ b/Xendit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Xendit" - s.version = "3.4.1" + s.version = "3.4.2" s.summary = "Xendit is an API for accepting payments online" s.homepage = "https://www.xendit.co" s.license = "MIT" diff --git a/Xendit/XDTCards.swift b/Xendit/XDTCards.swift index 035c272..b495e3e 100644 --- a/Xendit/XDTCards.swift +++ b/Xendit/XDTCards.swift @@ -74,15 +74,21 @@ public class XDTCards: CanTokenize, CanAuthenticate { completion(tokenWith3DSRecommendation, nil); }) } else { - handleCreditCardTokenization(fromViewController: fromViewController, authenticatedToken: authenticatedToken, amount: tokenizationRequest.amount, currency: currency, onBehalfOf: onBehalfOf, error: error, completion: completion) + handleCreditCardTokenization(fromViewController: fromViewController, authenticatedToken: authenticatedToken, amount: tokenizationRequest.amount, currency: currency, onBehalfOf: onBehalfOf, cardCvn: tokenizationRequest.cardData.cardCvn, error: error, completion: completion) } } } public static func createAuthentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, onBehalfOf: String?, customer: XenditCustomer?, completion: @escaping (XenditAuthentication?, XenditError?) -> Void) { + createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: nil, onBehalfOf: onBehalfOf, customer: customer, completion: completion); } public static func createAuthentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, currency: String?, onBehalfOf: String?, customer: XenditCustomer?, completion: @escaping (XenditAuthentication?, XenditError?) -> Void) { + + createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: nil, onBehalfOf: onBehalfOf, customer: customer, cardCvn: nil, completion: completion); + } + + public static func createAuthentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, currency: String?, onBehalfOf: String?, customer: XenditCustomer?, cardCvn: String?, completion: @escaping (XenditAuthentication?, XenditError?) -> Void) { if publishableKey == nil { completion(nil, XenditError(errorCode: "VALIDATION_ERROR", message: "Empty publishable key")) return @@ -96,12 +102,12 @@ public class XDTCards: CanTokenize, CanAuthenticate { (jwt, error) in if error != nil || jwt?.jwt == nil { // Continue with normal flow - create3DS1Authentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, completion: completion) + create3DS1Authentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, cardCvn: cardCvn, completion: completion) } else { // 3DS2 flow let environment = jwt?.environment; let jwt = jwt?.jwt - handleEmv3DSFlow(fromViewController: fromViewController, tokenId: tokenId, environment: environment!, amount: amount, currency: currency, jwt: jwt!, onBehalfOf: onBehalfOf) { + handleEmv3DSFlow(fromViewController: fromViewController, tokenId: tokenId, environment: environment!, amount: amount, currency: currency, jwt: jwt!, onBehalfOf: onBehalfOf, cardCvn: cardCvn) { (token, error) in if token == nil || error != nil { completion(nil, error) @@ -116,7 +122,7 @@ public class XDTCards: CanTokenize, CanAuthenticate { } } - private static func create3DS1Authentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, currency: String?, onBehalfOf: String?, completion: @escaping (XenditAuthentication?, XenditError?) -> Void) { + private static func create3DS1Authentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, currency: String?, onBehalfOf: String?, cardCvn: String?, completion: @escaping (XenditAuthentication?, XenditError?) -> Void) { if publishableKey == nil { completion(nil, XenditError(errorCode: "VALIDATION_ERROR", message: "Empty publishable key")) return @@ -130,6 +136,10 @@ public class XDTCards: CanTokenize, CanAuthenticate { requestBody["currency"] = currency } + if cardCvn != nil { + requestBody["card_cvn"] = cardCvn + } + var extraHeaders: [String: String] = [:] if onBehalfOf != nil || onBehalfOf != "" { extraHeaders["for-user-id"] = onBehalfOf @@ -143,7 +153,7 @@ public class XDTCards: CanTokenize, CanAuthenticate { XDTApiClient.create3DSRecommendationRequest(publishableKey: publishableKey!, tokenId: tokenId, completion: completion) } - private static func createAuthenticationWithSessionId(fromViewController: UIViewController, tokenId: String, sessionId: String, amount: NSNumber, currency: String?, onBehalfOf: String?, completion:@escaping (_ : XenditCCToken?, _ : XenditError?) -> Void) { + private static func createAuthenticationWithSessionId(fromViewController: UIViewController, tokenId: String, sessionId: String, amount: NSNumber, currency: String?, onBehalfOf: String?, cardCvn: String?, completion:@escaping (_ : XenditCCToken?, _ : XenditError?) -> Void) { var requestBody: [String: Any] = [ "amount" : amount, @@ -154,6 +164,10 @@ public class XDTCards: CanTokenize, CanAuthenticate { requestBody["currency"] = currency } + if cardCvn != nil { + requestBody["card_cvn"] = cardCvn + } + var header: [String: String] = [:] if onBehalfOf != nil { header["for-user-id"] = onBehalfOf! @@ -173,7 +187,7 @@ public class XDTCards: CanTokenize, CanAuthenticate { authentication?.authenticationTransactionId == nil || authentication?.requestPayload == nil { // Revert to 3DS1 flow - return create3DS1Authentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf) { (authentication, error) in + return create3DS1Authentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, cardCvn: cardCvn) { (authentication, error) in if error != nil { return completion(nil, error) } @@ -246,7 +260,7 @@ public class XDTCards: CanTokenize, CanAuthenticate { return nil } - private static func handleCreditCardTokenization(fromViewController: UIViewController, authenticatedToken: XenditAuthenticatedToken?, amount: NSNumber, currency: String?, onBehalfOf: String?, error: XenditError?, completion:@escaping (_ : XenditCCToken?, _ : XenditError?) -> Void) { + private static func handleCreditCardTokenization(fromViewController: UIViewController, authenticatedToken: XenditAuthenticatedToken?, amount: NSNumber, currency: String?, onBehalfOf: String?, cardCvn: String?, error: XenditError?, completion:@escaping (_ : XenditCCToken?, _ : XenditError?) -> Void) { if let error = error { // handle error message if error.errorCode == "INVALID_USER_ID" { @@ -265,7 +279,7 @@ public class XDTCards: CanTokenize, CanAuthenticate { if status != nil { if status == "IN_REVIEW" { if CreditCard.is3ds2Version(version: authenticatedToken?.threedsVersion) && jwt != nil { - handleEmv3DSFlow(fromViewController: fromViewController, tokenId: tokenId, environment: authenticatedToken!.environment!, amount: amount, currency: currency, jwt: jwt!, onBehalfOf: onBehalfOf, completion: completion) + handleEmv3DSFlow(fromViewController: fromViewController, tokenId: tokenId, environment: authenticatedToken!.environment!, amount: amount, currency: currency, jwt: jwt!, onBehalfOf: onBehalfOf, cardCvn: cardCvn, completion: completion) } else if let authenticationURL = authenticatedToken?.authenticationURL { cardAuthenticationProvider.authenticate( fromViewController: fromViewController, @@ -283,16 +297,16 @@ public class XDTCards: CanTokenize, CanAuthenticate { } } - private static func handleEmv3DSFlow(fromViewController: UIViewController, tokenId: String, environment: String, amount: NSNumber, currency: String?, jwt: String, onBehalfOf: String?, completion:@escaping (_ : XenditCCToken?, _ : XenditError?) -> Void) { + private static func handleEmv3DSFlow(fromViewController: UIViewController, tokenId: String, environment: String, amount: NSNumber, currency: String?, jwt: String, onBehalfOf: String?, cardCvn: String?, completion:@escaping (_ : XenditCCToken?, _ : XenditError?) -> Void) { let cardinalEnvironment = environment == "DEVELOPMENT" ? CardinalSessionEnvironment.staging : CardinalSessionEnvironment.production; configureCardinal(environment: cardinalEnvironment); cardinalSession?.setup(jwtString: jwt, completed: { (sessionId: String) in - createAuthenticationWithSessionId(fromViewController: fromViewController, tokenId: tokenId, sessionId: sessionId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, completion: completion) + createAuthenticationWithSessionId(fromViewController: fromViewController, tokenId: tokenId, sessionId: sessionId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, cardCvn: cardCvn, completion: completion) }) { (response : CardinalResponse) in // Revert to 3DS1 flow - create3DS1Authentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf) { (authentication, error) in + create3DS1Authentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, cardCvn: cardCvn) { (authentication, error) in if error != nil { return completion(nil, error) } diff --git a/Xendit/Xendit.swift b/Xendit/Xendit.swift index 7e61309..f86c522 100755 --- a/Xendit/Xendit.swift +++ b/Xendit/Xendit.swift @@ -33,7 +33,7 @@ import CardinalMobile let amount = authenticationRequest.amount let customer = authenticationRequest.customer let currency = authenticationRequest.currency - XDTCards.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, customer: customer, completion: completion) + XDTCards.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: currency, onBehalfOf: onBehalfOf, customer: customer, cardCvn: authenticationRequest.cardCvn, completion: completion) } @available(*, deprecated, message: "Use createToken(UIViewController, XenditTokenizationRequest, String, Callback) instead") @@ -60,19 +60,19 @@ import CardinalMobile @available(*, deprecated, message: "Use createAuthentication(UIViewController, XenditAuthenticationRequest, Callback) instead") public static func createAuthentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, onBehalfOf: String, completion:@escaping (_ : XenditAuthentication?, _ : XenditError?) -> Void) { XDTCards.setup(publishableKey: publishableKey!) - XDTCards.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, onBehalfOf: onBehalfOf, customer: nil, completion: completion) + XDTCards.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: nil, onBehalfOf: onBehalfOf, customer: nil, cardCvn: nil, completion: completion) } @available(*, deprecated, message: "Use createAuthentication(UIViewController, XenditAuthenticationRequest, Callback) instead") public static func createAuthentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, completion:@escaping (_ : XenditAuthentication?, _ : XenditError?) -> Void) { XDTCards.setup(publishableKey: publishableKey!) - self.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, onBehalfOf: "", completion: completion) + XDTCards.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: nil, onBehalfOf: nil, customer: nil, cardCvn: nil, completion: completion) } @available(*, deprecated, message: "Use createAuthentication(UIViewController, XenditAuthenticationRequest, Callback) instead") public static func createAuthentication(fromViewController: UIViewController, tokenId: String, amount: NSNumber, cardCVN: String, completion:@escaping (_ : XenditAuthentication?, _ : XenditError?) -> Void) { - self.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, completion: completion) - } + XDTCards.setup(publishableKey: publishableKey!) + XDTCards.createAuthentication(fromViewController: fromViewController, tokenId: tokenId, amount: amount, currency: nil, onBehalfOf: nil, customer: nil, cardCvn: cardCVN, completion: completion) } // Card data validation method public static func isCardNumberValid(cardNumber: String) -> Bool {