Skip to content

Commit

Permalink
Add Cardinal UI Type and Render Types (#1134)
Browse files Browse the repository at this point in the history
* Add uiType to BTThreeDSecureRequest
* Add renderTypes to BTThreeDSecureRequest
* Set default parameters in Demo app (from Cardinal docs)
* Add unit tests
* Android PR for this change: Add Cardinal UI Type and Render Type braintree_android#738 - we finally heard back from the merchants that these worked as expected, so exposing them on iOS
  • Loading branch information
jaxdesmarais authored Nov 15, 2023
1 parent 74f056a commit 93d3321
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Braintree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@
BEBC6F3329380B82004E25A0 /* BTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = BEBC6F3129380B82004E25A0 /* BTExceptionCatcher.m */; };
BEBD05222A1FE8BE0003C15C /* BTWebAuthenticationSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBD05212A1FE8BE0003C15C /* BTWebAuthenticationSession.swift */; };
BEBD05242A1FEE150003C15C /* MockWebAuthenticationSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBD05232A1FEE150003C15C /* MockWebAuthenticationSession.swift */; };
BEBF0C202B02793B0079DA74 /* BTThreeDSecureUIType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBF0C1F2B02793B0079DA74 /* BTThreeDSecureUIType.swift */; };
BEBF0C222B0279F10079DA74 /* BTThreeDSecureRenderType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBF0C212B0279F10079DA74 /* BTThreeDSecureRenderType.swift */; };
BEC3F11328A4401E0074DF0F /* BTHTTPError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEC3F11228A4401E0074DF0F /* BTHTTPError.swift */; };
BEC66DBE2901CC9E0030B6B2 /* BraintreeCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570B93AC285397520041BAFE /* BraintreeCore.framework */; };
BECBA0E62AEABC99002518AC /* BTCardClient_IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECBA0E52AEABC99002518AC /* BTCardClient_IntegrationTests.swift */; };
Expand Down Expand Up @@ -858,6 +860,8 @@
BEBC6F3429380BA6004E25A0 /* BTExceptionCatcher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BTExceptionCatcher.h; sourceTree = "<group>"; };
BEBD05212A1FE8BE0003C15C /* BTWebAuthenticationSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTWebAuthenticationSession.swift; sourceTree = "<group>"; };
BEBD05232A1FEE150003C15C /* MockWebAuthenticationSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockWebAuthenticationSession.swift; sourceTree = "<group>"; };
BEBF0C1F2B02793B0079DA74 /* BTThreeDSecureUIType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecureUIType.swift; sourceTree = "<group>"; };
BEBF0C212B0279F10079DA74 /* BTThreeDSecureRenderType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecureRenderType.swift; sourceTree = "<group>"; };
BEC3F11228A4401E0074DF0F /* BTHTTPError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTHTTPError.swift; sourceTree = "<group>"; };
BECA56C929C3F0A80098EC3C /* BTThreeDSecureV2UICustomization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecureV2UICustomization.swift; sourceTree = "<group>"; };
BECBA0E52AEABC99002518AC /* BTCardClient_IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTCardClient_IntegrationTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1527,11 +1531,13 @@
BE01A84229D32EA9000DFA24 /* BTThreeDSecureError.swift */,
BE01A82C29CCCDE9000DFA24 /* BTThreeDSecureLookup.swift */,
BE01A83429D1F7B9000DFA24 /* BTThreeDSecurePostalAddress.swift */,
BEBF0C212B0279F10079DA74 /* BTThreeDSecureRenderType.swift */,
80482F7F29D39A1D007E5F50 /* BTThreeDSecureRequest.swift */,
80482F8129D39BF5007E5F50 /* BTThreeDSecureRequestDelegate.swift */,
80482F8729D3A571007E5F50 /* BTThreeDSecureRequestedExemptionType.swift */,
BE80C00229C549BE00793A6C /* BTThreeDSecureResult.swift */,
80482F8529D3A498007E5F50 /* BTThreeDSecureShippingMethod.swift */,
BEBF0C1F2B02793B0079DA74 /* BTThreeDSecureUIType.swift */,
BE01A83E29D32CA0000DFA24 /* BTThreeDSecureV2Provider.swift */,
80CD33FF2A6042FC009545F5 /* CardinalSessionTestable.swift */,
801A0A1725890DF200DAF851 /* V2UICustomization */,
Expand Down Expand Up @@ -2884,11 +2890,13 @@
buildActionMask = 2147483647;
files = (
BE48CE4829D5DDA600F0825C /* BTThreeDSecureV2TextBoxCustomization.swift in Sources */,
BEBF0C222B0279F10079DA74 /* BTThreeDSecureRenderType.swift in Sources */,
80D1638729E75CF1001D880E /* BTThreeDSecureClient.swift in Sources */,
BEEBC3C129D5DD68009C7F77 /* BTThreeDSecureV2LabelCustomization.swift in Sources */,
BEEBC3C029D5DD16009C7F77 /* BTThreeDSecureV2UICustomization.swift in Sources */,
80482F8029D39A1D007E5F50 /* BTThreeDSecureRequest.swift in Sources */,
BE01A83D29D23833000DFA24 /* BTThreeDSecureAdditionalInformation.swift in Sources */,
BEBF0C202B02793B0079DA74 /* BTThreeDSecureUIType.swift in Sources */,
BE01A83F29D32CA0000DFA24 /* BTThreeDSecureV2Provider.swift in Sources */,
BE82E73F29C4A06B0059FE97 /* BTThreeDSecureV2ToolbarCustomization.swift in Sources */,
BE01A84129D32CE1000DFA24 /* BTThreeDSecureAuthenticateJWT.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## unreleased
* BraintreeThreeDSecure
* Add `cardAddChallengeRequested` to `BTThreeDSecureRequest`
* Add `cardAddChallengeRequested`, `uiType`, and `renderTypes` to `BTThreeDSecureRequest`
* Deprecate `BTThreeDSecureRequest.cardAddChallenge`
* Fix bug where defaults for `BTThreeDSecureRequest.accountType`, `BTThreeDSecureRequest.requestedExemptionType`, and `BTThreeDSecureRequest.dfReferenceID` were improperly returning an error if not passed into the request
* BraintreeCard
Expand Down
2 changes: 2 additions & 0 deletions Demo/Application/Features/ThreeDSecureViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class ThreeDSecureViewController: PaymentButtonBaseViewController {
request.requestedExemptionType = .lowValue
request.email = "[email protected]"
request.shippingMethod = .sameDay
request.uiType = .both
request.renderTypes = [.otp, .singleSelect, .multiSelect, .oob, .html]

let billingAddress = BTThreeDSecurePostalAddress()
billingAddress.givenName = "Jill"
Expand Down
44 changes: 44 additions & 0 deletions Sources/BraintreeThreeDSecure/BTThreeDSecureRenderType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Foundation
import CardinalMobile

/// Render types that the device supports for displaying specific challenge user interfaces within the 3D Secure challenge.
@objcMembers public class BTThreeDSecureRenderType: NSObject, OptionSet {

public let rawValue: Int

required public init(rawValue: Int) {
self.rawValue = rawValue
}

/// OTP
public static let otp = BTThreeDSecureRenderType(rawValue: 1)

/// HTML
public static let html = BTThreeDSecureRenderType(rawValue: 2)

/// Single select
public static let singleSelect = BTThreeDSecureRenderType(rawValue: 3)

/// Multi Select
public static let multiSelect = BTThreeDSecureRenderType(rawValue: 4)

/// OOB
public static let oob = BTThreeDSecureRenderType(rawValue: 5)

var cardinalValue: String {
switch self {
case .otp:
return CardinalSessionRenderTypeOTP
case .html:
return CardinalSessionRenderTypeHTML
case .singleSelect:
return CardinalSessionRenderTypeSingleSelect
case .multiSelect:
return CardinalSessionRenderTypeMultiSelect
case .oob:
return CardinalSessionRenderTypeOOB
default:
return ""
}
}
}
11 changes: 11 additions & 0 deletions Sources/BraintreeThreeDSecure/BTThreeDSecureRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ import BraintreeCore
/// Optional. UI Customization for 3DS2 challenge views.
public var v2UICustomization: BTThreeDSecureV2UICustomization?

/// Optional. Sets all UI types that the device supports for displaying specific challenge user interfaces in the 3D Secure challenge.
///
/// Defaults to `.both`
public var uiType: BTThreeDSecureUIType = .both

/// Optional. List of all the render types that the device supports for displaying specific challenge user interfaces within the 3D Secure challenge.
///
/// - Note: When using `BTThreeDSecureUIType.both` or `BTThreeDSecureUIType.html`, all `BTThreeDSecureRenderType` options must be set.
/// When using `BTThreeDSecureUIType.native`, all `BTThreeDSecureRenderType` options except `.html` must be set.
public var renderTypes: [BTThreeDSecureRenderType]?

/// A delegate for receiving information about the ThreeDSecure payment flow.
public weak var threeDSecureRequestDelegate: BTThreeDSecureRequestDelegate?

Expand Down
26 changes: 26 additions & 0 deletions Sources/BraintreeThreeDSecure/BTThreeDSecureUIType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation
import CardinalMobile

/// The interface types that the device supports for displaying specific challenge user interfaces within the 3D Secure challenge.
@objc public enum BTThreeDSecureUIType: Int {

/// Native
case native

/// HTML
case html

/// Both
case both

var cardinalValue: CardinalSessionUIType {
switch self {
case .native:
return .native
case .html:
return .HTML
case .both:
return .both
}
}
}
6 changes: 6 additions & 0 deletions Sources/BraintreeThreeDSecure/BTThreeDSecureV2Provider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ class BTThreeDSecureV2Provider {
cardinalEnvironment = .production
}

cardinalConfiguration.uiType = request.uiType.cardinalValue

if let renderTypes = request.renderTypes {
cardinalConfiguration.renderType = renderTypes.compactMap { $0.cardinalValue }
}

guard let cardinalAuthenticationJWT = configuration.cardinalAuthenticationJWT else {
completion(nil)
return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import XCTest
import CardinalMobile
@testable import BraintreeTestShared
@testable import BraintreeThreeDSecure

Expand Down Expand Up @@ -114,4 +115,42 @@ class BTThreeDSecureRequest_Tests: XCTestCase {
let request = BTThreeDSecureRequest()
XCTAssertEqual(request.requestedExemptionType.stringValue, nil)
}

// MARK: - UIType

func testUIType_whenUITypeNative_setsCardinalUITypeNative() {
let request = BTThreeDSecureRequest()
request.uiType = .native
XCTAssertEqual(request.uiType.cardinalValue, CardinalSessionUIType.native)
}

func testUIType_whenUITypeHTML_setsCardinalUITypeHTML() {
let request = BTThreeDSecureRequest()
request.uiType = .html
XCTAssertEqual(request.uiType.cardinalValue, CardinalSessionUIType.HTML)
}

func testUIType_whenUITypeBoth_setsCardinalUITypeBoth() {
let request = BTThreeDSecureRequest()
request.uiType = .both
XCTAssertEqual(request.uiType.cardinalValue, CardinalSessionUIType.both)
}

// MARK: RenderTypes

func testRenderTypes_whenAllRenderTypesAreSet_setsAllCardinalRenderTypes() {
let request = BTThreeDSecureRequest()
request.renderTypes = [.otp, .singleSelect, .multiSelect, .oob, .html]

XCTAssertEqual(
request.renderTypes?.compactMap { $0.cardinalValue },
[
CardinalSessionRenderTypeOTP,
CardinalSessionRenderTypeSingleSelect,
CardinalSessionRenderTypeMultiSelect,
CardinalSessionRenderTypeOOB,
CardinalSessionRenderTypeHTML
]
)
}
}

0 comments on commit 93d3321

Please sign in to comment.