Skip to content

Commit

Permalink
Merge pull request #37 from xendit/feat/CC-4623/improve-3ds-handling
Browse files Browse the repository at this point in the history
[CC-4623] Improve 3DS handling
  • Loading branch information
zakiarsyad authored Jun 11, 2021
2 parents 4f19f38 + 19d27ec commit 67872fb
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 31ceadafb7a670350be1722f7ac2941417d82516

COCOAPODS: 1.10.0
COCOAPODS: 1.10.1
2 changes: 1 addition & 1 deletion Xendit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "Xendit"
s.version = "3.2.0"
s.version = "3.3.0"
s.summary = "Xendit is an API for accepting payments online"
s.homepage = "https://www.xendit.co"
s.license = "MIT"
Expand Down
5 changes: 5 additions & 0 deletions Xendit/Models/XenditAuthenticatedToken.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ import Foundation
// Credit card metadata
open var cardInfo : XenditCardMetadata?

// Failure reason
open var failureReason : String?

func getPayerAuthenticationUrl() -> String? {
return authenticationURL;
}
Expand All @@ -51,6 +54,7 @@ import Foundation
if environment != nil { json["environment"] = environment }
if threedsVersion != nil { json["threeds_version"] = threedsVersion }
if cardInfo != nil { json["card_info"] = cardInfo?.toJsonObject() }
if failureReason != nil { json["failure_reason"] = failureReason }
return json
}

Expand All @@ -68,5 +72,6 @@ import Foundation
self.environment = response["environment"] as? String
self.threedsVersion = response["threeds_version"] as? String
self.cardInfo = XenditCardMetadata(response: response["card_info"] as? [String : Any])
self.failureReason = response["failure_reason"] as? String
}
}
9 changes: 9 additions & 0 deletions Xendit/Models/XenditAuthentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ import Foundation

open var cardInfo: XenditCardMetadata?

// 3DS version
open var threedsVersion : String?

// Failure reason
open var failureReason : String?

func getPayerAuthenticationUrl() -> String? {
return authenticationURL
Expand All @@ -45,6 +50,8 @@ import Foundation
if requestPayload != nil { json["pa_res"] = requestPayload }
if maskedCardNumber != nil { json["masked_card_number"] = maskedCardNumber }
if cardInfo != nil { json["card_info"] = cardInfo?.toJsonObject() }
if threedsVersion != nil { json["threeds_version"] = threedsVersion }
if failureReason != nil { json["failure_reason"] = failureReason }
return json
}

Expand All @@ -64,6 +71,8 @@ import Foundation
self.maskedCardNumber = response["masked_card_number"] as? String
self.tokenId = response["credit_card_token_id"] as? String
self.cardInfo = XenditCardMetadata(response: response["card_info"] as? [String: Any])
self.threedsVersion = response["threeds_version"] as? String
self.failureReason = response["failure_reason"] as? String
}
}

Expand Down
10 changes: 10 additions & 0 deletions Xendit/Models/XenditCCToken.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import Foundation

open var cardInfo : XenditCardMetadata?

// Failure reason
open var failureReason : String?

func toJsonObject() -> [String : Any] {
var json: [String: Any] = [:]
if id != nil { json["id"] = id }
Expand All @@ -39,6 +42,7 @@ import Foundation
if maskedCardNumber != nil { json["masked_card_number"] = maskedCardNumber }
if should3DS != nil { json["should_3ds"] = should3DS }
if cardInfo != nil { json["card_info"] = cardInfo!.toJsonObject() }
if failureReason != nil { json["failure_reason"] = failureReason }
return json
}
}
Expand All @@ -60,6 +64,9 @@ import Foundation
self.cardInfo = XenditCardMetadata(response: response["card_info"] as? [String : Any])
}

if (response["failure_reason"] != nil) {
self.failureReason = (response["failure_reason"] as? String)
}
}
}

Expand All @@ -73,6 +80,7 @@ import Foundation
self.authenticationURL = authenticatedToken.authenticationURL
self.maskedCardNumber = authenticatedToken.maskedCardNumber
self.cardInfo = authenticatedToken.cardInfo
self.failureReason = authenticatedToken.failureReason
}
}

Expand All @@ -86,6 +94,8 @@ import Foundation
self.authenticationURL = authentication.authenticationURL
self.maskedCardNumber = authentication.maskedCardNumber
self.cardInfo = authentication.cardInfo
self.failureReason = authentication.failureReason

}
}

Expand Down
10 changes: 10 additions & 0 deletions Xendit/Utils/CreditCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ class CreditCard {
return false
}

// Check 3DS EMV version
public static func is3ds2Version(version: String?) -> Bool {
if version != nil {
let index = version!.index(version!.startIndex, offsetBy: 1)
let currentMajorVersion = Int(version![..<index])!
return currentMajorVersion >= 2
}
return false
}

// Get Card Type
internal static func getCardType(cardNumber: String) -> CYBCardTypes {
if cardNumber.hasPrefix("4") {
Expand Down
15 changes: 8 additions & 7 deletions Xendit/XDTCards.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,13 @@ public class XDTCards: CanTokenize, CanAuthenticate {
}

XDTApiClient.createAuthenticationRequest(publishableKey: publishableKey!, tokenId: tokenId, bodyJson: requestBody, extraHeader: header) { (authentication, error) in
if error == nil &&
(authentication?.status == "VERIFIED" || !CreditCard.is3ds2Version(version: authentication?.threedsVersion)) {
// Handle frictionless flow & 3ds version 1.0
let token = XenditCCToken.init(tokenId: tokenId, authentication: authentication!)
return completion(token, nil)
}

if error != nil ||
authentication?.status == "FAILED" ||
authentication?.authenticationTransactionId == nil ||
Expand All @@ -166,12 +173,6 @@ public class XDTCards: CanTokenize, CanAuthenticate {
}
let authenticationTransactionId = authentication?.authenticationTransactionId
let requestPayload = authentication?.requestPayload
let status = authentication?.status
if status == "VERIFIED" {
// Handle frictionless flow
let token = XenditCCToken.init(tokenId: tokenId, authentication: authentication!)
return completion(token, nil)
}

let xdtDelegate = XDTValidationDelegate(completion: { (response, jwt, error) in
verifyAuthentication(authentication: authentication!) { (authentication, error) in
Expand Down Expand Up @@ -251,7 +252,7 @@ public class XDTCards: CanTokenize, CanAuthenticate {

if status != nil {
if status == "IN_REVIEW" {
if authenticatedToken?.threedsVersion == "2.0" && jwt != nil {
if CreditCard.is3ds2Version(version: authenticatedToken?.threedsVersion) && jwt != nil {
handleEmv3DSFlow(fromViewController: fromViewController, tokenId: tokenId, environment: authenticatedToken!.environment!, amount: amount, jwt: jwt!, onBehalfOf: onBehalfOf, completion: completion)
} else if let authenticationURL = authenticatedToken?.authenticationURL {
cardAuthenticationProvider.authenticate(
Expand Down

0 comments on commit 67872fb

Please sign in to comment.