effective_orders 6.19.2 → 6.19.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2119b880e68ea2d6a6cff0b63b19f46af89200c95a6c917b188620b6e5a51bd2
4
- data.tar.gz: '0651700787a2b4e1fc128a9d1c2afda4af0a0876de085bf6c13d4a6f4c3db243'
3
+ metadata.gz: 73f7c7e5f31c361565954b31a82a278a0c5127829cbd24be06b4c307205c5f74
4
+ data.tar.gz: d7821ca6b2a5e7a9b22c9e5d67c69a6a22f49a6c7211b88961b6cb42a8f7698a
5
5
  SHA512:
6
- metadata.gz: f85e8299609856e55e738c652acf1204cf21ed84733e468bc65181ee03e8c6b49e3915e5755ce1270898af2cde256b9aa1242536d33b04e1a85682b27780b92a
7
- data.tar.gz: b182d9dcbefd3dc1b028823a29085af08a31d57d90c448d98edc69dd3977093509ad16b25f53df4fe65be9dd2abc7dc2a484ecf52ebc365697d607d1c84c40b3
6
+ metadata.gz: '0967f05a59940c88a2b1ea47a8125c3501a9e1a0e1497fd5280fe4542f74b7bea94253fb72fd192adf32f6df958cfbc5179231d5c3d1351f0bf41bbc7ce49b1d'
7
+ data.tar.gz: 950b3b66593162a86e80a69dcea163415a0a7f1d1c0496dd3deeb886d8d1be7d9fb575fd3db334f8ab3e73662a8e9d3c3c2d8ec2d1fafd35fd49946a9dbf88ba
@@ -14,6 +14,7 @@ module Effective
14
14
  attr_accessor :currency
15
15
 
16
16
  attr_accessor :purchase_response
17
+ attr_accessor :read_timeout
17
18
 
18
19
  def initialize(environment: nil, client_id: nil, client_secret: nil, access_token: nil, currency: nil)
19
20
  self.environment = environment || EffectiveOrders.deluxe.fetch(:environment)
@@ -125,52 +126,133 @@ module Effective
125
126
  purchase_response
126
127
  end
127
128
 
129
+ def payment_approved?(order)
130
+ payment = search_payment(order)
131
+ return false if payment.blank?
132
+
133
+ payment.dig('payment', 'responseCode').present? && payment.dig('payment', 'authResponse').to_s.downcase.include?('approved')
134
+ end
135
+
136
+ # Search for an existing Payment
137
+ def search_payment(order)
138
+ date = (order.delayed_payment_purchase_ran_at || order.purchased_at || order.created_at || Time.zone.now)
139
+ response = post('/payments/search', params: { orderId: order.to_param, startDate: date.strftime('%m/%d/%Y'), endDate: (date + 1.day).strftime('%m/%d/%Y') })
140
+
141
+ # Sanity check response
142
+ raise('expected valid search') unless response.kind_of?(Hash) && response['isSuccess'] == true
143
+
144
+ # Find the payment for this order
145
+ payment = Array(response.dig('data', 'payments')).find { |payment| payment.dig('payment', 'orderId') == order.to_param }
146
+ return unless payment.present?
147
+
148
+ # Return the payment hash
149
+ payment
150
+ end
151
+
152
+ def purchase_delayed_order!(order)
153
+ raise('expected a delayed order') unless order.delayed?
154
+ raise('expected a deferred order') unless order.deferred?
155
+ raise('expected delayed payment intent') unless order.delayed_payment_intent.present?
156
+ raise('expected a delayed_ready_to_purchase? order') unless order.delayed_ready_to_purchase?
157
+
158
+ order.update_columns(delayed_payment_purchase_ran_at: Time.zone.now, delayed_payment_purchase_result: nil)
159
+
160
+ purchased = if order.total.to_i > 0
161
+ purchase!(order, order.delayed_payment_intent)
162
+ elsif order.free?
163
+ purchase_free!(order)
164
+ else
165
+ raise("Unexpected order amount: #{order.total}")
166
+ end
167
+
168
+ provider = (order.free? ? 'free' : order.payment_provider)
169
+ payment = self.payment()
170
+ card = payment["card"] || payment[:card]
171
+
172
+ if purchased
173
+ order.assign_attributes(delayed_payment_purchase_result: "success")
174
+ order.purchase!(payment: payment, provider: provider, card: card, email: true, skip_buyer_validations: true)
175
+
176
+ puts "Successfully purchased order #{order.id}"
177
+ else
178
+ order.assign_attributes(delayed_payment_purchase_result: "failed: #{Array(payment['responseMessage']).to_sentence.presence || 'none'}")
179
+ order.decline!(payment: payment, provider: provider, card: card, email: true)
180
+
181
+ puts "Failed to purchase order #{order.id} #{order.delayed_payment_purchase_result}"
182
+ end
183
+
184
+ purchased
185
+ end
186
+
187
+ def retry_purchase_delayed_order!(order)
188
+ raise('expected a delayed order') unless order.delayed?
189
+ raise('expected a deferred order') unless order.deferred?
190
+ raise('expected delayed payment intent') unless order.delayed_payment_intent.present?
191
+ raise('expected an order with a positive total') unless order.total.to_i > 0
192
+
193
+ order.update_columns(delayed_payment_purchase_ran_at: Time.zone.now, delayed_payment_purchase_result: nil)
194
+
195
+ # Look up the existing payment on Deluxe API
196
+ existing_payment = search_payment(order)
197
+ existing_purchased = existing_payment.present? && existing_payment.dig('payment', 'responseCode').present? && existing_payment.dig('payment', 'authResponse').to_s.downcase.include?('approved')
198
+
199
+ # If it doesn't exist, purchase it now
200
+ purchased = (existing_purchased || purchase!(order, order.delayed_payment_intent))
201
+
202
+ # Payment
203
+ provider = order.payment_provider
204
+ payment = (existing_payment if existing_purchased) || self.payment()
205
+ card = payment.dig('payment', 'card', 'cardType') || payment.dig('payment', 'card') || payment['card'] || payment[:card]
206
+
207
+ if purchased
208
+ order.assign_attributes(delayed_payment_purchase_result: "success")
209
+ order.purchase!(payment: payment, provider: provider, card: card, email: true, skip_buyer_validations: true)
210
+
211
+ puts "Successfully purchased order #{order.id}"
212
+ else
213
+ order.assign_attributes(delayed_payment_purchase_result: "failed: #{Array(payment['responseMessage']).to_sentence.presence || 'none'}")
214
+ order.decline!(payment: payment, provider: provider, card: card, email: true)
215
+
216
+ puts "Failed to purchase order #{order.id} #{order.delayed_payment_purchase_result}"
217
+ end
218
+
219
+ purchased
220
+ end
221
+
128
222
  # Called by rake task
129
223
  def purchase_delayed_orders!(orders)
130
- now = Time.zone.now
224
+ # Orders that failed to purchase and need to be retried
225
+ retry_orders = []
131
226
 
227
+ # First pass over all the orders
132
228
  Array(orders).each do |order|
133
229
  puts "Trying order #{order.id}"
134
230
 
135
231
  begin
136
- raise('expected a delayed order') unless order.delayed?
137
- raise('expected a deferred order') unless order.deferred?
138
- raise('expected delayed payment intent') unless order.delayed_payment_intent.present?
139
- raise('expected a delayed_ready_to_purchase? order') unless order.delayed_ready_to_purchase?
140
-
141
- order.update_columns(delayed_payment_purchase_ran_at: now, delayed_payment_purchase_result: nil)
142
-
143
- purchased = if order.total.to_i > 0
144
- purchase!(order, order.delayed_payment_intent)
145
- elsif order.free?
146
- purchase_free!(order)
147
- else
148
- raise("Unexpected order amount: #{order.total}")
149
- end
150
-
151
- provider = (order.free? ? 'free' : order.payment_provider)
152
- payment = self.payment()
153
- card = payment["card"] || payment[:card]
232
+ purchase_delayed_order!(order)
233
+ rescue => e
234
+ order.update_columns(delayed_payment_purchase_ran_at: Time.zone.now, delayed_payment_purchase_result: "error: #{e.message}")
235
+ retry_orders << order
154
236
 
155
- if purchased
156
- order.assign_attributes(delayed_payment_purchase_result: "success")
157
- order.purchase!(payment: payment, provider: provider, card: card, email: true, skip_buyer_validations: true)
237
+ puts "Error purchasing #{order.id}: #{e.message}"
238
+ end
239
+ end
158
240
 
159
- puts "Successfully purchased order #{order.id}"
160
- else
161
- order.assign_attributes(delayed_payment_purchase_result: "failed with message: #{Array(payment['responseMessage']).to_sentence.presence || 'none'}")
162
- order.decline!(payment: payment, provider: provider, card: card, email: true)
241
+ # Second pass over all the orders that raised an error on call to purchase
242
+ orders = Effective::Order.where(id: retry_orders.map(&:id))
163
243
 
164
- puts "Failed to purchase order #{order.id} #{order.delayed_payment_purchase_result}"
165
- end
244
+ Array(orders).each do |order|
245
+ puts "Retrying order #{order.id}"
166
246
 
247
+ begin
248
+ retry_purchase_delayed_order!(order)
167
249
  rescue => e
168
- order.update_columns(delayed_payment_purchase_ran_at: now, delayed_payment_purchase_result: "error: #{e.message}")
250
+ order.update_columns(delayed_payment_purchase_ran_at: Time.zone.now, delayed_payment_purchase_result: "error: #{e.message}")
169
251
 
170
252
  EffectiveLogger.error(e.message, associated: order) if defined?(EffectiveLogger)
171
253
  ExceptionNotifier.notify_exception(e, data: { order_id: order.id }) if defined?(ExceptionNotifier)
172
254
 
173
- puts "Error purchasing #{order.id}: #{e.message}"
255
+ puts "Error retry purchasing #{order.id}: #{e.message}"
174
256
 
175
257
  raise(e) if Rails.env.development? || Rails.env.test?
176
258
  end
@@ -260,7 +342,7 @@ module Effective
260
342
 
261
343
  orderData = {
262
344
  autoGenerateOrderId: true,
263
- orderID: order.to_param,
345
+ orderId: order.to_param,
264
346
  orderIdIsUnique: true
265
347
  }
266
348
 
@@ -282,7 +364,7 @@ module Effective
282
364
  uri = URI.parse(api_url + endpoint + query.to_s)
283
365
 
284
366
  http = Net::HTTP.new(uri.host, uri.port)
285
- http.read_timeout = 20
367
+ http.read_timeout = (read_timeout || 30)
286
368
  http.use_ssl = true
287
369
 
288
370
  result = with_retries do
@@ -301,19 +383,15 @@ module Effective
301
383
  uri = URI.parse(api_url + endpoint)
302
384
 
303
385
  http = Net::HTTP.new(uri.host, uri.port)
304
- http.read_timeout = 20
386
+ http.read_timeout = (read_timeout || 30)
305
387
  http.use_ssl = true
306
388
 
307
- result = with_retries do
308
- puts "[POST] #{uri} #{params}" if Rails.env.development?
389
+ puts "[POST] #{uri} #{params}" if Rails.env.development?
309
390
 
310
- response = http.post(uri.path, params.to_json, headers)
311
- raise Exception.new("#{response.code} #{response.body}") unless response.code == '200'
391
+ response = http.post(uri.path, params.to_json, headers)
392
+ raise Exception.new("#{response.code} #{response.body}") unless response.code == '200'
312
393
 
313
- response
314
- end
315
-
316
- JSON.parse(result.body)
394
+ JSON.parse(response.body)
317
395
  end
318
396
 
319
397
  private
@@ -1,3 +1,3 @@
1
1
  module EffectiveOrders
2
- VERSION = '6.19.2'.freeze
2
+ VERSION = '6.19.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_orders
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.19.2
4
+ version: 6.19.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-03 00:00:00.000000000 Z
11
+ date: 2025-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails