solidus_stripe 2.0.0 → 3.2.1
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/CHANGELOG.md +50 -1
- data/README.md +131 -7
- data/app/assets/javascripts/spree/frontend/solidus_stripe.js +6 -0
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-cart-page-checkout.js +88 -0
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-elements.js +148 -0
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-init.js +20 -0
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-intents.js +84 -0
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js +123 -0
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment.js +16 -0
- data/app/controllers/solidus_stripe/intents_controller.rb +29 -20
- data/app/decorators/models/spree/order_update_attributes_decorator.rb +39 -0
- data/app/decorators/models/spree/payment_decorator.rb +11 -0
- data/app/models/solidus_stripe/create_intents_order_service.rb +70 -0
- data/app/models/spree/payment_method/stripe_credit_card.rb +4 -9
- data/lib/generators/solidus_stripe/install/install_generator.rb +2 -5
- data/lib/solidus_stripe/engine.rb +0 -1
- data/lib/solidus_stripe/version.rb +1 -1
- data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +1 -1
- data/lib/views/frontend/spree/checkout/payment/v3/_elements.html.erb +1 -0
- data/lib/views/frontend/spree/checkout/payment/v3/_form_elements.html.erb +1 -3
- data/lib/views/frontend/spree/checkout/payment/v3/_intents.html.erb +1 -5
- data/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb +2 -5
- data/lib/views/frontend/spree/orders/_stripe_payment_request_button.html.erb +1 -79
- data/solidus_stripe.gemspec +1 -1
- data/spec/features/stripe_checkout_spec.rb +143 -68
- data/spec/spec_helper.rb +1 -0
- data/spec/support/solidus_address_helper.rb +15 -0
- metadata +17 -8
- data/app/assets/javascripts/solidus_stripe/stripe-init.js +0 -1
- data/app/assets/javascripts/solidus_stripe/stripe-init/base.js +0 -180
- data/lib/views/frontend/spree/checkout/payment/v3/_elements_js.html.erb +0 -28
- data/lib/views/frontend/spree/checkout/payment/v3/_intents_js.html.erb +0 -48
@@ -5,11 +5,8 @@ module SolidusStripe
|
|
5
5
|
class InstallGenerator < Rails::Generators::Base
|
6
6
|
class_option :auto_run_migrations, type: :boolean, default: false
|
7
7
|
|
8
|
-
def
|
9
|
-
|
10
|
-
if File.file? filename
|
11
|
-
inject_into_file filename, " *= require spree/frontend/solidus_stripe\n", before: '*/', verbose: true
|
12
|
-
end
|
8
|
+
def add_javascripts
|
9
|
+
append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/solidus_stripe\n"
|
13
10
|
end
|
14
11
|
|
15
12
|
def add_migrations
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if payment_method.v3_elements? %>
|
2
|
-
<%= render 'spree/checkout/payment/v3/
|
2
|
+
<%= render 'spree/checkout/payment/v3/elements', payment_method: payment_method %>
|
3
3
|
<% elsif payment_method.v3_intents? %>
|
4
4
|
<%= render 'spree/checkout/payment/v3/intents', payment_method: payment_method %>
|
5
5
|
<% else %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'spree/checkout/payment/v3/form_elements', payment_method: payment_method, stripe_v3_api: 'elements' %>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div id="payment-request-button" data-stripe-config="<%= payment_method.stripe_config(current_order).to_json %>"></div>
|
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
2
|
|
3
3
|
<%= image_tag 'credit_cards/credit_card.gif', id: 'credit-card-image' %>
|
4
4
|
<% param_prefix = "payment_source[#{payment_method.id}]" %>
|
@@ -38,5 +38,3 @@
|
|
38
38
|
<% end %>
|
39
39
|
|
40
40
|
<%= hidden_field_tag "#{param_prefix}[cc_type]", '', id: "cc_type", class: 'ccType' %>
|
41
|
-
|
42
|
-
<script src="https://js.stripe.com/v3/"></script>
|
@@ -1,5 +1 @@
|
|
1
|
-
<%= render 'spree/checkout/payment/v3/form_elements', payment_method: payment_method %>
|
2
|
-
|
3
|
-
<%= javascript_include_tag "solidus_stripe/stripe-init.js" %>
|
4
|
-
|
5
|
-
<%= render "spree/checkout/payment/v3/intents_js" %>
|
1
|
+
<%= render 'spree/checkout/payment/v3/form_elements', payment_method: payment_method, stripe_v3_api: 'payment-intents' %>
|
@@ -1,5 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<%= javascript_include_tag "solidus_stripe/stripe-init.js" %>
|
4
|
-
|
5
|
-
<%= render "spree/checkout/payment/v3/elements_js" %>
|
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,5 +1,5 @@
|
|
1
1
|
<% if current_order.present? && cart_checkout_payment_method.present? %>
|
2
|
-
<div id="stripe-payment-request" class="stripe-payment-request" style="display:none">
|
2
|
+
<div id="stripe-payment-request" class="stripe-payment-request" data-v3-api="payment-request-button" style="display:none">
|
3
3
|
<div id="payment-request-button"
|
4
4
|
data-stripe-config="<%= cart_checkout_payment_method.stripe_config(current_order).to_json %>"
|
5
5
|
data-order-token="<%= current_order.guest_token %>"
|
@@ -11,82 +11,4 @@
|
|
11
11
|
<div id="card-errors" class='errorExplanation' role="alert" style="display: none">
|
12
12
|
</div>
|
13
13
|
</div>
|
14
|
-
|
15
|
-
<script src="https://js.stripe.com/v3/"></script>
|
16
|
-
<%= javascript_include_tag "solidus_stripe/stripe-init" %>
|
17
|
-
|
18
|
-
<script>
|
19
|
-
var paymentRequestConfig = SolidusStripe.paymentMethod.config.payment_request;
|
20
|
-
var errorElement = $('#card-errors');
|
21
|
-
|
22
|
-
if (typeof paymentRequestConfig !== 'undefined') {
|
23
|
-
paymentRequestConfig.requestShipping = true;
|
24
|
-
|
25
|
-
var onPrButtonMounted = function(buttonId, success) {
|
26
|
-
var container = document.getElementById('stripe-payment-request');
|
27
|
-
|
28
|
-
if (success) {
|
29
|
-
container.style.display = '';
|
30
|
-
} else {
|
31
|
-
container.style.display = 'none';
|
32
|
-
}
|
33
|
-
};
|
34
|
-
|
35
|
-
var paymentRequest = setUpPaymentRequest(paymentRequestConfig, onPrButtonMounted);
|
36
|
-
|
37
|
-
function handlePayment(result) {
|
38
|
-
fetch('/stripe/update_order', {
|
39
|
-
method: 'POST',
|
40
|
-
headers: { 'Content-Type': 'application/json' },
|
41
|
-
body: JSON.stringify({
|
42
|
-
shipping_address: result.shippingAddress,
|
43
|
-
shipping_option: result.shippingOption,
|
44
|
-
email: result.payerEmail,
|
45
|
-
name: result.payerName,
|
46
|
-
authenticity_token: authToken
|
47
|
-
})
|
48
|
-
}).then(function(response) {
|
49
|
-
response.json().then(function(json) {
|
50
|
-
handleServerResponse(json, result);
|
51
|
-
})
|
52
|
-
});
|
53
|
-
};
|
54
|
-
|
55
|
-
function stripeTokenHandler(token) {
|
56
|
-
return {
|
57
|
-
order: {
|
58
|
-
payments_attributes: [
|
59
|
-
{
|
60
|
-
payment_method_id: SolidusStripe.paymentMethod.config.id,
|
61
|
-
source_attributes: {
|
62
|
-
gateway_payment_profile_id: token.id,
|
63
|
-
last_digits: token.card.last4,
|
64
|
-
month: token.card.exp_month,
|
65
|
-
year: token.card.exp_year
|
66
|
-
}
|
67
|
-
}
|
68
|
-
]
|
69
|
-
}
|
70
|
-
}
|
71
|
-
};
|
72
|
-
|
73
|
-
function submitPayment(payment) {
|
74
|
-
$.ajax({
|
75
|
-
url : $('[data-submit-url]').data('submit-url'),
|
76
|
-
headers: {
|
77
|
-
'X-Spree-Order-Token': $('[data-order-token]').data('order-token')
|
78
|
-
},
|
79
|
-
type : 'PATCH',
|
80
|
-
contentType: 'application/json',
|
81
|
-
data : JSON.stringify(stripeTokenHandler(payment.paymentMethod)),
|
82
|
-
success: function() {
|
83
|
-
window.location = $('[data-complete-url]').data('complete-url');
|
84
|
-
},
|
85
|
-
error: function(xhr,status,error) {
|
86
|
-
showError(xhr.responseJSON.error);
|
87
|
-
}
|
88
|
-
});
|
89
|
-
};
|
90
|
-
}
|
91
|
-
</script>
|
92
14
|
<% end %>
|
data/solidus_stripe.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
30
|
|
31
31
|
s.add_dependency 'solidus_core', ['>= 2.3', '< 3']
|
32
|
-
s.add_dependency 'solidus_support', '~> 0.4
|
32
|
+
s.add_dependency 'solidus_support', '~> 0.4'
|
33
33
|
# ActiveMerchant v1.58 through v1.59 introduced a breaking change
|
34
34
|
# to the stripe gateway.
|
35
35
|
#
|
@@ -6,6 +6,8 @@ RSpec.describe "Stripe checkout", type: :feature do
|
|
6
6
|
let(:zone) { FactoryBot.create(:zone) }
|
7
7
|
let(:country) { FactoryBot.create(:country) }
|
8
8
|
|
9
|
+
let(:card_3d_secure) { "4000 0025 0000 3155" }
|
10
|
+
|
9
11
|
before do
|
10
12
|
FactoryBot.create(:store)
|
11
13
|
zone.members << Spree::ZoneMember.create!(zoneable: country)
|
@@ -41,8 +43,7 @@ RSpec.describe "Stripe checkout", type: :feature do
|
|
41
43
|
expect(page).to have_current_path("/checkout/address")
|
42
44
|
|
43
45
|
within("#billing") do
|
44
|
-
|
45
|
-
fill_in "Last Name", with: "Solo"
|
46
|
+
fill_in_name
|
46
47
|
fill_in "Street Address", with: "YT-1300"
|
47
48
|
fill_in "City", with: "Mos Eisley"
|
48
49
|
select "United States of America", from: "Country"
|
@@ -100,8 +101,7 @@ RSpec.describe "Stripe checkout", type: :feature do
|
|
100
101
|
expect(page).to have_current_path("/checkout/address")
|
101
102
|
|
102
103
|
within("#billing") do
|
103
|
-
|
104
|
-
fill_in "Last Name", with: "Solo"
|
104
|
+
fill_in_name
|
105
105
|
fill_in "Street Address", with: "YT-1300"
|
106
106
|
fill_in "City", with: "Mos Eisley"
|
107
107
|
select "United States of America", from: "Country"
|
@@ -264,8 +264,7 @@ RSpec.describe "Stripe checkout", type: :feature do
|
|
264
264
|
expect(page).to have_current_path("/checkout/address")
|
265
265
|
|
266
266
|
within("#billing") do
|
267
|
-
|
268
|
-
fill_in "Last Name", with: "Solo"
|
267
|
+
fill_in_name
|
269
268
|
fill_in "Street Address", with: "YT-1300"
|
270
269
|
fill_in "City", with: "Mos Eisley"
|
271
270
|
select "United States of America", from: "Country"
|
@@ -304,24 +303,8 @@ RSpec.describe "Stripe checkout", type: :feature do
|
|
304
303
|
end
|
305
304
|
|
306
305
|
context "when using a valid 3D Secure card" do
|
307
|
-
let(:card_number) { "4000 0027 6000 3184" }
|
308
|
-
|
309
306
|
it "successfully completes the checkout" do
|
310
|
-
|
311
|
-
card_number.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
312
|
-
end
|
313
|
-
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
314
|
-
within_frame(find '#card_expiry iframe') do
|
315
|
-
'0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
|
316
|
-
end
|
317
|
-
|
318
|
-
click_button "Save and Continue"
|
319
|
-
|
320
|
-
within_3d_secure_modal do
|
321
|
-
expect(page).to have_content '$19.99 using 3D Secure'
|
322
|
-
|
323
|
-
click_button 'Complete authentication'
|
324
|
-
end
|
307
|
+
authenticate_3d_secure_card(card_3d_secure)
|
325
308
|
|
326
309
|
expect(page).to have_current_path("/checkout/confirm")
|
327
310
|
|
@@ -371,60 +354,133 @@ RSpec.describe "Stripe checkout", type: :feature do
|
|
371
354
|
end
|
372
355
|
end
|
373
356
|
|
374
|
-
|
375
|
-
|
376
|
-
"4000 0027 6000 3184".split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
377
|
-
end
|
378
|
-
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
379
|
-
within_frame(find '#card_expiry iframe') do
|
380
|
-
'0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
|
381
|
-
end
|
382
|
-
click_button "Save and Continue"
|
357
|
+
context "when reusing a card" do
|
358
|
+
stub_authorization!
|
383
359
|
|
384
|
-
|
385
|
-
|
360
|
+
it "succesfully creates a second payment that can be captured in the backend" do
|
361
|
+
authenticate_3d_secure_card(card_3d_secure)
|
362
|
+
|
363
|
+
expect(page).to have_current_path("/checkout/confirm")
|
364
|
+
click_button "Place Order"
|
365
|
+
expect(page).to have_content("Your order has been processed successfully")
|
366
|
+
|
367
|
+
visit spree.root_path
|
368
|
+
click_link "DL-44"
|
369
|
+
click_button "Add To Cart"
|
370
|
+
|
371
|
+
expect(page).to have_current_path("/cart")
|
372
|
+
click_button "Checkout"
|
373
|
+
|
374
|
+
# Address
|
375
|
+
expect(page).to have_current_path("/checkout/address")
|
376
|
+
|
377
|
+
within("#billing") do
|
378
|
+
fill_in_name
|
379
|
+
fill_in "Street Address", with: "YT-1300"
|
380
|
+
fill_in "City", with: "Mos Eisley"
|
381
|
+
select "United States of America", from: "Country"
|
382
|
+
select country.states.first.name, from: "order_bill_address_attributes_state_id"
|
383
|
+
fill_in "Zip", with: "12010"
|
384
|
+
fill_in "Phone", with: "(555) 555-5555"
|
385
|
+
end
|
386
|
+
click_on "Save and Continue"
|
387
|
+
|
388
|
+
# Delivery
|
389
|
+
expect(page).to have_current_path("/checkout/delivery")
|
390
|
+
expect(page).to have_content("UPS Ground")
|
391
|
+
click_on "Save and Continue"
|
392
|
+
|
393
|
+
# Payment
|
394
|
+
expect(page).to have_current_path("/checkout/payment")
|
395
|
+
choose "Use an existing card on file"
|
396
|
+
click_button "Save and Continue"
|
397
|
+
|
398
|
+
# Confirm
|
399
|
+
expect(page).to have_current_path("/checkout/confirm")
|
400
|
+
click_button "Place Order"
|
401
|
+
expect(page).to have_content("Your order has been processed successfully")
|
402
|
+
|
403
|
+
# Capture in backend
|
404
|
+
Spree::Order.complete.each do |order|
|
405
|
+
visit spree.admin_path
|
406
|
+
|
407
|
+
expect(page).to have_selector("#listing_orders tbody tr", count: 2)
|
408
|
+
|
409
|
+
click_link order.number
|
410
|
+
|
411
|
+
click_link "Payments"
|
412
|
+
find(".fa-capture").click
|
413
|
+
|
414
|
+
expect(page).to have_content "Payment Updated"
|
415
|
+
expect(find("table#payments")).to have_content "Completed"
|
416
|
+
end
|
386
417
|
end
|
418
|
+
end
|
387
419
|
|
388
|
-
|
389
|
-
|
390
|
-
expect(page).to have_content("Your order has been processed successfully")
|
420
|
+
context "when paying with multiple payment methods" do
|
421
|
+
stub_authorization!
|
391
422
|
|
392
|
-
|
393
|
-
|
394
|
-
click_button "Add To Cart"
|
423
|
+
context "when paying first with regular card, then with 3D-Secure card" do
|
424
|
+
let(:regular_card) { "4242 4242 4242 4242"}
|
395
425
|
|
396
|
-
|
397
|
-
|
426
|
+
it "voids the first stripe payment and successfully pays with 3DS card" do
|
427
|
+
within_frame find('#card_number iframe') do
|
428
|
+
regular_card.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
429
|
+
end
|
430
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
431
|
+
within_frame(find '#card_expiry iframe') do
|
432
|
+
'0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
|
433
|
+
end
|
434
|
+
click_button "Save and Continue"
|
398
435
|
|
399
|
-
|
400
|
-
expect(page).to have_current_path("/checkout/address")
|
436
|
+
expect(page).to have_content "Ending in 4242"
|
401
437
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
438
|
+
click_link "Payment"
|
439
|
+
|
440
|
+
authenticate_3d_secure_card(card_3d_secure)
|
441
|
+
click_button "Place Order"
|
442
|
+
expect(page).to have_content "Your order has been processed successfully"
|
443
|
+
|
444
|
+
visit spree.admin_path
|
445
|
+
click_link Spree::Order.complete.first.number
|
446
|
+
click_link "Payments"
|
447
|
+
|
448
|
+
payments = all('table#payments tbody tr')
|
449
|
+
|
450
|
+
expect(payments.first).to have_content "Stripe"
|
451
|
+
expect(payments.first).to have_content "Void"
|
452
|
+
|
453
|
+
expect(payments.last).to have_content "Stripe"
|
454
|
+
expect(payments.last).to have_content "Pending"
|
455
|
+
end
|
411
456
|
end
|
412
|
-
click_on "Save and Continue"
|
413
457
|
|
414
|
-
|
415
|
-
|
416
|
-
expect(page).to have_content("UPS Ground")
|
417
|
-
click_on "Save and Continue"
|
458
|
+
context "when paying first with 3D-Secure card, then with check" do
|
459
|
+
before { create :check_payment_method }
|
418
460
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
click_button "Save and Continue"
|
461
|
+
it "voids the stripe payment and successfully pays with check" do
|
462
|
+
authenticate_3d_secure_card(card_3d_secure)
|
463
|
+
expect(page).to have_current_path("/checkout/confirm")
|
423
464
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
465
|
+
click_link "Payment"
|
466
|
+
choose "Check"
|
467
|
+
click_button "Save and Continue"
|
468
|
+
expect(find(".payment-info")).to have_content "Check"
|
469
|
+
expect(page).to have_content "Your order has been processed successfully"
|
470
|
+
|
471
|
+
visit spree.admin_path
|
472
|
+
click_link Spree::Order.complete.first.number
|
473
|
+
click_link "Payments"
|
474
|
+
payments = all('table#payments tbody tr')
|
475
|
+
|
476
|
+
stripe_payment = payments.first
|
477
|
+
expect(stripe_payment).to have_content "Stripe"
|
478
|
+
expect(stripe_payment).to have_content "Void"
|
479
|
+
|
480
|
+
check_payment = payments.last
|
481
|
+
expect(check_payment).to have_content "Check"
|
482
|
+
end
|
483
|
+
end
|
428
484
|
end
|
429
485
|
|
430
486
|
it_behaves_like "Stripe Elements invalid payments"
|
@@ -432,9 +488,28 @@ RSpec.describe "Stripe checkout", type: :feature do
|
|
432
488
|
|
433
489
|
def within_3d_secure_modal
|
434
490
|
within_frame "__privateStripeFrame10" do
|
435
|
-
within_frame "
|
436
|
-
|
491
|
+
within_frame "__stripeJSChallengeFrame" do
|
492
|
+
within_frame "acsFrame" do
|
493
|
+
yield
|
494
|
+
end
|
437
495
|
end
|
438
496
|
end
|
439
497
|
end
|
498
|
+
|
499
|
+
def authenticate_3d_secure_card(card_number)
|
500
|
+
within_frame find('#card_number iframe') do
|
501
|
+
card_number.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
|
502
|
+
end
|
503
|
+
within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
|
504
|
+
within_frame(find '#card_expiry iframe') do
|
505
|
+
'0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
|
506
|
+
end
|
507
|
+
click_button "Save and Continue"
|
508
|
+
|
509
|
+
within_3d_secure_modal do
|
510
|
+
expect(page).to have_content '$19.99 using 3D Secure'
|
511
|
+
|
512
|
+
click_button 'Complete authentication'
|
513
|
+
end
|
514
|
+
end
|
440
515
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Since https://github.com/solidusio/solidus/pull/3524 was merged,
|
4
|
+
# we need to verify if we're using the single "Name" field or the
|
5
|
+
# previous first/last name combination.
|
6
|
+
module SolidusAddressNameHelper
|
7
|
+
def fill_in_name
|
8
|
+
if Spree::Config.preferences[:use_combined_first_and_last_name_in_address]
|
9
|
+
fill_in "Name", with: "Han Solo"
|
10
|
+
else
|
11
|
+
fill_in "First Name", with: "Han"
|
12
|
+
fill_in "Last Name", with: "Solo"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|