Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: do we care about alphabetical order here?
BraintreeCore before BraintreePayPal?

* Update`BTPostalAddress` to make all properties accessible on the initializer only vs via the dot syntax.

## 6.39.0 (2025-10-01)
* BraintreeCore
Expand Down
11 changes: 6 additions & 5 deletions Demo/Application/Features/IdealViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
15 changes: 8 additions & 7 deletions Demo/Application/Features/SEPADirectDebitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
26 changes: 17 additions & 9 deletions Sources/BraintreeCore/BTJSON.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a blocker, very much a take it or leave it. For these instead of making them all stored properties we could also just this inline:

Suggested change
recipientName: recipientName,
recipientName: self["recipientName"].asString() ?? self["fullName"].asString(),

streetAddress: streetAddress,
extendedAddress: extendedAddress,
locality: locality,
countryCodeAlpha2: countryCodeAlpha2,
postalCode: postalCode,
region: region
)
}
}
75 changes: 53 additions & 22 deletions Sources/BraintreeCore/BTPostalAddress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,46 @@ 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: 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,
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"
Expand All @@ -37,4 +53,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] {
[
"recipientName": recipientName,
"streetAddress": streetAddress,
"extendedAddress": extendedAddress,
"locality": locality,
"countryCodeAlpha2": countryCodeAlpha2,
"postalCode": postalCode,
"region": region
].compactMapValues { $0 }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ struct LocalPaymentPOSTBody: Encodable {
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"]
self.extendedAddress = addressComponents["extendedAddress"]
self.locality = addressComponents["locality"]
self.countryCodeAlpha2 = addressComponents["countryCodeAlpha2"]
self.postalCode = addressComponents["postalCode"]
self.region = addressComponents["region"]
}
}

Expand Down
15 changes: 8 additions & 7 deletions Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,14 @@ 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.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 {
Expand Down
20 changes: 12 additions & 8 deletions Sources/BraintreeSEPADirectDebit/Models/SEPADebitRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
extendedAddress: components["extendedAddress"],
locality: components["locality"],
region: components["region"],
postalCode: components["postalCode"],
countryCodeAlpha2: components["countryCodeAlpha2"]
)
}
}
}

Expand Down
35 changes: 19 additions & 16 deletions UnitTests/BraintreeCoreTests/BTPostalAddress_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,15 @@ class BTPayPalCheckoutRequest_Tests: XCTestCase {
request.userAuthenticationEmail = "[email protected]"
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading
Loading