From 8973eb7987edda2473d7fc3c1755d3aff221303d Mon Sep 17 00:00:00 2001 From: ageddam Date: Wed, 15 Oct 2025 13:02:07 -0500 Subject: [PATCH 1/5] make all properties internal on postal address --- .../Features/IdealViewController.swift | 11 +-- .../SEPADirectDebitViewController.swift | 15 ++-- Sources/BraintreeCore/BTJSON.swift | 26 ++++--- Sources/BraintreeCore/BTPostalAddress.swift | 76 +++++++++++++------ .../Models/LocalPaymentPOSTBody.swift | 14 ++-- .../Models/PayPalCheckoutPOSTBody.swift | 14 ++-- .../Models/SEPADebitRequest.swift | 20 +++-- .../BTPostalAddress_Tests.swift | 35 +++++---- .../BTLocalPaymentClient_UnitTests.swift | 15 ++-- .../BTPayPalCheckoutRequest_Tests.swift | 17 +++-- .../BTPayPalVaultRequest_Tests.swift | 17 +++-- .../BTSEPADirectDebitClient_Tests.swift | 17 +++-- .../SEPADirectDebitAPI_Tests.swift | 46 ++++++----- 13 files changed, 193 insertions(+), 130 deletions(-) diff --git a/Demo/Application/Features/IdealViewController.swift b/Demo/Application/Features/IdealViewController.swift index 3ab240c7ca..8035fc5bbc 100644 --- a/Demo/Application/Features/IdealViewController.swift +++ b/Demo/Application/Features/IdealViewController.swift @@ -49,11 +49,12 @@ class IdealViewController: PaymentButtonBaseViewController { private func startPaymentWithBank() { localPaymentClient = BTLocalPaymentClient(authorization: "sandbox_f252zhq7_hh4cpc39zq4rgjcg") - let postalAddress = BTPostalAddress() - postalAddress.countryCodeAlpha2 = "NL" - postalAddress.postalCode = "2585 GJ" - postalAddress.streetAddress = "836486 of 22321 Park Lake" - postalAddress.locality = "Den Haag" + let postalAddress = BTPostalAddress( + streetAddress: "836486 of 22321 Park Lake", + locality: "Den Haag", + countryCodeAlpha2: "NL", + postalCode: "2585 GJ" + ) let request = BTLocalPaymentRequest( paymentType: "ideal", diff --git a/Demo/Application/Features/SEPADirectDebitViewController.swift b/Demo/Application/Features/SEPADirectDebitViewController.swift index ec2efc92af..5749244c85 100644 --- a/Demo/Application/Features/SEPADirectDebitViewController.swift +++ b/Demo/Application/Features/SEPADirectDebitViewController.swift @@ -22,13 +22,14 @@ class SEPADirectDebitViewController: PaymentButtonBaseViewController { @objc func sepaDirectDebitButtonTapped() { self.progressBlock("Tapped SEPA Direct Debit") - let billingAddress = BTPostalAddress() - billingAddress.streetAddress = "Kantstraße 70" - billingAddress.extendedAddress = "#170" - billingAddress.locality = "Freistaat Sachsen" - billingAddress.region = "Annaberg-buchholz" - billingAddress.postalCode = "09456" - billingAddress.countryCodeAlpha2 = "FR" + let billingAddress = BTPostalAddress( + streetAddress: "Kantstraße 70", + extendedAddress: "#170", + locality: "Freistaat Sachsen", + countryCodeAlpha2: "FR", + postalCode: "09456", + region: "Annaberg-buchholz" + ) let sepaDirectDebitRequest = BTSEPADirectDebitRequest( accountHolderName: "John Doe", diff --git a/Sources/BraintreeCore/BTJSON.swift b/Sources/BraintreeCore/BTJSON.swift index d0111daa45..21d7398825 100644 --- a/Sources/BraintreeCore/BTJSON.swift +++ b/Sources/BraintreeCore/BTJSON.swift @@ -267,14 +267,22 @@ public class BTJSON: NSObject { public func asAddress() -> BTPostalAddress? { guard self.isObject else { return nil } - let address = BTPostalAddress() - address.recipientName = self["recipientName"].asString() ?? self["fullName"].asString() // Likely to be nil - address.streetAddress = self["street1"].asString() ?? self["line1"].asString() ?? self["addressLine1"].asString() - address.extendedAddress = self["street2"].asString() ?? self["line2"].asString() ?? self["addressLine2"].asString() - address.locality = self["city"].asString() ?? self["adminArea2"].asString() - address.region = self["state"].asString() ?? self["adminArea1"].asString() - address.postalCode = self["postalCode"].asString() - address.countryCodeAlpha2 = self["country"].asString() ?? self["countryCode"].asString() - return address + let recipientName = self["recipientName"].asString() ?? self["fullName"].asString() + let streetAddress = self["street1"].asString() ?? self["line1"].asString() ?? self["addressLine1"].asString() + let extendedAddress = self["street2"].asString() ?? self["line2"].asString() ?? self["addressLine2"].asString() + let locality = self["city"].asString() ?? self["adminArea2"].asString() + let region = self["state"].asString() ?? self["adminArea1"].asString() + let postalCode = self["postalCode"].asString() + let countryCodeAlpha2 = self["country"].asString() ?? self["countryCode"].asString() + + return BTPostalAddress( + recipientName: recipientName, + streetAddress: streetAddress, + extendedAddress: extendedAddress, + locality: locality, + countryCodeAlpha2: countryCodeAlpha2, + postalCode: postalCode, + region: region + ) } } diff --git a/Sources/BraintreeCore/BTPostalAddress.swift b/Sources/BraintreeCore/BTPostalAddress.swift index 103ada17dc..470490d1bd 100644 --- a/Sources/BraintreeCore/BTPostalAddress.swift +++ b/Sources/BraintreeCore/BTPostalAddress.swift @@ -3,30 +3,47 @@ import Foundation /// Generic postal address @objcMembers public class BTPostalAddress: NSObject, Encodable { + // MARK: - Internal Properties + // Property names follow the `Braintree_Address` convention as documented at: // https://developer.paypal.com/braintree/docs/reference/request/address/create - - /// Optional. Recipient name for shipping address. - public var recipientName: String? - - /// Line 1 of the Address (eg. number, street, etc). - public var streetAddress: String? - - /// Optional line 2 of the Address (eg. suite, apt #, etc.). - public var extendedAddress: String? - - /// City name - public var locality: String? - - /// 2 letter country code. - public var countryCodeAlpha2: String? - - /// Zip code or equivalent is usually required for countries that have them. - /// For a list of countries that do not have postal codes please refer to http://en.wikipedia.org/wiki/Postal_code. - public var postalCode: String? - - /// Either a two-letter state code (for the US), or an ISO-3166-2 country subdivision code of up to three letters. - public var region: String? + + let recipientName: String? + let streetAddress: String? + let extendedAddress: String? + let locality: String? + let countryCodeAlpha2: String? + let postalCode: String? + let region: String? + + // MARK: - Initializer + + /// Creats a postal address with all components + /// - Parameters: + /// - recipientName: Recipient name for shipping address. + /// - streetAddress: Line 1 of the Address (eg. number, street, etc). + /// - extendedAddress: Optional line 2 of the Address (eg. suite, apt #, etc.). + /// - locality: City name + /// - countryCodeAlpha2: 2 letter country code. + /// - postalCode: Zip code or equivalent is usually required for countries that have them. For a list of countries that do not have postal codes please refer to http://en.wikipedia.org/wiki/Postal_code. + /// - region: Either a two-letter state code (for the US), or an ISO-3166-2 country subdivision code of up to three letters. + public init( + recipientName: String? = nil, + streetAddress: String? = nil, + extendedAddress: String? = nil, + locality: String? = nil, + countryCodeAlpha2: String? = nil, + postalCode: String? = nil, + region: String? = nil + ) { + self.recipientName = recipientName + self.streetAddress = streetAddress + self.extendedAddress = extendedAddress + self.locality = locality + self.countryCodeAlpha2 = countryCodeAlpha2 + self.postalCode = postalCode + self.region = region + } enum CodingKeys: String, CodingKey { case countryCodeAlpha2 = "country_code" @@ -37,4 +54,19 @@ import Foundation case recipientName = "recipient_name" case streetAddress = "line1" } + + // MARK: - Helper Method + + /// Returns address components as a dictionary for accessing internal properties across modules + public func addressComponents() -> [String: String?] { + return [ + "recipientName": recipientName, + "streetAddress": streetAddress, + "extendedAddress": extendedAddress, + "locality": locality, + "countryCodeAlpha2": countryCodeAlpha2, + "postalCode": postalCode, + "region": region + ] + } } diff --git a/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift b/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift index fd00beedd6..431e523504 100644 --- a/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift +++ b/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift @@ -56,13 +56,15 @@ struct LocalPaymentPOSTBody: Encodable { self.returnURL = BTCoreConstants.callbackURLScheme + "://x-callback-url/braintree/local-payment/success" self.cancelURL = BTCoreConstants.callbackURLScheme + "://x-callback-url/braintree/local-payment/cancel" + if let address = localPaymentRequest.address { - self.streetAddress = address.streetAddress - self.extendedAddress = address.extendedAddress - self.locality = address.locality - self.countryCodeAlpha2 = address.countryCodeAlpha2 - self.postalCode = address.postalCode - self.region = address.region + let addressComponents = address.addressComponents() + self.streetAddress = addressComponents["streetAddress"] ?? nil + self.extendedAddress = addressComponents["extendedAddress"] ?? nil + self.locality = addressComponents["locality"] ?? nil + self.countryCodeAlpha2 = addressComponents["countryCodeAlpha2"] ?? nil + self.postalCode = addressComponents["postalCode"] ?? nil + self.region = addressComponents["region"] ?? nil } } diff --git a/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift b/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift index 9ae114f068..b405276a16 100644 --- a/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift +++ b/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift @@ -79,13 +79,13 @@ struct PayPalCheckoutPOSTBody: Encodable { } if let shippingAddressOverride = payPalRequest.shippingAddressOverride { - self.streetAddress = shippingAddressOverride.streetAddress - self.extendedAddress = shippingAddressOverride.extendedAddress - self.locality = shippingAddressOverride.locality - self.countryCodeAlpha2 = shippingAddressOverride.countryCodeAlpha2 - self.postalCode = shippingAddressOverride.postalCode - self.region = shippingAddressOverride.region - self.recipientName = shippingAddressOverride.recipientName + let addressComponents = shippingAddressOverride.addressComponents() + self.streetAddress = addressComponents["streetAddress"] ?? nil + self.extendedAddress = addressComponents["extendedAddress"] ?? nil + self.locality = addressComponents["locality"] ?? nil + self.countryCodeAlpha2 = addressComponents["countryCodeAlpha2"] ?? nil + self.postalCode = addressComponents["postalCode"] ?? nil + self.region = addressComponents["region"] ?? nil } if let merchantAccountID = payPalRequest.merchantAccountID { diff --git a/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift b/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift index 1b533e6ea4..44cb7b94fe 100644 --- a/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift +++ b/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift @@ -64,14 +64,18 @@ struct SEPADebitRequest: Encodable { self.mandateType = sepaDirectDebitRequest.mandateType?.description self.accountHolderName = sepaDirectDebitRequest.accountHolderName self.iban = sepaDirectDebitRequest.iban - self.billingAddress = BillingAddress( - streetAddress: sepaDirectDebitRequest.billingAddress?.streetAddress, - extendedAddress: sepaDirectDebitRequest.billingAddress?.extendedAddress, - locality: sepaDirectDebitRequest.billingAddress?.locality, - region: sepaDirectDebitRequest.billingAddress?.region, - postalCode: sepaDirectDebitRequest.billingAddress?.postalCode, - countryCodeAlpha2: sepaDirectDebitRequest.billingAddress?.countryCodeAlpha2 - ) + + self.billingAddress = sepaDirectDebitRequest.billingAddress.map { postalAddress in + let components = postalAddress.addressComponents() + return BillingAddress( + streetAddress: components["streetAddress"] ?? nil, + extendedAddress: components["extendedAddress"] ?? nil, + locality: components["locality"] ?? nil, + region: components["region"] ?? nil, + postalCode: components["postalCode"] ?? nil, + countryCodeAlpha2: components["countryCodeAlpha2"] ?? nil + ) + } } } diff --git a/UnitTests/BraintreeCoreTests/BTPostalAddress_Tests.swift b/UnitTests/BraintreeCoreTests/BTPostalAddress_Tests.swift index 62320c29b6..6b821e03df 100644 --- a/UnitTests/BraintreeCoreTests/BTPostalAddress_Tests.swift +++ b/UnitTests/BraintreeCoreTests/BTPostalAddress_Tests.swift @@ -3,22 +3,25 @@ import BraintreeCore class BTPostalAddress_Tests: XCTestCase { - func testAsParameters_setsAllProperties() { - let postalAddress = BTPostalAddress() - postalAddress.recipientName = "Jane Smith" - postalAddress.streetAddress = "555 Smith St." - postalAddress.extendedAddress = "#5" - postalAddress.locality = "Oakland" - postalAddress.region = "CA" - postalAddress.countryCodeAlpha2 = "US" - postalAddress.postalCode = "54321" + func testInitializer_setsAllProperties() { + let postalAddress = BTPostalAddress( + recipientName: "Jane Smith", + streetAddress: "555 Smith St.", + extendedAddress: "#5", + locality: "Oakland", + countryCodeAlpha2: "US", + postalCode: "54321", + region: "CA" + ) + + let addressComponents = postalAddress.addressComponents() - XCTAssertEqual(postalAddress.recipientName, "Jane Smith") - XCTAssertEqual(postalAddress.streetAddress, "555 Smith St.") - XCTAssertEqual(postalAddress.extendedAddress, "#5") - XCTAssertEqual(postalAddress.locality, "Oakland") - XCTAssertEqual(postalAddress.region, "CA") - XCTAssertEqual(postalAddress.countryCodeAlpha2, "US") - XCTAssertEqual(postalAddress.postalCode, "54321") + XCTAssertEqual(addressComponents["recipientName"], "Jane Smith") + XCTAssertEqual(addressComponents["streetAddress"], "555 Smith St.") + XCTAssertEqual(addressComponents["extendedAddress"], "#5") + XCTAssertEqual(addressComponents["locality"], "Oakland") + XCTAssertEqual(addressComponents["region"], "CA") + XCTAssertEqual(addressComponents["countryCodeAlpha2"], "US") + XCTAssertEqual(addressComponents["postalCode"], "54321") } } diff --git a/UnitTests/BraintreeLocalPaymentTests/BTLocalPaymentClient_UnitTests.swift b/UnitTests/BraintreeLocalPaymentTests/BTLocalPaymentClient_UnitTests.swift index d9e3bc7868..eb1d37f543 100644 --- a/UnitTests/BraintreeLocalPaymentTests/BTLocalPaymentClient_UnitTests.swift +++ b/UnitTests/BraintreeLocalPaymentTests/BTLocalPaymentClient_UnitTests.swift @@ -88,13 +88,14 @@ class BTLocalPaymentClient_UnitTests: XCTestCase { ] ) - let postalAddress = BTPostalAddress() - postalAddress.countryCodeAlpha2 = "NL" - postalAddress.region = "CA" - postalAddress.postalCode = "2585 GJ" - postalAddress.streetAddress = "836486 of 22321 Park Lake" - postalAddress.extendedAddress = "#102" - postalAddress.locality = "Den Haag" + let postalAddress = BTPostalAddress( + streetAddress: "836486 of 22321 Park Lake", + extendedAddress: "#102", + locality: "Den Haag", + countryCodeAlpha2: "NL", + postalCode: "2585 GJ", + region: "CA" + ) let paymentRequest = BTLocalPaymentRequest( paymentType: "ideal", diff --git a/UnitTests/BraintreePayPalTests/BTPayPalCheckoutRequest_Tests.swift b/UnitTests/BraintreePayPalTests/BTPayPalCheckoutRequest_Tests.swift index e379032cda..5b46b4219d 100644 --- a/UnitTests/BraintreePayPalTests/BTPayPalCheckoutRequest_Tests.swift +++ b/UnitTests/BraintreePayPalTests/BTPayPalCheckoutRequest_Tests.swift @@ -89,14 +89,15 @@ class BTPayPalCheckoutRequest_Tests: XCTestCase { request.userAuthenticationEmail = "fake@email.com" request.userPhoneNumber = BTPayPalPhoneNumber(countryCode: "1", nationalNumber: "4087463271") - let shippingAddress = BTPostalAddress() - shippingAddress.streetAddress = "123 Main" - shippingAddress.extendedAddress = "Unit 1" - shippingAddress.locality = "Chicago" - shippingAddress.region = "IL" - shippingAddress.postalCode = "11111" - shippingAddress.countryCodeAlpha2 = "US" - shippingAddress.recipientName = "Recipient" + let shippingAddress = BTPostalAddress( + recipientName: "Recipient", + streetAddress: "123 Main", + extendedAddress: "Unit 1", + locality: "Chicago", + countryCodeAlpha2: "US", + postalCode: "11111", + region: "IL" + ) request.shippingAddressOverride = shippingAddress request.isShippingAddressEditable = true diff --git a/UnitTests/BraintreePayPalTests/BTPayPalVaultRequest_Tests.swift b/UnitTests/BraintreePayPalTests/BTPayPalVaultRequest_Tests.swift index 0003b571c8..52699b78fb 100644 --- a/UnitTests/BraintreePayPalTests/BTPayPalVaultRequest_Tests.swift +++ b/UnitTests/BraintreePayPalTests/BTPayPalVaultRequest_Tests.swift @@ -56,14 +56,15 @@ class BTPayPalVaultRequest_Tests: XCTestCase { let request = BTPayPalVaultRequest() request.billingAgreementDescription = "desc" - let shippingAddress = BTPostalAddress() - shippingAddress.streetAddress = "123 Main" - shippingAddress.extendedAddress = "Unit 1" - shippingAddress.locality = "Chicago" - shippingAddress.region = "IL" - shippingAddress.postalCode = "11111" - shippingAddress.countryCodeAlpha2 = "US" - shippingAddress.recipientName = "Recipient" + let shippingAddress = BTPostalAddress( + recipientName: "Recipient", + streetAddress: "123 Main", + extendedAddress: "Unit 1", + locality: "Chicago", + countryCodeAlpha2: "US", + postalCode: "11111", + region: "IL" + ) request.shippingAddressOverride = shippingAddress request.isShippingAddressEditable = true request.offerCredit = true diff --git a/UnitTests/BraintreeSEPADirectDebitTests/BTSEPADirectDebitClient_Tests.swift b/UnitTests/BraintreeSEPADirectDebitTests/BTSEPADirectDebitClient_Tests.swift index 743512f022..20f14e49e6 100644 --- a/UnitTests/BraintreeSEPADirectDebitTests/BTSEPADirectDebitClient_Tests.swift +++ b/UnitTests/BraintreeSEPADirectDebitTests/BTSEPADirectDebitClient_Tests.swift @@ -6,20 +6,23 @@ import AuthenticationServices class BTSEPADirectDebitClient_Tests: XCTestCase { - var billingAddress = BTPostalAddress() + var billingAddress: BTPostalAddress! var sepaDirectDebitRequest: BTSEPADirectDebitRequest! + var mockAPIClient : MockAPIClient = MockAPIClient(authorization: "development_client_key") let authorization: String = "sandbox_9dbg82cq_dcpspy2brwdjr3qn" override func setUp() { mockAPIClient = MockAPIClient(authorization: authorization) - billingAddress.streetAddress = "Kantstraße 70" - billingAddress.extendedAddress = "#170" - billingAddress.locality = "Freistaat Sachsen" - billingAddress.region = "Annaberg-buchholz" - billingAddress.postalCode = "09456" - billingAddress.countryCodeAlpha2 = "FR" + billingAddress = BTPostalAddress( + streetAddress: "Kantstraße 70", + extendedAddress: "#170", + locality: "Freistaat Sachsen", + countryCodeAlpha2: "FR", + postalCode: "09456", + region: "Annaberg-buchholz" + ) sepaDirectDebitRequest = BTSEPADirectDebitRequest( accountHolderName: "John Doe", diff --git a/UnitTests/BraintreeSEPADirectDebitTests/SEPADirectDebitAPI_Tests.swift b/UnitTests/BraintreeSEPADirectDebitTests/SEPADirectDebitAPI_Tests.swift index 1435eb1592..3a42e78d3a 100644 --- a/UnitTests/BraintreeSEPADirectDebitTests/SEPADirectDebitAPI_Tests.swift +++ b/UnitTests/BraintreeSEPADirectDebitTests/SEPADirectDebitAPI_Tests.swift @@ -4,7 +4,8 @@ import XCTest @testable import BraintreeSEPADirectDebit class SEPADirectDebitAPI_Tests: XCTestCase { - var billingAddress = BTPostalAddress() + + var billingAddress: BTPostalAddress! var sepaDirectDebitRequest: BTSEPADirectDebitRequest! var successApprovalURL: String = "" var mockAPIClient : MockAPIClient = MockAPIClient(authorization: "development_client_key") @@ -28,12 +29,14 @@ class SEPADirectDebitAPI_Tests: XCTestCase { ) override func setUp() { - billingAddress.streetAddress = "Kantstraße 70" - billingAddress.extendedAddress = "#170" - billingAddress.locality = "Freistaat Sachsen" - billingAddress.region = "Annaberg-buchholz" - billingAddress.postalCode = "09456" - billingAddress.countryCodeAlpha2 = "FR" + billingAddress = BTPostalAddress( + streetAddress: "Kantstraße 70", + extendedAddress: "#170", + locality: "Freistaat Sachsen", + countryCodeAlpha2: "FR", + postalCode: "09456", + region: "Annaberg-buchholz" + ) sepaDirectDebitRequest = BTSEPADirectDebitRequest( accountHolderName: "John Doe", @@ -57,12 +60,15 @@ class SEPADirectDebitAPI_Tests: XCTestCase { } func testCreateMandate_properlyFormatsPOSTBody() { - billingAddress.streetAddress = "fake-street-addres" - billingAddress.extendedAddress = "fake-extended-address" - billingAddress.locality = "fake-locality" - billingAddress.region = "fake-region" - billingAddress.postalCode = "fake-postal-code" - billingAddress.countryCodeAlpha2 = "fake-country-code" + let billingAddress = BTPostalAddress( + streetAddress: "fake-street-addres", + extendedAddress: "fake-extended-address", + locality: "fake-locality", + countryCodeAlpha2: "fake-country-code", + postalCode: "fake-postal-code", + region: "fake-region" + ) + let sepaDirectDebitRequest = BTSEPADirectDebitRequest( accountHolderName: "fake-name", iban: "fake-iban", @@ -87,13 +93,13 @@ class SEPADirectDebitAPI_Tests: XCTestCase { XCTAssertEqual(sepaDebit["account_holder_name"] as! String, "fake-name") XCTAssertEqual(sepaDebit["iban"] as! String, "fake-iban") - let billingAddress = sepaDebit["billing_address"] as! [String: String] - XCTAssertEqual(billingAddress["address_line_1"], "fake-street-addres") - XCTAssertEqual(billingAddress["address_line_2"], "fake-extended-address") - XCTAssertEqual(billingAddress["admin_area_1"], "fake-locality") - XCTAssertEqual(billingAddress["admin_area_2"], "fake-region") - XCTAssertEqual(billingAddress["postal_code"], "fake-postal-code") - XCTAssertEqual(billingAddress["country_code"], "fake-country-code") + let billingAddressFields = sepaDebit["billing_address"] as! [String: String] + XCTAssertEqual(billingAddressFields["address_line_1"], "fake-street-addres") + XCTAssertEqual(billingAddressFields["address_line_2"], "fake-extended-address") + XCTAssertEqual(billingAddressFields["admin_area_1"], "fake-locality") + XCTAssertEqual(billingAddressFields["admin_area_2"], "fake-region") + XCTAssertEqual(billingAddressFields["postal_code"], "fake-postal-code") + XCTAssertEqual(billingAddressFields["country_code"], "fake-country-code") } func testCreateMandate_onSuccessfulHttpResponse_returnsCreateMandateResult() { From 77e4d3bd4fd07886b2ad3288373a2fa7940d2598 Mon Sep 17 00:00:00 2001 From: ageddam Date: Wed, 15 Oct 2025 13:05:19 -0500 Subject: [PATCH 2/5] update changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9056c29be4..49b45383eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * Update `BTPayPalLineItem` to make all properties accessible on the initializer only vs via the dot syntax. * BraintreeVenmo * Update `BTVenmoLineItem` to make all properties accessible on the initializer only vs via the dot syntax. +* BraintreeCore + * Update`BTPostalAddress` to make all properties accessible on the initializer only vs via the dot syntax. ## 6.39.0 (2025-10-01) * BraintreeCore From 8121015b96bdb344ac7782772dc7dc7bc6133c98 Mon Sep 17 00:00:00 2001 From: ageddam Date: Thu, 16 Oct 2025 12:40:38 -0500 Subject: [PATCH 3/5] cleaup --- Sources/BraintreeCore/BTPostalAddress.swift | 49 ++++++++++++------- .../Models/LocalPaymentPOSTBody.swift | 13 +++-- .../Models/PayPalCheckoutPOSTBody.swift | 13 ++--- .../Models/SEPADebitRequest.swift | 12 ++--- 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/Sources/BraintreeCore/BTPostalAddress.swift b/Sources/BraintreeCore/BTPostalAddress.swift index 470490d1bd..7dae084701 100644 --- a/Sources/BraintreeCore/BTPostalAddress.swift +++ b/Sources/BraintreeCore/BTPostalAddress.swift @@ -7,7 +7,6 @@ import Foundation // Property names follow the `Braintree_Address` convention as documented at: // https://developer.paypal.com/braintree/docs/reference/request/address/create - let recipientName: String? let streetAddress: String? let extendedAddress: String? @@ -20,13 +19,13 @@ import Foundation /// Creats a postal address with all components /// - Parameters: - /// - recipientName: Recipient name for shipping address. - /// - streetAddress: Line 1 of the Address (eg. number, street, etc). - /// - extendedAddress: Optional line 2 of the Address (eg. suite, apt #, etc.). - /// - locality: City name - /// - countryCodeAlpha2: 2 letter country code. - /// - postalCode: Zip code or equivalent is usually required for countries that have them. For a list of countries that do not have postal codes please refer to http://en.wikipedia.org/wiki/Postal_code. - /// - region: Either a two-letter state code (for the US), or an ISO-3166-2 country subdivision code of up to three letters. + /// - recipientName: Optional. Recipient name for shipping address. + /// - streetAddress: Optional. Line 1 of the Address (eg. number, street, etc). + /// - extendedAddress: Optional. Line 2 of the Address (eg. suite, apt #, etc.). + /// - locality: Optional. City name + /// - countryCodeAlpha2: Optional. 2 letter country code. + /// - postalCode: Optional. Zip code or equivalent is usually required for countries that have them. For a list of countries that do not have postal codes please refer to http://en.wikipedia.org/wiki/Postal_code. + /// - region: Optional. Either a two-letter state code (for the US), or an ISO-3166-2 country subdivision code of up to three letters. public init( recipientName: String? = nil, streetAddress: String? = nil, @@ -58,15 +57,29 @@ import Foundation // MARK: - Helper Method /// Returns address components as a dictionary for accessing internal properties across modules - public func addressComponents() -> [String: String?] { - return [ - "recipientName": recipientName, - "streetAddress": streetAddress, - "extendedAddress": extendedAddress, - "locality": locality, - "countryCodeAlpha2": countryCodeAlpha2, - "postalCode": postalCode, - "region": region - ] + public func addressComponents() -> [String: String] { + var components: [String: String] = [:] + if let recipientName = recipientName { + components["recipientName"] = recipientName + } + if let streetAddress = streetAddress { + components["streetAddress"] = streetAddress + } + if let extendedAddress = extendedAddress { + components["extendedAddress"] = extendedAddress + } + if let locality = locality { + components["locality"] = locality + } + if let countryCodeAlpha2 = countryCodeAlpha2 { + components["countryCodeAlpha2"] = countryCodeAlpha2 + } + if let postalCode = postalCode { + components["postalCode"] = postalCode + } + if let region = region { + components["region"] = region + } + return components } } diff --git a/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift b/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift index 431e523504..6cbdbaf78a 100644 --- a/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift +++ b/Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift @@ -56,15 +56,14 @@ struct LocalPaymentPOSTBody: Encodable { self.returnURL = BTCoreConstants.callbackURLScheme + "://x-callback-url/braintree/local-payment/success" self.cancelURL = BTCoreConstants.callbackURLScheme + "://x-callback-url/braintree/local-payment/cancel" - if let address = localPaymentRequest.address { let addressComponents = address.addressComponents() - self.streetAddress = addressComponents["streetAddress"] ?? nil - self.extendedAddress = addressComponents["extendedAddress"] ?? nil - self.locality = addressComponents["locality"] ?? nil - self.countryCodeAlpha2 = addressComponents["countryCodeAlpha2"] ?? nil - self.postalCode = addressComponents["postalCode"] ?? nil - self.region = addressComponents["region"] ?? nil + self.streetAddress = addressComponents["streetAddress"] + self.extendedAddress = addressComponents["extendedAddress"] + self.locality = addressComponents["locality"] + self.countryCodeAlpha2 = addressComponents["countryCodeAlpha2"] + self.postalCode = addressComponents["postalCode"] + self.region = addressComponents["region"] } } diff --git a/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift b/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift index b405276a16..cce4ab1bc7 100644 --- a/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift +++ b/Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift @@ -80,12 +80,13 @@ struct PayPalCheckoutPOSTBody: Encodable { if let shippingAddressOverride = payPalRequest.shippingAddressOverride { let addressComponents = shippingAddressOverride.addressComponents() - self.streetAddress = addressComponents["streetAddress"] ?? nil - self.extendedAddress = addressComponents["extendedAddress"] ?? nil - self.locality = addressComponents["locality"] ?? nil - self.countryCodeAlpha2 = addressComponents["countryCodeAlpha2"] ?? nil - self.postalCode = addressComponents["postalCode"] ?? nil - self.region = addressComponents["region"] ?? nil + self.recipientName = addressComponents["recipientName"] + self.streetAddress = addressComponents["streetAddress"] + self.extendedAddress = addressComponents["extendedAddress"] + self.locality = addressComponents["locality"] + self.countryCodeAlpha2 = addressComponents["countryCodeAlpha2"] + self.postalCode = addressComponents["postalCode"] + self.region = addressComponents["region"] } if let merchantAccountID = payPalRequest.merchantAccountID { diff --git a/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift b/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift index 44cb7b94fe..d6f16097d5 100644 --- a/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift +++ b/Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift @@ -68,12 +68,12 @@ struct SEPADebitRequest: Encodable { self.billingAddress = sepaDirectDebitRequest.billingAddress.map { postalAddress in let components = postalAddress.addressComponents() return BillingAddress( - streetAddress: components["streetAddress"] ?? nil, - extendedAddress: components["extendedAddress"] ?? nil, - locality: components["locality"] ?? nil, - region: components["region"] ?? nil, - postalCode: components["postalCode"] ?? nil, - countryCodeAlpha2: components["countryCodeAlpha2"] ?? nil + streetAddress: components["streetAddress"], + extendedAddress: components["extendedAddress"], + locality: components["locality"], + region: components["region"], + postalCode: components["postalCode"], + countryCodeAlpha2: components["countryCodeAlpha2"] ) } } From b92e3fc15a28ccdc139061a5acb56ff61cdcf95d Mon Sep 17 00:00:00 2001 From: ageddam Date: Thu, 16 Oct 2025 12:52:09 -0500 Subject: [PATCH 4/5] address swiftlint error --- Demo/Application/Features/SEPADirectDebitViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Demo/Application/Features/SEPADirectDebitViewController.swift b/Demo/Application/Features/SEPADirectDebitViewController.swift index 5749244c85..b5f764b54f 100644 --- a/Demo/Application/Features/SEPADirectDebitViewController.swift +++ b/Demo/Application/Features/SEPADirectDebitViewController.swift @@ -27,7 +27,7 @@ class SEPADirectDebitViewController: PaymentButtonBaseViewController { extendedAddress: "#170", locality: "Freistaat Sachsen", countryCodeAlpha2: "FR", - postalCode: "09456", + postalCode: "09456", region: "Annaberg-buchholz" ) From a2cc2fad0eee0b47aad211f0f62bae943439b5b9 Mon Sep 17 00:00:00 2001 From: ageddam Date: Fri, 17 Oct 2025 10:54:34 -0500 Subject: [PATCH 5/5] address pr comment --- Sources/BraintreeCore/BTPostalAddress.swift | 32 ++++++--------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/Sources/BraintreeCore/BTPostalAddress.swift b/Sources/BraintreeCore/BTPostalAddress.swift index 7dae084701..01c79eca1f 100644 --- a/Sources/BraintreeCore/BTPostalAddress.swift +++ b/Sources/BraintreeCore/BTPostalAddress.swift @@ -58,28 +58,14 @@ import Foundation /// Returns address components as a dictionary for accessing internal properties across modules public func addressComponents() -> [String: String] { - var components: [String: String] = [:] - if let recipientName = recipientName { - components["recipientName"] = recipientName - } - if let streetAddress = streetAddress { - components["streetAddress"] = streetAddress - } - if let extendedAddress = extendedAddress { - components["extendedAddress"] = extendedAddress - } - if let locality = locality { - components["locality"] = locality - } - if let countryCodeAlpha2 = countryCodeAlpha2 { - components["countryCodeAlpha2"] = countryCodeAlpha2 - } - if let postalCode = postalCode { - components["postalCode"] = postalCode - } - if let region = region { - components["region"] = region - } - return components + [ + "recipientName": recipientName, + "streetAddress": streetAddress, + "extendedAddress": extendedAddress, + "locality": locality, + "countryCodeAlpha2": countryCodeAlpha2, + "postalCode": postalCode, + "region": region + ].compactMapValues { $0 } } }