Skip to content

Commit

Permalink
split payment methods per setup mode
Browse files Browse the repository at this point in the history
  • Loading branch information
julienbourdeau committed Feb 24, 2025
1 parent 77bd208 commit ee7b064
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions app/models/payment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def payment_request_succeeded
# payable_type :string default("Invoice"), not null
# payment_type :enum default("provider"), not null
# provider_payment_data :jsonb
# provider_payment_method_data :jsonb not null
# reference :string
# status :string not null
# created_at :datetime not null
Expand Down
8 changes: 7 additions & 1 deletion app/models/payment_provider_customers/stripe_customer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

module PaymentProviderCustomers
class StripeCustomer < BaseCustomer
PAYMENT_METHODS = %w[card sepa_debit us_bank_account bacs_debit link boleto crypto].freeze
PAYMENT_METHODS_WITH_SETUP = %w[card sepa_debit us_bank_account bacs_debit link boleto].freeze
PAYMENT_METHODS_WITHOUT_SETUP = %w[crypto].freeze
PAYMENT_METHODS = (PAYMENT_METHODS_WITH_SETUP + PAYMENT_METHODS_WITHOUT_SETUP).freeze

validates :provider_payment_methods, presence: true
validate :allowed_provider_payment_methods
Expand All @@ -14,6 +16,10 @@ def provider_payment_methods
get_from_settings("provider_payment_methods")
end

def provider_payment_methods_with_setup
provider_payment_methods & PAYMENT_METHODS_WITH_SETUP
end

def provider_payment_methods=(provider_payment_methods)
push_to_settings(key: "provider_payment_methods", value: provider_payment_methods.to_a)
end
Expand Down
9 changes: 8 additions & 1 deletion app/services/payment_provider_customers/stripe_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ def generate_checkout_url(send_webhook: true)
return result unless customer # NOTE: Customer is nil when deleted.
return result if customer.organization.webhook_endpoints.none? && send_webhook && payment_provider(customer)

if stripe_customer.provider_payment_methods_with_setup.blank?
return result.single_validation_failure!(
field: :provider_payment_methods,
error_code: "no_payment_methods_to_setup_available",
)
end

res = ::Stripe::Checkout::Session.create(
checkout_link_params,
{
Expand Down Expand Up @@ -114,7 +121,7 @@ def checkout_link_params
{
success_url: success_redirect_url,
mode: "setup",
payment_method_types: stripe_customer.provider_payment_methods - %w[crypto], # NOTE: crypto doesn't work with setup mode
payment_method_types: stripe_customer.provider_payment_methods_with_setup,
customer: stripe_customer.provider_customer_id
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
end
end

describe "#provider_payment_methods_for_setup" do
it "returns only payment methods that require setup" do
expect(build(:stripe_customer, provider_payment_methods: %w[card]).provider_payment_methods_with_setup).to eq %w[card]
expect(build(:stripe_customer, provider_payment_methods: %w[card crypto]).provider_payment_methods_with_setup).to eq %w[card]
expect(build(:stripe_customer, provider_payment_methods: %w[crypto]).provider_payment_methods_with_setup).to eq []
end
end

describe "validation" do
describe "of provider payment methods" do
subject(:valid) { stripe_customer.valid? }
Expand Down
11 changes: 11 additions & 0 deletions spec/services/payment_provider_customers/stripe_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,17 @@
end
end

context "when customer has no payment method to be setup" do
let(:stripe_customer) { create(:stripe_customer, customer:, provider_customer_id: nil, provider_payment_methods: ::PaymentProviderCustomers::StripeCustomer::PAYMENT_METHODS_WITHOUT_SETUP) }

it "does not deliver a webhook" do
described_class.new(stripe_customer.reload).generate_checkout_url

expect(SendWebhookJob).not_to have_been_enqueued
.with("customer.checkout_url_generated", customer, checkout_url: "https://example.com")
end
end

context "when stripe raises an invalid request error" do
let(:stripe_error) { ::Stripe::InvalidRequestError.new("What is horrible request?!", {}) }

Expand Down

0 comments on commit ee7b064

Please sign in to comment.