-
-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45 from spaghetticode/payment-intents-single-payment
Create a single charge when using Stripe Payment Intents
- Loading branch information
Showing
8 changed files
with
290 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
app/decorators/models/spree/order_update_attributes_decorator.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree | ||
module OrderUpdateAttributesDecorator | ||
def assign_payments_attributes | ||
return if payments_attributes.empty? | ||
return if adding_new_stripe_payment_intents_card? | ||
|
||
stripe_intents_pending_payments.each(&:void_transaction!) | ||
|
||
super | ||
end | ||
|
||
private | ||
|
||
def adding_new_stripe_payment_intents_card? | ||
paying_with_stripe_intents? && stripe_intents_pending_payments.any? | ||
end | ||
|
||
def stripe_intents_pending_payments | ||
@stripe_intents_pending_payments ||= order.payments.valid.select do |payment| | ||
payment_method = payment.payment_method | ||
payment.pending? && stripe_intents?(payment_method) | ||
end | ||
end | ||
|
||
def paying_with_stripe_intents? | ||
if id = payments_attributes.first&.dig(:payment_method_id) | ||
stripe_intents?(Spree::PaymentMethod.find(id)) | ||
end | ||
end | ||
|
||
def stripe_intents?(payment_method) | ||
payment_method.respond_to?(:v3_intents?) && payment_method.v3_intents? | ||
end | ||
|
||
::Spree::OrderUpdateAttributes.prepend(self) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree | ||
module PaymentDecorator | ||
def gateway_order_identifier | ||
gateway_order_id | ||
end | ||
|
||
::Spree::Payment.prepend(self) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# frozen_string_literal: true | ||
|
||
module SolidusStripe | ||
class CreateIntentsOrderService | ||
attr_reader :intent, :stripe, :controller | ||
|
||
delegate :request, :current_order, :params, to: :controller | ||
|
||
def initialize(intent, stripe, controller) | ||
@intent, @stripe, @controller = intent, stripe, controller | ||
end | ||
|
||
def call | ||
invalidate_previous_payment_intents_payments | ||
payment = create_payment | ||
description = "Solidus Order ID: #{payment.gateway_order_identifier}" | ||
stripe.update_intent(nil, response['id'], nil, description: description) | ||
end | ||
|
||
private | ||
|
||
def invalidate_previous_payment_intents_payments | ||
if stripe.v3_intents? | ||
current_order.payments.pending.where(payment_method: stripe).each(&:void_transaction!) | ||
end | ||
end | ||
|
||
def create_payment | ||
Spree::OrderUpdateAttributes.new( | ||
current_order, | ||
payment_params, | ||
request_env: request.headers.env | ||
).apply | ||
|
||
Spree::Payment.find_by(response_code: response['id']).tap do |payment| | ||
payment.update!(state: :pending) | ||
end | ||
end | ||
|
||
def payment_params | ||
card = response['charges']['data'][0]['payment_method_details']['card'] | ||
address_attributes = form_data['payment_source'][stripe.id.to_s]['address_attributes'] | ||
|
||
{ | ||
payments_attributes: [{ | ||
payment_method_id: stripe.id, | ||
amount: current_order.total, | ||
response_code: response['id'], | ||
source_attributes: { | ||
month: card['exp_month'], | ||
year: card['exp_year'], | ||
cc_type: card['brand'], | ||
gateway_payment_profile_id: response['payment_method'], | ||
last_digits: card['last4'], | ||
name: current_order.bill_address.full_name, | ||
address_attributes: address_attributes | ||
} | ||
}] | ||
} | ||
end | ||
|
||
def response | ||
intent.params | ||
end | ||
|
||
def form_data | ||
Rack::Utils.parse_nested_query(params[:form_data]) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.