solidus_stripe 3.1.0 → 4.2.0

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +5 -0
  4. data/CHANGELOG.md +58 -2
  5. data/Gemfile +7 -0
  6. data/LICENSE +2 -2
  7. data/README.md +26 -8
  8. data/Rakefile +1 -1
  9. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-cart-page-checkout.js +42 -9
  10. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-intents.js +3 -2
  11. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js +56 -20
  12. data/app/controllers/solidus_stripe/intents_controller.rb +23 -18
  13. data/app/decorators/models/spree/refund_decorator.rb +9 -0
  14. data/app/models/solidus_stripe/address_from_params_service.rb +5 -2
  15. data/app/models/solidus_stripe/create_intents_payment_service.rb +113 -0
  16. data/app/models/spree/payment_method/stripe_credit_card.rb +16 -1
  17. data/bin/r +13 -0
  18. data/bin/rake +7 -0
  19. data/bin/sandbox +84 -0
  20. data/bin/sandbox_rails +18 -0
  21. data/bin/setup +1 -1
  22. data/config/routes.rb +4 -1
  23. data/lib/generators/solidus_stripe/install/install_generator.rb +7 -3
  24. data/lib/solidus_stripe/engine.rb +2 -2
  25. data/lib/solidus_stripe/factories.rb +4 -0
  26. data/lib/solidus_stripe/version.rb +1 -1
  27. data/lib/views/frontend/spree/checkout/payment/v3/_form_elements.html.erb +0 -1
  28. data/solidus_stripe.gemspec +34 -37
  29. data/spec/features/stripe_checkout_spec.rb +101 -48
  30. data/spec/models/solidus_stripe/address_from_params_service_spec.rb +19 -5
  31. data/spec/models/solidus_stripe/create_intents_payment_service_spec.rb +127 -0
  32. data/spec/models/spree/payment_method/stripe_credit_card_spec.rb +44 -1
  33. data/spec/spec_helper.rb +4 -1
  34. metadata +23 -16
  35. data/LICENSE.md +0 -26
  36. data/app/models/solidus_stripe/create_intents_order_service.rb +0 -70
@@ -217,7 +217,7 @@ RSpec.describe "Stripe checkout", type: :feature do
217
217
  end
218
218
  end
219
219
 
220
- context 'when using Stripe V3 API libarary with Elements', :js do
220
+ context 'when using Stripe V3 API library with Elements', :js do
221
221
  let(:preferred_v3_elements) { true }
222
222
  let(:preferred_v3_intents) { false }
223
223
 
@@ -240,60 +240,95 @@ RSpec.describe "Stripe checkout", type: :feature do
240
240
  expect(page).to have_content("Your order has been processed successfully")
241
241
  end
242
242
 
243
- it "can re-use saved cards" do
244
- within_frame find('#card_number iframe') do
245
- '4242 4242 4242 4242'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
246
- end
247
- within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
248
- within_frame(find '#card_expiry iframe') do
249
- '0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
250
- end
251
- click_button "Save and Continue"
252
- expect(page).to have_current_path("/checkout/confirm")
253
- click_button "Place Order"
254
- expect(page).to have_content("Your order has been processed successfully")
243
+ context "when reusing saved cards" do
244
+ stub_authorization!
255
245
 
256
- visit spree.root_path
257
- click_link "DL-44"
258
- click_button "Add To Cart"
246
+ it "completes the order, captures the payment and cancels the order" do
247
+ within_frame find('#card_number iframe') do
248
+ '4242 4242 4242 4242'.split('').each { |n| find_field('cardnumber').native.send_keys(n) }
249
+ end
250
+ within_frame(find '#card_cvc iframe') { fill_in 'cvc', with: '123' }
251
+ within_frame(find '#card_expiry iframe') do
252
+ '0132'.split('').each { |n| find_field('exp-date').native.send_keys(n) }
253
+ end
254
+ click_button "Save and Continue"
255
+ expect(page).to have_current_path("/checkout/confirm")
256
+ click_button "Place Order"
257
+ expect(page).to have_content("Your order has been processed successfully")
259
258
 
260
- expect(page).to have_current_path("/cart")
261
- click_button "Checkout"
259
+ visit spree.root_path
260
+ click_link "DL-44"
261
+ click_button "Add To Cart"
262
262
 
263
- # Address
264
- expect(page).to have_current_path("/checkout/address")
263
+ expect(page).to have_current_path("/cart")
264
+ click_button "Checkout"
265
265
 
266
- within("#billing") do
267
- fill_in_name
268
- fill_in "Street Address", with: "YT-1300"
269
- fill_in "City", with: "Mos Eisley"
270
- select "United States of America", from: "Country"
271
- select country.states.first.name, from: "order_bill_address_attributes_state_id"
272
- fill_in "Zip", with: "12010"
273
- fill_in "Phone", with: "(555) 555-5555"
274
- end
275
- click_on "Save and Continue"
266
+ # Address
267
+ expect(page).to have_current_path("/checkout/address")
276
268
 
277
- # Delivery
278
- expect(page).to have_current_path("/checkout/delivery")
279
- expect(page).to have_content("UPS Ground")
280
- click_on "Save and Continue"
269
+ within("#billing") do
270
+ fill_in_name
271
+ fill_in "Street Address", with: "YT-1300"
272
+ fill_in "City", with: "Mos Eisley"
273
+ select "United States of America", from: "Country"
274
+ select country.states.first.name, from: "order_bill_address_attributes_state_id"
275
+ fill_in "Zip", with: "12010"
276
+ fill_in "Phone", with: "(555) 555-5555"
277
+ end
278
+ click_on "Save and Continue"
281
279
 
282
- # Payment
283
- expect(page).to have_current_path("/checkout/payment")
284
- choose "Use an existing card on file"
285
- click_button "Save and Continue"
280
+ # Delivery
281
+ expect(page).to have_current_path("/checkout/delivery")
282
+ expect(page).to have_content("UPS Ground")
283
+ click_on "Save and Continue"
286
284
 
287
- # Confirm
288
- expect(page).to have_current_path("/checkout/confirm")
289
- click_button "Place Order"
290
- expect(page).to have_content("Your order has been processed successfully")
285
+ # Payment
286
+ expect(page).to have_current_path("/checkout/payment")
287
+ choose "Use an existing card on file"
288
+ click_button "Save and Continue"
289
+
290
+ # Confirm
291
+ expect(page).to have_current_path("/checkout/confirm")
292
+ click_button "Place Order"
293
+ expect(page).to have_content("Your order has been processed successfully")
294
+
295
+ Spree::Order.complete.each do |order|
296
+ # Capture in backend
297
+
298
+ visit spree.admin_path
299
+
300
+ expect(page).to have_selector("#listing_orders tbody tr", count: 2)
301
+
302
+ click_link order.number
303
+
304
+ click_link "Payments"
305
+ find(".fa-capture").click
306
+
307
+ expect(page).to have_content "Payment Updated"
308
+ expect(find("table#payments")).to have_content "Completed"
309
+
310
+ # Order cancel, after capture
311
+ click_link "Cart"
312
+
313
+ within "#sidebar" do
314
+ expect(page).to have_content "Completed"
315
+ end
316
+
317
+ find('input[value="Cancel"]').click
318
+
319
+ expect(page).to have_content "Order canceled"
320
+
321
+ within "#sidebar" do
322
+ expect(page).to have_content "Canceled"
323
+ end
324
+ end
325
+ end
291
326
  end
292
327
 
293
328
  it_behaves_like "Stripe Elements invalid payments"
294
329
  end
295
330
 
296
- context "when using Stripe V3 API libarary with Intents", :js do
331
+ context "when using Stripe V3 API library with Intents", :js do
297
332
  let(:preferred_v3_elements) { false }
298
333
  let(:preferred_v3_intents) { true }
299
334
 
@@ -400,8 +435,9 @@ RSpec.describe "Stripe checkout", type: :feature do
400
435
  click_button "Place Order"
401
436
  expect(page).to have_content("Your order has been processed successfully")
402
437
 
403
- # Capture in backend
404
438
  Spree::Order.complete.each do |order|
439
+ # Capture in backend
440
+
405
441
  visit spree.admin_path
406
442
 
407
443
  expect(page).to have_selector("#listing_orders tbody tr", count: 2)
@@ -413,6 +449,21 @@ RSpec.describe "Stripe checkout", type: :feature do
413
449
 
414
450
  expect(page).to have_content "Payment Updated"
415
451
  expect(find("table#payments")).to have_content "Completed"
452
+
453
+ # Order cancel, after capture
454
+ click_link "Cart"
455
+
456
+ within "#sidebar" do
457
+ expect(page).to have_content "Completed"
458
+ end
459
+
460
+ find('input[value="Cancel"]').click
461
+
462
+ expect(page).to have_content "Order canceled"
463
+
464
+ within "#sidebar" do
465
+ expect(page).to have_content "Canceled"
466
+ end
416
467
  end
417
468
  end
418
469
  end
@@ -487,9 +538,11 @@ RSpec.describe "Stripe checkout", type: :feature do
487
538
  end
488
539
 
489
540
  def within_3d_secure_modal
490
- within_frame "__privateStripeFrame10" do
491
- within_frame "challengeFrame" do
492
- yield
541
+ within_frame "__privateStripeFrame11" do
542
+ within_frame "__stripeJSChallengeFrame" do
543
+ within_frame "acsFrame" do
544
+ yield
545
+ end
493
546
  end
494
547
  end
495
548
  end
@@ -505,7 +558,7 @@ RSpec.describe "Stripe checkout", type: :feature do
505
558
  click_button "Save and Continue"
506
559
 
507
560
  within_3d_secure_modal do
508
- expect(page).to have_content '$19.99 using 3D Secure'
561
+ expect(page).to have_content '$19.99 USD using 3D Secure'
509
562
 
510
563
  click_button 'Complete authentication'
511
564
  end
@@ -14,7 +14,8 @@ RSpec.describe SolidusStripe::AddressFromParamsService do
14
14
  recipient: 'Clark Kent',
15
15
  city: 'Metropolis',
16
16
  postalCode: '12345',
17
- addressLine: [ '12, Lincoln Rd']
17
+ addressLine: [ '12, Lincoln Rd'],
18
+ phone: '555-555-0199'
18
19
  }
19
20
  end
20
21
 
@@ -39,7 +40,8 @@ RSpec.describe SolidusStripe::AddressFromParamsService do
39
40
  firstname: 'Clark',
40
41
  lastname: 'Kent',
41
42
  address1: params[:addressLine].first,
42
- address2: nil
43
+ address2: nil,
44
+ phone: '555-555-0199'
43
45
  )
44
46
  end
45
47
 
@@ -50,11 +52,23 @@ RSpec.describe SolidusStripe::AddressFromParamsService do
50
52
 
51
53
  context "when no user's address is compatible with the params" do
52
54
  before do
53
- user.addresses << create(:address)
55
+ user.addresses << create(:address, state: state)
54
56
  end
55
57
 
56
- it "returns a non-persisted address model" do
57
- expect(subject).to be_new_record
58
+ it "returns a non-persisted valid address" do
59
+ aggregate_failures do
60
+ expect(subject).to be_new_record
61
+ expect(subject).to be_valid
62
+ expect(subject.state).to eq state
63
+ end
64
+ end
65
+
66
+ context "when the region is the state name" do
67
+ before { params[:region] = state.name }
68
+
69
+ it "still can set the address state attribute" do
70
+ expect(subject.state).to eq state
71
+ end
58
72
  end
59
73
  end
60
74
  end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe SolidusStripe::CreateIntentsPaymentService do
6
+ let(:service) { described_class.new(intent_id, stripe, controller) }
7
+
8
+ let(:stripe) {
9
+ Spree::PaymentMethod::StripeCreditCard.create!(
10
+ name: "Stripe",
11
+ preferred_secret_key: "sk_test_VCZnDv3GLU15TRvn8i2EsaAN",
12
+ preferred_publishable_key: "pk_test_Cuf0PNtiAkkMpTVC2gwYDMIg",
13
+ preferred_v3_elements: false,
14
+ preferred_v3_intents: true
15
+ )
16
+ }
17
+
18
+ let(:order) { create :order, state: :payment, total: 19.99 }
19
+
20
+ let(:intent_id) { "pi_123123ABC" }
21
+ let(:controller) { double(current_order: order.reload, params: params, request: spy) }
22
+
23
+ let(:params) do
24
+ {
25
+ spree_payment_method_id: stripe.id,
26
+ stripe_payment_intent_id: intent_id,
27
+ form_data: {
28
+ addressLine: ["31 Cotton Rd"],
29
+ city: "San Diego",
30
+ country: "US",
31
+ phone: "+188836412312",
32
+ postalCode: "12345",
33
+ recipient: "James Edwards",
34
+ region: "CA"
35
+ }
36
+ }
37
+ end
38
+
39
+ let(:intent) do
40
+ double(params: {
41
+ "id" => intent_id,
42
+ "charges" => {
43
+ "data" => [{
44
+ "billing_details" => {
45
+ "name" => "John Doe"
46
+ },
47
+ "payment_method_details" => {
48
+ "card" => {
49
+ "brand" => "visa",
50
+ "exp_month" => 1,
51
+ "exp_year" => 2022,
52
+ "last4" => "4242"
53
+ },
54
+ }
55
+ }]
56
+ }
57
+ })
58
+ end
59
+
60
+ describe '#call' do
61
+ subject { service.call }
62
+
63
+ before do
64
+ allow(stripe).to receive(:show_intent) { intent }
65
+ allow_any_instance_of(Spree::CreditCard).to receive(:require_card_numbers?) { false }
66
+ allow_any_instance_of(Spree::PaymentMethod::StripeCreditCard).to receive(:create_profile) { true }
67
+ end
68
+
69
+ it { expect(subject).to be true }
70
+
71
+ it "creates a new pending payment" do
72
+ expect { subject }.to change { order.payments.count }
73
+ expect(order.payments.last.reload).to be_pending
74
+ end
75
+
76
+ it "creates a credit card with the correct information" do
77
+ expect { subject }.to change { Spree::CreditCard.count }
78
+ card = Spree::CreditCard.last
79
+
80
+ aggregate_failures do
81
+ expect(card.name).to eq "John Doe"
82
+ expect(card.cc_type).to eq "visa"
83
+ expect(card.month).to eq "1"
84
+ expect(card.year).to eq "2022"
85
+ expect(card.last_digits).to eq "4242"
86
+ end
87
+ end
88
+
89
+ context "when for any reason the payment could not be created" do
90
+ before { params[:form_data].delete(:city) }
91
+
92
+ it "returns false" do
93
+ expect(subject).to be false
94
+ end
95
+ end
96
+
97
+ context "when there are previous pending payments" do
98
+ let!(:payment) do
99
+ create(:payment, order: order).tap do |payment|
100
+ payment.update!(state: :pending)
101
+ end
102
+ end
103
+
104
+ before do
105
+ response = double(success?: true, authorization: payment.response_code)
106
+ allow_any_instance_of(Spree::PaymentMethod::StripeCreditCard).to receive(:void) { response }
107
+ end
108
+
109
+ context "when one of them is a Payment Intent" do
110
+ before do
111
+ payment.update!(payment_method: stripe)
112
+ payment.source.update!(payment_method: stripe)
113
+ end
114
+
115
+ it "invalidates it" do
116
+ expect { subject }.to change { payment.reload.state }.to 'void'
117
+ end
118
+ end
119
+
120
+ context "when none is a Payment Intent" do
121
+ it "does not invalidate them" do
122
+ expect { subject }.not_to change { payment.reload.state }
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -22,7 +22,8 @@ describe Spree::PaymentMethod::StripeCreditCard do
22
22
  let(:payment) {
23
23
  double('Spree::Payment',
24
24
  source: source,
25
- order: order
25
+ order: order,
26
+ amount: order.total
26
27
  )
27
28
  }
28
29
 
@@ -241,4 +242,46 @@ describe Spree::PaymentMethod::StripeCreditCard do
241
242
  expect(gateway).to receive(:capture).with(9855, '12345', anything).and_return(success_response)
242
243
  end
243
244
  end
245
+
246
+ describe '#try_void' do
247
+ let(:payment) { create :payment, amount: order.total }
248
+
249
+ shared_examples 'voids the payment transaction' do
250
+ it 'voids the payment transaction' do
251
+ expect(gateway).to receive(:void)
252
+
253
+ subject.try_void(payment)
254
+ end
255
+ end
256
+
257
+ context 'when using Payment Intents' do
258
+ before { subject.preferred_v3_intents = true }
259
+
260
+ context 'when the payment is completed' do
261
+ before do
262
+ allow(payment).to receive(:completed?) { true }
263
+ end
264
+
265
+ it 'creates a refund' do
266
+ expect { subject.try_void(payment) }.to change { Spree::Refund.count }.by(1)
267
+ end
268
+ end
269
+
270
+ context 'when the payment is not completed' do
271
+ it_behaves_like 'voids the payment transaction'
272
+ end
273
+ end
274
+
275
+ context 'when not using Payment Intents' do
276
+ before { subject.preferred_v3_intents = false }
277
+
278
+ context 'when the payment is completed' do
279
+ it_behaves_like 'voids the payment transaction'
280
+ end
281
+
282
+ context 'when the payment is not completed' do
283
+ it_behaves_like 'voids the payment transaction'
284
+ end
285
+ end
286
+ end
244
287
  end
@@ -13,7 +13,10 @@ require 'solidus_dev_support/rspec/feature_helper'
13
13
 
14
14
  # Requires supporting ruby files with custom matchers and macros, etc,
15
15
  # in spec/support/ and its subdirectories.
16
- Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
16
+ Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
17
+
18
+ # Requires factories defined in lib/solidus_stripe/factories.rb
19
+ require 'solidus_stripe/factories'
17
20
 
18
21
  RSpec.configure do |config|
19
22
  config.infer_spec_type_from_file_location!
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_stripe
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Solidus Team
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-10 00:00:00.000000000 Z
11
+ date: 2020-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solidus_core
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.4.0
39
+ version: '0.5'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 0.4.0
46
+ version: '0.5'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activemerchant
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -88,7 +88,6 @@ files:
88
88
  - CHANGELOG.md
89
89
  - Gemfile
90
90
  - LICENSE
91
- - LICENSE.md
92
91
  - README.md
93
92
  - Rakefile
94
93
  - app/assets/javascripts/spree/frontend/solidus_stripe.js
@@ -103,13 +102,18 @@ files:
103
102
  - app/controllers/spree/stripe_controller.rb
104
103
  - app/decorators/models/spree/order_update_attributes_decorator.rb
105
104
  - app/decorators/models/spree/payment_decorator.rb
105
+ - app/decorators/models/spree/refund_decorator.rb
106
106
  - app/models/solidus_stripe/address_from_params_service.rb
107
- - app/models/solidus_stripe/create_intents_order_service.rb
107
+ - app/models/solidus_stripe/create_intents_payment_service.rb
108
108
  - app/models/solidus_stripe/prepare_order_for_payment_service.rb
109
109
  - app/models/solidus_stripe/shipping_rates_service.rb
110
110
  - app/models/spree/payment_method/stripe_credit_card.rb
111
111
  - bin/console
112
+ - bin/r
112
113
  - bin/rails
114
+ - bin/rake
115
+ - bin/sandbox
116
+ - bin/sandbox_rails
113
117
  - bin/setup
114
118
  - config/routes.rb
115
119
  - db/migrate/20181010123508_update_stripe_payment_method_type_to_credit_card.rb
@@ -118,6 +122,7 @@ files:
118
122
  - lib/generators/solidus_stripe/install/install_generator.rb
119
123
  - lib/solidus_stripe.rb
120
124
  - lib/solidus_stripe/engine.rb
125
+ - lib/solidus_stripe/factories.rb
121
126
  - lib/solidus_stripe/version.rb
122
127
  - lib/tasks/solidus_stripe/db/seed.rake
123
128
  - lib/views/api/spree/api/payments/source_views/_stripe.json.jbuilder
@@ -135,40 +140,42 @@ files:
135
140
  - solidus_stripe.gemspec
136
141
  - spec/features/stripe_checkout_spec.rb
137
142
  - spec/models/solidus_stripe/address_from_params_service_spec.rb
143
+ - spec/models/solidus_stripe/create_intents_payment_service_spec.rb
138
144
  - spec/models/solidus_stripe/prepare_order_for_payment_service_spec.rb
139
145
  - spec/models/solidus_stripe/shipping_rates_service_spec.rb
140
146
  - spec/models/spree/payment_method/stripe_credit_card_spec.rb
141
147
  - spec/spec_helper.rb
142
148
  - spec/support/solidus_address_helper.rb
143
- homepage: https://solidus.io
149
+ homepage: https://github.com/solidusio/solidus_stripe#readme
144
150
  licenses:
145
151
  - BSD-3
146
152
  metadata:
147
- homepage_uri: https://solidus.io
148
- source_code_uri: https://solidus.io
149
- post_install_message:
153
+ homepage_uri: https://github.com/solidusio/solidus_stripe#readme
154
+ source_code_uri: https://github.com/solidusio/solidus_stripe
155
+ changelog_uri: https://github.com/solidusio/solidus_stripe/blob/master/CHANGELOG.md
156
+ post_install_message:
150
157
  rdoc_options: []
151
158
  require_paths:
152
159
  - lib
153
160
  required_ruby_version: !ruby/object:Gem::Requirement
154
161
  requirements:
155
- - - ">="
162
+ - - "~>"
156
163
  - !ruby/object:Gem::Version
157
- version: '2.2'
164
+ version: '2.4'
158
165
  required_rubygems_version: !ruby/object:Gem::Requirement
159
166
  requirements:
160
167
  - - ">="
161
168
  - !ruby/object:Gem::Version
162
169
  version: '0'
163
- requirements:
164
- - none
170
+ requirements: []
165
171
  rubygems_version: 3.0.3
166
- signing_key:
172
+ signing_key:
167
173
  specification_version: 4
168
174
  summary: Stripe Payment Method for Solidus
169
175
  test_files:
170
176
  - spec/features/stripe_checkout_spec.rb
171
177
  - spec/models/solidus_stripe/address_from_params_service_spec.rb
178
+ - spec/models/solidus_stripe/create_intents_payment_service_spec.rb
172
179
  - spec/models/solidus_stripe/prepare_order_for_payment_service_spec.rb
173
180
  - spec/models/solidus_stripe/shipping_rates_service_spec.rb
174
181
  - spec/models/spree/payment_method/stripe_credit_card_spec.rb