mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #6808 from andrewpbrett/authorize-payment-links
Allow a customer to perform further action for a Stripe payment if needed (#4181)
This commit is contained in:
@@ -27,6 +27,7 @@ module Spree
|
||||
def show
|
||||
@order = Spree::Order.find_by!(number: params[:id])
|
||||
ProcessPaymentIntent.new(params["payment_intent"], @order).call!
|
||||
@order.reload
|
||||
end
|
||||
|
||||
def empty
|
||||
|
||||
@@ -16,7 +16,7 @@ module Api
|
||||
end
|
||||
|
||||
def payments
|
||||
object.payments.joins(:payment_method).completed
|
||||
object.payments.joins(:payment_method).where('state IN (?)', %w(completed pending))
|
||||
end
|
||||
|
||||
def shop_id
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module Api
|
||||
class PaymentSerializer < ActiveModel::Serializer
|
||||
attributes :amount, :updated_at, :payment_method, :state
|
||||
attributes :amount, :updated_at, :payment_method, :state, :cvv_response_message
|
||||
|
||||
def payment_method
|
||||
object.payment_method.try(:name)
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# When directing a customer to Stripe to authorize the payment, we specify a
|
||||
# redirect_url that Stripe should return them to. When checking out, it's
|
||||
# /checkout; for admin payments and subscription payemnts it's the order url.
|
||||
# This class confirms that the payment intent matches what's in our database,
|
||||
# marks the payment as complete, and removes the cvv_response_message field,
|
||||
# which we use to indicate that authorization is required. It also completes the
|
||||
# Order, if appropriate.
|
||||
|
||||
class ProcessPaymentIntent
|
||||
def initialize(payment_intent, order)
|
||||
@payment_intent = payment_intent
|
||||
@@ -11,7 +19,8 @@ class ProcessPaymentIntent
|
||||
return unless valid?
|
||||
|
||||
last_payment.update_attribute(:cvv_response_message, nil)
|
||||
last_payment.complete!
|
||||
OrderWorkflow.new(@order).next
|
||||
last_payment.complete! if !last_payment.completed?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
%td.order3.show-for-large-up
|
||||
%i{"ng-class" => "{'ofn-i_012-warning': payment.state == 'invalid' || payment.state == 'void' || payment.state == 'failed'}"}
|
||||
%span{"ng-bind" => "::'spree.payment_states.' + payment.state | t | capitalize"}
|
||||
%span{"ng-if" => "payment.cvv_response_message.length > 0" }
|
||||
%a{"ng-href" => "{{payment.cvv_response_message}}", "ng-bind" => "::'spree.payment_states.authorise' | t | capitalize" }
|
||||
%td.order4.show-for-large-up
|
||||
%td.order5.text-right{"ng-class" => "{'credit' : payment.amount > 0, 'debit' : payment.amount < 0, 'paid' : payment.amount == 0}","ng-bind" => "::payment.amount | localizeCurrency"}
|
||||
%td.order6.show-for-large-up
|
||||
|
||||
@@ -3621,6 +3621,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
processing: processing
|
||||
void: void
|
||||
invalid: invalid
|
||||
authorise: authorise
|
||||
order_mailer:
|
||||
cancel_email:
|
||||
customer_greeting: "Dear %{name},"
|
||||
|
||||
@@ -79,6 +79,50 @@ describe Spree::OrdersController, type: :controller do
|
||||
end
|
||||
end
|
||||
|
||||
describe "confirming a payment intent" do
|
||||
let(:customer) { create(:customer) }
|
||||
let(:order) { create(:order, customer: customer, distributor: customer.enterprise) }
|
||||
let!(:payment) { create(
|
||||
:payment,
|
||||
cvv_response_message: "https://stripe.com/redirect",
|
||||
response_code: "pi_123",
|
||||
order: order,
|
||||
state: "pending")
|
||||
}
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { current_user }
|
||||
end
|
||||
|
||||
context "after returning from Stripe to authorize a payment" do
|
||||
let(:current_user) { order.user }
|
||||
|
||||
context "with a valid payment intent" do
|
||||
let(:payment_intent) { "pi_123" }
|
||||
|
||||
it "completes the payment" do
|
||||
get :show, id: order.number, payment_intent: payment_intent
|
||||
expect(response).to be_success
|
||||
payment.reload
|
||||
expect(payment.cvv_response_message).to be nil
|
||||
expect(payment.state).to eq("completed")
|
||||
end
|
||||
end
|
||||
|
||||
context "with an invalid payment intent" do
|
||||
let(:payment_intent) { "invalid" }
|
||||
|
||||
it "does not complete the payment" do
|
||||
get :show, id: order.number, payment_intent: payment_intent
|
||||
expect(response).to be_success
|
||||
payment.reload
|
||||
expect(payment.cvv_response_message).to eq("https://stripe.com/redirect")
|
||||
expect(payment.state).to eq("pending")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "viewing cart" do
|
||||
it "redirects home when no distributor is selected" do
|
||||
get :edit
|
||||
|
||||
51
spec/services/process_payment_intent_spec.rb
Normal file
51
spec/services/process_payment_intent_spec.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe ProcessPaymentIntent do
|
||||
let(:service) { described_class.new }
|
||||
|
||||
describe "processing a payment intent" do
|
||||
let(:customer) { create(:customer) }
|
||||
let(:order) { create(:order, customer: customer, distributor: customer.enterprise, state: "payment") }
|
||||
let!(:payment) { create(
|
||||
:payment,
|
||||
cvv_response_message: "https://stripe.com/redirect",
|
||||
response_code: "pi_123",
|
||||
order: order,
|
||||
state: "pending")
|
||||
}
|
||||
|
||||
context "an invalid intent" do
|
||||
let(:invalid_intent) { "invalid" }
|
||||
let(:service) { ProcessPaymentIntent.new(invalid_intent, order) }
|
||||
|
||||
it "does not complete the payment" do
|
||||
service.call!
|
||||
expect(payment.reload.state).to eq("pending")
|
||||
end
|
||||
end
|
||||
|
||||
context "a valid intent" do
|
||||
let(:valid_intent) { "pi_123" }
|
||||
let(:service) { ProcessPaymentIntent.new(valid_intent, order) }
|
||||
|
||||
before do
|
||||
allow(order).to receive(:deliver_order_confirmation_email)
|
||||
end
|
||||
|
||||
it "completes the payment" do
|
||||
service.call!
|
||||
payment.reload
|
||||
expect(payment.state).to eq("completed")
|
||||
expect(payment.cvv_response_message).to be nil
|
||||
end
|
||||
|
||||
it "completes the order" do
|
||||
service.call!
|
||||
expect(order.state).to eq("complete")
|
||||
expect(order).to have_received(:deliver_order_confirmation_email)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user