diff --git a/client/payment-method-icons/index.js b/client/payment-method-icons/index.js index c0c9c57060..cba34e594e 100644 --- a/client/payment-method-icons/index.js +++ b/client/payment-method-icons/index.js @@ -36,4 +36,5 @@ export default { oxxo: OxxoIcon, wechat_pay: WechatPayIcon, cashapp: CashAppIcon, + us_bank_account: CashAppIcon, }; diff --git a/client/payment-methods-map.js b/client/payment-methods-map.js index 3547955b42..3541314fdb 100644 --- a/client/payment-methods-map.js +++ b/client/payment-methods-map.js @@ -16,6 +16,16 @@ export default { currencies: [], allows_manual_capture: true, }, + us_bank_account: { + id: 'us_bank_account', + label: __( 'ACH Direct Debit', 'woocommerce-gateway-stripe' ), + description: __( + 'ACH lets you accept payments from customers with a US bank account.', + 'woocommerce-gateway-stripe' + ), + Icon: icons.cashapp, + currencies: [ 'USD' ], + }, giropay: { id: 'giropay', label: __( 'giropay', 'woocommerce-gateway-stripe' ), diff --git a/client/stripe-utils/constants.js b/client/stripe-utils/constants.js index 62c7ca2e6d..ad05bc2b44 100644 --- a/client/stripe-utils/constants.js +++ b/client/stripe-utils/constants.js @@ -2,6 +2,7 @@ * Payment method name constants without the `stripe` prefix */ export const PAYMENT_METHOD_CARD = 'card'; +export const PAYMENT_METHOD_ACH = 'us_bank_account'; export const PAYMENT_METHOD_GIROPAY = 'giropay'; export const PAYMENT_METHOD_EPS = 'eps'; export const PAYMENT_METHOD_IDEAL = 'ideal'; @@ -26,6 +27,7 @@ export const PAYMENT_METHOD_LINK = 'link'; * Payment method names constants with the `stripe` prefix */ export const PAYMENT_METHOD_STRIPE_CARD = 'stripe'; +export const PAYMENT_METHOD_STRIPE_ACH = 'stripe_us_bank_account'; export const PAYMENT_METHOD_STRIPE_GIROPAY = 'stripe_giropay'; export const PAYMENT_METHOD_STRIPE_EPS = 'stripe_eps'; export const PAYMENT_METHOD_STRIPE_IDEAL = 'stripe_ideal'; @@ -47,6 +49,7 @@ export const PAYMENT_METHOD_STRIPE_CASHAPP = 'stripe_cashapp'; export function getPaymentMethodsConstants() { return { card: PAYMENT_METHOD_STRIPE_CARD, + us_bank_account: PAYMENT_METHOD_STRIPE_ACH, giropay: PAYMENT_METHOD_STRIPE_GIROPAY, eps: PAYMENT_METHOD_STRIPE_EPS, ideal: PAYMENT_METHOD_STRIPE_IDEAL, diff --git a/includes/class-wc-stripe-intent-controller.php b/includes/class-wc-stripe-intent-controller.php index ccd967cfc9..af4da306c0 100644 --- a/includes/class-wc-stripe-intent-controller.php +++ b/includes/class-wc-stripe-intent-controller.php @@ -243,9 +243,9 @@ public function create_setup_intent() { // 4. Generate the setup intent $setup_intent = WC_Stripe_API::request( [ - 'customer' => $customer->get_id(), - 'confirm' => 'true', - 'payment_method' => $source_id, + 'customer' => $customer->get_id(), + 'confirm' => 'true', + 'payment_method' => $source_id, 'payment_method_types' => [ $source_object->type ], ], 'setup_intents' @@ -950,7 +950,7 @@ private function build_base_payment_intent_request_params( $payment_information */ public function is_mandate_data_required( $selected_payment_type, $is_using_saved_payment_method = false ) { - if ( in_array( $selected_payment_type, [ WC_Stripe_Payment_Methods::SEPA_DEBIT, WC_Stripe_Payment_Methods::BANCONTACT, WC_Stripe_Payment_Methods::IDEAL, WC_Stripe_Payment_Methods::SOFORT, WC_Stripe_Payment_Methods::LINK ], true ) ) { + if ( in_array( $selected_payment_type, [ WC_Stripe_Payment_Methods::ACH, WC_Stripe_Payment_Methods::SEPA_DEBIT, WC_Stripe_Payment_Methods::BANCONTACT, WC_Stripe_Payment_Methods::IDEAL, WC_Stripe_Payment_Methods::SOFORT, WC_Stripe_Payment_Methods::LINK ], true ) ) { return true; } @@ -1121,7 +1121,7 @@ public function confirm_change_payment_from_setup_intent_ajax() { // Check if the subscription has the delayed update all flag and attempt to update all subscriptions after the intent has been confirmed. If successful, display the "updated all subscriptions" notice. if ( WC_Subscriptions_Change_Payment_Gateway::will_subscription_update_all_payment_methods( $subscription ) && WC_Subscriptions_Change_Payment_Gateway::update_all_payment_methods_from_subscription( $subscription, $token->get_gateway_id() ) ) { - $notice = __( 'Payment method updated for all your current subscriptions.', 'woocommerce-gateway-stripe' ); + $notice = __( 'Payment method updated for all your current subscriptions.', 'woocommerce-gateway-stripe' ); } wc_add_notice( $notice ); diff --git a/includes/constants/class-wc-stripe-payment-methods.php b/includes/constants/class-wc-stripe-payment-methods.php index 65d2de25cc..b38501df2b 100644 --- a/includes/constants/class-wc-stripe-payment-methods.php +++ b/includes/constants/class-wc-stripe-payment-methods.php @@ -4,6 +4,8 @@ * Class WC_Stripe_Payment_Methods */ class WC_Stripe_Payment_Methods { + + const ACH = 'us_bank_account'; const AFFIRM = 'affirm'; const AFTERPAY_CLEARPAY = 'afterpay_clearpay'; const ALIPAY = 'alipay'; diff --git a/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php b/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php index c494fef352..9a0567d76b 100644 --- a/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php +++ b/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php @@ -22,6 +22,7 @@ class WC_Stripe_UPE_Payment_Gateway extends WC_Gateway_Stripe { */ const UPE_AVAILABLE_METHODS = [ WC_Stripe_UPE_Payment_Method_CC::class, + WC_Stripe_UPE_Payment_Method_ACH::class, WC_Stripe_UPE_Payment_Method_Alipay::class, WC_Stripe_UPE_Payment_Method_Giropay::class, WC_Stripe_UPE_Payment_Method_Klarna::class, @@ -2079,6 +2080,10 @@ protected function prepare_payment_information_from_request( WC_Order $order ) { 'has_subscription' => $this->has_subscription( $order->get_id() ), ]; + if ( 'us_bank_account' === $selected_payment_type ) { + WC_Stripe_API::attach_payment_method_to_customer( $payment_information['customer'], $payment_method_id ); + } + // Use the dynamic + short statement descriptor if enabled and it's a card payment. $is_short_statement_descriptor_enabled = 'yes' === $this->get_option( 'is_short_statement_descriptor_enabled', 'no' ); if ( WC_Stripe_Payment_Methods::CARD === $selected_payment_type && $is_short_statement_descriptor_enabled ) { diff --git a/includes/payment-methods/class-wc-stripe-upe-payment-method-ach.php b/includes/payment-methods/class-wc-stripe-upe-payment-method-ach.php new file mode 100644 index 0000000000..8a0da4ef59 --- /dev/null +++ b/includes/payment-methods/class-wc-stripe-upe-payment-method-ach.php @@ -0,0 +1,49 @@ +stripe_id = self::STRIPE_ID; + $this->title = __( 'ACH Direct Debit', 'woocommerce-gateway-stripe' ); + $this->is_reusable = false; // Usually ACH requires verification per transaction. + $this->supported_currencies = [ 'USD' ]; + $this->supported_countries = [ 'US' ]; + $this->label = __( 'ACH Direct Debit', 'woocommerce-gateway-stripe' ); + $this->description = __( 'Pay directly from your US bank account via ACH.', 'woocommerce-gateway-stripe' ); + } + + /** + * Checks if ACH is available for the Stripe account's country. + * + * @return bool True if US-based account; false otherwise. + */ + public function is_available_for_account_country() { + return in_array( WC_Stripe::get_instance()->account->get_account_country(), $this->supported_countries, true ); + } + + /** + * Returns string representing payment method type + * to query to retrieve saved payment methods from Stripe. + */ + public function get_retrievable_type() { + return $this->get_id(); + } +} diff --git a/woocommerce-gateway-stripe.php b/woocommerce-gateway-stripe.php index ccaaad0fdc..6a813b78b5 100644 --- a/woocommerce-gateway-stripe.php +++ b/woocommerce-gateway-stripe.php @@ -222,6 +222,7 @@ public function init() { require_once __DIR__ . '/includes/payment-methods/class-wc-stripe-upe-payment-gateway.php'; require_once __DIR__ . '/includes/payment-methods/class-wc-stripe-upe-payment-method.php'; require_once __DIR__ . '/includes/payment-methods/class-wc-stripe-upe-payment-method-cc.php'; + require_once __DIR__ . '/includes/payment-methods/class-wc-stripe-upe-payment-method-ach.php'; require_once __DIR__ . '/includes/payment-methods/class-wc-stripe-upe-payment-method-alipay.php'; require_once __DIR__ . '/includes/payment-methods/class-wc-stripe-upe-payment-method-giropay.php'; require_once __DIR__ . '/includes/payment-methods/class-wc-stripe-upe-payment-method-ideal.php';