solidus_stripe 4.4.0 → 5.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +95 -41
- data/.gitignore +3 -0
- data/.rubocop.yml +94 -4
- data/.yardopts +1 -0
- data/CHANGELOG.md +1 -265
- data/Gemfile +10 -30
- data/LICENSE +2 -2
- data/Procfile.dev +3 -0
- data/README.md +145 -215
- data/Rakefile +7 -6
- 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 +201 -75
- 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 -350
- data/spec/requests/payment_requests_spec.rb +0 -152
- data/spec/spec_helper.rb +0 -37
- data/spec/support/solidus_address_helper.rb +0 -15
data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
// Shared code between Payment Intents and Payment Request Button on cart page
|
2
|
-
|
3
|
-
(function() {
|
4
|
-
var PaymentRequestButtonShared;
|
5
|
-
|
6
|
-
PaymentRequestButtonShared = {
|
7
|
-
authToken: $('meta[name="csrf-token"]').attr('content'),
|
8
|
-
|
9
|
-
setUpPaymentRequest: function(opts) {
|
10
|
-
var opts = opts || {};
|
11
|
-
var config = this.config.payment_request;
|
12
|
-
|
13
|
-
if (config) {
|
14
|
-
config.requestShipping = opts.requestShipping || false;
|
15
|
-
|
16
|
-
var paymentRequest = this.stripe.paymentRequest({
|
17
|
-
country: config.country,
|
18
|
-
currency: config.currency,
|
19
|
-
total: {
|
20
|
-
label: config.label,
|
21
|
-
amount: config.amount
|
22
|
-
},
|
23
|
-
requestPayerName: true,
|
24
|
-
requestPayerEmail: true,
|
25
|
-
requestPayerPhone: true,
|
26
|
-
requestShipping: config.requestShipping,
|
27
|
-
shippingOptions: []
|
28
|
-
});
|
29
|
-
|
30
|
-
var prButton = this.elements.create('paymentRequestButton', {
|
31
|
-
paymentRequest: paymentRequest
|
32
|
-
});
|
33
|
-
|
34
|
-
var onButtonMount = function(result) {
|
35
|
-
var id = 'payment-request-button';
|
36
|
-
|
37
|
-
if (result) {
|
38
|
-
prButton.mount('#' + id);
|
39
|
-
} else {
|
40
|
-
document.getElementById(id).style.display = 'none';
|
41
|
-
}
|
42
|
-
if (typeof this.onPrButtonMounted === 'function') {
|
43
|
-
this.onPrButtonMounted(id, result);
|
44
|
-
}
|
45
|
-
}
|
46
|
-
paymentRequest.canMakePayment().then(onButtonMount.bind(this));
|
47
|
-
|
48
|
-
var onPrPaymentMethod = function(result) {
|
49
|
-
this.errorElement.text('').hide();
|
50
|
-
this.onPrPayment(result);
|
51
|
-
};
|
52
|
-
paymentRequest.on('paymentmethod', onPrPaymentMethod.bind(this));
|
53
|
-
|
54
|
-
var onShippingAddressChange = function(ev) {
|
55
|
-
var showError = this.showError.bind(this);
|
56
|
-
|
57
|
-
fetch('/stripe/shipping_rates', {
|
58
|
-
method: 'POST',
|
59
|
-
headers: { 'Content-Type': 'application/json' },
|
60
|
-
body: JSON.stringify({
|
61
|
-
authenticity_token: this.authToken,
|
62
|
-
shipping_address: ev.shippingAddress
|
63
|
-
})
|
64
|
-
}).then(function(response) {
|
65
|
-
return response.json();
|
66
|
-
}).then(function(result) {
|
67
|
-
if (result.error) {
|
68
|
-
showError(result.error);
|
69
|
-
return false;
|
70
|
-
} else {
|
71
|
-
ev.updateWith({
|
72
|
-
status: 'success',
|
73
|
-
shippingOptions: result.shipping_rates
|
74
|
-
});
|
75
|
-
}
|
76
|
-
});
|
77
|
-
};
|
78
|
-
paymentRequest.on('shippingaddresschange', onShippingAddressChange.bind(this));
|
79
|
-
}
|
80
|
-
},
|
81
|
-
|
82
|
-
handleServerResponse: function(response, payment) {
|
83
|
-
if (response.error) {
|
84
|
-
this.showError(response.error);
|
85
|
-
this.completePaymentRequest(payment, 'fail');
|
86
|
-
} else if (response.requires_action) {
|
87
|
-
var clientSecret = response.stripe_payment_intent_client_secret;
|
88
|
-
var onConfirmCardPayment = this.onConfirmCardPayment.bind(this);
|
89
|
-
|
90
|
-
this.stripe.confirmCardPayment(
|
91
|
-
clientSecret,
|
92
|
-
{payment_method: payment.paymentMethod.id},
|
93
|
-
{handleActions: false}
|
94
|
-
).then(function(confirmResult) {
|
95
|
-
onConfirmCardPayment(confirmResult, payment, clientSecret)
|
96
|
-
});
|
97
|
-
} else {
|
98
|
-
this.completePayment(payment, response.stripe_payment_intent_id)
|
99
|
-
}
|
100
|
-
},
|
101
|
-
|
102
|
-
onConfirmCardPayment: function(confirmResult, payment, clientSecret) {
|
103
|
-
onStripeResponse = function(response, payment) {
|
104
|
-
if (response.error) {
|
105
|
-
this.showError(response.error);
|
106
|
-
} else {
|
107
|
-
this.completePayment(payment, response.paymentIntent.id)
|
108
|
-
}
|
109
|
-
}.bind(this);
|
110
|
-
|
111
|
-
if (confirmResult.error) {
|
112
|
-
this.completePaymentRequest(payment, 'fail');
|
113
|
-
this.showError(confirmResult.error);
|
114
|
-
} else {
|
115
|
-
this.completePaymentRequest(payment, 'success');
|
116
|
-
this.stripe.confirmCardPayment(clientSecret).then(function(response) {
|
117
|
-
onStripeResponse(response, payment);
|
118
|
-
});
|
119
|
-
}
|
120
|
-
},
|
121
|
-
|
122
|
-
completePayment: function(payment, stripePaymentIntentId) {
|
123
|
-
var onCreateBackendPayment = function (response) {
|
124
|
-
if (response.error) {
|
125
|
-
this.completePaymentRequest(payment, 'fail');
|
126
|
-
this.showError(response.error);
|
127
|
-
} else {
|
128
|
-
this.completePaymentRequest(payment, 'success');
|
129
|
-
this.submitPayment(payment);
|
130
|
-
}
|
131
|
-
}.bind(this);
|
132
|
-
|
133
|
-
fetch('/stripe/create_payment', {
|
134
|
-
method: 'POST',
|
135
|
-
headers: { 'Content-Type': 'application/json' },
|
136
|
-
body: JSON.stringify({
|
137
|
-
form_data: this.form ? this.form.serialize() : payment.shippingAddress,
|
138
|
-
spree_payment_method_id: this.config.id,
|
139
|
-
stripe_payment_intent_id: stripePaymentIntentId,
|
140
|
-
authenticity_token: this.authToken
|
141
|
-
})
|
142
|
-
}).then(function(solidusPaymentResponse) {
|
143
|
-
return solidusPaymentResponse.json();
|
144
|
-
}).then(onCreateBackendPayment)
|
145
|
-
},
|
146
|
-
|
147
|
-
completePaymentRequest: function(payment, state) {
|
148
|
-
if (payment && typeof payment.complete === 'function') {
|
149
|
-
payment.complete(state);
|
150
|
-
if (state === 'fail') {
|
151
|
-
// restart the button (required in order to force address choice)
|
152
|
-
new SolidusStripe.CartPageCheckout().init();
|
153
|
-
}
|
154
|
-
}
|
155
|
-
}
|
156
|
-
};
|
157
|
-
|
158
|
-
Object.assign(SolidusStripe.PaymentIntents.prototype, PaymentRequestButtonShared);
|
159
|
-
Object.assign(SolidusStripe.CartPageCheckout.prototype, PaymentRequestButtonShared);
|
160
|
-
})()
|
@@ -1,16 +0,0 @@
|
|
1
|
-
window.SolidusStripe = window.SolidusStripe || {};
|
2
|
-
|
3
|
-
SolidusStripe.Payment = function() {
|
4
|
-
this.config = $('[data-stripe-config]').data('stripe-config');
|
5
|
-
this.element = $('#payment_method_' + this.config.id);
|
6
|
-
this.authToken = $('meta[name="csrf-token"]').attr('content');
|
7
|
-
|
8
|
-
this.stripe = Stripe(this.config.publishable_key);
|
9
|
-
this.elements = this.stripe.elements(this.elementsBaseOptions());
|
10
|
-
};
|
11
|
-
|
12
|
-
SolidusStripe.Payment.prototype.elementsBaseOptions = function () {
|
13
|
-
return {
|
14
|
-
locale: 'en'
|
15
|
-
};
|
16
|
-
};
|
@@ -1,6 +0,0 @@
|
|
1
|
-
//= require ./solidus_stripe/stripe-payment
|
2
|
-
//= require ./solidus_stripe/stripe-elements
|
3
|
-
//= require ./solidus_stripe/stripe-payment-intents
|
4
|
-
//= require ./solidus_stripe/stripe-cart-page-checkout
|
5
|
-
//= require ./solidus_stripe/stripe-payment-request-button-shared
|
6
|
-
//= require ./solidus_stripe/stripe-init
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SolidusStripe
|
4
|
-
class PaymentRequestController < Spree::BaseController
|
5
|
-
include Spree::Core::ControllerHelpers::Order
|
6
|
-
|
7
|
-
def shipping_rates
|
8
|
-
rates = SolidusStripe::ShippingRatesService.new(
|
9
|
-
current_order,
|
10
|
-
spree_current_user,
|
11
|
-
params[:shipping_address]
|
12
|
-
).call
|
13
|
-
|
14
|
-
if rates.any?
|
15
|
-
render json: { success: true, shipping_rates: rates }
|
16
|
-
else
|
17
|
-
render json: { success: false, error: 'No shipping method available for that address' }, status: :internal_server_error
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def update_order
|
22
|
-
current_order.restart_checkout_flow
|
23
|
-
|
24
|
-
address = SolidusStripe::AddressFromParamsService.new(
|
25
|
-
shipping_address_from_params,
|
26
|
-
spree_current_user
|
27
|
-
).call
|
28
|
-
|
29
|
-
if address.valid?
|
30
|
-
SolidusStripe::PrepareOrderForPaymentService.new(address, self).call
|
31
|
-
|
32
|
-
if current_order.payment?
|
33
|
-
render json: { success: true }
|
34
|
-
else
|
35
|
-
render json: { success: false, error: 'Order not ready for payment. Try manual checkout.' }, status: :internal_server_error
|
36
|
-
end
|
37
|
-
else
|
38
|
-
render json: { success: false, error: address.errors.full_messages.to_sentence }, status: :internal_server_error
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def shipping_address_from_params
|
45
|
-
return {} unless params[:shipping_address]
|
46
|
-
return params[:shipping_address] if params.dig(:shipping_address, :phone).present?
|
47
|
-
|
48
|
-
params[:shipping_address][:phone] = params[:phone]
|
49
|
-
params[:shipping_address]
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spree
|
4
|
-
class StripeController < SolidusStripe::IntentsController
|
5
|
-
include Core::ControllerHelpers::Order
|
6
|
-
|
7
|
-
def confirm_payment
|
8
|
-
Deprecation.warn "please use SolidusStripe::IntentsController#confirm"
|
9
|
-
|
10
|
-
confirm
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spree
|
4
|
-
module OrderUpdateAttributesDecorator
|
5
|
-
def assign_payments_attributes
|
6
|
-
return if payments_attributes.empty?
|
7
|
-
return if adding_new_stripe_payment_intents_card?
|
8
|
-
|
9
|
-
stripe_intents_pending_payments.each(&:void_transaction!)
|
10
|
-
|
11
|
-
super
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def adding_new_stripe_payment_intents_card?
|
17
|
-
paying_with_stripe_intents? && stripe_intents_pending_payments.any?
|
18
|
-
end
|
19
|
-
|
20
|
-
def stripe_intents_pending_payments
|
21
|
-
@stripe_intents_pending_payments ||= order.payments.valid.select do |payment|
|
22
|
-
payment_method = payment.payment_method
|
23
|
-
payment.pending? && stripe_intents?(payment_method)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def paying_with_stripe_intents?
|
28
|
-
if id = payments_attributes.first&.dig(:payment_method_id)
|
29
|
-
stripe_intents?(Spree::PaymentMethod.find(id))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def stripe_intents?(payment_method)
|
34
|
-
payment_method.respond_to?(:v3_intents?) && payment_method.v3_intents?
|
35
|
-
end
|
36
|
-
|
37
|
-
::Spree::OrderUpdateAttributes.prepend(self)
|
38
|
-
end
|
39
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SolidusStripe
|
4
|
-
class AddressFromParamsService
|
5
|
-
attr_reader :address_params, :user
|
6
|
-
|
7
|
-
def initialize(address_params, user = nil)
|
8
|
-
@address_params, @user = address_params, user
|
9
|
-
end
|
10
|
-
|
11
|
-
def call
|
12
|
-
if user
|
13
|
-
user.addresses.find_or_initialize_by(attributes)
|
14
|
-
else
|
15
|
-
Spree::Address.new(attributes)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def attributes
|
22
|
-
@attributes ||= begin
|
23
|
-
default_attributes.tap do |attributes|
|
24
|
-
# possibly anonymized attributes:
|
25
|
-
phone = address_params[:phone]
|
26
|
-
lines = address_params[:addressLine]
|
27
|
-
names = address_params[:recipient].split(' ')
|
28
|
-
|
29
|
-
name_attributes = if SolidusSupport.combined_first_and_last_name_in_address? && Spree::Address.column_names.include?("name")
|
30
|
-
{
|
31
|
-
name: address_params[:recipient]
|
32
|
-
}
|
33
|
-
else
|
34
|
-
{
|
35
|
-
firstname: names.first,
|
36
|
-
lastname: names.last,
|
37
|
-
}
|
38
|
-
end
|
39
|
-
|
40
|
-
attributes
|
41
|
-
.merge!(name_attributes)
|
42
|
-
.merge!(
|
43
|
-
state_id: state&.id,
|
44
|
-
phone: phone,
|
45
|
-
address1: lines.first,
|
46
|
-
address2: lines.second
|
47
|
-
)
|
48
|
-
.reject! { |_, value| value.blank? }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def country
|
54
|
-
@country ||= Spree::Country.find_by_iso(address_params[:country])
|
55
|
-
end
|
56
|
-
|
57
|
-
def state
|
58
|
-
@state ||= begin
|
59
|
-
region = address_params[:region]
|
60
|
-
country.states.find_by(abbr: region) || country.states.find_by(name: region)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def default_attributes
|
65
|
-
{
|
66
|
-
country_id: country.id,
|
67
|
-
city: address_params[:city],
|
68
|
-
zipcode: address_params[:postalCode]
|
69
|
-
}
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SolidusStripe
|
4
|
-
class CreateIntentsPaymentService
|
5
|
-
attr_reader :intent_id, :stripe, :controller
|
6
|
-
|
7
|
-
delegate :request, :current_order, :params, to: :controller
|
8
|
-
|
9
|
-
def initialize(intent_id, stripe, controller)
|
10
|
-
@intent_id, @stripe, @controller = intent_id, stripe, controller
|
11
|
-
end
|
12
|
-
|
13
|
-
def call
|
14
|
-
invalidate_previous_payment_intents_payments
|
15
|
-
if (payment = create_payment)
|
16
|
-
description = "Solidus Order ID: #{payment.gateway_order_identifier}"
|
17
|
-
stripe.update_intent(nil, intent_id, nil, description: description)
|
18
|
-
true
|
19
|
-
else
|
20
|
-
invalidate_current_payment_intent
|
21
|
-
false
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def intent
|
28
|
-
@intent ||= stripe.show_intent(intent_id, {})
|
29
|
-
end
|
30
|
-
|
31
|
-
def invalidate_current_payment_intent
|
32
|
-
stripe.cancel(intent_id)
|
33
|
-
end
|
34
|
-
|
35
|
-
def invalidate_previous_payment_intents_payments
|
36
|
-
if stripe.v3_intents?
|
37
|
-
current_order.payments.pending.where(payment_method: stripe).each(&:void_transaction!)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def create_payment
|
42
|
-
Spree::OrderUpdateAttributes.new(
|
43
|
-
current_order,
|
44
|
-
payment_params,
|
45
|
-
request_env: request.headers.env
|
46
|
-
).apply
|
47
|
-
|
48
|
-
created_payment = Spree::Payment.find_by(response_code: intent_id)
|
49
|
-
created_payment&.tap { |payment| payment.update!(state: :pending) }
|
50
|
-
end
|
51
|
-
|
52
|
-
def payment_params
|
53
|
-
{
|
54
|
-
payments_attributes: [{
|
55
|
-
payment_method_id: stripe.id,
|
56
|
-
amount: current_order.total,
|
57
|
-
response_code: intent_id,
|
58
|
-
source_attributes: {
|
59
|
-
month: intent_card['exp_month'],
|
60
|
-
year: intent_card['exp_year'],
|
61
|
-
cc_type: intent_card['brand'],
|
62
|
-
last_digits: intent_card['last4'],
|
63
|
-
gateway_payment_profile_id: intent_customer_profile,
|
64
|
-
name: card_holder_name || address_full_name,
|
65
|
-
address_attributes: address_attributes
|
66
|
-
}
|
67
|
-
}]
|
68
|
-
}
|
69
|
-
end
|
70
|
-
|
71
|
-
def intent_card
|
72
|
-
intent_data['payment_method_details']['card']
|
73
|
-
end
|
74
|
-
|
75
|
-
def intent_customer_profile
|
76
|
-
intent.params['payment_method']
|
77
|
-
end
|
78
|
-
|
79
|
-
def card_holder_name
|
80
|
-
(html_payment_source_data['name'] || intent_data['billing_details']['name']).presence
|
81
|
-
end
|
82
|
-
|
83
|
-
def intent_data
|
84
|
-
intent.params['charges']['data'][0]
|
85
|
-
end
|
86
|
-
|
87
|
-
def form_data
|
88
|
-
params[:form_data]
|
89
|
-
end
|
90
|
-
|
91
|
-
def html_payment_source_data
|
92
|
-
if form_data.is_a?(String)
|
93
|
-
data = Rack::Utils.parse_nested_query(form_data)
|
94
|
-
data['payment_source'][stripe.id.to_s]
|
95
|
-
else
|
96
|
-
{}
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def address_attributes
|
101
|
-
html_payment_source_data['address_attributes'] || SolidusStripe::AddressFromParamsService.new(form_data).call.attributes
|
102
|
-
end
|
103
|
-
|
104
|
-
def address_full_name
|
105
|
-
bill_address_name = SolidusSupport.combined_first_and_last_name_in_address? ? current_order.bill_address&.name : current_order.bill_address&.full_name
|
106
|
-
bill_address_name || form_data[:recipient]
|
107
|
-
end
|
108
|
-
|
109
|
-
def update_stripe_payment_description
|
110
|
-
description = "Solidus Order ID: #{payment.gateway_order_identifier}"
|
111
|
-
stripe.update_intent(nil, intent_id, nil, description: description)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SolidusStripe
|
4
|
-
class PrepareOrderForPaymentService
|
5
|
-
attr_reader :order, :address, :user, :email, :shipping_id
|
6
|
-
|
7
|
-
def initialize(address, controller)
|
8
|
-
@address = address
|
9
|
-
@order = controller.current_order
|
10
|
-
@user = controller.spree_current_user
|
11
|
-
@email = controller.params[:email]
|
12
|
-
@shipping_id = controller.params[:shipping_option][:id]
|
13
|
-
end
|
14
|
-
|
15
|
-
def call
|
16
|
-
set_order_addresses
|
17
|
-
manage_guest_checkout
|
18
|
-
advance_order_to_payment_state
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def set_shipping_rate
|
24
|
-
order.shipments.each do |shipment|
|
25
|
-
rate = shipment.shipping_rates.find_by(shipping_method: shipping_id)
|
26
|
-
shipment.selected_shipping_rate_id = rate.id
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def set_order_addresses
|
31
|
-
order.ship_address = address
|
32
|
-
order.bill_address ||= address
|
33
|
-
end
|
34
|
-
|
35
|
-
def manage_guest_checkout
|
36
|
-
order.email = email unless user
|
37
|
-
end
|
38
|
-
|
39
|
-
def advance_order_to_payment_state
|
40
|
-
while !order.payment?
|
41
|
-
set_shipping_rate if order.state == "delivery"
|
42
|
-
order.next || break
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SolidusStripe
|
4
|
-
class ShippingRatesService
|
5
|
-
attr_reader :order, :user, :shipping_address_params
|
6
|
-
|
7
|
-
def initialize(order, user, shipping_address_params)
|
8
|
-
@order = order
|
9
|
-
@user = user
|
10
|
-
@shipping_address_params = shipping_address_params
|
11
|
-
end
|
12
|
-
|
13
|
-
def call
|
14
|
-
# setting a temporary and probably incomplete address to the order
|
15
|
-
# only to calculate the available shipping options:
|
16
|
-
order.ship_address = address_from_params
|
17
|
-
|
18
|
-
available_shipping_methods.each_with_object([]) do |(id, rates), options|
|
19
|
-
options << shipping_method_data(id, rates)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def available_shipping_methods
|
26
|
-
shipments = Spree::Stock::SimpleCoordinator.new(order).shipments
|
27
|
-
all_rates = shipments.map(&:shipping_rates).flatten
|
28
|
-
|
29
|
-
all_rates.group_by(&:shipping_method_id).select do |_, rates|
|
30
|
-
rates.size == shipments.size
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def shipping_method_data(id, rates)
|
35
|
-
{
|
36
|
-
id: id.to_s,
|
37
|
-
label: Spree::ShippingMethod.find(id).name,
|
38
|
-
amount: (rates.sum(&:cost) * 100).to_i
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
|
-
def address_from_params
|
43
|
-
SolidusStripe::AddressFromParamsService.new(shipping_address_params, user).call
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|