diff --git a/lib/stripe/credit_card_cloner.rb b/lib/stripe/credit_card_cloner.rb index d760ee52a0..64b67b5345 100644 --- a/lib/stripe/credit_card_cloner.rb +++ b/lib/stripe/credit_card_cloner.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true # Here we clone -# - a card (card_*) or payment_method (pm_*) stored in a customer in a platform account +# - a card (card_*) or payment_method (pm_*) stored (in a customer) in a platform account # into -# - a payment method (pm_*) in a new customer in a connected account +# - a payment method (pm_*) (in a new customer) in a connected account # # This is required when using the Stripe Payment Intents API: # - the customer and payment methods are stored in the platform account @@ -18,13 +18,11 @@ module Stripe class CreditCardCloner def clone(credit_card, connected_account_id) - # No need to clone the card if there's no customer, i.e., it's a card for one time usage - if credit_card.gateway_customer_profile_id.blank? - return nil, credit_card.gateway_payment_profile_id - end - new_payment_method = clone_payment_method(credit_card, connected_account_id) + # If no customer is given, it will clone the payment method only + return nil, new_payment_method.id if credit_card.gateway_customer_profile_id.blank? + new_customer = Stripe::Customer.create({ email: credit_card.user.email }, stripe_account: connected_account_id) attach_payment_method_to_customer(new_payment_method.id, diff --git a/spec/lib/stripe/credit_card_cloner_spec.rb b/spec/lib/stripe/credit_card_cloner_spec.rb index 4158a78192..40854560d6 100644 --- a/spec/lib/stripe/credit_card_cloner_spec.rb +++ b/spec/lib/stripe/credit_card_cloner_spec.rb @@ -28,17 +28,13 @@ module Stripe before do allow(Stripe).to receive(:api_key) { "sk_test_12345" } - stub_request(:post, "https://api.stripe.com/v1/payment_methods") - .with(body: { customer: customer_id, payment_method: payment_method_id}, - headers: { 'Stripe-Account' => stripe_account_id }) - .to_return(payment_method_response_mock) - stub_request(:post, "https://api.stripe.com/v1/customers") .with(body: { email: credit_card.user.email }, headers: { 'Stripe-Account' => stripe_account_id }) .to_return(customer_response_mock) - stub_request(:post, "https://api.stripe.com/v1/payment_methods/#{new_payment_method_id}/attach") + stub_request(:post, + "https://api.stripe.com/v1/payment_methods/#{new_payment_method_id}/attach") .with(body: { customer: new_customer_id }, headers: { 'Stripe-Account' => stripe_account_id }) .to_return(payment_method_response_mock) @@ -47,24 +43,36 @@ module Stripe end context "when called with a card without a customer (one time usage card)" do - it "returns a nil customer and the given payment id" do + before do + stub_request(:post, "https://api.stripe.com/v1/payment_methods") + .with(body: { payment_method: payment_method_id }, + headers: { 'Stripe-Account' => stripe_account_id }) + .to_return(payment_method_response_mock) + end + + it "clones the payment method only" do customer_id, payment_method_id = cloner.clone(credit_card, stripe_account_id) + expect(payment_method_id).to eq new_payment_method_id expect(customer_id).to eq nil - expect(payment_method_id).to eq payment_method_id end end context "when called with a valid customer and payment_method" do before do + stub_request(:post, "https://api.stripe.com/v1/payment_methods") + .with(body: { customer: customer_id, payment_method: payment_method_id }, + headers: { 'Stripe-Account' => stripe_account_id }) + .to_return(payment_method_response_mock) + credit_card.update_attribute :gateway_customer_profile_id, customer_id end - it "clones the card successefully" do + it "clones both the payment method and the customer" do customer_id, payment_method_id = cloner.clone(credit_card, stripe_account_id) - expect(customer_id).to eq new_customer_id expect(payment_method_id).to eq new_payment_method_id + expect(customer_id).to eq new_customer_id end end end diff --git a/spec/requests/checkout/stripe_sca_spec.rb b/spec/requests/checkout/stripe_sca_spec.rb index 4dcccf5c03..9c8f3d1b96 100644 --- a/spec/requests/checkout/stripe_sca_spec.rb +++ b/spec/requests/checkout/stripe_sca_spec.rb @@ -75,10 +75,20 @@ describe "checking out an order with a Stripe SCA payment method", type: :reques end context "when the user submits a new card and doesn't request that the card is saved for later" do + let(:hubs_payment_method_response_mock) do + { status: 200, body: JSON.generate(id: hubs_stripe_payment_method) } + end + before do + # Clones the payment method to the hub's stripe account + stub_request(:post, "https://api.stripe.com/v1/payment_methods") + .with(body: { payment_method: stripe_payment_method }, + headers: { 'Stripe-Account' => 'abc123' }) + .to_return(hubs_payment_method_response_mock) + # Charges the card stub_request(:post, "https://api.stripe.com/v1/payment_intents") - .with(basic_auth: ["sk_test_12345", ""], body: /#{stripe_payment_method}.*#{order.number}/) + .with(basic_auth: ["sk_test_12345", ""], body: /#{hubs_stripe_payment_method}.*#{order.number}/) .to_return(payment_intent_response_mock) end