spree_gateway 3.8.0 → 3.9.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -11
- data/Gemfile +3 -1
- data/README.md +2 -2
- data/Rakefile +2 -2
- data/app/models/spree/gateway/stripe_ach_gateway.rb +1 -1
- data/app/models/spree/gateway/stripe_elements_gateway.rb +54 -0
- data/app/models/spree/gateway/stripe_gateway.rb +5 -0
- data/app/models/{spree → spree_gateway}/apple_pay_order_decorator.rb +2 -2
- data/app/models/{spree → spree_gateway}/apple_pay_payment_decorator.rb +2 -2
- data/app/models/spree_gateway/credit_card_decorator.rb +10 -0
- data/app/models/spree_gateway/order_decorator.rb +28 -0
- data/app/models/{spree → spree_gateway}/payment_decorator.rb +9 -2
- data/app/views/spree/checkout/_payment_confirm.html.erb +39 -0
- data/config/locales/en.yml +4 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20200422114908_add_intent_key_to_payment.rb +5 -0
- data/lib/controllers/spree/api/v2/storefront/intents_controller.rb +27 -0
- data/lib/spree_frontend/controllers/spree/checkout_controller_decorator.rb +19 -0
- data/lib/spree_gateway/engine.rb +10 -0
- data/lib/spree_gateway/version.rb +1 -1
- data/lib/views/frontend/spree/checkout/payment/_stripe_elements.html.erb +2 -1
- data/spec/features/admin/stripe_elements_payment_spec.rb +20 -29
- data/spec/features/stripe_checkout_spec.rb +37 -23
- data/spec/features/stripe_elements_3ds_checkout_spec.rb +225 -0
- data/spec/models/gateway/authorize_net_spec.rb +1 -1
- data/spec/models/gateway/balanced_gateway_spec.rb +1 -1
- data/spec/models/gateway/banwire_spec.rb +1 -1
- data/spec/models/gateway/beanstream_spec.rb +1 -1
- data/spec/models/gateway/braintree_gateway_spec.rb +24 -13
- data/spec/models/gateway/card_save_spec.rb +1 -1
- data/spec/models/gateway/{data_cache_spec.rb → data_cash_spec.rb} +1 -1
- data/spec/models/gateway/epay_spec.rb +1 -1
- data/spec/models/gateway/eway_rapid_spec.rb +1 -1
- data/spec/models/gateway/eway_spec.rb +1 -1
- data/spec/models/gateway/moneris_spec.rb +1 -1
- data/spec/models/gateway/pay_junction_spec.rb +1 -1
- data/spec/models/gateway/pay_pal_spec.rb +1 -1
- data/spec/models/gateway/payflow_pro_spec.rb +1 -1
- data/spec/models/gateway/paymill_spec.rb +1 -1
- data/spec/models/gateway/pin_gateway_spec.rb +1 -1
- data/spec/models/gateway/quickpay_spec.rb +1 -1
- data/spec/models/gateway/sage_pay_spec.rb +1 -1
- data/spec/models/gateway/secure_pay_au_spec.rb +1 -1
- data/spec/models/gateway/stripe_ach_gateway_spec.rb +2 -1
- data/spec/models/gateway/stripe_gateway_spec.rb +1 -0
- data/spec/models/gateway/usa_epay_transaction_spec.rb +2 -2
- data/spec/models/gateway/worldpay_spec.rb +1 -1
- data/spec/models/spree/order_spec.rb +4 -2
- data/spec/support/order_walktrough.rb +73 -0
- data/spec/support/within_stripe_3ds_popup.rb +10 -0
- data/spree_gateway.gemspec +9 -3
- metadata +34 -28
- data/Appraisals +0 -14
- data/gemfiles/spree_4_1.gemfile +0 -8
- data/gemfiles/spree_4_2.gemfile +0 -8
- data/gemfiles/spree_master.gemfile +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a29093f977d40e708b032c608a9e25f1949352bee57b9321fa36488000d7711f
|
4
|
+
data.tar.gz: 5f5d7ff9014be360d444df942dc24d1313ef0881e786ac37a49f4fe884b5d0fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 807b40308555c5149f146fa3fc38c52f10c47ec765a1988f0562adcc296115d43670f09052a80a2493edd166d6d195092e7861ae07457c8c47eedb0cca90559b
|
7
|
+
data.tar.gz: 0ce03934963ea212e16aed6148eff226362d90544789ec1fa283c69dbff81c1d2834c91bce4aab81794935c5d3e825ffb89f07b95d66d1d9994128b11f8e31de
|
data/.travis.yml
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
os: linux
|
2
2
|
dist: bionic
|
3
3
|
|
4
|
+
cache: bundler
|
5
|
+
|
4
6
|
addons:
|
5
7
|
apt:
|
6
8
|
sources:
|
@@ -11,25 +13,18 @@ addons:
|
|
11
13
|
services:
|
12
14
|
- mysql
|
13
15
|
- postgresql
|
16
|
+
- redis-server
|
14
17
|
|
15
18
|
language: ruby
|
16
19
|
|
17
20
|
rvm:
|
18
|
-
- 2.
|
21
|
+
- 2.7
|
22
|
+
- 3.0
|
19
23
|
|
20
24
|
env:
|
21
25
|
- DB=mysql
|
22
26
|
- DB=postgres
|
23
27
|
|
24
|
-
gemfile:
|
25
|
-
# - gemfiles/spree_4_1.gemfile
|
26
|
-
- gemfiles/spree_4_2.gemfile
|
27
|
-
- gemfiles/spree_master.gemfile
|
28
|
-
|
29
|
-
jobs:
|
30
|
-
allow_failures:
|
31
|
-
- gemfile: gemfiles/spree_master.gemfile
|
32
|
-
|
33
28
|
before_install:
|
34
29
|
- mysql -u root -e "GRANT ALL ON *.* TO 'travis'@'%';"
|
35
30
|
|
@@ -41,4 +36,4 @@ before_script:
|
|
41
36
|
|
42
37
|
script:
|
43
38
|
- bundle exec rake test_app
|
44
|
-
- bundle exec rake spec
|
39
|
+
- bundle exec rake spec
|
data/Gemfile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
gem 'rails-controller-testing'
|
4
|
-
gem 'spree', github: 'spree/spree', branch: '
|
4
|
+
gem 'spree', github: 'spree/spree', branch: 'main'
|
5
|
+
gem 'spree_backend', github: 'spree/spree', branch: 'main'
|
6
|
+
gem 'spree_frontend', github: 'spree/spree', branch: 'main'
|
5
7
|
|
6
8
|
gemspec
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Spree Gateway
|
2
2
|
|
3
|
-
[![Build Status](https://api.travis-ci.org/spree/spree_gateway.svg?branch=
|
3
|
+
[![Build Status](https://api.travis-ci.org/spree/spree_gateway.svg?branch=main)](https://travis-ci.org/spree/spree_gateway)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/spree/spree_gateway.svg)](https://codeclimate.com/github/spree/spree_gateway)
|
5
5
|
|
6
6
|
Community supported Spree Payment Method Gateways. It works as a wrapper for
|
@@ -100,6 +100,6 @@ We are [available for hire][spark].
|
|
100
100
|
|
101
101
|
[1]: http://www.fsf.org/licensing/essays/free-sw.html
|
102
102
|
[2]: https://github.com/spree/spree_gateway/issues
|
103
|
-
[3]: https://github.com/spree/spree_gateway/blob/
|
103
|
+
[3]: https://github.com/spree/spree_gateway/blob/main/LICENSE.md
|
104
104
|
[4]: https://github.com/spree
|
105
105
|
[5]: https://github.com/spree/spree_gateway/graphs/contributors
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'bundler'
|
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
4
|
require 'rspec/core/rake_task'
|
5
|
-
require 'spree/testing_support/
|
5
|
+
require 'spree/testing_support/extension_rake'
|
6
6
|
|
7
7
|
RSpec::Core::RakeTask.new
|
8
8
|
|
@@ -11,5 +11,5 @@ task :default => [:spec]
|
|
11
11
|
desc "Generates a dummy app for testing"
|
12
12
|
task :test_app do
|
13
13
|
ENV['LIB_NAME'] = 'spree_gateway'
|
14
|
-
Rake::Task['
|
14
|
+
Rake::Task['extension:test_app'].invoke
|
15
15
|
end
|
@@ -1,7 +1,61 @@
|
|
1
1
|
module Spree
|
2
2
|
class Gateway::StripeElementsGateway < Gateway::StripeGateway
|
3
|
+
preference :intents, :boolean, default: true
|
4
|
+
|
3
5
|
def method_type
|
4
6
|
'stripe_elements'
|
5
7
|
end
|
8
|
+
|
9
|
+
def provider_class
|
10
|
+
if get_preference(:intents)
|
11
|
+
ActiveMerchant::Billing::StripePaymentIntentsGateway
|
12
|
+
else
|
13
|
+
ActiveMerchant::Billing::StripeGateway
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_profile(payment)
|
18
|
+
return unless payment.source.gateway_customer_profile_id.nil?
|
19
|
+
|
20
|
+
options = {
|
21
|
+
email: payment.order.email,
|
22
|
+
login: preferred_secret_key
|
23
|
+
}.merge! address_for(payment)
|
24
|
+
|
25
|
+
source = update_source!(payment.source)
|
26
|
+
creditcard = source.gateway_payment_profile_id.present? ? source.gateway_payment_profile_id : source
|
27
|
+
response = provider.store(creditcard, options)
|
28
|
+
if response.success?
|
29
|
+
if get_preference(:intents)
|
30
|
+
payment.source.update!(
|
31
|
+
cc_type: payment.source.cc_type,
|
32
|
+
gateway_customer_profile_id: response.params['id'],
|
33
|
+
gateway_payment_profile_id: response.params['sources']['data'].first['id']
|
34
|
+
)
|
35
|
+
else
|
36
|
+
response_cc_type = response.params['sources']['data'].first['brand']
|
37
|
+
cc_type = CARD_TYPE_MAPPING.include?(response_cc_type) ? CARD_TYPE_MAPPING[response_cc_type] : payment.source.cc_type
|
38
|
+
payment.source.update!({
|
39
|
+
cc_type: cc_type, # side-effect of update_source!
|
40
|
+
gateway_customer_profile_id: response.params['id'],
|
41
|
+
gateway_payment_profile_id: response.params['default_source'] || response.params['default_card']
|
42
|
+
})
|
43
|
+
end
|
44
|
+
else
|
45
|
+
payment.send(:gateway_error, response.message)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def options_for_purchase_or_auth(money, creditcard, gateway_options)
|
52
|
+
money, creditcard, options = super
|
53
|
+
options[:execute_threed] = get_preference(:intents)
|
54
|
+
return money, creditcard, options
|
55
|
+
end
|
56
|
+
|
57
|
+
def public_preference_keys
|
58
|
+
%i[publishable_key test_mode intents]
|
59
|
+
end
|
6
60
|
end
|
7
61
|
end
|
@@ -54,6 +54,7 @@ module Spree
|
|
54
54
|
|
55
55
|
def create_profile(payment)
|
56
56
|
return unless payment.source.gateway_customer_profile_id.nil?
|
57
|
+
|
57
58
|
options = {
|
58
59
|
email: payment.order.email,
|
59
60
|
login: preferred_secret_key,
|
@@ -142,5 +143,9 @@ module Spree
|
|
142
143
|
url = 'https://spreecommerce.org'
|
143
144
|
"#{name_with_version} #{url}"
|
144
145
|
end
|
146
|
+
|
147
|
+
def public_preference_keys
|
148
|
+
%i[publishable_key test_mode]
|
149
|
+
end
|
145
150
|
end
|
146
151
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module SpreeGateway
|
2
2
|
module ApplePayOrderDecorator
|
3
3
|
def confirmation_required?
|
4
4
|
return false if paid_with_apple_pay?
|
@@ -17,4 +17,4 @@ module Spree
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
Spree::Order.prepend
|
20
|
+
::Spree::Order.prepend(::SpreeGateway::ApplePayOrderDecorator)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module SpreeGateway
|
2
2
|
module ApplePayPaymentDecorator
|
3
3
|
def apple_pay?
|
4
4
|
payment_method.is_a? Spree::Gateway::StripeApplePayGateway
|
@@ -6,4 +6,4 @@ module Spree
|
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
-
Spree::Payment.prepend
|
9
|
+
::Spree::Payment.prepend(::SpreeGateway::ApplePayPaymentDecorator)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module SpreeGateway
|
2
|
+
module OrderDecorator
|
3
|
+
def self.prepended(base)
|
4
|
+
return if base.checkout_steps.key?(:payment_confirm)
|
5
|
+
|
6
|
+
base.insert_checkout_step(
|
7
|
+
:payment_confirm,
|
8
|
+
before: :complete,
|
9
|
+
if: ->(order) { order.intents? }
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def process_payments!
|
14
|
+
# Payments are processed in confirm_payment step where after successful
|
15
|
+
# 3D Secure authentication `intent_client_key` is saved for payment.
|
16
|
+
# In case authentication is unsuccessful, `intent_client_key` is removed.
|
17
|
+
return if intents? && payments.valid.last.intent_client_key.present?
|
18
|
+
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def intents?
|
23
|
+
payments.valid.map { |p| p.payment_method&.has_preference?(:intents) && p.payment_method&.get_preference(:intents) }.any?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
::Spree::Order.prepend(::SpreeGateway::OrderDecorator)
|
@@ -1,5 +1,12 @@
|
|
1
|
-
module
|
1
|
+
module SpreeGateway
|
2
2
|
module PaymentDecorator
|
3
|
+
def handle_response(response, success_state, failure_state)
|
4
|
+
if response.success? && response.respond_to?(:params)
|
5
|
+
self.intent_client_key = response.params['client_secret'] if response.params['client_secret']
|
6
|
+
end
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
3
10
|
def verify!(**options)
|
4
11
|
process_verification(options)
|
5
12
|
end
|
@@ -26,4 +33,4 @@ module Spree
|
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
29
|
-
Spree::Payment.prepend
|
36
|
+
::Spree::Payment.prepend(::SpreeGateway::PaymentDecorator)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<div id='errorBox' class='errorExplanation alert alert-danger' style='display:none'></div>
|
2
|
+
<div id='successBox' class='alert alert-success' style='display:none'></div>
|
3
|
+
<div id='infoBox' class='alert alert-info'><%= t('spree.please_wait_for_confirmation_popup') %></div>
|
4
|
+
|
5
|
+
<% if @client_secret.present? && @pk_key.present? %>
|
6
|
+
<script type="text/javascript" src="https://js.stripe.com/v3/"></script>
|
7
|
+
<script>
|
8
|
+
var form = document.getElementById('checkout_form_payment_confirm');
|
9
|
+
|
10
|
+
function confirmCardPaymentResponseHandler(response) {
|
11
|
+
$.post("/api/v2/storefront/intents/handle_response", { response: response, order_token: "<%= @order.token %>" }).done(function (result) {
|
12
|
+
// conditional needs for spree 3.7
|
13
|
+
if(form.elements["commit"]) {
|
14
|
+
form.elements["commit"].disabled = false;
|
15
|
+
}
|
16
|
+
$('#successBox').html(result.message);
|
17
|
+
$('#successBox').show();
|
18
|
+
form.submit();
|
19
|
+
}).fail(function(result) {
|
20
|
+
if(form.elements["commit"]) {
|
21
|
+
form.elements["commit"].disabled = false;
|
22
|
+
}
|
23
|
+
$('#errorBox').html(result.responseJSON.error);
|
24
|
+
$('#errorBox').show();
|
25
|
+
});
|
26
|
+
}
|
27
|
+
|
28
|
+
var stripeElements = Stripe("<%= @pk_key %>");
|
29
|
+
stripeElements.confirmCardPayment("<%= @client_secret %>").then(function(result) {
|
30
|
+
$('#infoBox').hide();
|
31
|
+
confirmCardPaymentResponseHandler(result);
|
32
|
+
});
|
33
|
+
|
34
|
+
document.addEventListener('DOMContentLoaded', function(){
|
35
|
+
form.elements["commit"].value = "continue"
|
36
|
+
form.elements["commit"].disabled = true
|
37
|
+
});
|
38
|
+
</script>
|
39
|
+
<% end %>
|
data/config/locales/en.yml
CHANGED
@@ -10,6 +10,10 @@ en:
|
|
10
10
|
spree:
|
11
11
|
check: Check
|
12
12
|
payment_has_been_cancelled: The payment has been cancelled.
|
13
|
+
please_wait_for_confirmation_popup: Please wait for payment confirmation popup to appear.
|
14
|
+
payment_successfully_authorized: The payment was successfully authorized.
|
15
|
+
order_state:
|
16
|
+
payment_confirm: Verify payment
|
13
17
|
log_entry:
|
14
18
|
braintree:
|
15
19
|
message: Message
|
data/config/routes.rb
CHANGED
@@ -4,3 +4,15 @@
|
|
4
4
|
Rails.application.routes.draw do
|
5
5
|
get '/.well-known/apple-developer-merchantid-domain-association' => 'spree/apple_pay_domain_verification#show'
|
6
6
|
end
|
7
|
+
|
8
|
+
Spree::Core::Engine.add_routes do
|
9
|
+
namespace :api, defaults: { format: 'json' } do
|
10
|
+
namespace :v2 do
|
11
|
+
namespace :storefront do
|
12
|
+
namespace :intents do
|
13
|
+
post :handle_response
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Storefront
|
5
|
+
class IntentsController < ::Spree::Api::V2::BaseController
|
6
|
+
include Spree::Api::V2::Storefront::OrderConcern
|
7
|
+
|
8
|
+
def handle_response
|
9
|
+
if params['response']['error']
|
10
|
+
invalidate_payment
|
11
|
+
render_error_payload(params['response']['error']['message'])
|
12
|
+
else
|
13
|
+
render_serialized_payload { { message: I18n.t('spree.payment_successfully_authorized') } }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def invalidate_payment
|
20
|
+
payment = spree_current_order.payments.find_by!(response_code: params['response']['error']['payment_intent']['id'])
|
21
|
+
payment.update(state: 'failed', intent_client_key: nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Spree
|
2
|
+
module CheckoutControllerDecorator
|
3
|
+
def self.prepended(base)
|
4
|
+
base.before_action :process_payments_and_set_keys, only: :edit, if: proc { params[:state] == 'payment_confirm' }
|
5
|
+
end
|
6
|
+
|
7
|
+
def process_payments_and_set_keys
|
8
|
+
@order.tap do |order|
|
9
|
+
order.process_payments!
|
10
|
+
order.reload.payments.valid.where.not(intent_client_key: nil).last.tap do |payment|
|
11
|
+
@client_secret = payment.intent_client_key
|
12
|
+
@pk_key = payment.payment_method.preferred_publishable_key
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
::Spree::CheckoutController.prepend Spree::CheckoutControllerDecorator
|
data/lib/spree_gateway/engine.rb
CHANGED
@@ -41,9 +41,18 @@ module SpreeGateway
|
|
41
41
|
Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/spree/*_decorator*.rb')) do |c|
|
42
42
|
Rails.application.config.cache_classes ? require(c) : load(c)
|
43
43
|
end
|
44
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/spree_gateway/*_decorator*.rb')) do |c|
|
45
|
+
Rails.application.config.cache_classes ? require(c) : load(c)
|
46
|
+
end
|
44
47
|
Dir.glob(File.join(File.dirname(__FILE__), '../../lib/active_merchant/**/*_decorator*.rb')) do |c|
|
45
48
|
Rails.application.config.cache_classes ? require(c) : load(c)
|
46
49
|
end
|
50
|
+
|
51
|
+
if self.frontend_available?
|
52
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../lib/spree_frontend/controllers/spree/*_decorator*.rb')) do |c|
|
53
|
+
Rails.application.config.cache_classes ? require(c) : load(c)
|
54
|
+
end
|
55
|
+
end
|
47
56
|
end
|
48
57
|
|
49
58
|
def self.backend_available?
|
@@ -61,6 +70,7 @@ module SpreeGateway
|
|
61
70
|
paths['app/controllers'] << 'lib/controllers'
|
62
71
|
|
63
72
|
if self.frontend_available?
|
73
|
+
paths["app/controllers"] << "lib/spree_frontend/controllers"
|
64
74
|
paths["app/views"] << "lib/views/frontend"
|
65
75
|
end
|
66
76
|
|