Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create threeDSecure encodable #1515

Merged
merged 30 commits into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b6c1597
Add post body encodable
warmkesselj Jan 23, 2025
18b7cf0
Add init to post body
warmkesselj Feb 3, 2025
767a767
Track given and surname
warmkesselj Feb 4, 2025
268de91
Update to encodable
warmkesselj Feb 4, 2025
2b29623
AdditionalInfo alphabetical order
warmkesselj Feb 4, 2025
c6d8d03
Alphabetical order BTThreeDSecurePostBody
warmkesselj Feb 4, 2025
8cccab8
swiftlint
warmkesselj Feb 4, 2025
a0a8338
Update BTThreeDSecureclient to use encodable object
warmkesselj Feb 4, 2025
68c2b18
Add missing coding keys
warmkesselj Feb 5, 2025
4a4ef7b
Updates to alphabetize and refactor
warmkesselj Feb 5, 2025
a45ddc6
Merge branch 'v7' of https://github.com/braintree/braintree_ios into …
warmkesselj Feb 5, 2025
929f9fa
Update project file
warmkesselj Feb 5, 2025
0bc888d
Pr comments
warmkesselj Feb 6, 2025
dbe458c
PR comments
warmkesselj Feb 6, 2025
5019d7a
Remove BT prefix
warmkesselj Feb 10, 2025
9abc347
Passing fake data to ThreeDS
warmkesselj Feb 11, 2025
088cf18
Update PostBody
warmkesselj Feb 11, 2025
e220eb6
Remove unnecessary unit tests
warmkesselj Feb 11, 2025
c324282
Remove unnecessary unit tests
warmkesselj Feb 12, 2025
87e1c9b
PR comments
warmkesselj Feb 12, 2025
744e063
Unit test for additional info
warmkesselj Feb 14, 2025
39a6126
Update unit tests to check keys
warmkesselj Feb 25, 2025
f082677
Update to accountID from accountId adding coding keys
warmkesselj Feb 25, 2025
1364339
Test billing properties
warmkesselj Feb 25, 2025
573dee4
Swift lint issues
warmkesselj Feb 25, 2025
cb47ee7
Merge branch 'v7' into create-encodable-three_d_secure-encodable
warmkesselj Feb 25, 2025
e34e3a1
Update unit test
warmkesselj Feb 26, 2025
c014988
Merge branch 'v7' into create-encodable-three_d_secure-encodable
warmkesselj Feb 26, 2025
6118c27
Update name
warmkesselj Mar 3, 2025
7a021ae
Re-add line
warmkesselj Mar 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions Braintree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,14 @@
A9E5C23324FD6DAE00EE691F /* BraintreeTestShared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A903E1A624F9D34000C314E1 /* BraintreeTestShared.framework */; };
A9E5C23424FD6FAE00EE691F /* BTAPIClient_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842B68F01BCF083E0039634F /* BTAPIClient_Tests.swift */; };
A9E80A9324FEF37C00196BD3 /* BTThreeDSecureClient_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42F75E5A24D48138007DC5E7 /* BTThreeDSecureClient_Tests.swift */; };
A9E80A9524FEF37C00196BD3 /* BTThreeDSecureAdditionalInformation_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A1EE3D2236AAC600F6218B /* BTThreeDSecureAdditionalInformation_Tests.swift */; };
A9E80A9624FEF37C00196BD3 /* BTThreeDSecureAuthenticateJWT_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800E23DC22206A8300C5D22E /* BTThreeDSecureAuthenticateJWT_Tests.swift */; };
A9E80A9824FEF37C00196BD3 /* BTThreeDSecureLookup_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42F75E5824D46DA2007DC5E7 /* BTThreeDSecureLookup_Tests.swift */; };
A9E80A9924FEF37C00196BD3 /* BTThreeDSecurePostalAddress_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F921C1200EBB200076CD80 /* BTThreeDSecurePostalAddress_Tests.swift */; };
A9E80A9A24FEF37C00196BD3 /* BTThreeDSecureRequest_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42D79393233A62A7001FDD89 /* BTThreeDSecureRequest_Tests.swift */; };
A9E80A9B24FEF37C00196BD3 /* BTThreeDSecureResult_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 423B921824D1E0BF0048B655 /* BTThreeDSecureResult_Tests.swift */; };
A9E80A9C24FEF37C00196BD3 /* MockDelegates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42D79395233A65EB001FDD89 /* MockDelegates.swift */; };
A9E80A9F24FEF40C00196BD3 /* BraintreeTestShared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A903E1A624F9D34000C314E1 /* BraintreeTestShared.framework */; };
A9E80AA324FEF4D800196BD3 /* MockLocalPaymentRequestDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9E80AA224FEF4D800196BD3 /* MockLocalPaymentRequestDelegate.swift */; };
B87B26242D54176F0002225F /* ThreeDSecurePOSTBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = B87B26232D54176F0002225F /* ThreeDSecurePOSTBody.swift */; };
B8BA342E2D4811560030423C /* BTContactInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8BA342D2D4811560030423C /* BTContactInformation.swift */; };
BC17F9B428D23C5C004B18CC /* BTGraphQLMultiErrorNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC17F9B328D23C5C004B18CC /* BTGraphQLMultiErrorNode.swift */; };
BC17F9BC28D24C9E004B18CC /* BTGraphQLErrorTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC17F9BB28D24C9E004B18CC /* BTGraphQLErrorTree.swift */; };
Expand Down Expand Up @@ -680,7 +679,6 @@
0357C49B1F97ED1F00E63851 /* BTAmericanExpressClient_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTAmericanExpressClient_Tests.swift; sourceTree = "<group>"; };
035A59D91EA5DE97002960C8 /* BTLocalPaymentClient_UnitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BTLocalPaymentClient_UnitTests.swift; sourceTree = "<group>"; };
039A8BD91F9E993500D607E7 /* BTAmericanExpressRewardsBalance_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTAmericanExpressRewardsBalance_Tests.swift; sourceTree = "<group>"; };
03F921C1200EBB200076CD80 /* BTThreeDSecurePostalAddress_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecurePostalAddress_Tests.swift; sourceTree = "<group>"; };
04ECD89F2CC9CB1A000329EC /* LinkType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkType.swift; sourceTree = "<group>"; };
09357DCA2A2FBEC10096D449 /* BTVenmoLineItem_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTVenmoLineItem_Tests.swift; sourceTree = "<group>"; };
096C6B2529CCDCEB00912863 /* BTVenmoLineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTVenmoLineItem.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -812,7 +810,6 @@
80842DA62B8E49EF00A5CD92 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
8087C10E2BFBACCA0020FC2E /* TokenizationKey_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenizationKey_Tests.swift; sourceTree = "<group>"; };
808E4A152C581CD40006A737 /* AnalyticsSendable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSendable.swift; sourceTree = "<group>"; };
80A1EE3D2236AAC600F6218B /* BTThreeDSecureAdditionalInformation_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecureAdditionalInformation_Tests.swift; sourceTree = "<group>"; };
80A6C6182B21205900416D50 /* UIApplication+URLOpener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+URLOpener.swift"; sourceTree = "<group>"; };
80AD35F12BFBB1DD00BF890E /* TokenizationKeyError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenizationKeyError.swift; sourceTree = "<group>"; };
80B207322BF6C0F100787E37 /* TokenizationKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenizationKey.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -895,6 +892,7 @@
A9E5C22424FD6D0800EE691F /* BraintreeCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BraintreeCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A9E5C22824FD6D0800EE691F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A9E80AA224FEF4D800196BD3 /* MockLocalPaymentRequestDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockLocalPaymentRequestDelegate.swift; sourceTree = "<group>"; };
B87B26232D54176F0002225F /* ThreeDSecurePOSTBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeDSecurePOSTBody.swift; sourceTree = "<group>"; };
B8BA342D2D4811560030423C /* BTContactInformation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTContactInformation.swift; sourceTree = "<group>"; };
BC17F9B328D23C5C004B18CC /* BTGraphQLMultiErrorNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTGraphQLMultiErrorNode.swift; sourceTree = "<group>"; };
BC17F9BB28D24C9E004B18CC /* BTGraphQLErrorTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTGraphQLErrorTree.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1819,6 +1817,7 @@
3BEB03C429FD55CA001133D5 /* BTThreeDSecureAnalytics.swift */,
BE01A84029D32CE1000DFA24 /* BTThreeDSecureAuthenticateJWT.swift */,
80D1638529E75766001D880E /* BTThreeDSecureClient.swift */,
B87B26232D54176F0002225F /* ThreeDSecurePOSTBody.swift */,
BE01A84229D32EA9000DFA24 /* BTThreeDSecureError.swift */,
BE01A82C29CCCDE9000DFA24 /* BTThreeDSecureLookup.swift */,
BE01A83429D1F7B9000DFA24 /* BTThreeDSecurePostalAddress.swift */,
Expand All @@ -1844,10 +1843,8 @@
80581A8B25531D0A00006F53 /* BTConfiguration+ThreeDSecure_Tests.swift */,
3BEB03C629FD5669001133D5 /* BTThreeDSecureAnalytics_Tests.swift */,
42F75E5A24D48138007DC5E7 /* BTThreeDSecureClient_Tests.swift */,
80A1EE3D2236AAC600F6218B /* BTThreeDSecureAdditionalInformation_Tests.swift */,
800E23DC22206A8300C5D22E /* BTThreeDSecureAuthenticateJWT_Tests.swift */,
42F75E5824D46DA2007DC5E7 /* BTThreeDSecureLookup_Tests.swift */,
03F921C1200EBB200076CD80 /* BTThreeDSecurePostalAddress_Tests.swift */,
42D79393233A62A7001FDD89 /* BTThreeDSecureRequest_Tests.swift */,
423B921824D1E0BF0048B655 /* BTThreeDSecureResult_Tests.swift */,
80CD33FD2A603892009545F5 /* MockCardinalSession.swift */,
Expand Down Expand Up @@ -3355,6 +3352,7 @@
BE80C00129C4BFD700793A6C /* BTThreeDSecureV2BaseCustomization.swift in Sources */,
80482F8429D3A1D9007E5F50 /* BTThreeDSecureAccountType.swift in Sources */,
80482F8629D3A498007E5F50 /* BTThreeDSecureShippingMethod.swift in Sources */,
B87B26242D54176F0002225F /* ThreeDSecurePOSTBody.swift in Sources */,
80482F8829D3A571007E5F50 /* BTThreeDSecureRequestedExemptionType.swift in Sources */,
BE01A84329D32EA9000DFA24 /* BTThreeDSecureError.swift in Sources */,
3BEB03C529FD55CA001133D5 /* BTThreeDSecureAnalytics.swift in Sources */,
Expand All @@ -3372,11 +3370,9 @@
3BEB03C829FD5716001133D5 /* BTThreeDSecureAnalytics_Tests.swift in Sources */,
80FF7D1A25881C03001C32EF /* BTThreeDSecureV2UICustomization_Tests.swift in Sources */,
A9E80A9324FEF37C00196BD3 /* BTThreeDSecureClient_Tests.swift in Sources */,
A9E80A9524FEF37C00196BD3 /* BTThreeDSecureAdditionalInformation_Tests.swift in Sources */,
A9E80A9624FEF37C00196BD3 /* BTThreeDSecureAuthenticateJWT_Tests.swift in Sources */,
80FF7D9825882669001C32EF /* BTThreeDSecureV2ToolbarCustomization_Tests.swift in Sources */,
A9E80A9824FEF37C00196BD3 /* BTThreeDSecureLookup_Tests.swift in Sources */,
A9E80A9924FEF37C00196BD3 /* BTThreeDSecurePostalAddress_Tests.swift in Sources */,
A9E80A9A24FEF37C00196BD3 /* BTThreeDSecureRequest_Tests.swift in Sources */,
80FF7DC025882795001C32EF /* BTThreeDSecureV2LabelCustomization_Tests.swift in Sources */,
80581A8C25531D0A00006F53 /* BTConfiguration+ThreeDSecure_Tests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,58 +208,4 @@ import Foundation

/// Optional. The work phone number used for verification. Only numbers; remove dashes, parenthesis and other characters.
public var workPhoneNumber: String?

// MARK: - Internal Methods

func asParameters() -> [String: String] {
var parameters: [String: String?] = [
"shippingMethodIndicator": shippingMethodIndicator,
"productCode": productCode,
"deliveryTimeframe": deliveryTimeframe,
"deliveryEmail": deliveryEmail,
"reorderIndicator": reorderIndicator,
"preorderIndicator": preorderIndicator,
"preorderDate": preorderDate,
"giftCardAmount": giftCardAmount,
"giftCardCurrencyCode": giftCardCurrencyCode,
"giftCardCount": giftCardCount,
"accountAgeIndicator": accountAgeIndicator,
"accountCreateDate": accountCreateDate,
"accountChangeIndicator": accountChangeIndicator,
"accountChangeDate": accountChangeDate,
"accountPwdChangeIndicator": accountPwdChangeIndicator,
"accountPwdChangeDate": accountPwdChangeDate,
"shippingAddressUsageIndicator": shippingAddressUsageIndicator,
"shippingAddressUsageDate": shippingAddressUsageDate,
"transactionCountDay": transactionCountDay,
"transactionCountYear": transactionCountYear,
"addCardAttempts": addCardAttempts,
"accountPurchases": accountPurchases,
"fraudActivity": fraudActivity,
"shippingNameIndicator": shippingNameIndicator,
"paymentAccountIndicator": paymentAccountIndicator,
"paymentAccountAge": paymentAccountAge,
"addressMatch": addressMatch,
"accountId": accountID,
"ipAddress": ipAddress,
"orderDescription": orderDescription,
"taxAmount": taxAmount,
"userAgent": userAgent,
"authenticationIndicator": authenticationIndicator,
"installment": installment,
"purchaseDate": purchaseDate,
"recurringEnd": recurringEnd,
"recurringFrequency": recurringFrequency,
"sdkMaxTimeout": sdkMaxTimeout,
"workPhoneNumber": workPhoneNumber
]

let finalShippingAddress = shippingAddress?.asParameters(withPrefix: "shipping")
parameters = parameters.merging(finalShippingAddress ?? [:]) { $1 }

// Remove all nil values and their key
let filteredParameters: [String: String] = parameters.compactMapValues { $0 }

return filteredParameters
}
}
42 changes: 2 additions & 40 deletions Sources/BraintreeThreeDSecure/BTThreeDSecureClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ import BraintreeCore
return
}

let requestParameters = self.buildRequestDictionary(with: request)
let requestParameters = ThreeDSecurePOSTBody(request: request)
guard let urlSafeNonce = request.nonce.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
self.apiClient.sendAnalyticsEvent(BTThreeDSecureAnalytics.lookupFailed)
self.notifyFailure(
Expand All @@ -364,7 +364,7 @@ import BraintreeCore

self.apiClient.post(
"v1/payment_methods/\(urlSafeNonce)/three_d_secure/lookup",
parameters: requestParameters as [String: Any]
parameters: requestParameters
) { body, _, error in
if let error = error as NSError? {
// Provide more context for card validation error when status code 422
Expand Down Expand Up @@ -412,44 +412,6 @@ import BraintreeCore
}
}

private func buildRequestDictionary(with request: BTThreeDSecureRequest) -> [String: Any?] {
let customer: [String: String] = [:]

var requestParameters: [String: Any?] = [
"amount": request.amount,
"customer": customer,
"requestedThreeDSecureVersion": "2",
"dfReferenceId": request.dfReferenceID,
"accountType": request.accountType.stringValue,
"challengeRequested": request.challengeRequested,
"exemptionRequested": request.exemptionRequested,
"requestedExemptionType": request.requestedExemptionType.stringValue,
"dataOnlyRequested": request.dataOnlyRequested
]

if let customFields = request.customFields {
requestParameters["customFields"] = customFields
}

if request.cardAddChallengeRequested {
requestParameters["cardAdd"] = true
}

var additionalInformation: [String: String?] = [
"mobilePhoneNumber": request.mobilePhoneNumber,
"email": request.email,
"shippingMethod": request.shippingMethod.stringValue
]

additionalInformation = additionalInformation.merging(request.billingAddress?.asParameters(withPrefix: "billing") ?? [:]) { $1 }
additionalInformation = additionalInformation.merging(request.additionalInformation?.asParameters() ?? [:]) { $1 }

requestParameters["additionalInfo"] = additionalInformation
requestParameters = requestParameters.compactMapValues { $0 }

return requestParameters
}

// MARK: - Analytics Helper Methods

private func notifySuccess(
Expand Down
43 changes: 0 additions & 43 deletions Sources/BraintreeThreeDSecure/BTThreeDSecurePostalAddress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,47 +36,4 @@ import Foundation
/// Optional. The phone number associated with the address
/// - Note: Only numbers. Remove dashes, parentheses and other characters
public var phoneNumber: String?

// MARK: - Internal Methods

/// :nodoc:
/// The postal address as parameters which can be used for API requests.
/// The prefix value will be prepended to each key in the return dictionary
/// - Parameter prefix: The prefix to prepend to the key in the dictionary
/// - Returns: A dictionary representing the postal address.
@_documentation(visibility: private)
func asParameters(withPrefix prefix: String? = "") -> [String: String] {
var parameters: [String: String?] = [
prepend(prefix, toKey: "givenName"): givenName,
prepend(prefix, toKey: "surname"): surname,
prepend(prefix, toKey: "line1"): streetAddress,
prepend(prefix, toKey: "line2"): extendedAddress,
prepend(prefix, toKey: "line3"): line3,
prepend(prefix, toKey: "city"): locality,
prepend(prefix, toKey: "state"): region,
prepend(prefix, toKey: "postalCode"): postalCode,
prepend(prefix, toKey: "countryCode"): countryCodeAlpha2
]

let phoneKey: String = prefix == "shipping" ? "phone" : "phoneNumber"
parameters[prepend(prefix, toKey: phoneKey)] = phoneNumber

// Remove all nil values and their key
let filteredParameters: [String: String] = parameters.compactMapValues { $0 }

return filteredParameters
}

// MARK: Private Methods

private func prepend(_ prefix: String?, toKey key: String) -> String {
if let prefix, !prefix.isEmpty {
// Uppercase the first character in the key
let firstLetter = key.prefix(1).capitalized
let remainingLetters = key.dropFirst()
return prefix + firstLetter + remainingLetters
} else {
return key
}
}
}
Loading
Loading