solidus_stripe 4.4.1 → 5.0.0.alpha.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/.circleci/config.yml +92 -52
- data/.gitignore +3 -0
- data/.rubocop.yml +94 -4
- data/.yardopts +1 -0
- data/Gemfile +10 -30
- data/LICENSE +2 -2
- data/Procfile.dev +3 -0
- data/README.md +145 -215
- data/Rakefile +5 -44
- data/app/assets/javascripts/spree/backend/solidus_stripe.js +2 -0
- data/app/assets/stylesheets/spree/backend/solidus_stripe.css +4 -0
- data/app/controllers/solidus_stripe/intents_controller.rb +36 -52
- data/app/controllers/solidus_stripe/webhooks_controller.rb +28 -0
- data/app/models/concerns/solidus_stripe/log_entries.rb +31 -0
- data/app/models/solidus_stripe/customer.rb +21 -0
- data/app/models/solidus_stripe/gateway.rb +231 -0
- data/app/models/solidus_stripe/payment_intent.rb +111 -0
- data/app/models/solidus_stripe/payment_method.rb +106 -0
- data/app/models/solidus_stripe/payment_source.rb +31 -0
- data/app/models/solidus_stripe/slug_entry.rb +20 -0
- data/app/models/solidus_stripe.rb +7 -0
- data/app/subscribers/solidus_stripe/webhook/charge_subscriber.rb +28 -0
- data/app/subscribers/solidus_stripe/webhook/payment_intent_subscriber.rb +112 -0
- data/app/views/spree/admin/payments/source_forms/_stripe.html.erb +29 -0
- data/app/views/spree/admin/payments/source_forms/existing_payment/_stripe.html.erb +14 -0
- data/app/views/spree/admin/payments/source_forms/existing_payment/stripe/_card.html.erb +8 -0
- data/app/views/spree/admin/payments/source_forms/existing_payment/stripe/_default.html.erb +7 -0
- data/app/views/spree/admin/payments/source_views/_stripe.html.erb +15 -0
- data/app/views/spree/api/payments/source_views/_stripe.json.jbuilder +8 -0
- data/bin/dev +13 -0
- data/bin/dummy-app +29 -0
- data/bin/rails +38 -3
- data/bin/rails-dummy-app +3 -0
- data/bin/rails-engine +1 -11
- data/bin/rails-new +55 -0
- data/bin/rails-sandbox +1 -14
- data/bin/rspec +10 -0
- data/bin/sandbox +12 -74
- data/bin/setup +1 -0
- data/bin/update-migrations +56 -0
- data/codecov.yml +12 -0
- data/config/locales/en.yml +16 -1
- data/config/routes.rb +5 -11
- data/coverage.rb +42 -0
- data/db/migrate/20230109183332_create_solidus_stripe_payment_sources.rb +10 -0
- data/db/migrate/20230303154931_create_solidus_stripe_setup_intent.rb +10 -0
- data/db/migrate/20230306105520_create_solidus_stripe_payment_intents.rb +10 -0
- data/db/migrate/20230308122414_create_solidus_stripe_webhook_endpoints.rb +10 -0
- data/db/migrate/20230310152615_add_payment_method_reference_to_stripe_intents.rb +6 -0
- data/db/migrate/20230310171444_normalize_stripe_intent_id_attributes.rb +6 -0
- data/db/migrate/20230313150008_create_solidus_stripe_customers.rb +16 -0
- data/db/migrate/20230323154931_drop_solidus_stripe_setup_intent.rb +13 -0
- data/db/migrate/20230403094916_rename_webhook_endpoint_to_payment_method_slug_entries.rb +5 -0
- data/db/seeds.rb +6 -24
- data/lib/generators/solidus_stripe/install/install_generator.rb +121 -14
- data/lib/generators/solidus_stripe/install/templates/app/assets/stylesheets/spree/frontend/solidus_stripe.css +13 -0
- data/lib/generators/solidus_stripe/install/templates/app/javascript/controllers/solidus_stripe_confirm_controller.js +39 -0
- data/lib/generators/solidus_stripe/install/templates/app/javascript/controllers/solidus_stripe_payment_controller.js +89 -0
- data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/_stripe.html.erb +16 -0
- data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/stripe/_card.html.erb +8 -0
- data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/stripe/_default.html.erb +7 -0
- data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/payment/_stripe.html.erb +39 -0
- data/lib/generators/solidus_stripe/install/templates/app/views/orders/payment_info/_stripe.html.erb +20 -0
- data/lib/generators/solidus_stripe/install/templates/config/initializers/solidus_stripe.rb +31 -0
- data/lib/solidus_stripe/configuration.rb +24 -3
- data/lib/solidus_stripe/engine.rb +19 -6
- data/lib/solidus_stripe/money_to_stripe_amount_converter.rb +109 -0
- data/lib/solidus_stripe/refunds_synchronizer.rb +96 -0
- data/lib/solidus_stripe/seeds.rb +19 -0
- data/lib/solidus_stripe/testing_support/factories.rb +153 -0
- data/lib/solidus_stripe/version.rb +1 -1
- data/lib/solidus_stripe/webhook/event.rb +90 -0
- data/lib/solidus_stripe.rb +0 -2
- data/solidus_stripe.gemspec +29 -6
- data/spec/lib/solidus_stripe/configuration_spec.rb +21 -0
- data/spec/lib/solidus_stripe/money_to_stripe_amount_converter_spec.rb +133 -0
- data/spec/lib/solidus_stripe/refunds_synchronizer_spec.rb +238 -0
- data/spec/lib/solidus_stripe/seeds_spec.rb +43 -0
- data/spec/lib/solidus_stripe/webhook/event_spec.rb +134 -0
- data/spec/models/concerns/solidus_stripe/log_entries_spec.rb +54 -0
- data/spec/models/solidus_stripe/customer_spec.rb +47 -0
- data/spec/models/solidus_stripe/gateway_spec.rb +283 -0
- data/spec/models/solidus_stripe/payment_intent_spec.rb +17 -0
- data/spec/models/solidus_stripe/payment_method_spec.rb +137 -0
- data/spec/models/solidus_stripe/payment_source_spec.rb +25 -0
- data/spec/requests/solidus_stripe/intents_controller_spec.rb +29 -0
- data/spec/requests/solidus_stripe/webhooks_controller/charge/refunded_spec.rb +31 -0
- data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/canceled_spec.rb +23 -0
- data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/payment_failed_spec.rb +23 -0
- data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/succeeded_spec.rb +29 -0
- data/spec/requests/solidus_stripe/webhooks_controller_spec.rb +52 -0
- data/spec/solidus_stripe_spec_helper.rb +10 -0
- data/spec/subscribers/solidus_stripe/webhook/charge_subscriber_spec.rb +33 -0
- data/spec/subscribers/solidus_stripe/webhook/payment_intent_subscriber_spec.rb +297 -0
- data/spec/support/solidus_stripe/backend_test_helper.rb +210 -0
- data/spec/support/solidus_stripe/checkout_test_helper.rb +339 -0
- data/spec/support/solidus_stripe/factories.rb +5 -0
- data/spec/support/solidus_stripe/webhook/data_fixtures.rb +106 -0
- data/spec/support/solidus_stripe/webhook/event_with_context_factory.rb +82 -0
- data/spec/support/solidus_stripe/webhook/request_helper.rb +32 -0
- data/spec/system/backend/solidus_stripe/orders/payments_spec.rb +119 -0
- data/spec/system/frontend/.keep +0 -0
- data/spec/system/frontend/solidus_stripe/checkout_spec.rb +187 -0
- data/tmp/.keep +0 -0
- metadata +202 -78
- data/.rubocop_todo.yml +0 -298
- data/.travis.yml +0 -28
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-cart-page-checkout.js +0 -122
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-elements.js +0 -148
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-init.js +0 -20
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-intents.js +0 -84
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js +0 -160
- data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment.js +0 -16
- data/app/assets/javascripts/spree/frontend/solidus_stripe.js +0 -6
- data/app/controllers/solidus_stripe/payment_request_controller.rb +0 -52
- data/app/controllers/spree/stripe_controller.rb +0 -13
- data/app/decorators/models/spree/order_update_attributes_decorator.rb +0 -39
- data/app/decorators/models/spree/payment_decorator.rb +0 -11
- data/app/decorators/models/spree/refund_decorator.rb +0 -9
- data/app/models/solidus_stripe/address_from_params_service.rb +0 -72
- data/app/models/solidus_stripe/create_intents_payment_service.rb +0 -114
- data/app/models/solidus_stripe/prepare_order_for_payment_service.rb +0 -46
- data/app/models/solidus_stripe/shipping_rates_service.rb +0 -46
- data/app/models/spree/payment_method/stripe_credit_card.rb +0 -230
- data/bin/r +0 -13
- data/bin/sandbox_rails +0 -18
- data/db/migrate/20181010123508_update_stripe_payment_method_type_to_credit_card.rb +0 -21
- data/lib/assets/stylesheets/spree/frontend/solidus_stripe.scss +0 -11
- data/lib/solidus_stripe/testing_support/card_input_helper.rb +0 -34
- data/lib/tasks/solidus_stripe/db/seed.rake +0 -14
- data/lib/views/api/spree/api/payments/source_views/_stripe.json.jbuilder +0 -3
- data/lib/views/backend/spree/admin/log_entries/_stripe.html.erb +0 -28
- data/lib/views/backend/spree/admin/payments/source_forms/_stripe.html.erb +0 -1
- data/lib/views/backend/spree/admin/payments/source_views/_stripe.html.erb +0 -1
- data/lib/views/frontend/spree/checkout/existing_payment/_stripe.html.erb +0 -1
- data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +0 -8
- data/lib/views/frontend/spree/checkout/payment/v2/_javascript.html.erb +0 -78
- data/lib/views/frontend/spree/checkout/payment/v3/_elements.html.erb +0 -1
- data/lib/views/frontend/spree/checkout/payment/v3/_form_elements.html.erb +0 -40
- data/lib/views/frontend/spree/checkout/payment/v3/_intents.html.erb +0 -1
- data/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb +0 -2
- data/lib/views/frontend/spree/orders/_stripe_payment_request_button.html.erb +0 -14
- data/spec/features/stripe_checkout_spec.rb +0 -486
- data/spec/models/solidus_stripe/address_from_params_service_spec.rb +0 -87
- data/spec/models/solidus_stripe/create_intents_payment_service_spec.rb +0 -127
- data/spec/models/solidus_stripe/prepare_order_for_payment_service_spec.rb +0 -65
- data/spec/models/solidus_stripe/shipping_rates_service_spec.rb +0 -54
- data/spec/models/spree/payment_method/stripe_credit_card_spec.rb +0 -354
- data/spec/requests/payment_requests_spec.rb +0 -152
- data/spec/solidus_frontend_app_template.rb +0 -17
- data/spec/spec_helper.rb +0 -37
- data/spec/support/solidus_address_helper.rb +0 -15
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe SolidusStripe::PrepareOrderForPaymentService do
|
|
6
|
-
let(:service) { described_class.new(address, controller) }
|
|
7
|
-
|
|
8
|
-
let(:address) { create :address }
|
|
9
|
-
let(:user) { double("Spree::User") }
|
|
10
|
-
let(:email) { "foo@example.com" }
|
|
11
|
-
let(:order) { create :order_with_line_items, state: :cart, ship_address: nil, bill_address: nil }
|
|
12
|
-
let!(:shipping_method) { create :shipping_method, name: 'Air Mail', cost: 15 }
|
|
13
|
-
let!(:other_shipping_method) { create :shipping_method, name: 'DHL', cost: 7 }
|
|
14
|
-
let(:controller) do
|
|
15
|
-
double(
|
|
16
|
-
current_order: order,
|
|
17
|
-
spree_current_user: user,
|
|
18
|
-
params: {
|
|
19
|
-
email: email,
|
|
20
|
-
shipping_option: { id: shipping_method.id }
|
|
21
|
-
}
|
|
22
|
-
)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
before do
|
|
26
|
-
Spree::ZoneMember.create!(zone: Spree::Zone.first, zoneable: address.country)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
describe "#call" do
|
|
30
|
-
subject { service.call }
|
|
31
|
-
|
|
32
|
-
it "sets the order ship and bill address" do
|
|
33
|
-
expect { subject }.to change { order.ship_address }.to(address)
|
|
34
|
-
.and change { order.bill_address }.to(address)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
context "when the user is not logged in" do
|
|
38
|
-
let(:user) { nil }
|
|
39
|
-
|
|
40
|
-
it "sets the order email to allow guest checkout" do
|
|
41
|
-
expect { subject }.to change { order.email }.to(email)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it "sets the right shipping rate" do
|
|
46
|
-
expect { subject }.to change {
|
|
47
|
-
order.shipments.first.selected_shipping_rate.shipping_method_id
|
|
48
|
-
}.to(shipping_method.id)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
context "when the order can be advanced to payment state" do
|
|
52
|
-
it "advances the order to 'payment'" do
|
|
53
|
-
expect { subject }.to change { order.state }.to("payment")
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
context "when the order fails to be advanced to payment state" do
|
|
58
|
-
before { order.line_items.destroy_all }
|
|
59
|
-
|
|
60
|
-
it "leaves the order to a previous state" do
|
|
61
|
-
expect { subject }.not_to change { order.state }
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe SolidusStripe::ShippingRatesService do
|
|
6
|
-
let(:service) { described_class.new(order, user, params) }
|
|
7
|
-
|
|
8
|
-
let(:order) { create :order }
|
|
9
|
-
let(:user) { Spree::User.new }
|
|
10
|
-
|
|
11
|
-
let(:params) do
|
|
12
|
-
{
|
|
13
|
-
country: Spree::ZoneMember.first.zoneable.iso,
|
|
14
|
-
city: "Metropolis",
|
|
15
|
-
postalCode: "12345",
|
|
16
|
-
recipient: "",
|
|
17
|
-
addressLine: []
|
|
18
|
-
}
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
let(:ups_ground) { create(:shipping_method, cost: 5, available_to_all: false) }
|
|
22
|
-
let(:air_mail) { create(:shipping_method, cost: 8, name: "Air Mail", available_to_all: false) }
|
|
23
|
-
|
|
24
|
-
let(:fl_warehouse) { create(:stock_location, name: "FL Warehouse", shipping_methods: [ups_ground]) }
|
|
25
|
-
let(:ca_warehouse) { create(:stock_location, name: "CA Warehouse", shipping_methods: [air_mail]) }
|
|
26
|
-
|
|
27
|
-
before do
|
|
28
|
-
2.times { create :inventory_unit, order: order }
|
|
29
|
-
Spree::StockLocation.update_all backorderable_default: false
|
|
30
|
-
Spree::StockItem.find_by(stock_location: fl_warehouse, variant: order.variants.first).set_count_on_hand(1)
|
|
31
|
-
Spree::StockItem.find_by(stock_location: ca_warehouse, variant: order.variants.last).set_count_on_hand(1)
|
|
32
|
-
order.create_proposed_shipments
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
describe "#call" do
|
|
36
|
-
subject { service.call }
|
|
37
|
-
|
|
38
|
-
context "when there are no common shipping methods for all order shipments" do
|
|
39
|
-
it "cannot find any shipping rate" do
|
|
40
|
-
expect(subject).to be_empty
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
context "when there are common shipping methods for all order shipments" do
|
|
45
|
-
before { fl_warehouse.shipping_methods << ca_warehouse.shipping_methods.first }
|
|
46
|
-
|
|
47
|
-
context "when one shipping method is available for all shipments" do
|
|
48
|
-
it "sums the shipping rates for the shared shipping method" do
|
|
49
|
-
expect(subject).to eql [{ amount: 1600, id: air_mail.id.to_s, label: air_mail.name }]
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Spree::PaymentMethod::StripeCreditCard do
|
|
6
|
-
let(:secret_key) { 'key' }
|
|
7
|
-
let(:email) { 'customer@example.com' }
|
|
8
|
-
let(:source) { Spree::CreditCard.new }
|
|
9
|
-
|
|
10
|
-
let(:bill_address) { nil }
|
|
11
|
-
|
|
12
|
-
let(:order) {
|
|
13
|
-
double('Spree::Order',
|
|
14
|
-
email: email,
|
|
15
|
-
bill_address: bill_address,
|
|
16
|
-
currency: 'USD',
|
|
17
|
-
number: 'NUMBER',
|
|
18
|
-
total: 10.99
|
|
19
|
-
)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let(:payment) {
|
|
23
|
-
double('Spree::Payment',
|
|
24
|
-
source: source,
|
|
25
|
-
order: order,
|
|
26
|
-
amount: order.total
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let(:gateway) do
|
|
31
|
-
double('gateway').tap do |p|
|
|
32
|
-
allow(p).to receive(:purchase)
|
|
33
|
-
allow(p).to receive(:authorize)
|
|
34
|
-
allow(p).to receive(:capture)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
before do
|
|
39
|
-
subject.preferences = { secret_key: secret_key }
|
|
40
|
-
allow(subject).to receive(:options_for_purchase_or_auth).and_return(['money', 'cc', 'opts'])
|
|
41
|
-
allow(subject).to receive(:gateway).and_return gateway
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it 'can enable Stripe.js V3 Elements via preference setting' do
|
|
45
|
-
expect do
|
|
46
|
-
subject.preferred_v3_elements = true
|
|
47
|
-
end.to change { subject.v3_elements? }.from(false).to true
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
describe '#stripe_config' do
|
|
51
|
-
context 'when payment request feature is disabled' do
|
|
52
|
-
before { subject.preferences = { publishable_key: 'stripe_key' } }
|
|
53
|
-
|
|
54
|
-
it 'includes the basic configuration' do
|
|
55
|
-
config = subject.stripe_config(order)
|
|
56
|
-
expect(config.keys).to eq %i[id publishable_key]
|
|
57
|
-
expect(config[:publishable_key]).to include('stripe_key')
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
context 'when the payment request feature is enabled' do
|
|
62
|
-
before do
|
|
63
|
-
subject.preferences = {
|
|
64
|
-
publishable_key: 'stripe_key',
|
|
65
|
-
stripe_country: 'US',
|
|
66
|
-
v3_intents: true
|
|
67
|
-
}
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
it 'includes the payment request configuration as well' do
|
|
71
|
-
config = subject.stripe_config(order)
|
|
72
|
-
expect(config.keys).to eq %i[id publishable_key payment_request]
|
|
73
|
-
expect(config[:payment_request][:currency]).to eq 'usd'
|
|
74
|
-
expect(config[:payment_request][:amount]).to be 1099
|
|
75
|
-
expect(config[:payment_request][:label]).to include 'NUMBER'
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
describe '#create_profile' do
|
|
81
|
-
before do
|
|
82
|
-
allow(payment.source).to receive(:update_attributes!)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
context 'with an order that has a bill address' do
|
|
86
|
-
let(:bill_address) {
|
|
87
|
-
double('Spree::Address',
|
|
88
|
-
address1: '123 Happy Road',
|
|
89
|
-
address2: 'Apt 303',
|
|
90
|
-
city: 'Suzarac',
|
|
91
|
-
zipcode: '95671',
|
|
92
|
-
state: double('Spree::State', name: 'Oregon'),
|
|
93
|
-
country: double('Spree::Country', name: 'United States'))
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
it 'stores the bill address with the gateway' do
|
|
97
|
-
expect(subject.gateway).to receive(:store).with(payment.source, {
|
|
98
|
-
email: email,
|
|
99
|
-
login: secret_key,
|
|
100
|
-
|
|
101
|
-
address: {
|
|
102
|
-
address1: '123 Happy Road',
|
|
103
|
-
address2: 'Apt 303',
|
|
104
|
-
city: 'Suzarac',
|
|
105
|
-
zip: '95671',
|
|
106
|
-
state: 'Oregon',
|
|
107
|
-
country: 'United States'
|
|
108
|
-
}
|
|
109
|
-
}).and_return double.as_null_object
|
|
110
|
-
|
|
111
|
-
subject.create_profile payment
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
context 'with an order that does not have a bill address' do
|
|
116
|
-
it 'does not store a bill address with the gateway' do
|
|
117
|
-
expect(subject.gateway).to receive(:store).with(payment.source, {
|
|
118
|
-
email: email,
|
|
119
|
-
login: secret_key,
|
|
120
|
-
}).and_return double.as_null_object
|
|
121
|
-
|
|
122
|
-
subject.create_profile payment
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# Regression test for #141
|
|
126
|
-
context "correcting the card type" do
|
|
127
|
-
before do
|
|
128
|
-
# We don't care about this method for these tests
|
|
129
|
-
allow(subject.gateway).to receive(:store).and_return(double.as_null_object)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
it "converts 'American Express' to 'american_express'" do
|
|
133
|
-
payment.source.cc_type = 'American Express'
|
|
134
|
-
subject.create_profile(payment)
|
|
135
|
-
expect(payment.source.cc_type).to eq('american_express')
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
it "converts 'Diners Club' to 'diners_club'" do
|
|
139
|
-
payment.source.cc_type = 'Diners Club'
|
|
140
|
-
subject.create_profile(payment)
|
|
141
|
-
expect(payment.source.cc_type).to eq('diners_club')
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
it "converts 'Visa' to 'visa'" do
|
|
145
|
-
payment.source.cc_type = 'Visa'
|
|
146
|
-
subject.create_profile(payment)
|
|
147
|
-
expect(payment.source.cc_type).to eq('visa')
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
context 'with a card represents payment_profile' do
|
|
153
|
-
let(:source) { Spree::CreditCard.new(gateway_payment_profile_id: 'tok_profileid') }
|
|
154
|
-
let(:bill_address) { nil }
|
|
155
|
-
|
|
156
|
-
it 'stores the profile_id as a card' do
|
|
157
|
-
expect(subject.gateway).to receive(:store).with(source.gateway_payment_profile_id, anything).and_return double.as_null_object
|
|
158
|
-
|
|
159
|
-
subject.create_profile payment
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
context 'purchasing' do
|
|
165
|
-
after do
|
|
166
|
-
subject.purchase(19.99, 'credit card', {})
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
it 'send the payment to the gateway' do
|
|
170
|
-
expect(gateway).to receive(:purchase).with('money', 'cc', 'opts')
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
context 'purchasing with fractionless currency' do
|
|
175
|
-
after do
|
|
176
|
-
subject.purchase(1999, 'credit card', { currency: 'JPY' })
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
it 'send the payment to the gateway' do
|
|
180
|
-
expect(gateway).to receive(:purchase).with('money', 'cc', 'opts')
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
context 'authorizing' do
|
|
185
|
-
after do
|
|
186
|
-
subject.authorize(19.99, 'credit card', {})
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
it 'send the authorization to the gateway' do
|
|
190
|
-
expect(gateway).to receive(:authorize).with('money', 'cc', 'opts')
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
context 'authorizing with fractionless currency' do
|
|
195
|
-
after do
|
|
196
|
-
subject.authorize(1999, 'credit card', { currency: 'JPY' })
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
it 'send the authorization to the gateway' do
|
|
200
|
-
expect(gateway).to receive(:authorize).with('money', 'cc', 'opts')
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
context 'capturing' do
|
|
205
|
-
after do
|
|
206
|
-
subject.capture(1234, 'response_code', {})
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
it 'convert the amount to cents' do
|
|
210
|
-
expect(gateway).to receive(:capture).with(1234, anything, anything)
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
it 'use the response code as the authorization' do
|
|
214
|
-
expect(gateway).to receive(:capture).with(anything, 'response_code', anything)
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
context 'capturing with fractionless currency' do
|
|
219
|
-
after do
|
|
220
|
-
subject.capture(1234, 'response_code', { currency: 'JPY' })
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
it 'amount not converted to cents' do
|
|
224
|
-
expect(gateway).to receive(:capture).with(Spree::Money.new(123_400, { currency: 'JPY' }), anything, anything)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
it 'use the response code as the authorization' do
|
|
228
|
-
expect(gateway).to receive(:capture).with(anything, 'response_code', anything)
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
context 'capture with payment class' do
|
|
233
|
-
let(:payment_method) do
|
|
234
|
-
payment_method = described_class.new(active: true)
|
|
235
|
-
payment_method.set_preference :secret_key, secret_key
|
|
236
|
-
allow(payment_method).to receive(:options_for_purchase_or_auth).and_return(['money', 'cc', 'opts'])
|
|
237
|
-
allow(payment_method).to receive(:gateway).and_return gateway
|
|
238
|
-
allow(payment_method).to receive_messages source_required: true
|
|
239
|
-
payment_method
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
let!(:store) { FactoryBot.create(:store) }
|
|
243
|
-
let(:order) { Spree::Order.create! }
|
|
244
|
-
|
|
245
|
-
let(:card) do
|
|
246
|
-
FactoryBot.create(
|
|
247
|
-
:credit_card,
|
|
248
|
-
gateway_customer_profile_id: 'cus_abcde',
|
|
249
|
-
imported: false
|
|
250
|
-
)
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
let(:payment) do
|
|
254
|
-
payment = Spree::Payment.new
|
|
255
|
-
payment.source = card
|
|
256
|
-
payment.order = order
|
|
257
|
-
payment.payment_method = payment_method
|
|
258
|
-
payment.amount = 98.55
|
|
259
|
-
payment.state = 'pending'
|
|
260
|
-
payment.response_code = '12345'
|
|
261
|
-
payment
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
let!(:success_response) do
|
|
265
|
-
ActiveMerchant::Billing::Response.new(
|
|
266
|
-
true,
|
|
267
|
-
nil,
|
|
268
|
-
{},
|
|
269
|
-
avs_result: { 'code' => 'avs-code' },
|
|
270
|
-
cvv_result: 'cvv-code',
|
|
271
|
-
authorization: '123',
|
|
272
|
-
)
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
after do
|
|
276
|
-
payment.capture!
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
it 'gets correct amount' do
|
|
280
|
-
expect(gateway).to receive(:capture).with(9855, '12345', anything).and_return(success_response)
|
|
281
|
-
end
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
describe '#try_void' do
|
|
285
|
-
let(:payment) { create :payment, amount: order.total }
|
|
286
|
-
|
|
287
|
-
shared_examples 'voids the payment transaction' do
|
|
288
|
-
it 'voids the payment transaction' do
|
|
289
|
-
expect(gateway).to receive(:void)
|
|
290
|
-
|
|
291
|
-
subject.try_void(payment)
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
context 'when using Payment Intents' do
|
|
296
|
-
before { subject.preferred_v3_intents = true }
|
|
297
|
-
|
|
298
|
-
context 'when the payment is completed' do
|
|
299
|
-
before do
|
|
300
|
-
allow(payment).to receive(:completed?) { true }
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
it 'creates a refund' do
|
|
304
|
-
expect { subject.try_void(payment) }.to change { Spree::Refund.count }.by(1)
|
|
305
|
-
end
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
context 'when the payment is not completed' do
|
|
309
|
-
it_behaves_like 'voids the payment transaction'
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
context 'when not using Payment Intents' do
|
|
314
|
-
before { subject.preferred_v3_intents = false }
|
|
315
|
-
|
|
316
|
-
context 'when the payment is completed' do
|
|
317
|
-
it_behaves_like 'voids the payment transaction'
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
context 'when the payment is not completed' do
|
|
321
|
-
it_behaves_like 'voids the payment transaction'
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
describe '#options_for_purchase_or_auth' do
|
|
327
|
-
let(:card) do
|
|
328
|
-
FactoryBot.create(
|
|
329
|
-
:credit_card,
|
|
330
|
-
gateway_customer_profile_id: 'cus_abcde',
|
|
331
|
-
imported: false
|
|
332
|
-
)
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
before do
|
|
336
|
-
allow(subject).to receive(:options_for_purchase_or_auth).and_call_original
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
context 'transaction_options' do
|
|
340
|
-
it 'includes basic values and keys' do
|
|
341
|
-
options = subject.send(:options_for_purchase_or_auth, 19.99, card, {})
|
|
342
|
-
expect(options[0]).to eq(19.99)
|
|
343
|
-
expect(options[1]).to eq(card)
|
|
344
|
-
expect(options[2].keys).to eq([:description, :currency, :customer])
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
it 'includes statement_descriptor_suffix within options' do
|
|
348
|
-
transaction_options = { statement_descriptor_suffix: 'FFFFFFF' }
|
|
349
|
-
options = subject.send(:options_for_purchase_or_auth, 19.99, card, transaction_options)
|
|
350
|
-
expect(options.last[:statement_descriptor_suffix]).to eq('FFFFFFF')
|
|
351
|
-
end
|
|
352
|
-
end
|
|
353
|
-
end
|
|
354
|
-
end
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe "Payment Request", type: :request do
|
|
6
|
-
describe "POST /stripe/update_order" do
|
|
7
|
-
it "responds with { success: true } when the order is correctly updated" do
|
|
8
|
-
order = create(:order_ready_to_complete)
|
|
9
|
-
allow_any_instance_of(SolidusStripe::PaymentRequestController).to receive(:current_order).and_return(order)
|
|
10
|
-
|
|
11
|
-
with_disabled_forgery_protection do
|
|
12
|
-
post "/stripe/update_order", params: stripe_update_request_params(order: order)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
json = JSON.parse(response.body)
|
|
16
|
-
expect(json["success"]).to be_truthy
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
context "when phone number is provided as param and already set on the address" do
|
|
20
|
-
it "overrides the address field" do
|
|
21
|
-
order = create(:order_ready_to_complete)
|
|
22
|
-
allow_any_instance_of(SolidusStripe::PaymentRequestController).to receive(:current_order).and_return(order)
|
|
23
|
-
|
|
24
|
-
expect {
|
|
25
|
-
with_disabled_forgery_protection do
|
|
26
|
-
post "/stripe/update_order", params: stripe_update_request_params(order: order, shipping_address: default_shipping_address(phone: nil), phone: '911')
|
|
27
|
-
end
|
|
28
|
-
}.to change { order.shipping_address.phone }.to('911')
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
context "when phone number is provided both as shipping address param and main param, and already set on the address" do
|
|
33
|
-
it "overrides the address field giving precedence to the shipping address param" do
|
|
34
|
-
order = create(:order_ready_to_complete)
|
|
35
|
-
allow_any_instance_of(SolidusStripe::PaymentRequestController).to receive(:current_order).and_return(order)
|
|
36
|
-
|
|
37
|
-
expect {
|
|
38
|
-
with_disabled_forgery_protection do
|
|
39
|
-
post "/stripe/update_order", params: stripe_update_request_params(order: order, shipping_address: default_shipping_address(phone: '555'), phone: '911')
|
|
40
|
-
end
|
|
41
|
-
}.to change { order.shipping_address.phone }.to('555')
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context "when phone number is not required, not provided as param and not set on the shipping address" do
|
|
46
|
-
it "does not populate the address field" do
|
|
47
|
-
with_address_phone_not_required
|
|
48
|
-
order = create(:order_ready_to_complete, shipping_address: create(:address, phone: nil))
|
|
49
|
-
allow_any_instance_of(SolidusStripe::PaymentRequestController).to receive(:current_order).and_return(order)
|
|
50
|
-
|
|
51
|
-
expect {
|
|
52
|
-
with_disabled_forgery_protection do
|
|
53
|
-
post "/stripe/update_order", params: stripe_update_request_params(order: order, shipping_address: default_shipping_address(phone: nil), phone: nil)
|
|
54
|
-
end
|
|
55
|
-
}.not_to change { order.shipping_address.phone }
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context "when phone number is not required, provided as param and not set on the shipping address" do
|
|
60
|
-
it "populates the address field with the phone passed as param" do
|
|
61
|
-
with_address_phone_not_required
|
|
62
|
-
order = create(:order_ready_to_complete, shipping_address: create(:address, phone: nil))
|
|
63
|
-
allow_any_instance_of(SolidusStripe::PaymentRequestController).to receive(:current_order).and_return(order)
|
|
64
|
-
|
|
65
|
-
expect {
|
|
66
|
-
with_disabled_forgery_protection do
|
|
67
|
-
post "/stripe/update_order", params: stripe_update_request_params(order: order, shipping_address: default_shipping_address(phone: nil), phone: '911')
|
|
68
|
-
end
|
|
69
|
-
}.to change { order.shipping_address.phone }.from(nil).to('911')
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
context "when phone number is not required, provided as param but already set on the shipping address" do
|
|
74
|
-
it "populates the address field with the phone passed in the shipping field" do
|
|
75
|
-
with_address_phone_not_required
|
|
76
|
-
order = create(:order_ready_to_complete, shipping_address: create(:address, phone: nil))
|
|
77
|
-
allow_any_instance_of(SolidusStripe::PaymentRequestController).to receive(:current_order).and_return(order)
|
|
78
|
-
|
|
79
|
-
expect {
|
|
80
|
-
with_disabled_forgery_protection do
|
|
81
|
-
post "/stripe/update_order", params: stripe_update_request_params(order: order, shipping_address: default_shipping_address(phone: '555'), phone: '911')
|
|
82
|
-
end
|
|
83
|
-
}.to change { order.shipping_address.phone }.from(nil).to('555')
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
private
|
|
89
|
-
|
|
90
|
-
def with_address_phone_not_required
|
|
91
|
-
if Spree::Config.respond_to?(:address_requires_phone)
|
|
92
|
-
stub_spree_preferences(address_requires_phone: false)
|
|
93
|
-
else
|
|
94
|
-
allow_any_instance_of(Spree::Address).to receive(:require_phone?).and_return(false)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def with_disabled_forgery_protection
|
|
99
|
-
original_allow_forgery_protection_value = ActionController::Base.allow_forgery_protection
|
|
100
|
-
ActionController::Base.allow_forgery_protection = false
|
|
101
|
-
|
|
102
|
-
yield
|
|
103
|
-
|
|
104
|
-
ActionController::Base.allow_forgery_protection = original_allow_forgery_protection_value
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def stripe_update_request_params(
|
|
108
|
-
order:,
|
|
109
|
-
shipping_address: nil,
|
|
110
|
-
name: 'Clark Kent',
|
|
111
|
-
phone: '555-555-0199'
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
{
|
|
115
|
-
shipping_address: shipping_address || default_shipping_address,
|
|
116
|
-
shipping_option: {
|
|
117
|
-
id: order.shipments.first.shipping_rates.first.shipping_method.id
|
|
118
|
-
},
|
|
119
|
-
name: name,
|
|
120
|
-
phone: phone,
|
|
121
|
-
email: order.email
|
|
122
|
-
}
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def default_shipping_address(
|
|
126
|
-
country: nil,
|
|
127
|
-
region: nil,
|
|
128
|
-
recipient: 'Clark Kent',
|
|
129
|
-
city: 'Metropolis',
|
|
130
|
-
postal_code: '12345',
|
|
131
|
-
address_line: ['12, Lincoln Rd'],
|
|
132
|
-
phone: '555-555-0199'
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
if country.blank? || region.blank?
|
|
136
|
-
state = create(:state)
|
|
137
|
-
|
|
138
|
-
country ||= state.country.iso
|
|
139
|
-
region ||= state.abbr
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
{
|
|
143
|
-
country: country,
|
|
144
|
-
region: region,
|
|
145
|
-
recipient: recipient,
|
|
146
|
-
city: city,
|
|
147
|
-
postalCode: postal_code,
|
|
148
|
-
addressLine: address_line,
|
|
149
|
-
phone: phone
|
|
150
|
-
}
|
|
151
|
-
end
|
|
152
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
create_file "public/robots.txt"
|
|
4
|
-
bundle_command "add solidus_frontend --github solidusio/solidus_frontend --branch #{ENV['SOLIDUS_BRANCH'] || 'main'}"
|
|
5
|
-
generate "solidus_frontend:install --auto-accept"
|
|
6
|
-
empty_directory 'lib/generators/solidus_frontend/install'
|
|
7
|
-
|
|
8
|
-
create_file 'lib/generators/solidus_frontend/install/install_generator.rb', <<-CODE
|
|
9
|
-
puts "SolidusFrontend::Generators::InstallGenerator was disabled."
|
|
10
|
-
module SolidusFrontend
|
|
11
|
-
module Generators
|
|
12
|
-
class InstallGenerator < Rails::Generators::Base
|
|
13
|
-
class_option :auto_accept, type: :boolean, default: false
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
CODE
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Configure Rails Environment
|
|
4
|
-
ENV['RAILS_ENV'] = 'test'
|
|
5
|
-
|
|
6
|
-
# Run Coverage report
|
|
7
|
-
require 'solidus_dev_support/rspec/coverage'
|
|
8
|
-
|
|
9
|
-
# Create the dummy app if it's still missing.
|
|
10
|
-
dummy_env = "#{__dir__}/dummy/config/environment.rb"
|
|
11
|
-
system 'bin/rake extension:test_app' unless File.exist? dummy_env
|
|
12
|
-
require dummy_env
|
|
13
|
-
|
|
14
|
-
# Requires factories and other useful helpers defined in spree_core.
|
|
15
|
-
require 'solidus_dev_support/rspec/feature_helper'
|
|
16
|
-
|
|
17
|
-
# Requires supporting ruby files with custom matchers and macros, etc,
|
|
18
|
-
# in spec/support/ and its subdirectories.
|
|
19
|
-
Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
|
|
20
|
-
|
|
21
|
-
# Requires factories defined in lib/solidus_stripe/testing_support/factories.rb
|
|
22
|
-
SolidusDevSupport::TestingSupport::Factories.load_for(SolidusStripe::Engine)
|
|
23
|
-
|
|
24
|
-
# Requires card input helper defined in lib/solidus_stripe/testing_support/card_input_helper.rb
|
|
25
|
-
require 'solidus_stripe/testing_support/card_input_helper'
|
|
26
|
-
|
|
27
|
-
RSpec.configure do |config|
|
|
28
|
-
config.infer_spec_type_from_file_location!
|
|
29
|
-
config.use_transactional_fixtures = false
|
|
30
|
-
|
|
31
|
-
config.include SolidusAddressNameHelper, type: :feature
|
|
32
|
-
config.include SolidusCardInputHelper, type: :feature
|
|
33
|
-
|
|
34
|
-
if Spree.solidus_gem_version < Gem::Version.new('2.11')
|
|
35
|
-
config.extend Spree::TestingSupport::AuthorizationHelpers::Request, type: :system
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
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 SolidusSupport.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
|