Skip to content

Commit

Permalink
allow manual passing of bank account info
Browse files Browse the repository at this point in the history
  • Loading branch information
charliecruzan-stripe committed Mar 31, 2022
1 parent d81f48a commit 9115057
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 47 deletions.
16 changes: 16 additions & 0 deletions ios/Mappers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,14 @@ class Mappers {
}
return "Unknown"
}

class func mapToUSBankAccountHolderType(type: String?) -> STPPaymentMethodUSBankAccountHolderType {
switch type {
case "Company": return STPPaymentMethodUSBankAccountHolderType.company
case "Individual": return STPPaymentMethodUSBankAccountHolderType.individual
default: return STPPaymentMethodUSBankAccountHolderType.individual
}
}

class func mapFromUSBankAccountType(type: STPPaymentMethodUSBankAccountType?) -> String {
if let type = type {
Expand All @@ -940,4 +948,12 @@ class Mappers {
}
return "Unknown"
}

class func mapToUSBankAccountType(type: String?) -> STPPaymentMethodUSBankAccountType {
switch type {
case "Savings": return STPPaymentMethodUSBankAccountType.savings
case "Checking": return STPPaymentMethodUSBankAccountType.checking
default: return STPPaymentMethodUSBankAccountType.checking
}
}
}
44 changes: 42 additions & 2 deletions ios/PaymentMethodFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class PaymentMethodFactory {
case STPPaymentMethodType.klarna:
return try createKlarnaPaymentMethodParams()
case STPPaymentMethodType.USBankAccount:
return nil
return try createUSBankAccountPaymentMethodParams()
// case STPPaymentMethodType.weChatPay:
// return try createWeChatPayPaymentMethodParams()
default:
Expand Down Expand Up @@ -95,7 +95,7 @@ class PaymentMethodFactory {
case STPPaymentMethodType.weChatPay:
return try createWeChatPayPaymentMethodOptions()
case STPPaymentMethodType.USBankAccount:
return nil
return try createUSBankAccountPaymentMethodOptions()
default:
throw PaymentMethodError.paymentNotSupported
}
Expand All @@ -110,6 +110,15 @@ class PaymentMethodFactory {
// }
//

private func createUSBankAccountPaymentMethodOptions() throws -> STPConfirmPaymentMethodOptions {
let paymentOptions = STPConfirmPaymentMethodOptions()
if let usage = self.params?["setupFutureUsage"] as? String {
paymentOptions.usBankAccountOptions = STPConfirmUSBankAccountOptions(setupFutureUsage: Mappers.mapToPaymentIntentFutureUsage(usage: usage))
}

return paymentOptions
}

private func createWeChatPayPaymentMethodOptions() throws -> STPConfirmPaymentMethodOptions {
guard let appId = self.params?["appId"] as? String else {
throw PaymentMethodError.weChatPayPaymentMissingParams
Expand Down Expand Up @@ -319,6 +328,28 @@ class PaymentMethodFactory {
throw PaymentMethodError.klarnaPaymentMissingParams
}
}

private func createUSBankAccountPaymentMethodParams() throws -> STPPaymentMethodParams {
let params = STPPaymentMethodUSBankAccountParams()

guard let accountNumber = self.params?["accountNumber"] as? String else {
throw PaymentMethodError.usBankAccountPaymentMissingAccountNumber
}
guard let routingNumber = self.params?["routingNumber"] as? String else {
throw PaymentMethodError.usBankAccountPaymentMissingRoutingNumber
}

params.accountNumber = accountNumber
params.routingNumber = routingNumber
params.accountHolderType = Mappers.mapToUSBankAccountHolderType(type: self.params?["accountHolderType"] as? String)
params.accountType = Mappers.mapToUSBankAccountType(type: self.params?["accountType"] as? String)

if let billingDetails = billingDetailsParams, billingDetails.name != nil {
return STPPaymentMethodParams(usBankAccount: params, billingDetails: billingDetails, metadata: nil)
} else {
throw PaymentMethodError.usBankAccountPaymentMissingParams
}
}
}

enum PaymentMethodError: Error {
Expand All @@ -335,6 +366,9 @@ enum PaymentMethodError: Error {
case afterpayClearpayPaymentMissingParams
case klarnaPaymentMissingParams
case weChatPayPaymentMissingParams
case usBankAccountPaymentMissingParams
case usBankAccountPaymentMissingAccountNumber
case usBankAccountPaymentMissingRoutingNumber
}

extension PaymentMethodError: LocalizedError {
Expand Down Expand Up @@ -366,6 +400,12 @@ extension PaymentMethodError: LocalizedError {
return NSLocalizedString("You must provide appId", comment: "Create payment error")
case .klarnaPaymentMissingParams:
return NSLocalizedString("Klarna requires that you provide the following billing details: email, country", comment: "Create payment error")
case .usBankAccountPaymentMissingParams:
return NSLocalizedString("When creating a US bank account payment method, you must provide the following billing details: name", comment: "Create payment error")
case .usBankAccountPaymentMissingAccountNumber:
return NSLocalizedString("When creating a US bank account payment method, you must provide the bank account number", comment: "Create payment error")
case .usBankAccountPaymentMissingRoutingNumber:
return NSLocalizedString("When creating a US bank account payment method, you must provide the bank routing number", comment: "Create payment error")
}
}
}
102 changes: 58 additions & 44 deletions ios/StripeSdk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,27 +268,30 @@ class StripeSdk: RCTEventEmitter, STPApplePayContextDelegate, STPBankSelectionVi
resolve(Errors.createError(ErrorType.Failed, "You must provide paymentMethodType"))
return
}
var paymentMethodParams: STPPaymentMethodParams?
let factory = PaymentMethodFactory.init(params: params, cardFieldView: cardFieldView, cardFormView: cardFormView)

do {
paymentMethodParams = try factory.createParams(paymentMethodType: paymentMethodType)
} catch {
resolve(Errors.createError(ErrorType.Failed, error.localizedDescription))
return
}

var err: NSDictionary? = nil
let setupIntentParams: STPSetupIntentConfirmParams = {
switch paymentMethodType {
case .USBankAccount:
if (paymentMethodType == .USBankAccount && params["accountNumber"] == nil) { // Payment method is assumed to be already attached
return STPSetupIntentConfirmParams(clientSecret: setupIntentClientSecret, paymentMethodType: .USBankAccount)
default:
return STPSetupIntentConfirmParams(clientSecret: setupIntentClientSecret)
} else {
let parameters = STPSetupIntentConfirmParams(clientSecret: setupIntentClientSecret)
let factory = PaymentMethodFactory.init(params: params, cardFieldView: cardFieldView, cardFormView: cardFormView)
do {
let paymentMethodParams = try factory.createParams(paymentMethodType: paymentMethodType)
parameters.paymentMethodParams = paymentMethodParams
} catch {
err = Errors.createError(ErrorType.Failed, error as NSError?)
}

return parameters
}
}()

setupIntentParams.paymentMethodParams = paymentMethodParams

if (err != nil) {
resolve(err)
return
}

if let urlScheme = urlScheme {
setupIntentParams.returnURL = Mappers.mapToReturnURL(urlScheme: urlScheme)
}
Expand Down Expand Up @@ -780,46 +783,57 @@ class StripeSdk: RCTEventEmitter, STPApplePayContextDelegate, STPBankSelectionVi
return
}
}


let (error, paymentIntentParams) = createPaymentIntentParams(paymentIntentClientSecret: paymentIntentClientSecret, paymentMethodType: paymentMethodType, params: params, options: options)

if (error != nil) {
resolve(error)
} else {
STPPaymentHandler.shared().confirmPayment(paymentIntentParams, with: self, completion: onCompleteConfirmPayment)
}
}

func createPaymentIntentParams(
paymentIntentClientSecret: String,
paymentMethodType: STPPaymentMethodType,
params: NSDictionary,
options: NSDictionary
) -> (NSDictionary?, STPPaymentIntentParams) {
let factory = PaymentMethodFactory.init(params: params, cardFieldView: cardFieldView, cardFormView: cardFormView)
var err: NSDictionary? = nil

let paymentIntentParams: STPPaymentIntentParams = {
switch paymentMethodType {
case .USBankAccount:
if (paymentMethodType == .USBankAccount && params["accountNumber"] == nil) { // Payment method is assumed to be already attached
return STPPaymentIntentParams(clientSecret: paymentIntentClientSecret, paymentMethodType: .USBankAccount)
default:
return STPPaymentIntentParams(clientSecret: paymentIntentClientSecret)
} else {
let paymentMethodId = params["paymentMethodId"] as? String
let parameters = STPPaymentIntentParams(clientSecret: paymentIntentClientSecret)

if paymentMethodId != nil {
parameters.paymentMethodId = paymentMethodId
} else {
do {
let paymentMethodParams = try factory.createParams(paymentMethodType: paymentMethodType)
let paymentMethodOptions = try factory.createOptions(paymentMethodType: paymentMethodType)
parameters.paymentMethodParams = paymentMethodParams
parameters.paymentMethodOptions = paymentMethodOptions
} catch {
err = Errors.createError(ErrorType.Failed, error as NSError?)
}
}
return parameters
}
}()

let paymentMethodId = params["paymentMethodId"] as? String
if let setupFutureUsage = params["setupFutureUsage"] as? String {
paymentIntentParams.setupFutureUsage = Mappers.mapToPaymentIntentFutureUsage(usage: setupFutureUsage)
}

if paymentMethodId != nil {
paymentIntentParams.paymentMethodId = paymentMethodId
} else {
var paymentMethodParams: STPPaymentMethodParams?
var paymentMethodOptions: STPConfirmPaymentMethodOptions?
let factory = PaymentMethodFactory.init(params: params, cardFieldView: cardFieldView, cardFormView: cardFormView)

do {
paymentMethodParams = try factory.createParams(paymentMethodType: paymentMethodType)
paymentMethodOptions = try factory.createOptions(paymentMethodType: paymentMethodType)
} catch {
resolve(Errors.createError(ErrorType.Failed, error.localizedDescription))
return
}
paymentIntentParams.paymentMethodParams = paymentMethodParams
paymentIntentParams.paymentMethodOptions = paymentMethodOptions
paymentIntentParams.shipping = Mappers.mapToShippingDetails(shippingDetails: params["shippingDetails"] as? NSDictionary)
}

if let urlScheme = urlScheme {
if let urlScheme = urlScheme {
paymentIntentParams.returnURL = Mappers.mapToReturnURL(urlScheme: urlScheme)
}
paymentIntentParams.shipping = Mappers.mapToShippingDetails(shippingDetails: params["shippingDetails"] as? NSDictionary)

let paymentHandler = STPPaymentHandler.shared()
paymentHandler.confirmPayment(paymentIntentParams, with: self, completion: onCompleteConfirmPayment)
return (err, paymentIntentParams)
}

@objc(retrievePaymentIntent:resolver:rejecter:)
Expand Down
12 changes: 11 additions & 1 deletion src/types/PaymentMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,19 @@ export namespace PaymentMethodCreateParams {
formDetails: AuBECSDebitFormComponent.FormDetails;
}

/** Before using this payment method type, ensure you have already collected the account information for this intent with `collectUSBankAccount`. */
/** Before using this payment method type, ensure you have already collected the bank information
* for this intent with `collectBankAccountForPayment`. Otherwise, you will need to pass in the bank account
* details manually.*/
export type USBankAccountParams = {
type: 'USBankAccount';
billingDetails?: Pick<Required<BillingDetails>, 'name'> & BillingDetails;
accountNumber?: string;
routingNumber?: string;
/** Defaults to Individual */
accountHolderType?: BankAcccountHolderType;
/** Defaults to Checking */
accountType?: BankAcccountType;
setupFutureUsage?: PaymentIntents.FutureUsage;
};
}

Expand Down

0 comments on commit 9115057

Please sign in to comment.