diff --git a/Braintree.xcodeproj/project.pbxproj b/Braintree.xcodeproj/project.pbxproj index c74c966ff8..73048b300f 100644 --- a/Braintree.xcodeproj/project.pbxproj +++ b/Braintree.xcodeproj/project.pbxproj @@ -290,6 +290,8 @@ BEED3B8C291C56B900BA114B /* BraintreeCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570B93AC285397520041BAFE /* BraintreeCore.framework */; }; BEF1089029019CAE003B2FDA /* BTAnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEE2E4E329007FF100C03FDD /* BTAnalyticsService.swift */; }; BEF1089129019DB9003B2FDA /* BTAPIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 570B93AF2853980C0041BAFE /* BTAPIClient.swift */; }; + BEF177A62B51C7ED004F0F35 /* SEPADebitAccountsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEF177A52B51C7ED004F0F35 /* SEPADebitAccountsRequest.swift */; }; + BEF177A82B51D6A7004F0F35 /* SEPADebitRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEF177A72B51D6A7004F0F35 /* SEPADebitRequest.swift */; }; BEF3F17E27CE9EDF00072467 /* BTSEPADirectDebitClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEF3F17127CE9E6C00072467 /* BTSEPADirectDebitClient.swift */; }; BEF5D2E6294A18B300FFD56D /* BTPayPalLineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEF5D2E5294A18B300FFD56D /* BTPayPalLineItem.swift */; }; BEFD1AF4284F92130070076E /* PPRiskMagnes.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C36BD4226B30AA600F0A559 /* PPRiskMagnes.xcframework */; }; @@ -902,6 +904,8 @@ BEE2E4E5290080BD00C03FDD /* BTAnalyticsServiceError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTAnalyticsServiceError.swift; sourceTree = ""; }; BEEB56582AE9B2A30029F264 /* BTAPIClient_IntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTAPIClient_IntegrationTests.swift; sourceTree = ""; }; BEEB565A2AE9B3030029F264 /* BTIntegrationTestsConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTIntegrationTestsConstants.swift; sourceTree = ""; }; + BEF177A52B51C7ED004F0F35 /* SEPADebitAccountsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEPADebitAccountsRequest.swift; sourceTree = ""; }; + BEF177A72B51D6A7004F0F35 /* SEPADebitRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEPADebitRequest.swift; sourceTree = ""; }; BEF3F17127CE9E6C00072467 /* BTSEPADirectDebitClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTSEPADirectDebitClient.swift; sourceTree = ""; }; BEF3F17C27CE9EC600072467 /* BraintreeSEPADirectDebit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BraintreeSEPADirectDebit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BEF5D2E5294A18B300FFD56D /* BTPayPalLineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalLineItem.swift; sourceTree = ""; }; @@ -1729,6 +1733,8 @@ BE642D8727D0094600694A5B /* BTSEPADirectDebitNonce.swift */, BE642D8527D0047800694A5B /* BTSEPADirectDebitRequest.swift */, BE0B163C27E0CC7400868C77 /* CreateMandateResult.swift */, + BEF177A52B51C7ED004F0F35 /* SEPADebitAccountsRequest.swift */, + BEF177A72B51D6A7004F0F35 /* SEPADebitRequest.swift */, BE0B163E27E0CD7C00868C77 /* SEPADirectDebitAPI.swift */, ); path = BraintreeSEPADirectDebit; @@ -3097,10 +3103,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BEF177A82B51D6A7004F0F35 /* SEPADebitRequest.swift in Sources */, BE642D8827D0094600694A5B /* BTSEPADirectDebitNonce.swift in Sources */, BE642D8A27D00F1300694A5B /* BTSEPADirectDebitMandateType.swift in Sources */, 3BC0E09229E4673C009217D6 /* BTSEPADirectAnalytics.swift in Sources */, BE642D8627D0047800694A5B /* BTSEPADirectDebitRequest.swift in Sources */, + BEF177A62B51C7ED004F0F35 /* SEPADebitAccountsRequest.swift in Sources */, BE0B163D27E0CC7400868C77 /* CreateMandateResult.swift in Sources */, BEF3F17E27CE9EDF00072467 /* BTSEPADirectDebitClient.swift in Sources */, BE0B163F27E0CD7C00868C77 /* SEPADirectDebitAPI.swift in Sources */, diff --git a/Sources/BraintreeSEPADirectDebit/SEPADebitAccountsRequest.swift b/Sources/BraintreeSEPADirectDebit/SEPADebitAccountsRequest.swift new file mode 100644 index 0000000000..9243788b53 --- /dev/null +++ b/Sources/BraintreeSEPADirectDebit/SEPADebitAccountsRequest.swift @@ -0,0 +1,35 @@ +import Foundation + +/// The POST body for `v1/payment_methods/sepa_debit_accounts` +struct SEPADebitAccountsRequest: Encodable { + + private let createMandateResult: SEPADebitAccountRequest + + enum CodingKeys: String, CodingKey { + case createMandateResult = "sepa_debit_account" + } + + struct SEPADebitAccountRequest: Encodable { + + let last4: String? + let merchantOrPartnerCustomerID: String? + let bankReferenceToken: String? + let mandateType: String? + + enum CodingKeys: String, CodingKey { + case last4 = "last_4" + case merchantOrPartnerCustomerID = "merchant_or_partner_customer_id" + case bankReferenceToken = "bank_reference_token" + case mandateType = "mandate_type" + } + } + + init(createMandateResult: CreateMandateResult) { + self.createMandateResult = SEPADebitAccountRequest( + last4: createMandateResult.ibanLastFour, + merchantOrPartnerCustomerID: createMandateResult.customerID, + bankReferenceToken: createMandateResult.bankReferenceToken, + mandateType: createMandateResult.mandateType + ) + } +} diff --git a/Sources/BraintreeSEPADirectDebit/SEPADebitRequest.swift b/Sources/BraintreeSEPADirectDebit/SEPADebitRequest.swift new file mode 100644 index 0000000000..3c143430cd --- /dev/null +++ b/Sources/BraintreeSEPADirectDebit/SEPADebitRequest.swift @@ -0,0 +1,83 @@ +import Foundation + +#if canImport(BraintreeCore) +import BraintreeCore +#endif + +/// The POST body for `v1/sepa_debit` +struct SEPADebitRequest: Encodable { + + let merchantAccountID: String? + let cancelURL: String? + let returnURL: String? + let locale: String? + + private let sepaAccountRequest: SEPAAccountRequest + + enum CodingKeys: String, CodingKey { + case sepaAccountRequest = "sepa_debit" + case merchantAccountID = "merchant_account_id" + case cancelURL = "cancel_url" + case returnURL = "return_url" + case locale = "locale" + } + + struct SEPAAccountRequest: Encodable { + + let merchantOrPartnerCustomerID: String? + let mandateType: String? + let accountHolderName: String? + let iban: String? + let billingAddress: BillingAddress? + + enum CodingKeys: String, CodingKey { + case merchantOrPartnerCustomerID = "merchant_or_partner_customer_id" + case mandateType = "mandate_type" + case accountHolderName = "account_holder_name" + case iban = "iban" + case billingAddress = "billing_address" + } + + struct BillingAddress: Encodable { + + let streetAddress: String? + let extendedAddress: String? + let locality: String? + let region: String? + let postalCode: String? + let countryCodeAlpha2: String? + + enum CodingKeys: String, CodingKey { + case streetAddress = "address_line_1" + case extendedAddress = "address_line_2" + case locality = "admin_area_1" + case region = "admin_area_2" + case postalCode = "postal_code" + case countryCodeAlpha2 = "country_code" + } + } + + init(sepaDirectDebitRequest: BTSEPADirectDebitRequest) { + self.merchantOrPartnerCustomerID = sepaDirectDebitRequest.customerID + 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 + ) + } + } + + init(sepaDirectDebitRequest: BTSEPADirectDebitRequest) { + self.sepaAccountRequest = SEPAAccountRequest(sepaDirectDebitRequest: sepaDirectDebitRequest) + self.merchantAccountID = sepaDirectDebitRequest.merchantAccountID + self.cancelURL = BTCoreConstants.callbackURLScheme + "://sepa/cancel" + self.returnURL = BTCoreConstants.callbackURLScheme + "://sepa/success" + self.locale = sepaDirectDebitRequest.locale + } +} diff --git a/Sources/BraintreeSEPADirectDebit/SEPADirectDebitAPI.swift b/Sources/BraintreeSEPADirectDebit/SEPADirectDebitAPI.swift index 15c60648f2..bf668b03be 100644 --- a/Sources/BraintreeSEPADirectDebit/SEPADirectDebitAPI.swift +++ b/Sources/BraintreeSEPADirectDebit/SEPADirectDebitAPI.swift @@ -17,34 +17,8 @@ class SEPADirectDebitAPI { sepaDirectDebitRequest: BTSEPADirectDebitRequest, completion: @escaping (CreateMandateResult?, Error?) -> Void ) { - let billingAddress = sepaDirectDebitRequest.billingAddress - - let billingAddressDictionary: [String: String?] = [ - "address_line_1": billingAddress?.streetAddress, - "address_line_2": billingAddress?.extendedAddress, - "admin_area_1": billingAddress?.locality, - "admin_area_2": billingAddress?.region, - "postal_code": billingAddress?.postalCode, - "country_code": billingAddress?.countryCodeAlpha2 - ] - - let sepaDebitDictionary: [String: Any] = [ - "merchant_or_partner_customer_id": sepaDirectDebitRequest.customerID ?? "", - "mandate_type": sepaDirectDebitRequest.mandateType?.description ?? "", - "account_holder_name": sepaDirectDebitRequest.accountHolderName ?? "", - "iban": sepaDirectDebitRequest.iban ?? "", - "billing_address": billingAddressDictionary - ] - - let json: [String: Any] = [ - "sepa_debit": sepaDebitDictionary, - "merchant_account_id": sepaDirectDebitRequest.merchantAccountID ?? "", - "cancel_url": BTCoreConstants.callbackURLScheme + "://sepa/cancel", - "return_url": BTCoreConstants.callbackURLScheme + "://sepa/success", - "locale": sepaDirectDebitRequest.locale ?? "" - ] - - apiClient.post("v1/sepa_debit", parameters: json) { body, response, error in + let sepaDebitRequest = SEPADebitRequest(sepaDirectDebitRequest: sepaDirectDebitRequest) + apiClient.post("v1/sepa_debit", parameters: sepaDebitRequest) { body, response, error in if let error = error { completion(nil, error) return @@ -61,16 +35,8 @@ class SEPADirectDebitAPI { } func tokenize(createMandateResult: CreateMandateResult, completion: @escaping (BTSEPADirectDebitNonce?, Error?) -> Void) { - let sepaDebitAccountDictionary: [String: String?] = [ - "last_4": createMandateResult.ibanLastFour, - "merchant_or_partner_customer_id": createMandateResult.customerID, - "bank_reference_token": createMandateResult.bankReferenceToken, - "mandate_type": createMandateResult.mandateType - ] - - let json: [String: Any] = ["sepa_debit_account": sepaDebitAccountDictionary] - - apiClient.post("v1/payment_methods/sepa_debit_accounts", parameters: json) { body, response, error in + let sepaDebitAccountsRequest = SEPADebitAccountsRequest(createMandateResult: createMandateResult) + apiClient.post("v1/payment_methods/sepa_debit_accounts", parameters: sepaDebitAccountsRequest) { body, response, error in if let error = error { completion(nil, error) return