solidus_stripe 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +35 -0
- data/.gem_release.yml +8 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.rubocop.yml +319 -0
- data/.travis.yml +28 -0
- data/Gemfile +25 -0
- data/LICENSE.md +26 -0
- data/README.md +115 -0
- data/Rakefile +23 -0
- data/app/models/spree/payment_method/stripe_credit_card.rb +136 -0
- data/bin/rails +7 -0
- data/db/migrate/20181010123508_update_stripe_payment_method_type_to_credit_card.rb +21 -0
- data/db/seeds.rb +26 -0
- data/lib/assets/stylesheets/spree/frontend/solidus_stripe.scss +6 -0
- data/lib/generators/solidus_stripe/install/install_generator.rb +46 -0
- data/lib/solidus_stripe.rb +7 -0
- data/lib/solidus_stripe/engine.rb +23 -0
- data/lib/solidus_stripe/version.rb +5 -0
- data/lib/tasks/solidus_stripe/db/seed.rake +14 -0
- data/lib/views/api/spree/api/payments/source_views/_stripe.json.jbuilder +3 -0
- data/lib/views/backend/spree/admin/log_entries/_stripe.html.erb +28 -0
- data/lib/views/backend/spree/admin/payments/source_forms/_stripe.html.erb +1 -0
- data/lib/views/backend/spree/admin/payments/source_views/_stripe.html.erb +1 -0
- data/lib/views/frontend/spree/checkout/existing_payment/_stripe.html.erb +1 -0
- data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +6 -0
- data/lib/views/frontend/spree/checkout/payment/v2/_javascript.html.erb +77 -0
- data/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb +133 -0
- data/solidus_stripe.gemspec +45 -0
- data/spec/features/stripe_checkout_spec.rb +279 -0
- data/spec/models/spree/payment_method/stripe_credit_card_spec.rb +205 -0
- data/spec/spec_helper.rb +20 -0
- metadata +264 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
<tr>
|
2
|
+
<td><%= t(:message, :scope => [:spree, :log_entry, :stripe]) %></td>
|
3
|
+
<td><%= entry.parsed_details.message %></td>
|
4
|
+
</tr>
|
5
|
+
<tr>
|
6
|
+
<td><%= t(:charge_id, :scope => [:spree, :log_entry, :stripe]) %></td>
|
7
|
+
<td><%= entry.parsed_details.params['id'] %></td>
|
8
|
+
</tr>
|
9
|
+
<% if card = entry.parsed_details.params['card'] %>
|
10
|
+
<tr>
|
11
|
+
<td><%= t(:card_id, :scope => [:spree, :log_entry, :stripe]) %></td>
|
12
|
+
<td><%= card['id'] %></td>
|
13
|
+
</tr>
|
14
|
+
|
15
|
+
<tr>
|
16
|
+
<td><%= t(:cvc_check, :scope => [:spree, :log_entry, :stripe]) %></td>
|
17
|
+
<td><%= card['cvc_check'] %></td>
|
18
|
+
</tr>
|
19
|
+
|
20
|
+
<tr>
|
21
|
+
<td><%= t(:address_zip_check, :scope => [:spree, :log_entry, :stripe]) %></td>
|
22
|
+
<td><%= card['address_zip_check'] %></td>
|
23
|
+
</tr>
|
24
|
+
<% end %>
|
25
|
+
<tr>
|
26
|
+
<td><%= t(:cvv_result, :scope => [:spree, :log_entry, :stripe]) %></td>
|
27
|
+
<td><%= entry.parsed_details.cvv_result['message'].to_s %></td>
|
28
|
+
</tr>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render "spree/admin/payments/source_forms/gateway", payment_method: payment_method, previous_cards: payment_method.reusable_sources(@order) %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render "spree/admin/payments/source_views/gateway", payment: payment %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: "spree/checkout/existing_payment/gateway", locals: { wallet_payment_source: wallet_payment_source, default: default } %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<% if payment_method.v3_elements? %>
|
2
|
+
<%= render 'spree/checkout/payment/v3/stripe', payment_method: payment_method %>
|
3
|
+
<% else %>
|
4
|
+
<%= render "spree/checkout/payment/gateway", payment_method: payment_method %>
|
5
|
+
<%= render 'spree/checkout/payment/v2/javascript', payment_method: payment_method %>
|
6
|
+
<% end %>
|
@@ -0,0 +1,77 @@
|
|
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
|
+
Spree.stripePaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
|
8
|
+
var mapCC, stripeResponseHandler;
|
9
|
+
|
10
|
+
mapCC = function(ccType) {
|
11
|
+
if (ccType === 'MasterCard') {
|
12
|
+
return 'mastercard';
|
13
|
+
} else if (ccType === 'Visa') {
|
14
|
+
return 'visa';
|
15
|
+
} else if (ccType === 'American Express') {
|
16
|
+
return 'amex';
|
17
|
+
} else if (ccType === 'Discover') {
|
18
|
+
return 'discover';
|
19
|
+
} else if (ccType === 'Diners Club') {
|
20
|
+
return 'dinersclub';
|
21
|
+
} else if (ccType === 'JCB') {
|
22
|
+
return 'jcb';
|
23
|
+
}
|
24
|
+
};
|
25
|
+
|
26
|
+
stripeResponseHandler = function(status, response) {
|
27
|
+
var paymentMethodId, token;
|
28
|
+
if (response.error) {
|
29
|
+
$('#stripeError').html(response.error.message);
|
30
|
+
return $('#stripeError').show();
|
31
|
+
} else {
|
32
|
+
Spree.stripePaymentMethod.find('#card_number, #card_expiry, #card_code').prop("disabled", true);
|
33
|
+
Spree.stripePaymentMethod.find(".ccType").prop("disabled", false);
|
34
|
+
Spree.stripePaymentMethod.find(".ccType").val(mapCC(response.card.brand));
|
35
|
+
token = response['id'];
|
36
|
+
paymentMethodId = Spree.stripePaymentMethod.prop('id').split("_")[2];
|
37
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][gateway_payment_profile_id]' value='" + token + "'/>");
|
38
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][last_digits]' value='" + response.card.last4 + "'/>");
|
39
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][month]' value='" + response.card.exp_month + "'/>");
|
40
|
+
Spree.stripePaymentMethod.append("<input type='hidden' class='stripeToken' name='payment_source[" + paymentMethodId + "][year]' value='" + response.card.exp_year + "'/>");
|
41
|
+
return Spree.stripePaymentMethod.parents("form").get(0).submit();
|
42
|
+
}
|
43
|
+
};
|
44
|
+
|
45
|
+
$(document).ready(function() {
|
46
|
+
Spree.stripePaymentMethod.prepend("<div id='stripeError' class='errorExplanation' style='display:none'></div>");
|
47
|
+
return $('#checkout_form_payment [data-hook=buttons]').click(function() {
|
48
|
+
var expiration, params;
|
49
|
+
$('#stripeError').hide();
|
50
|
+
if (Spree.stripePaymentMethod.is(':visible')) {
|
51
|
+
expiration = $('.cardExpiry:visible').payment('cardExpiryVal');
|
52
|
+
params = $.extend({
|
53
|
+
number: $('.cardNumber:visible').val(),
|
54
|
+
cvc: $('.cardCode:visible').val(),
|
55
|
+
exp_month: expiration.month || 0,
|
56
|
+
exp_year: expiration.year || 0
|
57
|
+
}, Spree.stripeAdditionalInfo);
|
58
|
+
Stripe.card.createToken(params, stripeResponseHandler);
|
59
|
+
return false;
|
60
|
+
}
|
61
|
+
});
|
62
|
+
});
|
63
|
+
</script>
|
64
|
+
|
65
|
+
<%- if @order.has_checkout_step?('address') -%>
|
66
|
+
<script>
|
67
|
+
Spree.stripeAdditionalInfo = {
|
68
|
+
name: "<%= @order.bill_address.full_name %>",
|
69
|
+
address_line1: "<%= @order.bill_address.address1 %>",
|
70
|
+
address_line2: "<%= @order.bill_address.address2 %>",
|
71
|
+
address_city: "<%= @order.bill_address.city %>",
|
72
|
+
address_state: "<%= @order.bill_address.state_text %>",
|
73
|
+
address_zip: "<%= @order.bill_address.zipcode %>",
|
74
|
+
address_country: "<%= @order.bill_address.country %>"
|
75
|
+
}
|
76
|
+
</script>
|
77
|
+
<%- end -%>
|
@@ -0,0 +1,133 @@
|
|
1
|
+
<%= image_tag 'credit_cards/credit_card.gif', id: 'credit-card-image' %>
|
2
|
+
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
3
|
+
|
4
|
+
<div class="field field-required">
|
5
|
+
<%= label_tag "name_on_card_#{payment_method.id}", t('spree.name_on_card') %>
|
6
|
+
<%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}", { id: "name_on_card_#{payment_method.id}", autocomplete: "cc-name" } %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="field field-required" data-hook="card_number">
|
10
|
+
<%= label_tag "card_number", t('spree.card_number') %>
|
11
|
+
<div id="card_number"></div>
|
12
|
+
<span id="card_type" style="display:none;">
|
13
|
+
( <span id="looks_like" ><%= t('spree.card_type_is') %> <span id="type"></span></span>
|
14
|
+
<span id="unrecognized"><%= t('spree.unrecognized_card_type') %></span>
|
15
|
+
)
|
16
|
+
</span>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div class="field field-required" data-hook="card_expiration">
|
20
|
+
<%= label_tag "card_expiry", t('spree.expiration') %>
|
21
|
+
<div id="card_expiry"></div>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="field field-required" data-hook="card_code">
|
25
|
+
<%= label_tag "card_cvc", t('spree.card_code') %>
|
26
|
+
<div id="card_cvc"></div>
|
27
|
+
<%= link_to "(#{t('spree.what_is_this')})", spree.cvv_path, target: '_blank', "data-hook" => "cvv_link", id: "cvv_link" %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div id="card-errors" class='errorExplanation' role="alert" style="display: none"></div>
|
31
|
+
|
32
|
+
<% if @order.bill_address %>
|
33
|
+
<%= fields_for "#{param_prefix}[address_attributes]", @order.bill_address do |f| %>
|
34
|
+
<%= render partial: 'spree/address/form_hidden', locals: { form: f } %>
|
35
|
+
<% end %>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
<%= hidden_field_tag "#{param_prefix}[cc_type]", '', id: "cc_type", class: 'ccType' %>
|
39
|
+
|
40
|
+
<script src="https://js.stripe.com/v3/"></script>
|
41
|
+
|
42
|
+
<script>
|
43
|
+
Spree.stripePaymentMethod = $('#payment_method_' + <%= payment_method.id %>);
|
44
|
+
|
45
|
+
var stripe = Stripe("<%= payment_method.preferred_publishable_key %>");
|
46
|
+
|
47
|
+
var elements = stripe.elements({locale: 'en'});
|
48
|
+
|
49
|
+
var style = {
|
50
|
+
base: {
|
51
|
+
color: 'black',
|
52
|
+
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
|
53
|
+
fontSmoothing: 'antialiased',
|
54
|
+
fontSize: '14px',
|
55
|
+
'::placeholder': {
|
56
|
+
color: 'silver'
|
57
|
+
}
|
58
|
+
},
|
59
|
+
invalid: {
|
60
|
+
color: 'red',
|
61
|
+
iconColor: 'red'
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
65
|
+
var cardNumber = elements.create('cardNumber', {style: style});
|
66
|
+
var cardExpiry = elements.create('cardExpiry', {style: style});
|
67
|
+
var cardCvc = elements.create('cardCvc', {style: style});
|
68
|
+
|
69
|
+
cardNumber.mount('#card_number');
|
70
|
+
cardExpiry.mount('#card_expiry');
|
71
|
+
cardCvc.mount('#card_cvc');
|
72
|
+
|
73
|
+
$(function() {
|
74
|
+
var form = Spree.stripePaymentMethod.parents('form');
|
75
|
+
var submitButton = form.find('input[type="submit"]');
|
76
|
+
var errorElement = form.find('#card-errors');
|
77
|
+
var cardType = form.find('input#cc_type');
|
78
|
+
|
79
|
+
cardNumber.addEventListener('change', function(event) {
|
80
|
+
if (event.error) {
|
81
|
+
errorElement.text(event.error.message).show();
|
82
|
+
} else {
|
83
|
+
errorElement.hide().text('');
|
84
|
+
}
|
85
|
+
});
|
86
|
+
|
87
|
+
form.bind('submit', function(event) {
|
88
|
+
if (Spree.stripePaymentMethod.is(':visible')) {
|
89
|
+
event.preventDefault();
|
90
|
+
|
91
|
+
stripe.createToken(cardNumber).then(function(result) {
|
92
|
+
if (result.error) {
|
93
|
+
errorElement.text(result.error.message).show();
|
94
|
+
setTimeout(function() {
|
95
|
+
$.rails.enableElement(submitButton[0]);
|
96
|
+
submitButton.removeAttr('disabled').removeClass('disabled');
|
97
|
+
}, 100);
|
98
|
+
} else {
|
99
|
+
stripeTokenHandler(result.token);
|
100
|
+
}
|
101
|
+
});
|
102
|
+
}
|
103
|
+
});
|
104
|
+
|
105
|
+
function stripeTokenHandler(token) {
|
106
|
+
var paymentMethodId = Spree.stripePaymentMethod.prop('id').split("_")[2];
|
107
|
+
var baseSelector = `<input type='hidden' class='stripeToken' name='payment_source[${paymentMethodId}]`;
|
108
|
+
|
109
|
+
Spree.stripePaymentMethod.append(`${baseSelector}[gateway_payment_profile_id]' value='${token.id}'/>`);
|
110
|
+
Spree.stripePaymentMethod.append(`${baseSelector}[last_digits]' value='${token.card.last4}'/>`);
|
111
|
+
Spree.stripePaymentMethod.append(`${baseSelector}[month]' value='${token.card.exp_month}'/>`);
|
112
|
+
Spree.stripePaymentMethod.append(`${baseSelector}[year]' value='${token.card.exp_year}'/>`);
|
113
|
+
cardType.val(mapCC(token.card.type));
|
114
|
+
form[0].submit();
|
115
|
+
};
|
116
|
+
|
117
|
+
function mapCC(ccType) {
|
118
|
+
if (ccType === 'MasterCard') {
|
119
|
+
return 'mastercard';
|
120
|
+
} else if (ccType === 'Visa') {
|
121
|
+
return 'visa';
|
122
|
+
} else if (ccType === 'American Express') {
|
123
|
+
return 'amex';
|
124
|
+
} else if (ccType === 'Discover') {
|
125
|
+
return 'discover';
|
126
|
+
} else if (ccType === 'Diners Club') {
|
127
|
+
return 'dinersclub';
|
128
|
+
} else if (ccType === 'JCB') {
|
129
|
+
return 'jcb';
|
130
|
+
}
|
131
|
+
};
|
132
|
+
})
|
133
|
+
</script>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'solidus_stripe/version'
|
6
|
+
|
7
|
+
# encoding: UTF-8
|
8
|
+
|
9
|
+
Gem::Specification.new do |s|
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.name = "solidus_stripe"
|
12
|
+
s.version = SolidusStripe::VERSION
|
13
|
+
s.summary = "Stripe Payment Method for Solidus"
|
14
|
+
s.description = s.summary
|
15
|
+
s.required_ruby_version = ">= 2.2"
|
16
|
+
|
17
|
+
s.author = "Solidus Team"
|
18
|
+
s.email = "contact@solidus.io"
|
19
|
+
s.homepage = "https://solidus.io"
|
20
|
+
s.license = 'BSD-3'
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
24
|
+
s.require_path = "lib"
|
25
|
+
s.requirements << "none"
|
26
|
+
|
27
|
+
s.add_dependency "solidus_core", [">= 2.3", "< 3"]
|
28
|
+
s.add_dependency "solidus_support", ">= 0.3.1"
|
29
|
+
|
30
|
+
# ActiveMerchant v1.58 through v1.59 introduced a breaking change
|
31
|
+
# to the stripe gateway.
|
32
|
+
#
|
33
|
+
# This was resolved in v1.60, but we still need to skip 1.58 & 1.59.
|
34
|
+
s.add_dependency "activemerchant", "~> 1.48", "!= 1.58.0", "!= 1.59.0"
|
35
|
+
|
36
|
+
s.add_development_dependency "capybara"
|
37
|
+
s.add_development_dependency "capybara-screenshot"
|
38
|
+
s.add_development_dependency "database_cleaner", "~> 1.5"
|
39
|
+
s.add_development_dependency "factory_bot", "~> 4.4"
|
40
|
+
s.add_development_dependency "gem-release", "~> 2.0"
|
41
|
+
s.add_development_dependency "rspec-rails", "~> 3.2"
|
42
|
+
s.add_development_dependency 'selenium-webdriver', '~> 3.142'
|
43
|
+
s.add_development_dependency "simplecov"
|
44
|
+
s.add_development_dependency "sqlite3"
|
45
|
+
end
|
@@ -0,0 +1,279 @@
|
|
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
|
+
before do
|
10
|
+
FactoryBot.create(:store)
|
11
|
+
zone.members << Spree::ZoneMember.create!(zoneable: country)
|
12
|
+
FactoryBot.create(:free_shipping_method)
|
13
|
+
|
14
|
+
Spree::PaymentMethod::StripeCreditCard.create!(
|
15
|
+
name: "Stripe",
|
16
|
+
preferred_secret_key: "sk_test_VCZnDv3GLU15TRvn8i2EsaAN",
|
17
|
+
preferred_publishable_key: "pk_test_Cuf0PNtiAkkMpTVC2gwYDMIg",
|
18
|
+
preferred_v3_elements: preferred_v3_elements
|
19
|
+
)
|
20
|
+
|
21
|
+
FactoryBot.create(:product, name: "DL-44")
|
22
|
+
|
23
|
+
visit spree.root_path
|
24
|
+
click_link "DL-44"
|
25
|
+
click_button "Add To Cart"
|
26
|
+
|
27
|
+
expect(page).to have_current_path("/cart")
|
28
|
+
click_button "Checkout"
|
29
|
+
|
30
|
+
expect(page).to have_current_path("/checkout/registration")
|
31
|
+
click_link "Create a new account"
|
32
|
+
within("#new_spree_user") do
|
33
|
+
fill_in "Email", with: "mary@example.com"
|
34
|
+
fill_in "Password", with: "superStrongPassword"
|
35
|
+
fill_in "Password Confirmation", with: "superStrongPassword"
|
36
|
+
end
|
37
|
+
click_button "Create"
|
38
|
+
|
39
|
+
# Address
|
40
|
+
expect(page).to have_current_path("/checkout/address")
|
41
|
+
|
42
|
+
within("#billing") do
|
43
|
+
fill_in "First Name", with: "Han"
|
44
|
+
fill_in "Last Name", with: "Solo"
|
45
|
+
fill_in "Street Address", with: "YT-1300"
|
46
|
+
fill_in "City", with: "Mos Eisley"
|
47
|
+
select "United States of America", from: "Country"
|
48
|
+
select country.states.first.name, from: "order_bill_address_attributes_state_id"
|
49
|
+
fill_in "Zip", with: "12010"
|
50
|
+
fill_in "Phone", with: "(555) 555-5555"
|
51
|
+
end
|
52
|
+
click_on "Save and Continue"
|
53
|
+
|
54
|
+
# Delivery
|
55
|
+
expect(page).to have_current_path("/checkout/delivery")
|
56
|
+
expect(page).to have_content("UPS Ground")
|
57
|
+
end
|
58
|
+
|
59
|
+
# This will fetch a token from Stripe.com and then pass that to the webserver.
|
60
|
+
# The server then processes the payment using that token.
|
61
|
+
|
62
|
+
context 'when using Stripe V2 API library' do
|
63
|
+
let(:preferred_v3_elements) { false }
|
64
|
+
|
65
|
+
before do
|
66
|
+
click_on "Save and Continue"
|
67
|
+
expect(page).to have_current_path("/checkout/payment")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "can process a valid payment", js: true do
|
71
|
+
fill_in "Card Number", with: "4242 4242 4242 4242"
|
72
|
+
fill_in "Card Code", with: "123"
|
73
|
+
fill_in "Expiration", with: "01 / #{Time.now.year + 1}"
|
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 Number", with: "4242 4242 4242 4242"
|
82
|
+
fill_in "Card Code", with: "123"
|
83
|
+
fill_in "Expiration", with: "01 / #{Time.now.year + 1}"
|
84
|
+
click_button "Save and Continue"
|
85
|
+
|
86
|
+
expect(page).to have_current_path("/checkout/confirm")
|
87
|
+
click_button "Place Order"
|
88
|
+
expect(page).to have_content("Your order has been processed successfully")
|
89
|
+
|
90
|
+
visit spree.root_path
|
91
|
+
click_link "DL-44"
|
92
|
+
click_button "Add To Cart"
|
93
|
+
|
94
|
+
expect(page).to have_current_path("/cart")
|
95
|
+
click_button "Checkout"
|
96
|
+
|
97
|
+
# Address
|
98
|
+
expect(page).to have_current_path("/checkout/address")
|
99
|
+
|
100
|
+
within("#billing") do
|
101
|
+
fill_in "First Name", with: "Han"
|
102
|
+
fill_in "Last Name", with: "Solo"
|
103
|
+
fill_in "Street Address", with: "YT-1300"
|
104
|
+
fill_in "City", with: "Mos Eisley"
|
105
|
+
select "United States of America", from: "Country"
|
106
|
+
select country.states.first.name, from: "order_bill_address_attributes_state_id"
|
107
|
+
fill_in "Zip", with: "12010"
|
108
|
+
fill_in "Phone", with: "(555) 555-5555"
|
109
|
+
end
|
110
|
+
click_on "Save and Continue"
|
111
|
+
|
112
|
+
# Delivery
|
113
|
+
expect(page).to have_current_path("/checkout/delivery")
|
114
|
+
expect(page).to have_content("UPS Ground")
|
115
|
+
click_on "Save and Continue"
|
116
|
+
|
117
|
+
# Payment
|
118
|
+
expect(page).to have_current_path("/checkout/payment")
|
119
|
+
choose "Use an existing card on file"
|
120
|
+
click_button "Save and Continue"
|
121
|
+
|
122
|
+
# Confirm
|
123
|
+
expect(page).to have_current_path("/checkout/confirm")
|
124
|
+
click_button "Place Order"
|
125
|
+
expect(page).to have_content("Your order has been processed successfully")
|
126
|
+
end
|
127
|
+
|
128
|
+
it "shows an error with a missing credit card number", js: true do
|
129
|
+
fill_in "Expiration", with: "01 / #{Time.now.year + 1}"
|
130
|
+
click_button "Save and Continue"
|
131
|
+
expect(page).to have_content("Could not find payment information")
|
132
|
+
end
|
133
|
+
|
134
|
+
it "shows an error with a missing expiration date", js: true do
|
135
|
+
fill_in "Card Number", with: "4242 4242 4242 4242"
|
136
|
+
click_button "Save and Continue"
|
137
|
+
expect(page).to have_content("Your card's expiration year is invalid.")
|
138
|
+
end
|
139
|
+
|
140
|
+
it "shows an error with an invalid credit card number", js: true do
|
141
|
+
fill_in "Card Number", with: "1111 1111 1111 1111"
|
142
|
+
fill_in "Expiration", with: "01 / #{Time.now.year + 1}"
|
143
|
+
click_button "Save and Continue"
|
144
|
+
expect(page).to have_content("Your card number is incorrect.")
|
145
|
+
end
|
146
|
+
|
147
|
+
it "shows an error with invalid security fields", js: true do
|
148
|
+
fill_in "Card Number", with: "4242 4242 4242 4242"
|
149
|
+
fill_in "Expiration", with: "01 / #{Time.now.year + 1}"
|
150
|
+
fill_in "Card Code", with: "12"
|
151
|
+
click_button "Save and Continue"
|
152
|
+
expect(page).to have_content("Your card's security code is invalid.")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "shows an error with invalid expiry fields", js: true do
|
156
|
+
fill_in "Card Number", with: "4242 4242 4242 4242"
|
157
|
+
fill_in "Expiration", with: "00 / #{Time.now.year + 1}"
|
158
|
+
fill_in "Card Code", with: "123"
|
159
|
+
click_button "Save and Continue"
|
160
|
+
expect(page).to have_content("Your card's expiration month is invalid.")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context 'when using Stripe V3 API libarary with Elements' do
|
165
|
+
let(:preferred_v3_elements) { true }
|
166
|
+
|
167
|
+
before do
|
168
|
+
click_on "Save and Continue"
|
169
|
+
expect(page).to have_current_path("/checkout/payment")
|
170
|
+
end
|
171
|
+
|
172
|
+
it "can process a valid payment", js: true do
|
173
|
+
within_frame find('#card_number iframe') do
|
174
|
+
'4242 4242 4242 4242'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
175
|
+
end
|
176
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
177
|
+
within_frame(find '#card_expiry iframe') { fill_in 'exp-date', with: "0132" }
|
178
|
+
click_button "Save and Continue"
|
179
|
+
expect(page).to have_current_path("/checkout/confirm")
|
180
|
+
click_button "Place Order"
|
181
|
+
expect(page).to have_content("Your order has been processed successfully")
|
182
|
+
end
|
183
|
+
|
184
|
+
it "can re-use saved cards", js: true do
|
185
|
+
within_frame find('#card_number iframe') do
|
186
|
+
'4242 4242 4242 4242'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
187
|
+
end
|
188
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
189
|
+
within_frame(find '#card_expiry iframe') { fill_in 'exp-date', with: "0132" }
|
190
|
+
click_button "Save and Continue"
|
191
|
+
expect(page).to have_current_path("/checkout/confirm")
|
192
|
+
click_button "Place Order"
|
193
|
+
expect(page).to have_content("Your order has been processed successfully")
|
194
|
+
|
195
|
+
visit spree.root_path
|
196
|
+
click_link "DL-44"
|
197
|
+
click_button "Add To Cart"
|
198
|
+
|
199
|
+
expect(page).to have_current_path("/cart")
|
200
|
+
click_button "Checkout"
|
201
|
+
|
202
|
+
# Address
|
203
|
+
expect(page).to have_current_path("/checkout/address")
|
204
|
+
|
205
|
+
within("#billing") do
|
206
|
+
fill_in "First Name", with: "Han"
|
207
|
+
fill_in "Last Name", with: "Solo"
|
208
|
+
fill_in "Street Address", with: "YT-1300"
|
209
|
+
fill_in "City", with: "Mos Eisley"
|
210
|
+
select "United States of America", from: "Country"
|
211
|
+
select country.states.first.name, from: "order_bill_address_attributes_state_id"
|
212
|
+
fill_in "Zip", with: "12010"
|
213
|
+
fill_in "Phone", with: "(555) 555-5555"
|
214
|
+
end
|
215
|
+
click_on "Save and Continue"
|
216
|
+
|
217
|
+
# Delivery
|
218
|
+
expect(page).to have_current_path("/checkout/delivery")
|
219
|
+
expect(page).to have_content("UPS Ground")
|
220
|
+
click_on "Save and Continue"
|
221
|
+
|
222
|
+
# Payment
|
223
|
+
expect(page).to have_current_path("/checkout/payment")
|
224
|
+
choose "Use an existing card on file"
|
225
|
+
click_button "Save and Continue"
|
226
|
+
|
227
|
+
# Confirm
|
228
|
+
expect(page).to have_current_path("/checkout/confirm")
|
229
|
+
click_button "Place Order"
|
230
|
+
expect(page).to have_content("Your order has been processed successfully")
|
231
|
+
end
|
232
|
+
|
233
|
+
it "shows an error with a missing credit card number", js: true do
|
234
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
235
|
+
within_frame(find '#card_expiry iframe') { fill_in 'exp-date', with: "0132" }
|
236
|
+
click_button "Save and Continue"
|
237
|
+
expect(page).to have_content("Your card number is incomplete.")
|
238
|
+
end
|
239
|
+
|
240
|
+
it "shows an error with a missing expiration date", js: true do
|
241
|
+
within_frame find('#card_number iframe') do
|
242
|
+
'4242 4242 4242 4242'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
243
|
+
end
|
244
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
245
|
+
click_button "Save and Continue"
|
246
|
+
expect(page).to have_content("Your card's expiration date is incomplete.")
|
247
|
+
end
|
248
|
+
|
249
|
+
it "shows an error with an invalid credit card number", js: true do
|
250
|
+
within_frame find('#card_number iframe') do
|
251
|
+
'1111 1111 1111 1111'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
252
|
+
end
|
253
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
254
|
+
within_frame(find '#card_expiry iframe') { fill_in 'exp-date', with: "0132" }
|
255
|
+
click_button "Save and Continue"
|
256
|
+
expect(page).to have_content("Your card number is invalid.")
|
257
|
+
end
|
258
|
+
|
259
|
+
it "shows an error with invalid security fields", js: true do
|
260
|
+
within_frame find('#card_number iframe') do
|
261
|
+
'4242 4242 4242 4242'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
262
|
+
end
|
263
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '12' }
|
264
|
+
within_frame(find '#card_expiry iframe') { fill_in 'exp-date', with: "0132" }
|
265
|
+
click_button "Save and Continue"
|
266
|
+
expect(page).to have_content("Your card's security code is incomplete.")
|
267
|
+
end
|
268
|
+
|
269
|
+
it "shows an error with invalid expiry fields", js: true do
|
270
|
+
within_frame find('#card_number iframe') do
|
271
|
+
'4242 4242 4242 4242'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
272
|
+
end
|
273
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
274
|
+
within_frame(find '#card_expiry iframe') { fill_in 'exp-date', with: "013" }
|
275
|
+
click_button "Save and Continue"
|
276
|
+
expect(page).to have_content("Your card's expiration date is incomplete.")
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|