spree_gateway 3.7.4 → 3.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +36 -37
- data/Appraisals +3 -8
- data/app/models/spree/check.rb +41 -0
- data/app/models/spree/credit_card_decorator.rb +10 -0
- data/app/models/spree/gateway/stripe_ach_gateway.rb +60 -0
- data/app/models/spree/gateway/stripe_elements_gateway.rb +50 -0
- data/app/models/spree/gateway/stripe_gateway.rb +1 -0
- data/app/models/spree/order_decorator.rb +28 -0
- data/app/models/spree/payment_decorator.rb +36 -0
- data/app/views/spree/checkout/_payment_confirm.html.erb +39 -0
- data/config/initializers/spree_permitted_attributes.rb +5 -0
- data/config/locales/en.yml +23 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20200317135551_add_spree_check_payment_source.rb +22 -0
- data/db/migrate/20200422114908_add_intent_key_to_payment.rb +5 -0
- data/gemfiles/{spree_3_5.gemfile → spree_4_1.gemfile} +1 -1
- data/lib/active_merchant/billing/stripe_gateway_decorator.rb +13 -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 +8 -0
- data/lib/spree_gateway/version.rb +1 -1
- data/lib/views/backend/spree/admin/payments/source_forms/_stripe_ach.html.erb +86 -0
- data/lib/views/backend/spree/admin/payments/source_forms/_stripe_apple_pay.html.erb +0 -0
- data/lib/views/backend/spree/admin/payments/source_views/_stripe_ach.html.erb +21 -0
- data/lib/views/backend/spree/admin/payments/source_views/_stripe_apple_pay.html.erb +1 -0
- data/lib/views/frontend/spree/checkout/payment/_stripe_ach.html.erb +81 -0
- data/lib/views/frontend/spree/checkout/payment/_stripe_ach_verify.html.erb +16 -0
- data/lib/views/frontend/spree/checkout/payment/_stripe_apple_pay.html.erb +10 -1
- data/lib/views/frontend/spree/checkout/payment/_stripe_elements.html.erb +2 -1
- data/spec/factories/check_factory.rb +10 -0
- data/spec/features/admin/stripe_elements_payment_spec.rb +32 -32
- data/spec/features/stripe_checkout_spec.rb +30 -19
- data/spec/features/stripe_elements_3ds_checkout_spec.rb +224 -0
- data/spec/models/gateway/stripe_ach_gateway_spec.rb +186 -0
- data/spec/models/gateway/stripe_gateway_spec.rb +1 -0
- data/spec/spec_helper.rb +7 -65
- data/spec/support/order_walktrough.rb +73 -0
- data/spec/support/within_stripe_3ds_popup.rb +10 -0
- data/spree_gateway.gemspec +10 -22
- metadata +44 -282
- data/gemfiles/spree_4_0.gemfile +0 -8
- data/spec/support/capybara_helper.rb +0 -15
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,22 @@
|
|
1
|
+
class AddSpreeCheckPaymentSource < ActiveRecord::Migration[5.1]
|
2
|
+
def change
|
3
|
+
create_table :spree_checks do |t|
|
4
|
+
t.references :payment_method
|
5
|
+
t.references :user
|
6
|
+
t.string "account_holder_name"
|
7
|
+
t.string "account_holder_type"
|
8
|
+
t.string "routing_number"
|
9
|
+
t.string "account_number"
|
10
|
+
t.string "account_type", default: 'checking'
|
11
|
+
t.string "status"
|
12
|
+
t.string "last_digits"
|
13
|
+
t.string "gateway_customer_profile_id"
|
14
|
+
t.string "gateway_payment_profile_id"
|
15
|
+
|
16
|
+
t.datetime "created_at", null: false
|
17
|
+
t.datetime "updated_at", null: false
|
18
|
+
t.datetime "deleted_at"
|
19
|
+
end
|
20
|
+
add_index :spree_payment_methods, :id
|
21
|
+
end
|
22
|
+
end
|
@@ -1,6 +1,19 @@
|
|
1
1
|
module ActiveMerchant
|
2
2
|
module Billing
|
3
3
|
module StripeGatewayDecorator
|
4
|
+
def verify(source, **options)
|
5
|
+
customer = source.gateway_customer_profile_id
|
6
|
+
bank_account_token = source.gateway_payment_profile_id
|
7
|
+
|
8
|
+
commit(:post, "customers/#{CGI.escape(customer)}/sources/#{bank_account_token}/verify", amounts: options[:amounts])
|
9
|
+
end
|
10
|
+
|
11
|
+
def retrieve(source, **options)
|
12
|
+
customer = source.gateway_customer_profile_id
|
13
|
+
bank_account_token = source.gateway_payment_profile_id
|
14
|
+
commit(:get, "customers/#{CGI.escape(customer)}/bank_accounts/#{bank_account_token}")
|
15
|
+
end
|
16
|
+
|
4
17
|
private
|
5
18
|
|
6
19
|
def headers(options = {})
|
@@ -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
@@ -32,6 +32,7 @@ module SpreeGateway
|
|
32
32
|
app.config.spree.payment_methods << Spree::Gateway::StripeGateway
|
33
33
|
app.config.spree.payment_methods << Spree::Gateway::StripeElementsGateway
|
34
34
|
app.config.spree.payment_methods << Spree::Gateway::StripeApplePayGateway
|
35
|
+
app.config.spree.payment_methods << Spree::Gateway::StripeAchGateway
|
35
36
|
app.config.spree.payment_methods << Spree::Gateway::UsaEpayTransaction
|
36
37
|
app.config.spree.payment_methods << Spree::Gateway::Worldpay
|
37
38
|
end
|
@@ -43,6 +44,12 @@ module SpreeGateway
|
|
43
44
|
Dir.glob(File.join(File.dirname(__FILE__), '../../lib/active_merchant/**/*_decorator*.rb')) do |c|
|
44
45
|
Rails.application.config.cache_classes ? require(c) : load(c)
|
45
46
|
end
|
47
|
+
|
48
|
+
if self.frontend_available?
|
49
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../lib/spree_frontend/controllers/spree/*_decorator*.rb')) do |c|
|
50
|
+
Rails.application.config.cache_classes ? require(c) : load(c)
|
51
|
+
end
|
52
|
+
end
|
46
53
|
end
|
47
54
|
|
48
55
|
def self.backend_available?
|
@@ -60,6 +67,7 @@ module SpreeGateway
|
|
60
67
|
paths['app/controllers'] << 'lib/controllers'
|
61
68
|
|
62
69
|
if self.frontend_available?
|
70
|
+
paths["app/controllers"] << "lib/spree_frontend/controllers"
|
63
71
|
paths["app/views"] << "lib/views/frontend"
|
64
72
|
end
|
65
73
|
|
@@ -0,0 +1,86 @@
|
|
1
|
+
<fieldset data-id="bank_transfer">
|
2
|
+
<div id="bank_transfer_form<%= payment_method.id %>" class="margint" data-hook>
|
3
|
+
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
4
|
+
|
5
|
+
<div data-hook="account_holder_name" class="form-group">
|
6
|
+
<%= label_tag "account_holder_name#{payment_method.id}", raw(Spree.t('stripe.ach.account_holder_name') + required_span_tag) %>
|
7
|
+
<%= text_field_tag "#{param_prefix}[account_holder_name]", '', class: 'required form-control', id: "account_holder_name#{payment_method.id}" %>
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<div data-hook="account_holder_type">
|
11
|
+
<%= label_tag "account_holder_type#{payment_method.id}", raw(Spree.t('stripe.ach.account_holder_type') + required_span_tag) %>
|
12
|
+
<%= select_tag "#{param_prefix}[account_holder_type]", options_for_select(%w(Individual Company)), {id: "account_holder_type#{payment_method.id}", class: 'required form-control'} %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div data-hook="routing_number">
|
16
|
+
<%= label_tag "routing_number#{payment_method.id}", raw(Spree.t('stripe.ach.routing_number') + required_span_tag)%>
|
17
|
+
<%= text_field_tag "#{param_prefix}[routing_number]", '', class: 'required form-control', id: "routing_number#{payment_method.id}", maxlength: 9 %>
|
18
|
+
</div>
|
19
|
+
<div data-hook="account_number">
|
20
|
+
<%= label_tag "account_number#{payment_method.id}", raw(Spree.t('stripe.ach.account_number') + required_span_tag) %>
|
21
|
+
<%= text_field_tag "#{param_prefix}[account_number]", '', class: 'required form-control', id: "account_number#{payment_method.id}" %>
|
22
|
+
</div>
|
23
|
+
<div data-hook="account_number">
|
24
|
+
<%= label_tag "verify_account_number#{payment_method.id}", raw(Spree.t('stripe.ach.verify_account_number') + required_span_tag) %>
|
25
|
+
<%= text_field_tag "#{param_prefix}[verify_account_number]", '', class: 'required form-control', id: "verify_account_number#{payment_method.id}" %>
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
</fieldset>
|
29
|
+
|
30
|
+
<script type="text/javascript" src="https://js.stripe.com/v3/"></script>
|
31
|
+
<script type="text/javascript">
|
32
|
+
var stripe = Stripe("<%= payment_method.preferred_publishable_key %>");
|
33
|
+
</script>
|
34
|
+
|
35
|
+
<script>
|
36
|
+
stripeResponseHandler = function(response) {
|
37
|
+
var token, paymentMethodId;
|
38
|
+
if (response.error) {
|
39
|
+
$('#stripeError').html(response.error.message);
|
40
|
+
const param_map = {
|
41
|
+
account_holder_name: '#account_holder_name',
|
42
|
+
account_holder_type: '#account_holder_type',
|
43
|
+
account_number: '#account_number',
|
44
|
+
routing_number: '#routing_number'
|
45
|
+
}
|
46
|
+
if (response.error.param){
|
47
|
+
errorField = Spree.stripePaymentMethod.find(param_map[response.error.param])
|
48
|
+
errorField.addClass('error');
|
49
|
+
errorField.parent().addClass('has-error');
|
50
|
+
}
|
51
|
+
return $('#stripeError').show();
|
52
|
+
} else {
|
53
|
+
Spree.stripePaymentMethod.find('#account_holder_name, #account_holder_type, #account_number, #routing_number').prop("disabled", true);
|
54
|
+
token = response.token['id'];
|
55
|
+
paymentMethodId = Spree.stripePaymentMethod.prop('id').split("_")[2];
|
56
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][gateway_payment_profile_id]' value='" + token + "'/>");
|
57
|
+
return Spree.stripePaymentMethod.parents("form").trigger('submit');
|
58
|
+
}
|
59
|
+
};
|
60
|
+
|
61
|
+
window.addEventListener('DOMContentLoaded', function() {
|
62
|
+
Spree.stripePaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
|
63
|
+
|
64
|
+
Spree.ready(function() {
|
65
|
+
Spree.stripePaymentMethod.prepend("<div id='stripeError' class='errorExplanation alert alert-danger' style='display:none'></div>");
|
66
|
+
return $('#new_payment [data-hook=buttons]').click(function() {
|
67
|
+
var params;
|
68
|
+
$('#stripeError').hide();
|
69
|
+
Spree.stripePaymentMethod.find('#account_holder_name, #account_holder_type, #account_number, #routing_number').removeClass('error');
|
70
|
+
if (Spree.stripePaymentMethod.is(':visible')) {
|
71
|
+
params = $.extend({
|
72
|
+
country: 'US',
|
73
|
+
currency: 'usd',
|
74
|
+
account_holder_name: $('.account_holder_name:visible').val(),
|
75
|
+
account_holder_type: $('.account_holder_type:visible').val(),
|
76
|
+
routing_number: $('.routing_number:visible').val(),
|
77
|
+
account_number: $('.account_number:visible').val()
|
78
|
+
}, Spree.stripeAdditionalInfo);
|
79
|
+
stripe.createToken('bank_account', params).then(stripeResponseHandler);
|
80
|
+
return false;
|
81
|
+
}
|
82
|
+
});
|
83
|
+
});
|
84
|
+
});
|
85
|
+
</script>
|
86
|
+
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<fieldset data-hook="bank_transfer">
|
2
|
+
<legend><%= Spree.t(:bank_transfer) %></legend>
|
3
|
+
<table class="table table-condensed table-bordered">
|
4
|
+
<tr>
|
5
|
+
<th width="20%"><%= Spree.t('stripe.ach.account_holder_name') %>:</th>
|
6
|
+
<td><%= payment.source.account_holder_name %></td>
|
7
|
+
</tr>
|
8
|
+
<tr>
|
9
|
+
<th><%= Spree.t('stripe.ach.account_holder_type') %>:</th>
|
10
|
+
<td><%= payment.source.account_holder_type %></td>
|
11
|
+
</tr>
|
12
|
+
<tr>
|
13
|
+
<th><%= Spree.t('stripe.ach.routing_number') %>:</th>
|
14
|
+
<td><%= payment.source.routing_number %></td>
|
15
|
+
</tr>
|
16
|
+
<tr>
|
17
|
+
<th><%= Spree.t('stripe.ach.account_number') %>:</th>
|
18
|
+
<td><%= payment.source.account_number %></td>
|
19
|
+
</tr>
|
20
|
+
</table>
|
21
|
+
</fieldset>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render "spree/admin/payments/source_views/gateway", payment: payment %>
|
@@ -0,0 +1,81 @@
|
|
1
|
+
<div class="payment-gateway">
|
2
|
+
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
3
|
+
<div class="payment-gateway-half-fields">
|
4
|
+
<div class="mb-4 payment-gateway-field checkout-content-inner-field">
|
5
|
+
<%= text_field_tag "#{param_prefix}[account_holder_name]", "#{@order.bill_address_firstname} #{@order.bill_address_lastname}", { id: "account_holder_name", class: 'spree-flat-input', placeholder: Spree.t('stripe.ach.account_holder_name')} %>
|
6
|
+
</div>
|
7
|
+
<div class="mb-4 payment-gateway-field checkout-content-inner-field">
|
8
|
+
<%= select_tag "#{param_prefix}[account_holder_type]", options_for_select(%w(Individual Company)), {id: "account_holder_type", class: 'spree-flat-input', placeholder: Spree.t('stripe.ach.account_holder_type')} %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class="mb-4 payment-gateway-field checkout-content-inner-field" data-hook="account_number">
|
12
|
+
<%= text_field_tag "#{param_prefix}[routing_number]", '', {id: 'routing_number', class: 'spree-flat-input', autocomplete: "off", placeholder: Spree.t('stripe.ach.routing_number'), maxlength: 9} %>
|
13
|
+
</div>
|
14
|
+
<div class="mb-4 payment-gateway-field checkout-content-inner-field" data-hook="account_number">
|
15
|
+
<%= text_field_tag "#{param_prefix}[account_number]", '', {id: 'account_number', class: 'spree-flat-input', autocomplete: "off", placeholder: Spree.t('stripe.ach.account_number')} %>
|
16
|
+
</div>
|
17
|
+
<div class="mb-4 payment-gateway-field checkout-content-inner-field" data-hook="account_number">
|
18
|
+
<%= text_field_tag "#{param_prefix}[verify_account_number]", '', {id: 'verify_account_number', class: 'spree-flat-input', autocomplete: "off", placeholder: Spree.t('stripe.ach.verify_account_number')} %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<script type="text/javascript" src="https://js.stripe.com/v3/"></script>
|
24
|
+
<script type="text/javascript">
|
25
|
+
var stripe = Stripe("<%= payment_method.preferred_publishable_key %>");
|
26
|
+
</script>
|
27
|
+
|
28
|
+
<script>
|
29
|
+
stripeResponseHandler = function(response) {
|
30
|
+
var paymentMethodId, token, bank_acc_status;
|
31
|
+
if (response.error) {
|
32
|
+
$('#stripeError').html(response.error.message);
|
33
|
+
var param_map = {
|
34
|
+
account_holder_name: '#account_holder_name',
|
35
|
+
account_holder_type: '#account_holder_type',
|
36
|
+
account_number: '#account_number',
|
37
|
+
routing_number: '#routing_number'
|
38
|
+
}
|
39
|
+
if (response.error.param){
|
40
|
+
errorField = Spree.stripePaymentMethod.find(param_map[response.error.param])
|
41
|
+
errorField.addClass('error');
|
42
|
+
errorField.parent().addClass('has-error');
|
43
|
+
}
|
44
|
+
return $('#stripeError').show();
|
45
|
+
} else {
|
46
|
+
token = response.token['id'];
|
47
|
+
bank_acc_status = response.token.bank_account['status'];
|
48
|
+
paymentMethodId = Spree.stripePaymentMethod.prop('id').split("_")[2];
|
49
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][gateway_payment_profile_id]' value='" + token + "'/>");
|
50
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeStatus' name='payment_source[" + paymentMethodId + "][status]' value='" + bank_acc_status + "'/>")
|
51
|
+
return Spree.stripePaymentMethod.parents("form").trigger('submit');
|
52
|
+
}
|
53
|
+
};
|
54
|
+
|
55
|
+
window.addEventListener('DOMContentLoaded', function () {
|
56
|
+
Spree.stripePaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
|
57
|
+
Spree.stripePaymentMethod.prepend("<div id='stripeError' class='errorExplanation alert alert-danger' style='display:none'></div>");
|
58
|
+
|
59
|
+
$('#checkout_form_payment [data-hook=buttons]').click(function (e) {
|
60
|
+
var params;
|
61
|
+
$('#stripeError').hide();
|
62
|
+
Spree.stripePaymentMethod.find('#account_holder_name, #account_holder_type, #account_number, #routing_number').removeClass('error');
|
63
|
+
if (Spree.stripePaymentMethod.is(':visible')) {
|
64
|
+
e.preventDefault();
|
65
|
+
|
66
|
+
params = $.extend({
|
67
|
+
country: 'US',
|
68
|
+
currency: 'usd',
|
69
|
+
account_holder_name: $('#account_holder_name:visible').val(),
|
70
|
+
account_holder_type: $('#account_holder_type:visible').val(),
|
71
|
+
routing_number: $('#routing_number:visible').val(),
|
72
|
+
account_number: $('#account_number:visible').val()
|
73
|
+
}, Spree.stripeAdditionalInfo);
|
74
|
+
|
75
|
+
stripe.createToken('bank_account', params).then(stripeResponseHandler);
|
76
|
+
|
77
|
+
return false;
|
78
|
+
}
|
79
|
+
});
|
80
|
+
});
|
81
|
+
</script>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<p class="payment-type checkout-content-header">
|
2
|
+
<%= Spree.t('stripe.ach.verify_bank_account').upcase %>
|
3
|
+
</p>
|
4
|
+
|
5
|
+
<div class="payment-gateway">
|
6
|
+
<div class="payment-gateway-half-fields">
|
7
|
+
<input type="hidden" name="order[payment_id]" value= <%= payment.id %> />
|
8
|
+
<input type='hidden' name='verifyAch' value=true />
|
9
|
+
<div class="mb-4 payment-gateway-field checkout-content-inner-field">
|
10
|
+
<%= number_field_tag "amounts[]", nil, { id: "deposit1", class: 'spree-flat-input', placeholder: Spree.t('stripe.ach.first_deposit') } %>
|
11
|
+
</div>
|
12
|
+
<div class="mb-4 payment-gateway-field checkout-content-inner-field">
|
13
|
+
<%= number_field_tag "amounts[]", nil, { id: "deposit2", class: 'spree-flat-input', placeholder: Spree.t('stripe.ach.second_deposit') } %>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
@@ -9,7 +9,6 @@
|
|
9
9
|
<script>
|
10
10
|
var stripeApplePay = Stripe("<%= payment_method.preferred_publishable_key %>");
|
11
11
|
var elements = stripeApplePay.elements();
|
12
|
-
|
13
12
|
var paymentRequest = stripeApplePay.paymentRequest({
|
14
13
|
country: '<%= payment_method.preferred_country_code.try(:upcase) %>',
|
15
14
|
currency: '<%= @order.currency.downcase %>',
|
@@ -64,6 +63,15 @@
|
|
64
63
|
form.appendChild(hiddenInput);
|
65
64
|
};
|
66
65
|
|
66
|
+
function hideApplePayRadioButtonForNonAppleDevices() {
|
67
|
+
var isSafari = !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/);
|
68
|
+
var isiOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
69
|
+
|
70
|
+
if (!isSafari && !isiOS) {
|
71
|
+
$('input[name$="order[payments_attributes][][payment_method_id]"][value="<%= payment_method.id %>"]').closest('li').hide()
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
67
75
|
paymentRequest.on('token', function(ev) {
|
68
76
|
var form = document.getElementById('checkout_form_payment');
|
69
77
|
var token = ev.token;
|
@@ -83,6 +91,7 @@
|
|
83
91
|
|
84
92
|
window.addEventListener('DOMContentLoaded', function() {
|
85
93
|
Spree.stripeApplePayPaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
|
94
|
+
hideApplePayRadioButtonForNonAppleDevices();
|
86
95
|
|
87
96
|
prButton.on('ready', function () {
|
88
97
|
Spree.stripeApplePayPaymentMethod.prepend("<div id='stripeApplePayError' class='errorExplanation alert alert-danger' style='display:none'></div>");
|
@@ -0,0 +1,10 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
factory :check, class: Spree::Check do
|
3
|
+
account_holder_name { 'John Doe' }
|
4
|
+
account_holder_type { 'Individual' }
|
5
|
+
account_type { 'checking' }
|
6
|
+
routing_number { '110000000' }
|
7
|
+
account_number { '000123456789' }
|
8
|
+
association(:payment_method, factory: :credit_card_payment_method)
|
9
|
+
end
|
10
|
+
end
|
@@ -1,53 +1,43 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe 'Admin Panel Stripe elements payment', type: :feature
|
3
|
+
describe 'Admin Panel Stripe elements payment', type: :feature do
|
4
4
|
stub_authorization!
|
5
5
|
|
6
|
-
let!(:country)
|
7
|
-
let!(:state)
|
6
|
+
let!(:country) { create(:country, states_required: true) }
|
7
|
+
let!(:state) { create(:state, country: country) }
|
8
8
|
let!(:shipping_method) { create(:shipping_method) }
|
9
|
-
let!(:stock_location)
|
10
|
-
let!(:mug)
|
11
|
-
let!(:zone)
|
9
|
+
let!(:stock_location) { create(:stock_location) }
|
10
|
+
let!(:mug) { create(:product, name: 'RoR Mug') }
|
11
|
+
let!(:zone) { create(:zone) }
|
12
12
|
let!(:stripe_elements_payment_method) do
|
13
13
|
Spree::Gateway::StripeElementsGateway.create!(
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
name: 'Stripe Element',
|
15
|
+
preferred_secret_key: 'sk_test_VCZnDv3GLU15TRvn8i2EsaAN',
|
16
|
+
preferred_publishable_key: 'pk_test_Cuf0PNtiAkkMpTVC2gwYDMIg'
|
17
17
|
)
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
let!(:order) { OrderWalkthrough.up_to(:payment) }
|
21
21
|
before { visit spree.new_admin_order_payment_path(order.number) }
|
22
22
|
|
23
23
|
it 'can process a valid payment' do
|
24
24
|
fill_in_stripe_payment
|
25
25
|
wait_for { !page.has_current_path?(spree.admin_order_payments_path(order.number)) }
|
26
|
-
|
26
|
+
|
27
27
|
expect(page.body).to have_content('Payment has been successfully created!')
|
28
28
|
expect(page).to have_current_path spree.admin_order_payments_path(order.number)
|
29
29
|
end
|
30
|
-
|
31
|
-
if Spree.version.to_f >= 4.1
|
32
|
-
it 'shows an error with an invalid card name' do
|
33
|
-
fill_in_stripe_payment(true)
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
else
|
39
|
-
it 'can proces valid payment with invalid card name' do
|
40
|
-
fill_in_stripe_payment(true)
|
41
|
-
wait_for { !page.has_current_path?(spree.admin_order_payments_path(order.number)) }
|
31
|
+
it 'shows an error with an invalid card name' do
|
32
|
+
fill_in_stripe_payment(true)
|
42
33
|
|
43
|
-
|
44
|
-
|
45
|
-
end
|
34
|
+
expect(page).to have_content("Credit card Name can't be blank")
|
35
|
+
expect(page).to have_current_path spree.admin_order_payments_path(order.number)
|
46
36
|
end
|
47
37
|
|
48
38
|
it 'shows an error with an invalid card number' do
|
49
39
|
fill_in_stripe_payment(false, true)
|
50
|
-
|
40
|
+
|
51
41
|
expect(page).to have_content('The card number is not a valid credit card number.')
|
52
42
|
expect(page).to have_current_path spree.new_admin_order_payment_path(order.number)
|
53
43
|
end
|
@@ -62,7 +52,7 @@ describe 'Admin Panel Stripe elements payment', type: :feature, :js => true do
|
|
62
52
|
it 'shows an error with an invalid card expiration' do
|
63
53
|
fill_in_stripe_payment(false, false, false, true)
|
64
54
|
|
65
|
-
if Spree.version.to_f >= 4.1
|
55
|
+
if Spree.version.to_f >= 4.1 || Spree.version.to_f >= 3.7
|
66
56
|
expect(page).to have_content('Credit card Month is not a number')
|
67
57
|
expect(page).to have_content('Credit card Year is not a number')
|
68
58
|
expect(page).to have_current_path spree.admin_order_payments_path(order.number)
|
@@ -75,20 +65,30 @@ describe 'Admin Panel Stripe elements payment', type: :feature, :js => true do
|
|
75
65
|
def fill_in_stripe_payment(invalid_name = false, invalid_number = false, invalid_code = false, invalid_expiration = false)
|
76
66
|
fill_in 'Name *', with: invalid_name ? '' : 'Stripe Elements Gateway Payment'
|
77
67
|
fill_in_card_number(invalid_number)
|
78
|
-
|
68
|
+
fill_in_cvc(invalid_code)
|
79
69
|
fill_in_card_expiration(invalid_expiration)
|
80
70
|
|
81
|
-
click_button
|
71
|
+
click_button 'Update'
|
82
72
|
end
|
83
73
|
|
84
74
|
def fill_in_card_number(invalid_number)
|
85
75
|
number = invalid_number ? '123' : '4242 4242 4242 4242'
|
86
|
-
fill_in_field('Card Number *',
|
76
|
+
fill_in_field('Card Number *', "#card_number#{stripe_elements_payment_method.id}", number)
|
87
77
|
end
|
88
78
|
|
89
79
|
def fill_in_card_expiration(invalid_expiration)
|
90
|
-
|
91
|
-
|
80
|
+
valid_expiry = Spree.version.to_f >= 4.2 ? "01/#{Time.current.year + 1}" : "01 / #{Time.current.year + 1}"
|
81
|
+
invalid_expiry = Spree.version.to_f >= 4.2 ? '01/' : '01 / '
|
82
|
+
|
83
|
+
card_expiry = invalid_expiration ? invalid_expiry : valid_expiry
|
84
|
+
fill_in_field('Expiration *', "#card_expiry#{stripe_elements_payment_method.id}", card_expiry)
|
85
|
+
end
|
86
|
+
|
87
|
+
def fill_in_cvc(invalid_code)
|
88
|
+
value = invalid_code ? '1' : '123'
|
89
|
+
label = Spree.version.to_f >= 4.2 ? 'Card Varification Code (CVC) *' : 'Card Code *'
|
90
|
+
|
91
|
+
fill_in label, with: value
|
92
92
|
end
|
93
93
|
|
94
94
|
def fill_in_field(field_name, field_id, number)
|