From e1846b1030e7e4b58743eb04ca2d85896150d7c0 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Thu, 10 Jun 2021 10:45:41 +0100 Subject: [PATCH] Extract Stripe payment helper methods to a service --- app/models/spree/payment.rb | 19 ------- app/services/stripe_payment_status.rb | 32 ++++++++++++ spec/services/stripe_payment_status_spec.rb | 55 +++++++++++++++++++++ 3 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 app/services/stripe_payment_status.rb create mode 100644 spec/services/stripe_payment_status_spec.rb diff --git a/app/models/spree/payment.rb b/app/models/spree/payment.rb index 3ec6743e02..3bb4b60858 100644 --- a/app/models/spree/payment.rb +++ b/app/models/spree/payment.rb @@ -153,25 +153,6 @@ module Spree I18n.t('payment_method_fee') end - # Returns the current payment status from a live call to the Stripe API. - # Returns nil if the payment is not a Stripe payment or does not have a payment intent. - # If the payment requires authorization the status will be "requires_action". - # If the payment has been captured the status will be "succeeded". - # https://stripe.com/docs/api/payment_intents/object#payment_intent_object-status - def stripe_status - return if response_code.blank? - - Stripe::PaymentIntentValidator.new.call(self).status - rescue Stripe::StripeError - # The Stripe::PaymentIntentValidator will raise an error if the Stripe API call indicates - # the last attempted action on the payment intent failed. - "failed" - end - - def stripe_captured? - stripe_status == "succeeded" - end - def clear_authorization_url update_attribute(:cvv_response_message, nil) end diff --git a/app/services/stripe_payment_status.rb b/app/services/stripe_payment_status.rb new file mode 100644 index 0000000000..49f5c998ac --- /dev/null +++ b/app/services/stripe_payment_status.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class StripePaymentStatus + def initialize(payment) + @payment = payment + end + + # Returns the current payment status from a live call to the Stripe API. + # Returns nil if the payment is not a Stripe payment or does not have a payment intent. + # If the payment requires authorization the status will be "requires_action". + # If the payment has been captured the status will be "succeeded". + # Docs: https://stripe.com/docs/api/payment_intents/object#payment_intent_object-status + def stripe_status + return if payment.response_code.blank? + + Stripe::PaymentIntentValidator.new.call(self).status + rescue Stripe::StripeError + # Stripe::PaymentIntentValidator will raise an error if the response from the Stripe API + # call indicates the last attempted action on the payment intent failed. + "failed" + end + + # If the payment is a Stripe payment and has been captured in the associated Stripe account, + # returns true, otherwise false. + def stripe_captured? + stripe_status == "succeeded" + end + + private + + attr_reader :payment +end diff --git a/spec/services/stripe_payment_status_spec.rb b/spec/services/stripe_payment_status_spec.rb new file mode 100644 index 0000000000..912c87e213 --- /dev/null +++ b/spec/services/stripe_payment_status_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe StripePaymentStatus do + subject { StripePaymentStatus.new(payment) } + let(:payment) { build(:payment) } + + describe '#stripe_status' do + context "when the payment is not a Stripe payment or does not have a payment intent" do + it "returns nil" do + expect(subject.stripe_status).to be_nil + end + end + + context "when the payment has a payment intent" do + before { allow(payment).to receive(:response_code) { "pi_1234" } } + + it "fetches the status with Stripe::PaymentIntentValidator" do + expect(Stripe::PaymentIntentValidator). + to receive_message_chain(:new, :call, :status) { true } + + subject.stripe_status + end + + context "and the last action on the Stripe payment failed" do + it "returns failed response" do + allow(Stripe::PaymentIntentValidator). + to receive_message_chain(:new, :call, :status).and_raise(Stripe::StripeError) + + expect(subject.stripe_status).to eq "failed" + end + end + end + end + + describe '#stripe_captured?' do + context "when the payment is not a Stripe payment or does not have a payment intent" do + it "returns false" do + expect(subject.stripe_captured?).to eq false + end + end + + context "when the Stripe payment has been captured" do + before { allow(payment).to receive(:response_code) { "pi_1234" } } + + it "returns true" do + allow(Stripe::PaymentIntentValidator). + to receive_message_chain(:new, :call, :status) { "succeeded" } + + expect(subject.stripe_captured?).to eq true + end + end + end +end