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 PayPal Vault #1492

Merged
merged 55 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
d53299c
Add file with paypal request properties
richherrera Dec 30, 2024
cf7ad1e
Add var to BTConfiguration extension
richherrera Dec 30, 2024
964d7e8
Add country iso code var
richherrera Dec 30, 2024
7460d9d
Add checkout properties to POST body model
richherrera Dec 30, 2024
0a3dbf4
Disable nesting lint
richherrera Jan 2, 2025
f5952e6
Address some lints
richherrera Jan 2, 2025
3168bf5
Add dot
richherrera Jan 2, 2025
623c681
Rename struct
richherrera Jan 2, 2025
8006e18
Add Encodable protocol to BTPostalAddress class
richherrera Jan 3, 2025
d1c1cd1
Add Encodable protocol to BTPayPalBillingCycle struct
richherrera Jan 3, 2025
14390fd
Add Encodable protocol to BTPayPalBillingPricing struct
richherrera Jan 3, 2025
06fd294
Add Encodable protocol to BTPayPalRecurringBillingDetails struct
richherrera Jan 3, 2025
6f0daad
Add Encodable protocol to BTPayPalRecurringBillingPlanType enum
richherrera Jan 3, 2025
428b0a4
Add PayPalVaultPOSTBody file
richherrera Jan 3, 2025
2b072da
Add encodable properties
richherrera Jan 3, 2025
09d964d
Add Encodable protocol to BTPayPalLineItem class
richherrera Jan 6, 2025
c7e226e
Merge branch 'paypal-checkout-encodable' into paypal-vault-encodable
richherrera Jan 6, 2025
9543469
Use encodable for BTLineItems
richherrera Jan 6, 2025
27c0a44
Add error to catch encodable exception
richherrera Jan 6, 2025
4a6e7d8
Use encoded objects
richherrera Jan 6, 2025
42af3f7
Use Configuration.isPayPalEnabled instead of json format
richherrera Jan 6, 2025
2200e5c
Add PayPalExperienceProfile as a shared object to be use for Checkout…
richherrera Jan 6, 2025
1553b22
Add PayPalRequest protocol, BTPayPalRequest conforms PayPalRequest
richherrera Jan 9, 2025
f9c90ec
BTPayPalCheckoutRequest conforms PayPalRequest
richherrera Jan 9, 2025
abe2c7e
Move lineItems parameters on init
richherrera Jan 9, 2025
b0cea93
BTPayPalVaultRequest conforms PayPalRequest
richherrera Jan 9, 2025
4a3b49c
Update BTPayPalRequest UTs
richherrera Jan 9, 2025
49886c7
Update BTPayPalClient to use an interface instead of concrete class
richherrera Jan 9, 2025
47727f4
Merge branch 'v7' into paypal-checkout-encodable
richherrera Jan 9, 2025
3c1701e
Disable cyclomatic_complexity lint
richherrera Jan 9, 2025
b6ce34b
Disable function_body_length lint
richherrera Jan 9, 2025
50c23ac
Merge branch 'paypal-checkout-encodable' into paypal-vault-encodable
richherrera Jan 9, 2025
8e12bf8
Address PR comments
richherrera Jan 9, 2025
8b18aeb
Remove parameters method
richherrera Jan 9, 2025
b903ba2
Remove BTPayPalRequest class
richherrera Jan 9, 2025
44d61f4
Add PayPalConstanst enum
richherrera Jan 9, 2025
7f0a207
Remove unnecessary error
richherrera Jan 9, 2025
39ca19f
Move encoded method
richherrera Jan 9, 2025
169ff3a
Update UTs
richherrera Jan 9, 2025
d6284ec
Move BTPayPalRequest UTs to BTPayPalCheckout and BTPayPalVault requests
richherrera Jan 10, 2025
7601a15
Delete BTPayPalRequest UTs
richherrera Jan 10, 2025
e446f03
Use if let syntax
richherrera Jan 10, 2025
ac6f13e
Address PR comments
richherrera Jan 10, 2025
e478437
Remove BTLineItems custom encode method
richherrera Jan 13, 2025
6dfb488
Revert unnecessary changes
richherrera Jan 13, 2025
5b86155
Merge branch 'paypal-checkout-encodable' into paypal-vault-encodable
richherrera Jan 13, 2025
f90356b
Rename PayPalRequest protocol to BTPayPalRequest
richherrera Jan 13, 2025
df8eba1
Remove unnecessary parameters methods
richherrera Jan 13, 2025
3fa9a0d
Remove unnecessary parameters methods
richherrera Jan 13, 2025
f3ccfe4
Add quotation marks
richherrera Jan 21, 2025
876599d
Add docstrings and move the enums to their own file.
richherrera Jan 21, 2025
e56a718
Merge branch 'paypal-checkout-encodable' into paypal-vault-encodable
richherrera Jan 21, 2025
09357ff
Address PR comments
richherrera Jan 21, 2025
5cf34f5
Merge branch 'v7' into paypal-vault-encodable
richherrera Jan 21, 2025
362f9bb
Update paypalrequest property
richherrera Jan 21, 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
20 changes: 20 additions & 0 deletions Braintree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
458570782C34A699009CEF7A /* ConfigurationLoader_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 458570772C34A699009CEF7A /* ConfigurationLoader_Tests.swift */; };
4585707A2C34B1E1009CEF7A /* MockClientAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 458570792C34B1E1009CEF7A /* MockClientAuthorization.swift */; };
4585707C2C34B7B5009CEF7A /* MockConfigurationLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4585707B2C34B7B5009CEF7A /* MockConfigurationLoader.swift */; };
45E8CE4C2D1F29BA00D7A2DC /* PayPalCheckoutPOSTBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E8CE4B2D1F29BA00D7A2DC /* PayPalCheckoutPOSTBody.swift */; };
45E8CE4E2D28611700D7A2DC /* PayPalVaultPOSTBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E8CE4D2D28611700D7A2DC /* PayPalVaultPOSTBody.swift */; };
45E8CE502D2C773600D7A2DC /* PayPalExperienceProfilePOSTBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E8CE4F2D2C772000D7A2DC /* PayPalExperienceProfilePOSTBody.swift */; };
45EFC3972C2DBF32005E7F5B /* ConfigurationLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45EFC3962C2DBF32005E7F5B /* ConfigurationLoader.swift */; };
460C0C220F594AE8EE205E57 /* Pods_Tests_BraintreeCoreTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9239C9FE850C3587DE61A3A2 /* Pods_Tests_BraintreeCoreTests.framework */; };
5708E0A628809AD9007946B9 /* BTJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5708E0A528809AD9007946B9 /* BTJSON.swift */; };
Expand Down Expand Up @@ -725,6 +728,9 @@
458570772C34A699009CEF7A /* ConfigurationLoader_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationLoader_Tests.swift; sourceTree = "<group>"; };
458570792C34B1E1009CEF7A /* MockClientAuthorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockClientAuthorization.swift; sourceTree = "<group>"; };
4585707B2C34B7B5009CEF7A /* MockConfigurationLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockConfigurationLoader.swift; sourceTree = "<group>"; };
45E8CE4B2D1F29BA00D7A2DC /* PayPalCheckoutPOSTBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalCheckoutPOSTBody.swift; sourceTree = "<group>"; };
45E8CE4D2D28611700D7A2DC /* PayPalVaultPOSTBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalVaultPOSTBody.swift; sourceTree = "<group>"; };
45E8CE4F2D2C772000D7A2DC /* PayPalExperienceProfilePOSTBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayPalExperienceProfilePOSTBody.swift; sourceTree = "<group>"; };
45EFC3962C2DBF32005E7F5B /* ConfigurationLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationLoader.swift; sourceTree = "<group>"; };
463DED22C0F426A474E6D7E2 /* Pods-Tests-BraintreeCoreTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-BraintreeCoreTests.release.xcconfig"; path = "Target Support Files/Pods-Tests-BraintreeCoreTests/Pods-Tests-BraintreeCoreTests.release.xcconfig"; sourceTree = "<group>"; };
541AEE40A1F01913E0638CC9 /* Pods-Tests-BraintreeCoreTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-BraintreeCoreTests.debug.xcconfig"; path = "Target Support Files/Pods-Tests-BraintreeCoreTests/Pods-Tests-BraintreeCoreTests.debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1298,6 +1304,7 @@
BE349112294B798300D2CF68 /* BTPayPalRequest.swift */,
BE6BC22D2BA9CFFC00C3E321 /* BTPayPalReturnURL.swift */,
BE349110294B77E100D2CF68 /* BTPayPalVaultRequest.swift */,
45E8CE4A2D1F291400D7A2DC /* Models */,
62A659A32B98CB23008DFD67 /* PrivacyInfo.xcprivacy */,
807D22F32C29ADA8009FFEA4 /* RecurringBillingMetadata */,
62B811872CC002470024A688 /* BTPayPalPhoneNumber.swift */,
Expand All @@ -1313,6 +1320,16 @@
path = Models;
sourceTree = "<group>";
};
45E8CE4A2D1F291400D7A2DC /* Models */ = {
isa = PBXGroup;
children = (
45E8CE4B2D1F29BA00D7A2DC /* PayPalCheckoutPOSTBody.swift */,
45E8CE4D2D28611700D7A2DC /* PayPalVaultPOSTBody.swift */,
45E8CE4F2D2C772000D7A2DC /* PayPalExperienceProfilePOSTBody.swift */,
);
path = Models;
sourceTree = "<group>";
};
570B93AE285397D20041BAFE /* BraintreeCore */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -3102,12 +3119,15 @@
BEF5D2E6294A18B300FFD56D /* BTPayPalLineItem.swift in Sources */,
BE349113294B798300D2CF68 /* BTPayPalRequest.swift in Sources */,
BE549F112BF5445F00B6F441 /* BTPayPalReturnURL.swift in Sources */,
45E8CE502D2C773600D7A2DC /* PayPalExperienceProfilePOSTBody.swift in Sources */,
57544F5C295254A500DEB7B0 /* BTJSON+PayPal.swift in Sources */,
3B7A261129C0CAA40087059D /* BTPayPalAnalytics.swift in Sources */,
BE8E5CEF294B6937001BF017 /* BTPayPalCheckoutRequest.swift in Sources */,
807D22F02C29A93A009FFEA4 /* BTPayPalBillingCycle.swift in Sources */,
45E8CE4E2D28611700D7A2DC /* PayPalVaultPOSTBody.swift in Sources */,
5754481E294A2A1D00DEB7B0 /* BTPayPalCreditFinancingAmount.swift in Sources */,
57D9436E2968A8080079EAB1 /* BTPayPalLocaleCode.swift in Sources */,
45E8CE4C2D1F29BA00D7A2DC /* PayPalCheckoutPOSTBody.swift in Sources */,
57544F582952298900DEB7B0 /* BTPayPalAccountNonce.swift in Sources */,
8014221C2BAE935B009F9999 /* BTPayPalApprovalURLParser.swift in Sources */,
BE349111294B77E100D2CF68 /* BTPayPalVaultRequest.swift in Sources */,
Expand Down
12 changes: 11 additions & 1 deletion Sources/BraintreeCore/BTPostalAddress.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

/// Generic postal address
@objcMembers public class BTPostalAddress: NSObject {
@objcMembers public class BTPostalAddress: NSObject, Encodable {

// Property names follow the `Braintree_Address` convention as documented at:
// https://developer.paypal.com/braintree/docs/reference/request/address/create
Expand All @@ -27,4 +27,14 @@ import Foundation

/// 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?

enum CodingKeys: String, CodingKey {
case countryCodeAlpha2 = "country_code"
case extendedAddress = "line2"
case locality = "city"
case postalCode = "postal_code"
case region = "state"
case recipientName = "recipient_name"
case streetAddress = "line1"
}
}
10 changes: 10 additions & 0 deletions Sources/BraintreePayPal/BTConfiguration+PayPal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,14 @@ extension BTConfiguration {
var isBillingAgreementsEnabled: Bool {
json?["paypal"]["billingAgreementsEnabled"].isTrue ?? false
}

/// Retrieves the display name associated with the PayPal account.
var displayName: String? {
json?["paypal"]["displayName"].asString()
}

/// Retrieves the currencyIsoCode.
var currencyIsoCode: String? {
json?["paypal"]["currencyIsoCode"].asString()
}
}
29 changes: 23 additions & 6 deletions Sources/BraintreePayPal/BTPayPalClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -350,19 +350,21 @@ import BraintreeDataCollector

self.isConfigFromCache = configuration.isFromCache

guard json["paypalEnabled"].isTrue else {
guard configuration.isPayPalEnabled else {
jaxdesmarais marked this conversation as resolved.
Show resolved Hide resolved
self.notifyFailure(with: BTPayPalError.disabled, completion: completion)
return
}

self.payPalRequest = request

guard let parameters = self.encodedPostBody(fromRequest: request, configuration: configuration) else {
self.notifyFailure(with: BTPayPalError.failedToCreateEncodable, completion: completion)
return
}

self.apiClient.post(
request.hermesPath,
parameters: request.parameters(
with: configuration,
universalLink: self.universalLink,
isPayPalAppInstalled: self.application.isPayPalAppInstalled()
)
parameters: parameters
) { body, _, error in
if let error = error as? NSError {
guard let jsonResponseBody = error.userInfo[BTCoreConstants.jsonResponseBodyKey] as? BTJSON else {
Expand Down Expand Up @@ -401,6 +403,21 @@ import BraintreeDataCollector
}
}
}

private func encodedPostBody(fromRequest payPalRequest: BTPayPalRequest, configuration: BTConfiguration) -> Encodable? {
richherrera marked this conversation as resolved.
Show resolved Hide resolved
if let checkoutRequest = payPalRequest as? BTPayPalCheckoutRequest {
richherrera marked this conversation as resolved.
Show resolved Hide resolved
return PayPalCheckoutPOSTBody(payPalRequest: checkoutRequest, configuration: configuration)
} else if let vaultRequest = payPalRequest as? BTPayPalVaultRequest {
return PayPalVaultPOSTBody(
payPalRequest: vaultRequest,
configuration: configuration,
isPayPalAppInstalled: application.isPayPalAppInstalled(),
universalLink: universalLink
)
} else {
return nil
}
}

private func launchPayPalApp(
with payPalAppRedirectURL: URL,
Expand Down
7 changes: 7 additions & 0 deletions Sources/BraintreePayPal/BTPayPalError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ public enum BTPayPalError: Error, CustomNSError, LocalizedError, Equatable {

/// 13. Missing PayPal Request
case missingPayPalRequest

/// 14. Unable to create Encodable
case failedToCreateEncodable

public static var errorDomain: String {
"com.braintreepayments.BTPayPalErrorDomain"
Expand Down Expand Up @@ -79,6 +82,8 @@ public enum BTPayPalError: Error, CustomNSError, LocalizedError, Equatable {
return 12
case .missingPayPalRequest:
return 13
case .failedToCreateEncodable:
return 14
}
}

Expand Down Expand Up @@ -114,6 +119,8 @@ public enum BTPayPalError: Error, CustomNSError, LocalizedError, Equatable {
return "Missing BA Token for PayPal App Switch."
case .missingPayPalRequest:
return "The PayPal Request was missing or invalid."
case .failedToCreateEncodable:
return "Unable to create Encodable object"
richherrera marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
44 changes: 43 additions & 1 deletion Sources/BraintreePayPal/BTPayPalLineItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import Foundation

/// Credit
case credit

var stringValue: String {
switch self {
case .debit:
return "debit"
case .credit:
return "credit"
}
}
}

// swiftlint:disable identifier_name
Expand Down Expand Up @@ -61,7 +70,7 @@ import Foundation
}

/// A PayPal line item to be displayed in the PayPal checkout flow.
@objcMembers public class BTPayPalLineItem: NSObject {
@objcMembers public class BTPayPalLineItem: NSObject, Encodable {

// MARK: - Public Properties

Expand Down Expand Up @@ -114,6 +123,39 @@ import Foundation
self.kind = kind
}

enum CodingKeys: String, CodingKey {
case imageURL = "image_url"
case itemDescription = "description"
case kind
case name
case productCode = "product_code"
case quantity
case unitAmount = "unit_amount"
case unitTaxAmount = "unit_tax_amount"
case upcCode = "upc_code"
case upcType = "upc_type"
case url
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(quantity, forKey: .quantity)
try container.encode(unitAmount, forKey: .unitAmount)
try container.encode(name, forKey: .name)
try container.encode(kind.stringValue, forKey: .kind)

if let unitTaxAmount, !unitTaxAmount.isEmpty {
try container.encode(unitAmount, forKey: .unitTaxAmount)
}

try container.encodeIfPresent(itemDescription, forKey: .itemDescription)
try container.encodeIfPresent(productCode, forKey: .productCode)
try container.encodeIfPresent(url?.absoluteString, forKey: .url)
try container.encodeIfPresent(imageURL?.absoluteString, forKey: .imageURL)
try container.encodeIfPresent(upcCode, forKey: .upcCode)
try container.encodeIfPresent(upcType.stringValue, forKey: .upcType)
}

// MARK: - Internal Methods

/// Returns the line item in a dictionary.
Expand Down
4 changes: 2 additions & 2 deletions Sources/BraintreePayPal/BTPayPalRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ import BraintreeCore
/// - hermesPath: Required :nodoc: The hermes path or endpoint URI path. This property is not covered by semantic versioning.
/// - paymentType: Required :nodoc: The payment type, either checkout or vault. This property is not covered by semantic versioning.
/// - isShippingAddressRequired: Defaults to false. When set to true, the shipping address selector will be displayed.
/// - isShippingAddressEditable: Defaults to false. Set to true to enable user editing of the shipping address.
/// - isShippingAddressEditable: Defaults to false. Set to true to enable user editing of the shipping address.
/// - Note: Only applies when `shippingAddressOverride` is set.
/// - localeCode: Optional: A locale code to use for the transaction.
/// - shippingAddressOverride: Optional: A valid shipping address to be displayed in the transaction flow. An error will occur if this address is not valid.
/// - landingPageType: Optional: Landing page type. Defaults to `.none`.
/// - landingPageType: Optional: Landing page type. Defaults to `.none`.
/// - Note: Setting the BTPayPalRequest's landingPageType changes the PayPal page to display when a user lands on the PayPal site to complete the payment.
/// `.login` specifies a PayPal account login page is used.
/// `.billing` specifies a non-PayPal account landing page is used.
Expand Down
131 changes: 131 additions & 0 deletions Sources/BraintreePayPal/Models/PayPalCheckoutPOSTBody.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import Foundation

#if canImport(BraintreeCore)
import BraintreeCore
#endif

/// The POST body for v1/paypal_hermes/create_payment_resource
struct PayPalCheckoutPOSTBody: Encodable {

// MARK: - Private Properties

private let amount: String
private let intent: String
private let offerPayLater: Bool
private let userPhoneNumber: BTPayPalPhoneNumber?
private let returnURL: String
private let cancelURL: String
private let experienceProfile: PayPalExperienceProfile

private var billingAgreementDescription: BillingAgreemeentDescription?
private var currencyCode: String?
private var lineItems: [BTPayPalLineItem]?
private var merchantAccountID: String?
private var requestBillingAgreement: Bool?
private var riskCorrelationID: String?
private var userAuthenticationEmail: String?

// Address properties
private var streetAddress: String?
private var extendedAddress: String?
private var locality: String?
private var countryCodeAlpha2: String?
private var postalCode: String?
private var region: String?
private var recipientName: String?

// MARK: - Initializer

init(payPalRequest: BTPayPalCheckoutRequest, configuration: BTConfiguration) {
self.amount = payPalRequest.amount
self.intent = payPalRequest.intent.stringValue
self.offerPayLater = payPalRequest.offerPayLater

let currencyIsoCode = payPalRequest.currencyCode != nil ? payPalRequest.currencyCode : configuration.currencyIsoCode

if let currencyIsoCode {
self.currencyCode = currencyIsoCode
}

if payPalRequest.requestBillingAgreement {
self.requestBillingAgreement = payPalRequest.requestBillingAgreement

if let billingAgreementDescription = payPalRequest.billingAgreementDescription {
self.billingAgreementDescription = BillingAgreemeentDescription(description: billingAgreementDescription)
}
}

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
}

if let merchantAccountID = payPalRequest.merchantAccountID {
self.merchantAccountID = merchantAccountID
}

if let riskCorrelationID = payPalRequest.riskCorrelationID {
self.riskCorrelationID = riskCorrelationID
}

if let lineItems = payPalRequest.lineItems, !lineItems.isEmpty {
self.lineItems = lineItems
}

if let userAuthenticationEmail = payPalRequest.userAuthenticationEmail, !userAuthenticationEmail.isEmpty {
self.userAuthenticationEmail = userAuthenticationEmail
}

self.userPhoneNumber = payPalRequest.userPhoneNumber
self.returnURL = BTCoreConstants.callbackURLScheme + "://\(BTPayPalRequest.callbackURLHostAndPath)success"
self.cancelURL = BTCoreConstants.callbackURLScheme + "://\(BTPayPalRequest.callbackURLHostAndPath)cancel"
self.experienceProfile = PayPalExperienceProfile(payPalRequest: payPalRequest, configuration: configuration)
}

enum CodingKeys: String, CodingKey {
case amount
case billingAgreementDescription = "billing_agreement_details"
case cancelURL = "cancel_url"
case currencyCode = "currency_iso_code"
case experienceProfile = "experience_profile"
case intent
case lineItems = "line_items"
case merchantAccountID = "merchant_account_id"
case offerPayLater = "offer_pay_later"
case requestBillingAgreement = "request_billing_agreement"
case returnURL = "return_url"
case riskCorrelationID = "correlation_id"
case userAuthenticationEmail = "payer_email"
case userPhoneNumber = "phone_number"

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

extension PayPalCheckoutPOSTBody {

struct BillingAgreemeentDescription: Encodable {

// MARK: - Private Properties

private let description: String

// MARK: - Initializer

init(description: String) {
self.description = description
}
}
}
Loading
Loading