From 404e7c1f37127070f5cbf151cc6694c54e316ae1 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Tue, 28 Jan 2020 12:10:03 +0000 Subject: [PATCH] Make credit card cloner clone the payment method even if the customer is not given This makes the payments without saving card work again in the frontoffice as well as the payments taken by the seller in the backoffice --- lib/stripe/credit_card_cloner.rb | 12 ++++------ spec/lib/stripe/credit_card_cloner_spec.rb | 28 ++++++++++++++-------- spec/requests/checkout/stripe_sca_spec.rb | 12 +++++++++- 3 files changed, 34 insertions(+), 18 deletions(-) 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