Refactor Stripe::PaymentIntentValidator

This makes the interface a lot simpler and moves the fetching of the information it requires inside the service itself.
This commit is contained in:
Matt-Yorkley
2021-06-09 22:14:46 +01:00
parent 9795734dc8
commit e5a85caef6
6 changed files with 30 additions and 25 deletions

View File

@@ -129,8 +129,7 @@ module Spree
payment = fetch_payment(creditcard, gateway_options)
raise Stripe::StripeError, I18n.t(:no_pending_payments) unless payment&.response_code
payment_intent_response = Stripe::PaymentIntentValidator.new.
call(payment.response_code, stripe_account_id)
payment_intent_response = Stripe::PaymentIntentValidator.new.call(payment)
raise_if_not_in_capture_state(payment_intent_response)

View File

@@ -69,16 +69,6 @@ class ProcessPaymentIntent
end
def payment_intent_status
@payment_intent_status ||= Stripe::PaymentIntentValidator.new.
call(payment_intent, stripe_account_id).
status
end
def stripe_account_id
StripeAccount.find_by(enterprise_id: preferred_enterprise_id).stripe_user_id
end
def preferred_enterprise_id
payment.payment_method.preferred_enterprise_id
@payment_intent_status ||= Stripe::PaymentIntentValidator.new.call(payment).status
end
end

View File

@@ -3,9 +3,11 @@
# This class validates if a given payment intent ID is valid in Stripe
module Stripe
class PaymentIntentValidator
def call(payment_intent_id, stripe_account_id)
payment_intent_response = Stripe::PaymentIntent.retrieve(payment_intent_id,
stripe_account: stripe_account_id)
def call(payment)
payment_intent_response = Stripe::PaymentIntent.retrieve(
payment_intent_id(payment),
stripe_account: stripe_account_id(payment)
)
raise_if_last_payment_error_present(payment_intent_response)
@@ -14,6 +16,16 @@ module Stripe
private
def payment_intent_id(payment)
payment.response_code
end
def stripe_account_id(payment)
enterprise_id = payment.payment_method&.preferred_enterprise_id
StripeAccount.find_by(enterprise_id: enterprise_id)&.stripe_user_id
end
def raise_if_last_payment_error_present(payment_intent_response)
return unless payment_intent_response.respond_to?(:last_payment_error) &&
payment_intent_response.last_payment_error.present?

View File

@@ -115,7 +115,7 @@ describe Spree::OrdersController, type: :controller do
before do
allow_any_instance_of(Stripe::PaymentIntentValidator)
.to receive(:call)
.with(payment_intent, kind_of(String))
.with(payment)
.and_return(payment_intent_response)
allow(Spree::Order).to receive(:find_by!) { order }
@@ -161,7 +161,7 @@ describe Spree::OrdersController, type: :controller do
before do
allow_any_instance_of(Stripe::PaymentIntentValidator)
.to receive(:call)
.with(payment_intent, kind_of(String))
.with(payment)
.and_raise(Stripe::StripeError, "error message")
end

View File

@@ -7,13 +7,18 @@ module Stripe
describe PaymentIntentValidator do
describe "#call" do
let(:validator) { Stripe::PaymentIntentValidator.new }
let(:payment) { build(:payment, response_code: payment_intent_id) }
let(:payment_intent_id) { "pi_123" }
let(:stripe_account_id) { "abc123" }
let(:stripe_account_mock) { double(stripe_user_id: stripe_account_id) }
let(:payment_intent_response_mock) { { status: 200, body: payment_intent_response_body } }
before do
Stripe.api_key = "sk_test_12345"
allow(payment).to receive_message_chain(:payment_method, :preferred_enterprise_id) { 1 }
allow(StripeAccount).to receive(:find_by) { stripe_account_mock }
stub_request(:get, "https://api.stripe.com/v1/payment_intents/#{payment_intent_id}")
.with(headers: { 'Stripe-Account' => stripe_account_id })
.to_return(payment_intent_response_mock)
@@ -26,7 +31,7 @@ module Stripe
it "returns payment intent id and does not raise" do
expect {
result = validator.call(payment_intent_id, stripe_account_id)
result = validator.call(payment)
expect(result).to eq payment_intent_response_body
}.to_not raise_error Stripe::StripeError
end
@@ -39,7 +44,7 @@ module Stripe
it "raises Stripe error with payment intent last_payment_error as message" do
expect {
validator.call(payment_intent_id, stripe_account_id)
validator.call(payment)
}.to raise_error Stripe::StripeError, "No money"
end
end

View File

@@ -52,8 +52,7 @@ describe ProcessPaymentIntent do
context "where the stripe payment intent validation responds with errors" do
before do
allow(validator)
.to receive(:call).with(intent, anything).and_raise(Stripe::StripeError,
"error message")
.to receive(:call).with(payment).and_raise(Stripe::StripeError, "error message")
end
it "returns returns the error message" do
@@ -77,7 +76,7 @@ describe ProcessPaymentIntent do
before do
allow(order).to receive(:deliver_order_confirmation_email)
allow(validator).to receive(:call).with(intent, anything).and_return(intent_response)
allow(validator).to receive(:call).with(payment).and_return(intent_response)
end
it "validates the intent" do
@@ -143,7 +142,7 @@ describe ProcessPaymentIntent do
before do
payment.update_attribute(:state, "failed")
allow(validator).to receive(:call).with(intent, anything).and_return(intent)
allow(validator).to receive(:call).with(payment).and_return(intent)
end
it "does not return any error message" do
@@ -166,7 +165,7 @@ describe ProcessPaymentIntent do
before do
allow(order).to receive(:process_payments!) { nil }
allow(validator).to receive(:call).with(intent, anything).and_return(intent_response)
allow(validator).to receive(:call).with(payment).and_return(intent_response)
end
it "returns a failed result" do