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.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +95 -41
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +94 -4
  5. data/.yardopts +1 -0
  6. data/CHANGELOG.md +1 -265
  7. data/Gemfile +10 -30
  8. data/LICENSE +2 -2
  9. data/Procfile.dev +3 -0
  10. data/README.md +145 -215
  11. data/Rakefile +7 -6
  12. data/app/assets/javascripts/spree/backend/solidus_stripe.js +2 -0
  13. data/app/assets/stylesheets/spree/backend/solidus_stripe.css +4 -0
  14. data/app/controllers/solidus_stripe/intents_controller.rb +36 -52
  15. data/app/controllers/solidus_stripe/webhooks_controller.rb +28 -0
  16. data/app/models/concerns/solidus_stripe/log_entries.rb +31 -0
  17. data/app/models/solidus_stripe/customer.rb +21 -0
  18. data/app/models/solidus_stripe/gateway.rb +231 -0
  19. data/app/models/solidus_stripe/payment_intent.rb +111 -0
  20. data/app/models/solidus_stripe/payment_method.rb +106 -0
  21. data/app/models/solidus_stripe/payment_source.rb +31 -0
  22. data/app/models/solidus_stripe/slug_entry.rb +20 -0
  23. data/app/models/solidus_stripe.rb +7 -0
  24. data/app/subscribers/solidus_stripe/webhook/charge_subscriber.rb +28 -0
  25. data/app/subscribers/solidus_stripe/webhook/payment_intent_subscriber.rb +112 -0
  26. data/app/views/spree/admin/payments/source_forms/_stripe.html.erb +29 -0
  27. data/app/views/spree/admin/payments/source_forms/existing_payment/_stripe.html.erb +14 -0
  28. data/app/views/spree/admin/payments/source_forms/existing_payment/stripe/_card.html.erb +8 -0
  29. data/app/views/spree/admin/payments/source_forms/existing_payment/stripe/_default.html.erb +7 -0
  30. data/app/views/spree/admin/payments/source_views/_stripe.html.erb +15 -0
  31. data/app/views/spree/api/payments/source_views/_stripe.json.jbuilder +8 -0
  32. data/bin/dev +13 -0
  33. data/bin/dummy-app +29 -0
  34. data/bin/rails +38 -3
  35. data/bin/rails-dummy-app +3 -0
  36. data/bin/rails-engine +1 -11
  37. data/bin/rails-new +55 -0
  38. data/bin/rails-sandbox +1 -14
  39. data/bin/rspec +10 -0
  40. data/bin/sandbox +12 -74
  41. data/bin/setup +1 -0
  42. data/bin/update-migrations +56 -0
  43. data/codecov.yml +12 -0
  44. data/config/locales/en.yml +16 -1
  45. data/config/routes.rb +5 -11
  46. data/coverage.rb +42 -0
  47. data/db/migrate/20230109183332_create_solidus_stripe_payment_sources.rb +10 -0
  48. data/db/migrate/20230303154931_create_solidus_stripe_setup_intent.rb +10 -0
  49. data/db/migrate/20230306105520_create_solidus_stripe_payment_intents.rb +10 -0
  50. data/db/migrate/20230308122414_create_solidus_stripe_webhook_endpoints.rb +10 -0
  51. data/db/migrate/20230310152615_add_payment_method_reference_to_stripe_intents.rb +6 -0
  52. data/db/migrate/20230310171444_normalize_stripe_intent_id_attributes.rb +6 -0
  53. data/db/migrate/20230313150008_create_solidus_stripe_customers.rb +16 -0
  54. data/db/migrate/20230323154931_drop_solidus_stripe_setup_intent.rb +13 -0
  55. data/db/migrate/20230403094916_rename_webhook_endpoint_to_payment_method_slug_entries.rb +5 -0
  56. data/db/seeds.rb +6 -24
  57. data/lib/generators/solidus_stripe/install/install_generator.rb +121 -14
  58. data/lib/generators/solidus_stripe/install/templates/app/assets/stylesheets/spree/frontend/solidus_stripe.css +13 -0
  59. data/lib/generators/solidus_stripe/install/templates/app/javascript/controllers/solidus_stripe_confirm_controller.js +39 -0
  60. data/lib/generators/solidus_stripe/install/templates/app/javascript/controllers/solidus_stripe_payment_controller.js +89 -0
  61. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/_stripe.html.erb +16 -0
  62. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/stripe/_card.html.erb +8 -0
  63. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/existing_payment/stripe/_default.html.erb +7 -0
  64. data/lib/generators/solidus_stripe/install/templates/app/views/checkouts/payment/_stripe.html.erb +39 -0
  65. data/lib/generators/solidus_stripe/install/templates/app/views/orders/payment_info/_stripe.html.erb +20 -0
  66. data/lib/generators/solidus_stripe/install/templates/config/initializers/solidus_stripe.rb +31 -0
  67. data/lib/solidus_stripe/configuration.rb +24 -3
  68. data/lib/solidus_stripe/engine.rb +19 -6
  69. data/lib/solidus_stripe/money_to_stripe_amount_converter.rb +109 -0
  70. data/lib/solidus_stripe/refunds_synchronizer.rb +96 -0
  71. data/lib/solidus_stripe/seeds.rb +19 -0
  72. data/lib/solidus_stripe/testing_support/factories.rb +153 -0
  73. data/lib/solidus_stripe/version.rb +1 -1
  74. data/lib/solidus_stripe/webhook/event.rb +90 -0
  75. data/lib/solidus_stripe.rb +0 -2
  76. data/solidus_stripe.gemspec +29 -6
  77. data/spec/lib/solidus_stripe/configuration_spec.rb +21 -0
  78. data/spec/lib/solidus_stripe/money_to_stripe_amount_converter_spec.rb +133 -0
  79. data/spec/lib/solidus_stripe/refunds_synchronizer_spec.rb +238 -0
  80. data/spec/lib/solidus_stripe/seeds_spec.rb +43 -0
  81. data/spec/lib/solidus_stripe/webhook/event_spec.rb +134 -0
  82. data/spec/models/concerns/solidus_stripe/log_entries_spec.rb +54 -0
  83. data/spec/models/solidus_stripe/customer_spec.rb +47 -0
  84. data/spec/models/solidus_stripe/gateway_spec.rb +283 -0
  85. data/spec/models/solidus_stripe/payment_intent_spec.rb +17 -0
  86. data/spec/models/solidus_stripe/payment_method_spec.rb +137 -0
  87. data/spec/models/solidus_stripe/payment_source_spec.rb +25 -0
  88. data/spec/requests/solidus_stripe/intents_controller_spec.rb +29 -0
  89. data/spec/requests/solidus_stripe/webhooks_controller/charge/refunded_spec.rb +31 -0
  90. data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/canceled_spec.rb +23 -0
  91. data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/payment_failed_spec.rb +23 -0
  92. data/spec/requests/solidus_stripe/webhooks_controller/payment_intent/succeeded_spec.rb +29 -0
  93. data/spec/requests/solidus_stripe/webhooks_controller_spec.rb +52 -0
  94. data/spec/solidus_stripe_spec_helper.rb +10 -0
  95. data/spec/subscribers/solidus_stripe/webhook/charge_subscriber_spec.rb +33 -0
  96. data/spec/subscribers/solidus_stripe/webhook/payment_intent_subscriber_spec.rb +297 -0
  97. data/spec/support/solidus_stripe/backend_test_helper.rb +210 -0
  98. data/spec/support/solidus_stripe/checkout_test_helper.rb +339 -0
  99. data/spec/support/solidus_stripe/factories.rb +5 -0
  100. data/spec/support/solidus_stripe/webhook/data_fixtures.rb +106 -0
  101. data/spec/support/solidus_stripe/webhook/event_with_context_factory.rb +82 -0
  102. data/spec/support/solidus_stripe/webhook/request_helper.rb +32 -0
  103. data/spec/system/backend/solidus_stripe/orders/payments_spec.rb +119 -0
  104. data/spec/system/frontend/.keep +0 -0
  105. data/spec/system/frontend/solidus_stripe/checkout_spec.rb +187 -0
  106. data/tmp/.keep +0 -0
  107. metadata +201 -75
  108. data/.rubocop_todo.yml +0 -298
  109. data/.travis.yml +0 -28
  110. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-cart-page-checkout.js +0 -122
  111. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-elements.js +0 -148
  112. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-init.js +0 -20
  113. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-intents.js +0 -84
  114. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment-request-button-shared.js +0 -160
  115. data/app/assets/javascripts/spree/frontend/solidus_stripe/stripe-payment.js +0 -16
  116. data/app/assets/javascripts/spree/frontend/solidus_stripe.js +0 -6
  117. data/app/controllers/solidus_stripe/payment_request_controller.rb +0 -52
  118. data/app/controllers/spree/stripe_controller.rb +0 -13
  119. data/app/decorators/models/spree/order_update_attributes_decorator.rb +0 -39
  120. data/app/decorators/models/spree/payment_decorator.rb +0 -11
  121. data/app/decorators/models/spree/refund_decorator.rb +0 -9
  122. data/app/models/solidus_stripe/address_from_params_service.rb +0 -72
  123. data/app/models/solidus_stripe/create_intents_payment_service.rb +0 -114
  124. data/app/models/solidus_stripe/prepare_order_for_payment_service.rb +0 -46
  125. data/app/models/solidus_stripe/shipping_rates_service.rb +0 -46
  126. data/app/models/spree/payment_method/stripe_credit_card.rb +0 -230
  127. data/bin/r +0 -13
  128. data/bin/sandbox_rails +0 -18
  129. data/db/migrate/20181010123508_update_stripe_payment_method_type_to_credit_card.rb +0 -21
  130. data/lib/assets/stylesheets/spree/frontend/solidus_stripe.scss +0 -11
  131. data/lib/solidus_stripe/testing_support/card_input_helper.rb +0 -34
  132. data/lib/tasks/solidus_stripe/db/seed.rake +0 -14
  133. data/lib/views/api/spree/api/payments/source_views/_stripe.json.jbuilder +0 -3
  134. data/lib/views/backend/spree/admin/log_entries/_stripe.html.erb +0 -28
  135. data/lib/views/backend/spree/admin/payments/source_forms/_stripe.html.erb +0 -1
  136. data/lib/views/backend/spree/admin/payments/source_views/_stripe.html.erb +0 -1
  137. data/lib/views/frontend/spree/checkout/existing_payment/_stripe.html.erb +0 -1
  138. data/lib/views/frontend/spree/checkout/payment/_stripe.html.erb +0 -8
  139. data/lib/views/frontend/spree/checkout/payment/v2/_javascript.html.erb +0 -78
  140. data/lib/views/frontend/spree/checkout/payment/v3/_elements.html.erb +0 -1
  141. data/lib/views/frontend/spree/checkout/payment/v3/_form_elements.html.erb +0 -40
  142. data/lib/views/frontend/spree/checkout/payment/v3/_intents.html.erb +0 -1
  143. data/lib/views/frontend/spree/checkout/payment/v3/_stripe.html.erb +0 -2
  144. data/lib/views/frontend/spree/orders/_stripe_payment_request_button.html.erb +0 -14
  145. data/spec/features/stripe_checkout_spec.rb +0 -486
  146. data/spec/models/solidus_stripe/address_from_params_service_spec.rb +0 -87
  147. data/spec/models/solidus_stripe/create_intents_payment_service_spec.rb +0 -127
  148. data/spec/models/solidus_stripe/prepare_order_for_payment_service_spec.rb +0 -65
  149. data/spec/models/solidus_stripe/shipping_rates_service_spec.rb +0 -54
  150. data/spec/models/spree/payment_method/stripe_credit_card_spec.rb +0 -350
  151. data/spec/requests/payment_requests_spec.rb +0 -152
  152. data/spec/spec_helper.rb +0 -37
  153. data/spec/support/solidus_address_helper.rb +0 -15
@@ -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,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spree
4
- module PaymentDecorator
5
- def gateway_order_identifier
6
- gateway_order_id
7
- end
8
-
9
- ::Spree::Payment.prepend(self)
10
- end
11
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spree
4
- module RefundDecorator
5
- attr_reader :response
6
-
7
- ::Spree::Refund.prepend(self)
8
- end
9
- 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