solidus_stripe 4.3.0 → 5.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +98 -23
  3. data/.github/stale.yml +1 -17
  4. data/.gitignore +3 -0
  5. data/.rubocop.yml +94 -2
  6. data/.yardopts +1 -0
  7. data/CHANGELOG.md +1 -231
  8. data/Gemfile +10 -25
  9. data/LICENSE +2 -2
  10. data/Procfile.dev +3 -0
  11. data/README.md +155 -223
  12. data/Rakefile +7 -3
  13. data/app/assets/javascripts/spree/backend/solidus_stripe.js +2 -0
  14. data/app/assets/stylesheets/spree/backend/solidus_stripe.css +4 -0
  15. data/app/controllers/solidus_stripe/intents_controller.rb +36 -52
  16. data/app/controllers/solidus_stripe/webhooks_controller.rb +28 -0
  17. data/app/models/concerns/solidus_stripe/log_entries.rb +31 -0
  18. data/app/models/solidus_stripe/customer.rb +21 -0
  19. data/app/models/solidus_stripe/gateway.rb +231 -0
  20. data/app/models/solidus_stripe/payment_intent.rb +111 -0
  21. data/app/models/solidus_stripe/payment_method.rb +106 -0
  22. data/app/models/solidus_stripe/payment_source.rb +31 -0
  23. data/app/models/solidus_stripe/slug_entry.rb +20 -0
  24. data/app/models/solidus_stripe.rb +7 -0
  25. data/app/subscribers/solidus_stripe/webhook/charge_subscriber.rb +28 -0
  26. data/app/subscribers/solidus_stripe/webhook/payment_intent_subscriber.rb +112 -0
  27. data/app/views/spree/admin/payments/source_forms/_stripe.html.erb +29 -0
  28. data/app/views/spree/admin/payments/source_forms/existing_payment/_stripe.html.erb +14 -0
  29. data/app/views/spree/admin/payments/source_forms/existing_payment/stripe/_card.html.erb +8 -0
  30. data/app/views/spree/admin/payments/source_forms/existing_payment/stripe/_default.html.erb +7 -0
  31. data/app/views/spree/admin/payments/source_views/_stripe.html.erb +15 -0
  32. data/app/views/spree/api/payments/source_views/_stripe.json.jbuilder +8 -0
  33. data/bin/dev +13 -0
  34. data/bin/dummy-app +29 -0
  35. data/bin/rails +38 -3
  36. data/bin/rails-dummy-app +3 -0
  37. data/bin/rails-engine +1 -11
  38. data/bin/rails-new +55 -0
  39. data/bin/rails-sandbox +1 -14
  40. data/bin/rspec +10 -0
  41. data/bin/sandbox +12 -74
  42. data/bin/setup +1 -0
  43. data/bin/update-migrations +56 -0
  44. data/codecov.yml +12 -0
  45. data/config/locales/en.yml +16 -1
  46. data/config/routes.rb +5 -11
  47. data/coverage.rb +42 -0
  48. data/db/migrate/20230109183332_create_solidus_stripe_payment_sources.rb +10 -0
  49. data/db/migrate/20230303154931_create_solidus_stripe_setup_intent.rb +10 -0
  50. data/db/migrate/20230306105520_create_solidus_stripe_payment_intents.rb +10 -0
  51. data/db/migrate/20230308122414_create_solidus_stripe_webhook_endpoints.rb +10 -0
  52. data/db/migrate/20230310152615_add_payment_method_reference_to_stripe_intents.rb +6 -0
  53. data/db/migrate/20230310171444_normalize_stripe_intent_id_attributes.rb +6 -0
  54. data/db/migrate/20230313150008_create_solidus_stripe_customers.rb +16 -0
  55. data/db/migrate/20230323154931_drop_solidus_stripe_setup_intent.rb +13 -0
  56. data/db/migrate/20230403094916_rename_webhook_endpoint_to_payment_method_slug_entries.rb +5 -0
  57. data/db/seeds.rb +6 -24
  58. data/lib/generators/solidus_stripe/install/install_generator.rb +121 -14
  59. data/lib/generators/solidus_stripe/install/templates/app/assets/stylesheets/spree/frontend/solidus_stripe.css +13 -0
  60. data/lib/generators/solidus_stripe/install/templates/app/javascript/controllers/solidus_stripe_confirm_controller.js +39 -0
  61. data/lib/generators/solidus_stripe/install/templates/app/javascript/controllers/solidus_stripe_payment_controller.js +89 -0
  62. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/_stripe.html.erb +16 -0
  63. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/stripe/_card.html.erb +8 -0
  64. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/stripe/_default.html.erb +7 -0
  65. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/payment/_stripe.html.erb +39 -0
  66. data/lib/generators/solidus_stripe/install/templates/app/views/orders/payment_info/_stripe.html.erb +20 -0
  67. data/lib/generators/solidus_stripe/install/templates/config/initializers/solidus_stripe.rb +31 -0
  68. data/lib/solidus_stripe/configuration.rb +24 -3
  69. data/lib/solidus_stripe/engine.rb +19 -6
  70. data/lib/solidus_stripe/money_to_stripe_amount_converter.rb +109 -0
  71. data/lib/solidus_stripe/refunds_synchronizer.rb +96 -0
  72. data/lib/solidus_stripe/seeds.rb +19 -0
  73. data/lib/solidus_stripe/testing_support/factories.rb +153 -0
  74. data/lib/solidus_stripe/version.rb +1 -1
  75. data/lib/solidus_stripe/webhook/event.rb +90 -0
  76. data/lib/solidus_stripe.rb +0 -2
  77. data/solidus_stripe.gemspec +29 -5
  78. data/spec/lib/solidus_stripe/configuration_spec.rb +21 -0
  79. data/spec/lib/solidus_stripe/money_to_stripe_amount_converter_spec.rb +133 -0
  80. data/spec/lib/solidus_stripe/refunds_synchronizer_spec.rb +238 -0
  81. data/spec/lib/solidus_stripe/seeds_spec.rb +43 -0
  82. data/spec/lib/solidus_stripe/webhook/event_spec.rb +134 -0
  83. data/spec/models/concerns/solidus_stripe/log_entries_spec.rb +54 -0
  84. data/spec/models/solidus_stripe/customer_spec.rb +47 -0
  85. data/spec/models/solidus_stripe/gateway_spec.rb +283 -0
  86. data/spec/models/solidus_stripe/payment_intent_spec.rb +17 -0
  87. data/spec/models/solidus_stripe/payment_method_spec.rb +137 -0
  88. data/spec/models/solidus_stripe/payment_source_spec.rb +25 -0
  89. data/spec/requests/solidus_stripe/intents_controller_spec.rb +29 -0
  90. data/spec/requests/solidus_stripe/webhooks_controller/charge/refunded_spec.rb +31 -0
  91. data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/canceled_spec.rb +23 -0
  92. data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/payment_failed_spec.rb +23 -0
  93. data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/succeeded_spec.rb +29 -0
  94. data/spec/requests/solidus_stripe/webhooks_controller_spec.rb +52 -0
  95. data/spec/solidus_stripe_spec_helper.rb +10 -0
  96. data/spec/subscribers/solidus_stripe/webhook/charge_subscriber_spec.rb +33 -0
  97. data/spec/subscribers/solidus_stripe/webhook/payment_intent_subscriber_spec.rb +297 -0
  98. data/spec/support/solidus_stripe/backend_test_helper.rb +210 -0
  99. data/spec/support/solidus_stripe/checkout_test_helper.rb +339 -0
  100. data/spec/support/solidus_stripe/factories.rb +5 -0
  101. data/spec/support/solidus_stripe/webhook/data_fixtures.rb +106 -0
  102. data/spec/support/solidus_stripe/webhook/event_with_context_factory.rb +82 -0
  103. data/spec/support/solidus_stripe/webhook/request_helper.rb +32 -0
  104. data/spec/system/backend/solidus_stripe/orders/payments_spec.rb +119 -0
  105. data/spec/system/frontend/.keep +0 -0
  106. data/spec/system/frontend/solidus_stripe/checkout_spec.rb +187 -0
  107. data/tmp/.keep +0 -0
  108. metadata +210 -69
  109. data/.travis.yml +0 -28
  110. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-cart-page-checkout.js +0 -122
  111. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-elements.js +0 -148
  112. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-init.js +0 -20
  113. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-intents.js +0 -84
  114. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js +0 -160
  115. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment.js +0 -16
  116. data/app/assets/javascripts/spree/frontend/solidus_stripe.js +0 -6
  117. data/app/controllers/solidus_stripe/payment_request_controller.rb +0 -52
  118. data/app/controllers/spree/stripe_controller.rb +0 -13
  119. data/app/decorators/models/spree/order_update_attributes_decorator.rb +0 -39
  120. data/app/decorators/models/spree/payment_decorator.rb +0 -11
  121. data/app/decorators/models/spree/refund_decorator.rb +0 -9
  122. data/app/models/solidus_stripe/address_from_params_service.rb +0 -72
  123. data/app/models/solidus_stripe/create_intents_payment_service.rb +0 -114
  124. data/app/models/solidus_stripe/prepare_order_for_payment_service.rb +0 -46
  125. data/app/models/solidus_stripe/shipping_rates_service.rb +0 -46
  126. data/app/models/spree/payment_method/stripe_credit_card.rb +0 -217
  127. data/bin/r +0 -13
  128. data/bin/sandbox_rails +0 -18
  129. data/db/migrate/20181010123508_update_stripe_payment_method_type_to_credit_card.rb +0 -21
  130. data/lib/assets/stylesheets/spree/frontend/solidus_stripe.scss +0 -11
  131. data/lib/solidus_stripe/testing_support/card_input_helper.rb +0 -34
  132. data/lib/tasks/solidus_stripe/db/seed.rake +0 -14
  133. data/lib/views/api/spree/api/payments/source_views/_stripe.json.jbuilder +0 -3
  134. data/lib/views/backend/spree/admin/log_entries/_stripe.html.erb +0 -28
  135. data/lib/views/backend/spree/admin/payments/source_forms/_stripe.html.erb +0 -1
  136. data/lib/views/backend/spree/admin/payments/source_views/_stripe.html.erb +0 -1
  137. data/lib/views/frontend/spree/checkout/existing_payment/_stripe.html.erb +0 -1
  138. data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +0 -8
  139. data/lib/views/frontend/spree/checkout/payment/v2/_javascript.html.erb +0 -78
  140. data/lib/views/frontend/spree/checkout/payment/v3/_elements.html.erb +0 -1
  141. data/lib/views/frontend/spree/checkout/payment/v3/_form_elements.html.erb +0 -40
  142. data/lib/views/frontend/spree/checkout/payment/v3/_intents.html.erb +0 -1
  143. data/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb +0 -2
  144. data/lib/views/frontend/spree/orders/_stripe_payment_request_button.html.erb +0 -14
  145. data/spec/features/stripe_checkout_spec.rb +0 -486
  146. data/spec/models/solidus_stripe/address_from_params_service_spec.rb +0 -87
  147. data/spec/models/solidus_stripe/create_intents_payment_service_spec.rb +0 -127
  148. data/spec/models/solidus_stripe/prepare_order_for_payment_service_spec.rb +0 -65
  149. data/spec/models/solidus_stripe/shipping_rates_service_spec.rb +0 -54
  150. data/spec/models/spree/payment_method/stripe_credit_card_spec.rb +0 -316
  151. data/spec/requests/payment_requests_spec.rb +0 -152
  152. data/spec/spec_helper.rb +0 -37
  153. data/spec/support/solidus_address_helper.rb +0 -15
@@ -1,78 +0,0 @@
1
- <script type="text/javascript" src="https://js.stripe.com/v2/"></script>
2
- <script type="text/javascript">
3
- Stripe.setPublishableKey("<%= payment_method.preferred_publishable_key %>");
4
- </script>
5
-
6
- <script>
7
- window.SolidusStripe = window.SolidusStripe || {};
8
- SolidusStripe.paymentMethod = $('#payment_method_' + <%= payment_method.id %>);
9
- var mapCC, stripeResponseHandler;
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
-
27
- stripeResponseHandler = function(status, response) {
28
- var paymentMethodId, token;
29
- if (response.error) {
30
- $('#stripeError').html(response.error.message);
31
- return $('#stripeError').show();
32
- } else {
33
- SolidusStripe.paymentMethod.find('#card_number, #card_expiry, #card_code').prop("disabled", true);
34
- SolidusStripe.paymentMethod.find(".ccType").prop("disabled", false);
35
- SolidusStripe.paymentMethod.find(".ccType").val(mapCC(response.card.brand));
36
- token = response['id'];
37
- paymentMethodId = SolidusStripe.paymentMethod.prop('id').split("_")[2];
38
- SolidusStripe.paymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][gateway_payment_profile_id]' value='" + token + "'/>");
39
- SolidusStripe.paymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][last_digits]' value='" + response.card.last4 + "'/>");
40
- SolidusStripe.paymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][month]' value='" + response.card.exp_month + "'/>");
41
- SolidusStripe.paymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][year]' value='" + response.card.exp_year + "'/>");
42
- return SolidusStripe.paymentMethod.parents("form").get(0).submit();
43
- }
44
- };
45
-
46
- $(document).ready(function() {
47
- SolidusStripe.paymentMethod.prepend("<div id='stripeError' class='errorExplanation' style='display:none'></div>");
48
- return $('#checkout_form_payment [data-hook=buttons]').click(function() {
49
- var expiration, params;
50
- $('#stripeError').hide();
51
- if (SolidusStripe.paymentMethod.is(':visible')) {
52
- expiration = $('.cardExpiry:visible').payment('cardExpiryVal');
53
- params = $.extend({
54
- number: $('.cardNumber:visible').val(),
55
- cvc: $('.cardCode:visible').val(),
56
- exp_month: expiration.month || 0,
57
- exp_year: expiration.year || 0
58
- }, Spree.stripeAdditionalInfo);
59
- Stripe.card.createToken(params, stripeResponseHandler);
60
- return false;
61
- }
62
- });
63
- });
64
- </script>
65
-
66
- <%- if @order.has_checkout_step?('address') -%>
67
- <script>
68
- Spree.stripeAdditionalInfo = {
69
- name: "<%= SolidusSupport.combined_first_and_last_name_in_address? ? @order.bill_address.name : @order.bill_address.full_name %>",
70
- address_line1: "<%= @order.bill_address.address1 %>",
71
- address_line2: "<%= @order.bill_address.address2 %>",
72
- address_city: "<%= @order.bill_address.city %>",
73
- address_state: "<%= @order.bill_address.state_text %>",
74
- address_zip: "<%= @order.bill_address.zipcode %>",
75
- address_country: "<%= @order.bill_address.country %>"
76
- }
77
- </script>
78
- <%- end -%>
@@ -1 +0,0 @@
1
- <%= render 'spree/checkout/payment/v3/form_elements', payment_method: payment_method, stripe_v3_api: 'elements' %>
@@ -1,40 +0,0 @@
1
- <div id="payment-request-button" data-stripe-config="<%= payment_method.stripe_config(current_order).to_json %>" data-v3-api="<%= stripe_v3_api %>"></div>
2
-
3
- <% param_prefix = "payment_source[#{payment_method.id}]" %>
4
- <% name = SolidusSupport.combined_first_and_last_name_in_address? ? @order.name : "#{@order.billing_firstname} #{@order.billing_lastname}" %>
5
-
6
- <div class="field field-required">
7
- <%= label_tag "name_on_card_#{payment_method.id}", t('spree.name_on_card') %>
8
- <%= text_field_tag "#{param_prefix}[name]", name, { id: "name_on_card_#{payment_method.id}", autocomplete: "cc-name" } %>
9
- </div>
10
-
11
- <div class="field field-required" data-hook="card_number">
12
- <%= label_tag "card_number", t('spree.card_number') %>
13
- <div id="card_number"></div>
14
- <span id="card_type" style="display:none;">
15
- ( <span id="looks_like" ><%= t('spree.card_type_is') %> <span id="type"></span></span>
16
- <span id="unrecognized"><%= t('spree.unrecognized_card_type') %></span>
17
- )
18
- </span>
19
- </div>
20
-
21
- <div class="field field-required" data-hook="card_expiration">
22
- <%= label_tag "card_expiry", t('spree.expiration') %>
23
- <div id="card_expiry"></div>
24
- </div>
25
-
26
- <div class="field field-required" data-hook="card_code">
27
- <%= label_tag "card_cvc", t('spree.card_code') %>
28
- <div id="card_cvc"></div>
29
- <%= link_to "(#{t('spree.what_is_this')})", spree.cvv_path, target: '_blank', "data-hook" => "cvv_link", id: "cvv_link" %>
30
- </div>
31
-
32
- <div id="card-errors" class='errorExplanation' role="alert" style="display: none"></div>
33
-
34
- <% if @order.bill_address %>
35
- <%= fields_for "#{param_prefix}[address_attributes]", @order.bill_address do |f| %>
36
- <%= render partial: 'spree/address/form_hidden', locals: { form: f } %>
37
- <% end %>
38
- <% end %>
39
-
40
- <%= hidden_field_tag "#{param_prefix}[cc_type]", '', id: "cc_type", class: 'ccType' %>
@@ -1 +0,0 @@
1
- <%= render 'spree/checkout/payment/v3/form_elements', payment_method: payment_method, stripe_v3_api: 'payment-intents' %>
@@ -1,2 +0,0 @@
1
- <% ActiveSupport::Deprecation.warn 'Partial `spree/checkout/payment/v3/_stripe.html.erb` is deprecated and will be removed soon. Please use partial `spree/checkout/payment/v3/elements`', caller(1) %>
2
- <%= render 'spree/checkout/payment/v3/elements', payment_method: payment_method, stripe_v3_api: 'elements' %>
@@ -1,14 +0,0 @@
1
- <% if current_order.present? && cart_checkout_payment_method.present? %>
2
- <div id="stripe-payment-request" class="stripe-payment-request" data-v3-api="payment-request-button" style="display:none">
3
- <div id="payment-request-button"
4
- data-stripe-config="<%= cart_checkout_payment_method.stripe_config(current_order).to_json %>"
5
- data-order-token="<%= current_order.guest_token %>"
6
- data-submit-url="<%= api_checkout_path(current_order.number) %>"
7
- data-complete-url="<%= checkout_path %>"
8
- class="payment-request-button">
9
- </div>
10
-
11
- <div id="card-errors" class='errorExplanation' role="alert" style="display: none">
12
- </div>
13
- </div>
14
- <% end %>
@@ -1,486 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe "Stripe checkout", type: :feature do
6
- let(:zone) { FactoryBot.create(:zone) }
7
- let(:country) { FactoryBot.create(:country) }
8
-
9
- let(:card_3d_secure) { "4000 0025 0000 3155" }
10
-
11
- before do
12
- FactoryBot.create(:store)
13
- zone.members << Spree::ZoneMember.create!(zoneable: country)
14
- FactoryBot.create(:free_shipping_method)
15
-
16
- Spree::PaymentMethod::StripeCreditCard.create!(
17
- name: "Stripe",
18
- preferred_secret_key: "sk_test_VCZnDv3GLU15TRvn8i2EsaAN",
19
- preferred_publishable_key: "pk_test_Cuf0PNtiAkkMpTVC2gwYDMIg",
20
- preferred_v3_elements: preferred_v3_elements,
21
- preferred_v3_intents: preferred_v3_intents
22
- )
23
-
24
- FactoryBot.create(:product, name: "DL-44")
25
-
26
- visit spree.root_path
27
- click_link "DL-44"
28
- click_button "Add To Cart"
29
-
30
- expect(page).to have_current_path("/cart")
31
- click_button "Checkout"
32
-
33
- expect(page).to have_current_path("/checkout/registration")
34
- click_link "Create a new account"
35
- within("#new_spree_user") do
36
- fill_in "Email", with: "mary@example.com"
37
- fill_in "Password", with: "superStrongPassword"
38
- fill_in "Password Confirmation", with: "superStrongPassword"
39
- end
40
- click_button "Create"
41
-
42
- # Address
43
- expect(page).to have_current_path("/checkout/address")
44
-
45
- within("#billing") do
46
- fill_in_name
47
- fill_in "Street Address", with: "YT-1300"
48
- fill_in "City", with: "Mos Eisley"
49
- select "United States of America", from: "Country"
50
- select country.states.first.name, from: "order_bill_address_attributes_state_id"
51
- fill_in "Zip", with: "12010"
52
- fill_in "Phone", with: "(555) 555-5555"
53
- end
54
- click_on "Save and Continue"
55
-
56
- # Delivery
57
- expect(page).to have_current_path("/checkout/delivery")
58
- expect(page).to have_content("UPS Ground")
59
- click_on "Save and Continue"
60
-
61
- # Payment
62
- expect(page).to have_current_path("/checkout/payment")
63
- end
64
-
65
- # This will fetch a token from Stripe.com and then pass that to the webserver.
66
- # The server then processes the payment using that token.
67
-
68
- context 'when using Stripe V2 API library' do
69
- let(:preferred_v3_elements) { false }
70
- let(:preferred_v3_intents) { false }
71
-
72
- it "can process a valid payment", js: true do
73
- fill_in_card
74
- click_button "Save and Continue"
75
- expect(page).to have_current_path("/checkout/confirm")
76
- click_button "Place Order"
77
- expect(page).to have_content("Your order has been processed successfully")
78
- end
79
-
80
- it "can re-use saved cards", js: true do
81
- fill_in_card
82
- click_button "Save and Continue"
83
-
84
- expect(page).to have_current_path("/checkout/confirm")
85
- click_button "Place Order"
86
- expect(page).to have_content("Your order has been processed successfully")
87
-
88
- visit spree.root_path
89
- click_link "DL-44"
90
- click_button "Add To Cart"
91
-
92
- expect(page).to have_current_path("/cart")
93
- click_button "Checkout"
94
-
95
- # Address
96
- expect(page).to have_current_path("/checkout/address")
97
-
98
- within("#billing") do
99
- fill_in_name
100
- fill_in "Street Address", with: "YT-1300"
101
- fill_in "City", with: "Mos Eisley"
102
- select "United States of America", from: "Country"
103
- select country.states.first.name, from: "order_bill_address_attributes_state_id"
104
- fill_in "Zip", with: "12010"
105
- fill_in "Phone", with: "(555) 555-5555"
106
- end
107
- click_on "Save and Continue"
108
-
109
- # Delivery
110
- expect(page).to have_current_path("/checkout/delivery")
111
- expect(page).to have_content("UPS Ground")
112
- click_on "Save and Continue"
113
-
114
- # Payment
115
- expect(page).to have_current_path("/checkout/payment")
116
- choose "Use an existing card on file"
117
- click_button "Save and Continue"
118
-
119
- # Confirm
120
- expect(page).to have_current_path("/checkout/confirm")
121
- click_button "Place Order"
122
- expect(page).to have_content("Your order has been processed successfully")
123
- end
124
-
125
- it "shows an error with a missing credit card number", js: true do
126
- fill_in_card({ number: "", code: "" })
127
- click_button "Save and Continue"
128
- expect(page).to have_content("Could not find payment information")
129
- end
130
-
131
- it "shows an error with a missing expiration date", js: true do
132
- fill_in_card({ exp_month: "", exp_year: "" })
133
- click_button "Save and Continue"
134
- expect(page).to have_content("Your card's expiration year is invalid.")
135
- end
136
-
137
- it "shows an error with an invalid credit card number", js: true do
138
- fill_in_card({ number: "1111 1111 1111 1111" })
139
- click_button "Save and Continue"
140
- expect(page).to have_content("Your card number is incorrect.")
141
- end
142
-
143
- it "shows an error with invalid security fields", js: true do
144
- fill_in_card({ code: "12" })
145
- click_button "Save and Continue"
146
- expect(page).to have_content("Your card's security code is invalid.")
147
- end
148
-
149
- it "shows an error with invalid expiry fields", js: true do
150
- fill_in_card({ exp_month: "00" })
151
- click_button "Save and Continue"
152
- expect(page).to have_content("Your card's expiration month is invalid.")
153
- end
154
- end
155
-
156
- shared_examples "Stripe Elements invalid payments" do
157
- it "shows an error with a missing credit card number" do
158
- fill_in_card({ number: "" })
159
- click_button "Save and Continue"
160
- expect(page).to have_content("Your card number is incomplete.")
161
- end
162
-
163
- it "shows an error with a missing expiration date" do
164
- fill_in_card({ exp_month: "", exp_year: "" })
165
- click_button "Save and Continue"
166
- expect(page).to have_content("Your card's expiration date is incomplete.")
167
- end
168
-
169
- it "shows an error with an invalid credit card number" do
170
- fill_in_card({ number: "1111 1111 1111 1111" })
171
- click_button "Save and Continue"
172
- expect(page).to have_content("Your card number is invalid.")
173
- end
174
-
175
- it "shows an error with invalid security fields" do
176
- fill_in_card({ code: "12" })
177
- click_button "Save and Continue"
178
- expect(page).to have_content("Your card's security code is incomplete.")
179
- end
180
-
181
- it "shows an error with invalid expiry fields" do
182
- fill_in_card({ exp_month: "01", exp_year: "3" })
183
- click_button "Save and Continue"
184
- expect(page).to have_content("Your card's expiration date is incomplete.")
185
- end
186
- end
187
-
188
- context 'when using Stripe V3 API library with Elements', :js do
189
- let(:preferred_v3_elements) { true }
190
- let(:preferred_v3_intents) { false }
191
-
192
- it "can process a valid payment" do
193
- fill_in_card
194
- click_button "Save and Continue"
195
- expect(page).to have_current_path("/checkout/confirm")
196
- click_button "Place Order"
197
- expect(page).to have_content("Your order has been processed successfully")
198
- end
199
-
200
- context "when reusing saved cards" do
201
- stub_authorization!
202
-
203
- it "completes the order, captures the payment and cancels the order" do
204
- fill_in_card
205
- click_button "Save and Continue"
206
- expect(page).to have_current_path("/checkout/confirm")
207
- click_button "Place Order"
208
- expect(page).to have_content("Your order has been processed successfully")
209
-
210
- visit spree.root_path
211
- click_link "DL-44"
212
- click_button "Add To Cart"
213
-
214
- expect(page).to have_current_path("/cart")
215
- click_button "Checkout"
216
-
217
- # Address
218
- expect(page).to have_current_path("/checkout/address")
219
-
220
- within("#billing") do
221
- fill_in_name
222
- fill_in "Street Address", with: "YT-1300"
223
- fill_in "City", with: "Mos Eisley"
224
- select "United States of America", from: "Country"
225
- select country.states.first.name, from: "order_bill_address_attributes_state_id"
226
- fill_in "Zip", with: "12010"
227
- fill_in "Phone", with: "(555) 555-5555"
228
- end
229
- click_on "Save and Continue"
230
-
231
- # Delivery
232
- expect(page).to have_current_path("/checkout/delivery")
233
- expect(page).to have_content("UPS Ground")
234
- click_on "Save and Continue"
235
-
236
- # Payment
237
- expect(page).to have_current_path("/checkout/payment")
238
- choose "Use an existing card on file"
239
- click_button "Save and Continue"
240
-
241
- # Confirm
242
- expect(page).to have_current_path("/checkout/confirm")
243
- click_button "Place Order"
244
- expect(page).to have_content("Your order has been processed successfully")
245
-
246
- Spree::Order.complete.each do |order|
247
- # Capture in backend
248
-
249
- visit spree.admin_path
250
-
251
- expect(page).to have_selector("#listing_orders tbody tr", count: 2)
252
-
253
- click_link order.number
254
-
255
- click_link "Payments"
256
- find(".fa-capture").click
257
-
258
- expect(page).to have_content "Payment Updated"
259
- expect(find("table#payments")).to have_content "Completed"
260
-
261
- # Order cancel, after capture
262
- click_link "Cart"
263
-
264
- within "#sidebar" do
265
- expect(page).to have_content "Completed"
266
- end
267
-
268
- page.accept_alert do
269
- find('input[value="Cancel"]').click
270
- end
271
-
272
- expect(page).to have_content "Order canceled"
273
-
274
- within "#sidebar" do
275
- expect(page).to have_content "Canceled"
276
- end
277
- end
278
- end
279
- end
280
-
281
- it_behaves_like "Stripe Elements invalid payments"
282
- end
283
-
284
- context "when using Stripe V3 API library with Intents", :js do
285
- let(:preferred_v3_elements) { false }
286
- let(:preferred_v3_intents) { true }
287
-
288
- context "when using a valid 3D Secure card" do
289
- it "successfully completes the checkout" do
290
- authenticate_3d_secure_card(card_3d_secure)
291
-
292
- expect(page).to have_current_path("/checkout/confirm")
293
-
294
- click_button "Place Order"
295
-
296
- expect(page).to have_content("Your order has been processed successfully")
297
- end
298
- end
299
-
300
- context "when using a card without enough money" do
301
- it "fails the payment" do
302
- fill_in_card({ number: "4000 0000 0000 9995" })
303
- click_button "Save and Continue"
304
-
305
- expect(page).to have_content "Your card has insufficient funds."
306
- end
307
- end
308
-
309
- context "when entering the wrong 3D verification code" do
310
- it "fails the payment" do
311
- fill_in_card({ number: "4000 0084 0000 1629" })
312
- click_button "Save and Continue"
313
-
314
- within_3d_secure_modal do
315
- click_button 'Complete authentication'
316
- end
317
-
318
- expect(page).to have_content "Your card was declined."
319
- end
320
- end
321
-
322
- context "when reusing a card" do
323
- stub_authorization!
324
-
325
- it "succesfully creates a second payment that can be captured in the backend" do
326
- authenticate_3d_secure_card(card_3d_secure)
327
-
328
- expect(page).to have_current_path("/checkout/confirm")
329
- click_button "Place Order"
330
- expect(page).to have_content("Your order has been processed successfully")
331
-
332
- visit spree.root_path
333
- click_link "DL-44"
334
- click_button "Add To Cart"
335
-
336
- expect(page).to have_current_path("/cart")
337
- click_button "Checkout"
338
-
339
- # Address
340
- expect(page).to have_current_path("/checkout/address")
341
-
342
- within("#billing") do
343
- fill_in_name
344
- fill_in "Street Address", with: "YT-1300"
345
- fill_in "City", with: "Mos Eisley"
346
- select "United States of America", from: "Country"
347
- select country.states.first.name, from: "order_bill_address_attributes_state_id"
348
- fill_in "Zip", with: "12010"
349
- fill_in "Phone", with: "(555) 555-5555"
350
- end
351
- click_on "Save and Continue"
352
-
353
- # Delivery
354
- expect(page).to have_current_path("/checkout/delivery")
355
- expect(page).to have_content("UPS Ground")
356
- click_on "Save and Continue"
357
-
358
- # Payment
359
- expect(page).to have_current_path("/checkout/payment")
360
- choose "Use an existing card on file"
361
- click_button "Save and Continue"
362
-
363
- # Confirm
364
- expect(page).to have_current_path("/checkout/confirm")
365
- click_button "Place Order"
366
- expect(page).to have_content("Your order has been processed successfully")
367
-
368
- Spree::Order.complete.each do |order|
369
- # Capture in backend
370
-
371
- visit spree.admin_path
372
-
373
- expect(page).to have_selector("#listing_orders tbody tr", count: 2)
374
-
375
- click_link order.number
376
-
377
- click_link "Payments"
378
- find(".fa-capture").click
379
-
380
- expect(page).to have_content "Payment Updated"
381
- expect(find("table#payments")).to have_content "Completed"
382
-
383
- # Order cancel, after capture
384
- click_link "Cart"
385
-
386
- within "#sidebar" do
387
- expect(page).to have_content "Completed"
388
- end
389
-
390
- page.accept_alert do
391
- find('input[value="Cancel"]').click
392
- end
393
-
394
- expect(page).to have_content "Order canceled"
395
-
396
- within "#sidebar" do
397
- expect(page).to have_content "Canceled"
398
- end
399
- end
400
- end
401
- end
402
-
403
- context "when paying with multiple payment methods" do
404
- stub_authorization!
405
-
406
- context "when paying first with regular card, then with 3D-Secure card" do
407
- let(:regular_card) { "4242 4242 4242 4242" }
408
-
409
- it "voids the first stripe payment and successfully pays with 3DS card" do
410
- fill_in_card({ number: regular_card })
411
- click_button "Save and Continue"
412
-
413
- expect(page).to have_content "Ending in #{regular_card.last(4)}"
414
-
415
- click_link "Payment"
416
-
417
- authenticate_3d_secure_card(card_3d_secure)
418
- click_button "Place Order"
419
- expect(page).to have_content "Your order has been processed successfully"
420
-
421
- visit spree.admin_path
422
- click_link Spree::Order.complete.first.number
423
- click_link "Payments"
424
-
425
- payments = all('table#payments tbody tr')
426
-
427
- expect(payments.first).to have_content "Stripe"
428
- expect(payments.first).to have_content "Void"
429
-
430
- expect(payments.last).to have_content "Stripe"
431
- expect(payments.last).to have_content "Pending"
432
- end
433
- end
434
-
435
- context "when paying first with 3D-Secure card, then with check" do
436
- before { create :check_payment_method }
437
-
438
- it "voids the stripe payment and successfully pays with check" do
439
- authenticate_3d_secure_card(card_3d_secure)
440
- expect(page).to have_current_path("/checkout/confirm")
441
-
442
- click_link "Payment"
443
- choose "Check"
444
- click_button "Save and Continue"
445
- expect(find(".payment-info")).to have_content "Check"
446
- expect(page).to have_content "Your order has been processed successfully"
447
-
448
- visit spree.admin_path
449
- click_link Spree::Order.complete.first.number
450
- click_link "Payments"
451
- payments = all('table#payments tbody tr')
452
-
453
- stripe_payment = payments.first
454
- expect(stripe_payment).to have_content "Stripe"
455
- expect(stripe_payment).to have_content "Void"
456
-
457
- check_payment = payments.last
458
- expect(check_payment).to have_content "Check"
459
- end
460
- end
461
- end
462
-
463
- it_behaves_like "Stripe Elements invalid payments"
464
- end
465
-
466
- def within_3d_secure_modal
467
- within_frame find("iframe[src*='authorize-with-url-inner']") do
468
- within_frame "__stripeJSChallengeFrame" do
469
- within_frame "acsFrame" do
470
- yield
471
- end
472
- end
473
- end
474
- end
475
-
476
- def authenticate_3d_secure_card(card_number)
477
- fill_in_card({ number: card_number })
478
- click_button "Save and Continue"
479
-
480
- within_3d_secure_modal do
481
- expect(page).to have_content '$19.99 USD using 3D Secure'
482
-
483
- click_button 'Complete authentication'
484
- end
485
- end
486
- end