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

[V7] Add Encodable protocol for Local Payments. #1468

Merged
merged 4 commits into from
Dec 2, 2024
Merged
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
12 changes: 12 additions & 0 deletions Braintree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
42FC237125CE0E110047C49A /* BTPayPalCheckoutRequest_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42FC237025CE0E110047C49A /* BTPayPalCheckoutRequest_Tests.swift */; };
45227FC52C330FDE00A15018 /* MockURLSessionTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45227FC32C330FDE00A15018 /* MockURLSessionTask.swift */; };
45227FC72C33104100A15018 /* MockBTHTTPNetworkTiming.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45227FC62C33104100A15018 /* MockBTHTTPNetworkTiming.swift */; };
454722B02CF0DA34000DCF4E /* LocalPaymentPOSTBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454722AF2CF0DA27000DCF4E /* LocalPaymentPOSTBody.swift */; };
457D7FC82C29CEC300EF6523 /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D7FC72C29CEC300EF6523 /* RepeatingTimer.swift */; };
457D7FCA2C2A250E00EF6523 /* RepeatingTimer_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D7FC92C2A250E00EF6523 /* RepeatingTimer_Tests.swift */; };
458570782C34A699009CEF7A /* ConfigurationLoader_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 458570772C34A699009CEF7A /* ConfigurationLoader_Tests.swift */; };
Expand Down Expand Up @@ -722,6 +723,7 @@
42FC237025CE0E110047C49A /* BTPayPalCheckoutRequest_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalCheckoutRequest_Tests.swift; sourceTree = "<group>"; };
45227FC32C330FDE00A15018 /* MockURLSessionTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockURLSessionTask.swift; sourceTree = "<group>"; };
45227FC62C33104100A15018 /* MockBTHTTPNetworkTiming.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBTHTTPNetworkTiming.swift; sourceTree = "<group>"; };
454722AF2CF0DA27000DCF4E /* LocalPaymentPOSTBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalPaymentPOSTBody.swift; sourceTree = "<group>"; };
457D7FC72C29CEC300EF6523 /* RepeatingTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer.swift; sourceTree = "<group>"; };
457D7FC92C2A250E00EF6523 /* RepeatingTimer_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer_Tests.swift; sourceTree = "<group>"; };
458570772C34A699009CEF7A /* ConfigurationLoader_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationLoader_Tests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1278,6 +1280,7 @@
80BA64B129D7937E00E15264 /* BTLocalPaymentRequest.swift */,
80BA64B329D795D000E15264 /* BTLocalPaymentRequestDelegate.swift */,
80BA64AB29D788E000E15264 /* BTLocalPaymentResult.swift */,
454722AE2CF0DA14000DCF4E /* Models */,
3B5A41E82BA2375600921922 /* PrivacyInfo.xcprivacy */,
);
path = BraintreeLocalPayment;
Expand Down Expand Up @@ -1308,6 +1311,14 @@
path = BraintreePayPal;
sourceTree = "<group>";
};
454722AE2CF0DA14000DCF4E /* Models */ = {
isa = PBXGroup;
children = (
454722AF2CF0DA27000DCF4E /* LocalPaymentPOSTBody.swift */,
);
path = Models;
sourceTree = "<group>";
};
570B93AE285397D20041BAFE /* BraintreeCore */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -3070,6 +3081,7 @@
files = (
80BA64B429D795D000E15264 /* BTLocalPaymentRequestDelegate.swift in Sources */,
80E2460F29E492DF00945A1D /* BTLocalPaymentClient.swift in Sources */,
454722B02CF0DA34000DCF4E /* LocalPaymentPOSTBody.swift in Sources */,
80BA64B229D7937E00E15264 /* BTLocalPaymentRequest.swift in Sources */,
BE9834A22A041B6200B6C3CC /* BTConfiguration+LocalPayment.swift in Sources */,
80CF988529DB64D400D51979 /* BTLocalPaymentError.swift in Sources */,
Expand Down
64 changes: 3 additions & 61 deletions Sources/BraintreeLocalPayment/BTLocalPaymentClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ import BraintreeDataCollector
// MARK: - Private Methods

private func start(request: BTLocalPaymentRequest, configuration: BTConfiguration) {
let requestParameters = buildRequestDictionary(with: request)
apiClient.post("v1/local_payments/create", parameters: requestParameters) { body, _, error in
let localPaymentRequest = LocalPaymentPOSTBody(localPaymentRequest: request)
apiClient.post("v1/local_payments/create", parameters: localPaymentRequest) { body, _, error in
if let error {
self.notifyFailure(with: error, completion: self.merchantCompletion)
return
Expand Down Expand Up @@ -207,65 +207,7 @@ import BraintreeDataCollector
}
}
}

private func buildRequestDictionary(with request: BTLocalPaymentRequest) -> [String: Any] {
var requestParameters: [String: Any] = [
"amount": request.amount,
"funding_source": request.paymentType,
"intent": "sale",
"currency_iso_code": request.currencyCode,
"return_url": "\(BTCoreConstants.callbackURLScheme)://x-callback-url/braintree/local-payment/success",
"cancel_url": "\(BTCoreConstants.callbackURLScheme)://x-callback-url/braintree/local-payment/cancel"
]

if let countryCode = request.paymentTypeCountryCode {
requestParameters["payment_type_country_code"] = countryCode
}

if let address = request.address {
requestParameters["line1"] = address.streetAddress
requestParameters["line2"] = address.extendedAddress
requestParameters["city"] = address.locality
requestParameters["state"] = address.region
requestParameters["postal_code"] = address.postalCode
requestParameters["country_code"] = address.countryCodeAlpha2
}

if let givenName = request.givenName {
requestParameters["first_name"] = givenName
}

if let surname = request.surname {
requestParameters["last_name"] = surname
}

if let email = request.email {
requestParameters["payer_email"] = email
}

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

if let merchantAccountID = request.merchantAccountID {
requestParameters["merchant_account_id"] = merchantAccountID
}

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

var experienceProfile: [String: Any] = ["no_shipping": !request.isShippingAddressRequired]

if let displayName = request.displayName {
experienceProfile["brand_name"] = displayName
}

requestParameters["experience_profile"] = experienceProfile

return requestParameters
}


private func onPayment(with url: URL?, error: Error?) {
if let error {
notifyFailure(with: error, completion: merchantCompletion)
Expand Down
6 changes: 4 additions & 2 deletions Sources/BraintreeLocalPayment/BTLocalPaymentRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import BraintreeDataCollector
/// Used to initialize a local payment flow
@objcMembers public class BTLocalPaymentRequest: NSObject {

// MARK: - Public Properties

public weak var localPaymentFlowDelegate: BTLocalPaymentRequestDelegate?

// MARK: - Internal Properties

let paymentType: String
Expand All @@ -26,8 +30,6 @@ import BraintreeDataCollector
let phone: String?
let isShippingAddressRequired: Bool
let bic: String?

public weak var localPaymentFlowDelegate: BTLocalPaymentRequestDelegate?

var paymentID: String?
var correlationID: String?
Expand Down
108 changes: 108 additions & 0 deletions Sources/BraintreeLocalPayment/Models/LocalPaymentPOSTBody.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import Foundation

#if canImport(BraintreeCore)
import BraintreeCore
#endif

/// The POST body for v1/local_payments/create
struct LocalPaymentPOSTBody: Encodable {

// MARK: - Private Properties

private let paymentType: String
private let amount: String
private let currencyCode: String
private let paymentTypeCountryCode: String?
private let merchantAccountID: String?
private let address: BTPostalAddress?
private let email: String?
private let givenName: String?
private let surname: String?
private let phone: String?
private let bic: String?
private let intent: String
private let returnURL: String
private let cancelURL: String
private let experienceProfile: ExperienceProfile

private var streetAddress: String?
private var extendedAddress: String?
private var locality: String?
private var countryCodeAlpha2: String?
private var postalCode: String?
private var region: String?

// MARK: - Initializer

init(
localPaymentRequest: BTLocalPaymentRequest
) {
self.paymentType = localPaymentRequest.paymentType
self.amount = localPaymentRequest.amount
self.currencyCode = localPaymentRequest.currencyCode
self.paymentTypeCountryCode = localPaymentRequest.paymentTypeCountryCode
self.merchantAccountID = localPaymentRequest.merchantAccountID
self.address = localPaymentRequest.address
self.email = localPaymentRequest.email
self.givenName = localPaymentRequest.givenName
self.surname = localPaymentRequest.surname
self.phone = localPaymentRequest.phone
self.bic = localPaymentRequest.bic
self.experienceProfile = ExperienceProfile(
noShipping: !localPaymentRequest.isShippingAddressRequired,
brandName: localPaymentRequest.displayName
)
self.intent = "sale"
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
}
}

enum CodingKeys: String, CodingKey {
case paymentType = "funding_source"
case amount
case currencyCode = "currency_iso_code"
case paymentTypeCountryCode = "payment_type_country_code"
case merchantAccountID = "merchant_account_id"
case email = "payer_email"
case givenName = "first_name"
case surname = "last_name"
case phone
case bic
case intent
case returnURL = "return_url"
case cancelURL = "cancel_url"
case experienceProfile = "experience_profile"

// Address keys
case streetAddress = "line1"
case extendedAddress = "line2"
case locality = "city"
case countryCodeAlpha2 = "country_code"
case postalCode = "postal_code"
case region = "state"
}
}

extension LocalPaymentPOSTBody {

struct ExperienceProfile: Encodable {

let noShipping: Bool
let brandName: String?

// swiftlint:disable nesting
enum CodingKeys: String, CodingKey {
case noShipping = "no_shipping"
case brandName = "brand_name"
}
}
}
Loading