Add new payment method StripeSCA that will use the Stripe Payment Intents API instead of the Stripe Charges API that the current StripeConnect gatreway uses

This commit is contained in:
luisramos0
2020-01-13 17:27:17 +00:00
committed by Luis Ramos
parent 5724c3bb0a
commit f691d1aafd
6 changed files with 127 additions and 7 deletions

View File

@@ -7,6 +7,8 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
purchase: ->
if @paymentMethod()?.method_type == 'stripe' && !@secrets.selected_card
StripeElements.requestToken(@secrets, @submit)
else if @paymentMethod()?.method_type == 'stripe_sca' && !@secrets.selected_card
StripeElements.createPaymentMethod(@secrets, @submit)
else
@submit()
@@ -59,7 +61,7 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
last_name: @order.bill_address.lastname
}
if @paymentMethod()?.method_type == 'stripe'
if @paymentMethod()?.method_type == 'stripe' || @paymentMethod()?.method_type == 'stripe_sca'
if @secrets.selected_card
angular.extend munged_order, {
existing_card_id: @secrets.selected_card

View File

@@ -1,12 +1,10 @@
Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
new class StripeElements
# TODO: add locale here for translations of error messages etc. from Stripe
# These are both set from the StripeElements directive
stripe: null
card: null
# New Stripe Elements method
# Create Token to be used with the Stripe Charges API
requestToken: (secrets, submit, loading_message = t("processing_payment")) ->
return unless @stripe? && @card?
@@ -23,6 +21,24 @@ Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
secrets.card = response.token.card
submit()
# Create Payment Method to be used with the Stripe Payment Intents API
createPaymentMethod: (secrets, submit, loading_message = t("processing_payment")) ->
return unless @stripe? && @card?
Loading.message = loading_message
cardData = @makeCardData(secrets)
@stripe.createPaymentMethod({ type: 'card', card: @card }
@card, cardData).then (response) =>
if(response.error)
Loading.clear()
RailsFlashLoader.loadFlash({error: t("error") + ": #{response.error.message}"})
else
secrets.token = response.paymentMethod.id
secrets.cc_type = response.paymentMethod.card.brand
secrets.card = response.paymentMethod.card
submit()
# Maps the brand returned by Stripe to that required by activemerchant
mapCC: (ccType) ->
switch ccType

View File

@@ -110,7 +110,7 @@ module Spree
else
Gateway.providers.reject{ |p| p.name.include? "Bogus" }.sort_by(&:name)
end
@providers.reject!{ |p| p.name.ends_with? "StripeConnect" } unless show_stripe?
@providers.reject!{ |provider| stripe_provider?(provider) } unless show_stripe?
@calculators = PaymentMethod.calculators.sort_by(&:name)
end
@@ -134,12 +134,12 @@ module Spree
# current payment_method is already a Stripe method
def show_stripe?
Spree::Config.stripe_connect_enabled ||
@payment_method.try(:type) == "Spree::Gateway::StripeConnect"
stripe_payment_method?
end
def restrict_stripe_account_change
return unless @payment_method
return unless @payment_method.type == "Spree::Gateway::StripeConnect"
return unless stripe_payment_method?
return unless @payment_method.preferred_enterprise_id.andand > 0
@stripe_account_holder = Enterprise.find(@payment_method.preferred_enterprise_id)
@@ -147,6 +147,16 @@ module Spree
params[:payment_method][:preferred_enterprise_id] = @stripe_account_holder.id
end
def stripe_payment_method?
@payment_method.try(:type) == "Spree::Gateway::StripeConnect" ||
@payment_method.try(:type) == "Spree::Gateway::StripeSCA"
end
def stripe_provider?(provider)
provider.name.ends_with?("StripeConnect") ||
provider.name.ends_with?("StripeSCA")
end
end
end
end

View File

@@ -0,0 +1,88 @@
require 'stripe/profile_storer'
require 'active_merchant/billing/gateways/stripe_payment_intents'
require 'active_merchant/billing/gateways/stripe_decorator'
module Spree
class Gateway
class StripeSCA < Gateway
preference :enterprise_id, :integer
validate :ensure_enterprise_selected
attr_accessible :preferred_enterprise_id
def method_type
'stripe_sca'
end
def provider_class
ActiveMerchant::Billing::StripePaymentIntentsGateway
end
def payment_profiles_supported?
true
end
def stripe_account_id
StripeAccount.find_by_enterprise_id(preferred_enterprise_id).andand.stripe_user_id
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def purchase(money, creditcard, gateway_options)
provider.purchase(*options_for_purchase_or_auth(money, creditcard, gateway_options))
rescue Stripe::StripeError => e
# This will be an error caused by generating a stripe token
failed_activemerchant_billing_response(e.message)
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def void(response_code, _creditcard, gateway_options)
gateway_options[:stripe_account] = stripe_account_id
provider.void(response_code, gateway_options)
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def credit(money, _creditcard, response_code, gateway_options)
gateway_options[:stripe_account] = stripe_account_id
provider.refund(money, response_code, gateway_options)
end
def create_profile(payment)
return unless payment.source.gateway_customer_profile_id.nil?
profile_storer = Stripe::ProfileStorer.new(payment, provider, stripe_account_id)
profile_storer.create_customer_from_token
end
private
# In this gateway, what we call 'secret_key' is the 'login'
def options
options = super
options.merge(login: Stripe.api_key)
end
def options_for_purchase_or_auth(money, creditcard, gateway_options)
options = {}
options[:description] = "Spree Order ID: #{gateway_options[:order_id]}"
options[:currency] = gateway_options[:currency]
options[:stripe_account] = stripe_account_id
options[:customer] = creditcard.gateway_customer_profile_id
creditcard = creditcard.gateway_payment_profile_id
[money, creditcard, options]
end
def failed_activemerchant_billing_response(error_message)
ActiveMerchant::Billing::Response.new(false, error_message)
end
def ensure_enterprise_selected
return if preferred_enterprise_id.andand > 0
errors.add(:stripe_account_owner, I18n.t(:error_required))
end
end
end
end

View File

@@ -1,6 +1,9 @@
= @payment_method
- case @payment_method
- when Spree::Gateway::StripeConnect
= render 'stripe_connect'
- when Spree::Gateway::StripeSCA
= render 'stripe_connect'
- else
- if @payment_method.preferences.present?
%fieldset.alpha.eleven.columns.no-border-bottom#gateway_fields

View File

@@ -92,6 +92,7 @@ module Openfoodnetwork
app.config.spree.payment_methods << Spree::Gateway::Migs
app.config.spree.payment_methods << Spree::Gateway::Pin
app.config.spree.payment_methods << Spree::Gateway::StripeConnect
app.config.spree.payment_methods << Spree::Gateway::StripeSCA
end
# Settings in config/environments/* take precedence over those specified here.