spree_gateway 3.7.2 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +31 -38
  3. data/Appraisals +4 -10
  4. data/app/models/spree/check.rb +41 -0
  5. data/app/models/spree/checkout_controller_decorator.rb +19 -0
  6. data/app/models/spree/gateway/stripe_ach_gateway.rb +60 -0
  7. data/app/models/spree/gateway/stripe_elements_gateway.rb +50 -0
  8. data/app/models/spree/gateway/stripe_gateway.rb +1 -0
  9. data/app/models/spree/order_decorator.rb +28 -0
  10. data/app/models/spree/payment_decorator.rb +34 -0
  11. data/app/views/spree/checkout/_payment_confirm.html.erb +34 -0
  12. data/config/initializers/spree_permitted_attributes.rb +5 -0
  13. data/config/locales/en.yml +23 -0
  14. data/config/routes.rb +12 -0
  15. data/db/migrate/20200317135551_add_spree_check_payment_source.rb +22 -0
  16. data/db/migrate/20200422114908_add_intent_key_to_payment.rb +5 -0
  17. data/gemfiles/{spree_3_2.gemfile → spree_4_1.gemfile} +1 -1
  18. data/gemfiles/{spree_3_5.gemfile → spree_4_2.gemfile} +1 -1
  19. data/lib/active_merchant/billing/stripe_gateway_decorator.rb +13 -0
  20. data/lib/controllers/spree/api/v2/storefront/intents_controller.rb +27 -0
  21. data/lib/spree_gateway.rb +1 -0
  22. data/lib/spree_gateway/engine.rb +1 -0
  23. data/lib/spree_gateway/version.rb +1 -1
  24. data/lib/views/backend/spree/admin/payments/source_forms/_stripe_ach.html.erb +86 -0
  25. data/lib/views/backend/spree/admin/payments/source_forms/_stripe_apple_pay.html.erb +0 -0
  26. data/lib/views/backend/spree/admin/payments/source_forms/_stripe_elements.html.erb +79 -0
  27. data/lib/views/backend/spree/admin/payments/source_views/_stripe_ach.html.erb +21 -0
  28. data/lib/views/backend/spree/admin/payments/source_views/_stripe_apple_pay.html.erb +1 -0
  29. data/lib/views/backend/spree/admin/payments/source_views/_stripe_elements.html.erb +1 -0
  30. data/lib/views/frontend/spree/checkout/payment/_stripe_ach.html.erb +81 -0
  31. data/lib/views/frontend/spree/checkout/payment/_stripe_ach_verify.html.erb +16 -0
  32. data/lib/views/frontend/spree/checkout/payment/_stripe_apple_pay.html.erb +10 -1
  33. data/lib/views/frontend/spree/checkout/payment/_stripe_elements.html.erb +2 -1
  34. data/spec/factories/check_factory.rb +10 -0
  35. data/spec/features/admin/stripe_elements_payment_spec.rb +109 -0
  36. data/spec/features/stripe_checkout_spec.rb +3 -0
  37. data/spec/features/stripe_elements_3ds_checkout_spec.rb +105 -0
  38. data/spec/models/gateway/stripe_ach_gateway_spec.rb +186 -0
  39. data/spec/models/gateway/stripe_gateway_spec.rb +1 -0
  40. data/spec/spec_helper.rb +7 -64
  41. data/spec/support/within_stripe_3ds_popup.rb +10 -0
  42. data/spree_gateway.gemspec +4 -22
  43. metadata +43 -269
  44. data/gemfiles/spree_3_7.gemfile +0 -9
  45. data/gemfiles/spree_4_0.gemfile +0 -8
@@ -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
@@ -0,0 +1,5 @@
1
+ class AddIntentKeyToPayment < ActiveRecord::Migration[4.2]
2
+ def change
3
+ add_column :spree_payments, :intent_client_key, :string
4
+ end
5
+ end
@@ -3,6 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "rails-controller-testing"
6
- gem "spree", "~> 3.2.0"
6
+ gem "spree", "~> 4.1.0"
7
7
 
8
8
  gemspec path: "../"
@@ -3,6 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "rails-controller-testing"
6
- gem "spree", "~> 3.5.0"
6
+ gem "spree", "~> 4.2.0.beta"
7
7
 
8
8
  gemspec path: "../"
@@ -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
@@ -2,3 +2,4 @@ require 'spree_core'
2
2
  require 'spree_gateway/engine'
3
3
  require 'spree_gateway/version'
4
4
  require 'spree_extension'
5
+ require 'deface'
@@ -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
@@ -1,5 +1,5 @@
1
1
  module SpreeGateway
2
2
  def self.version
3
- '3.7.2'
3
+ '3.9.0'
4
4
  end
5
5
  end
@@ -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
+
@@ -0,0 +1,79 @@
1
+ <%= render "spree/admin/payments/source_forms/gateway", payment_method: payment_method, previous_cards: payment_method.reusable_sources(@order) %>
2
+
3
+ <script type="text/javascript" src="https://js.stripe.com/v2/"></script>
4
+ <script type="text/javascript">
5
+ Stripe.setPublishableKey("<%= payment_method.preferred_publishable_key %>");
6
+ </script>
7
+
8
+ <script>
9
+ var mapCC, stripeElementResponseHandler;
10
+
11
+ mapCC = function(ccType) {
12
+ if (ccType === 'MasterCard') {
13
+ return 'mastercard';
14
+ } else if (ccType === 'Visa') {
15
+ return 'visa';
16
+ } else if (ccType === 'American Express') {
17
+ return 'amex';
18
+ } else if (ccType === 'Discover') {
19
+ return 'discover';
20
+ } else if (ccType === 'Diners Club') {
21
+ return 'dinersclub';
22
+ } else if (ccType === 'JCB') {
23
+ return 'jcb';
24
+ }
25
+ };
26
+ stripeElementResponseHandler = function(status, response) {
27
+ var paymentMethodId, token;
28
+ if (response.error) {
29
+ $('#stripeError').html(response.error.message);
30
+ var param_map = {
31
+ number: '#card_number',
32
+ exp_month: '#card_expiry',
33
+ exp_year: '#card_expiry',
34
+ cvc: '#card_code'
35
+ }
36
+ if (response.error.param) {
37
+ errorField = Spree.stripeElementsPaymentMethod.find(param_map[response.error.param])
38
+ errorField.addClass('error');
39
+ errorField.parent().addClass('has-error');
40
+ }
41
+ return $('#stripeError').show();
42
+ } else {
43
+ Spree.stripeElementsPaymentMethod.find('#card_number<%= payment_method.id %>, #card_expiry<%= payment_method.id %>, #card_code<%= payment_method.id %>').prop("disabled", true);
44
+ Spree.stripeElementsPaymentMethod.find(".ccType").prop("disabled", false);
45
+ Spree.stripeElementsPaymentMethod.find(".ccType").val(mapCC(response.card.brand));
46
+ token = response['id'];
47
+ paymentMethodId = Spree.stripeElementsPaymentMethod.prop('id').split("_")[2];
48
+ Spree.stripeElementsPaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][gateway_payment_profile_id]' value='" + token + "'/>");
49
+ Spree.stripeElementsPaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][last_digits]' value='" + response.card.last4 + "'/>");
50
+ Spree.stripeElementsPaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][month]' value='" + response.card.exp_month + "'/>");
51
+ Spree.stripeElementsPaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][year]' value='" + response.card.exp_year + "'/>");
52
+ return Spree.stripeElementsPaymentMethod.parents("form").trigger('submit');
53
+ }
54
+ };
55
+
56
+ window.addEventListener('DOMContentLoaded', function() {
57
+ Spree.stripeElementsPaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
58
+
59
+ Spree.ready(function() {
60
+ Spree.stripeElementsPaymentMethod.prepend("<div id='stripeError' class='errorExplanation alert alert-danger' style='display:none'></div>");
61
+ return $('#new_payment [data-hook=buttons]').click(function() {
62
+ var expiration, params;
63
+ $('#stripeError').hide();
64
+ Spree.stripeElementsPaymentMethod.find('#card_number, #card_expiry, #card_code').removeClass('error');
65
+ if (Spree.stripeElementsPaymentMethod.is(':visible')) {
66
+ expiration = $('.cardExpiry:visible').payment('cardExpiryVal');
67
+ params = $.extend({
68
+ number: $('.cardNumber:visible').val(),
69
+ cvc: $('.cardCode:visible').val(),
70
+ exp_month: expiration.month || 0,
71
+ exp_year: expiration.year || 0
72
+ }, Spree.stripeAdditionalInfo);
73
+ Stripe.card.createToken(params, stripeElementResponseHandler);
74
+ return false;
75
+ }
76
+ });
77
+ });
78
+ });
79
+ </script>
@@ -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 @@
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>");