flowcommerce_spree 0.0.3 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -6
- data/app/controllers/concerns/current_zone_loader_decorator.rb +11 -17
- data/app/controllers/flowcommerce_spree/inventory_controller.rb +23 -0
- data/app/controllers/flowcommerce_spree/orders_controller.rb +20 -0
- data/app/controllers/flowcommerce_spree/webhooks_controller.rb +16 -18
- data/app/controllers/users/sessions_controller_decorator.rb +19 -2
- data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +0 -16
- data/app/models/flowcommerce_spree/settings.rb +1 -0
- data/app/models/spree/address_decorator.rb +1 -1
- data/app/models/spree/calculator/flow_io.rb +24 -12
- data/app/models/spree/calculator/shipping/flow_io.rb +5 -2
- data/app/models/spree/flow_io_credit_card_decorator.rb +21 -0
- data/app/models/spree/flow_io_order_decorator.rb +181 -0
- data/app/models/spree/flow_io_product_decorator.rb +5 -0
- data/app/models/spree/flow_io_variant_decorator.rb +16 -6
- data/app/models/spree/gateway/flow_io.rb +61 -24
- data/app/models/spree/{credit_card_decorator.rb → payment_capture_event_decorator.rb} +1 -1
- data/app/models/spree/zones/flow_io_product_zone_decorator.rb +4 -0
- data/app/overrides/spree/admin/order_sidebar_summary_flow_link.rb +13 -0
- data/app/overrides/spree/admin/products/order_price_flow_message.rb +9 -0
- data/app/serializers/api/v2/order_serializer_decorator.rb +20 -0
- data/app/services/flowcommerce_spree/import_experience_items.rb +1 -21
- data/app/services/flowcommerce_spree/import_item.rb +45 -0
- data/app/services/flowcommerce_spree/order_sync.rb +50 -222
- data/app/services/flowcommerce_spree/order_updater.rb +78 -0
- data/app/services/flowcommerce_spree/webhooks/capture_upserted_v2.rb +76 -0
- data/app/services/flowcommerce_spree/webhooks/card_authorization_upserted_v2.rb +66 -0
- data/app/services/flowcommerce_spree/webhooks/experience_upserted_v2.rb +25 -0
- data/app/services/flowcommerce_spree/webhooks/fraud_status_changed.rb +35 -0
- data/app/services/flowcommerce_spree/webhooks/local_item_upserted.rb +40 -0
- data/app/views/spree/admin/payments/source_views/_flow_io_gateway.html.erb +21 -0
- data/app/workers/flowcommerce_spree/import_item_worker.rb +24 -0
- data/config/routes.rb +3 -1
- data/db/migrate/20201021755957_add_meta_to_spree_tables.rb +6 -4
- data/lib/flow/simple_gateway.rb +0 -36
- data/lib/flowcommerce_spree.rb +6 -2
- data/lib/flowcommerce_spree/engine.rb +6 -1
- data/lib/flowcommerce_spree/experience_service.rb +1 -27
- data/lib/flowcommerce_spree/logging_http_client.rb +29 -13
- data/lib/flowcommerce_spree/session.rb +5 -25
- data/lib/flowcommerce_spree/version.rb +1 -1
- data/lib/tasks/flowcommerce_spree.rake +4 -1
- metadata +77 -28
- data/app/mailers/spree/spree_order_mailer_decorator.rb +0 -24
- data/app/models/spree/line_item_decorator.rb +0 -15
- data/app/models/spree/order_decorator.rb +0 -244
- data/app/views/spree/order_mailer/confirm_email.html.erb +0 -86
- data/app/views/spree/order_mailer/confirm_email.text.erb +0 -38
- data/lib/flow/error.rb +0 -73
- data/lib/flow/pay_pal.rb +0 -25
- data/lib/flowcommerce_spree/webhook_service.rb +0 -184
- data/lib/simple_csv_writer.rb +0 -44
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
class OrderUpdater
|
5
|
+
def initialize(order:)
|
6
|
+
unless order&.zone&.flow_io_active_or_archiving_experience?
|
7
|
+
raise(ArgumentError, 'Experience not defined or not active')
|
8
|
+
end
|
9
|
+
|
10
|
+
@experience = order.flow_io_experience_key
|
11
|
+
@order = order
|
12
|
+
@client = FlowcommerceSpree.client
|
13
|
+
end
|
14
|
+
|
15
|
+
def upsert_data(flow_io_order = nil)
|
16
|
+
return if @order.state == 'complete'
|
17
|
+
|
18
|
+
flow_io_order ||= @client.orders.get_by_number(FlowcommerceSpree::ORGANIZATION, @order.number).to_hash
|
19
|
+
|
20
|
+
@order.flow_data['order'] = flow_io_order
|
21
|
+
return if @order.flow_data.dig('order', 'submitted_at').blank?
|
22
|
+
|
23
|
+
attrs_to_update = { meta: @order.meta.to_json, email: @order.flow_customer_email, payment_state: 'pending' }
|
24
|
+
attrs_to_update.merge!(@order.prepare_flow_addresses)
|
25
|
+
@order.update_columns(attrs_to_update)
|
26
|
+
@order.state = 'delivery'
|
27
|
+
@order.save!
|
28
|
+
@order.create_proposed_shipments
|
29
|
+
@order.shipment.update_amounts
|
30
|
+
@order.line_items.each(&:store_ets)
|
31
|
+
@order.charge_taxes
|
32
|
+
|
33
|
+
@order.state = 'payment'
|
34
|
+
@order.save!
|
35
|
+
end
|
36
|
+
|
37
|
+
def finalize_order
|
38
|
+
@order.reload
|
39
|
+
@order.finalize!
|
40
|
+
@order.update_totals
|
41
|
+
@order.save
|
42
|
+
@order.after_completed_order
|
43
|
+
end
|
44
|
+
|
45
|
+
def complete_checkout
|
46
|
+
upsert_data
|
47
|
+
map_payments_to_spree
|
48
|
+
finalize_order if @order.state == 'complete'
|
49
|
+
end
|
50
|
+
|
51
|
+
def map_payments_to_spree
|
52
|
+
@order.flow_io_payments&.each do |p|
|
53
|
+
payment =
|
54
|
+
@order.payments.find_or_initialize_by(response_code: p['reference'], payment_method_id: payment_method_id)
|
55
|
+
next unless payment.new_record?
|
56
|
+
|
57
|
+
payment.amount = p.dig('total', 'amount')
|
58
|
+
payment.pend
|
59
|
+
|
60
|
+
# For now this additional update is overwriting the generated identifier with flow.io payment identifier.
|
61
|
+
# TODO: Check and possibly refactor in Spree 3.0, where the `before_create :set_unique_identifier`
|
62
|
+
# has been removed.
|
63
|
+
payment.update_column(:identifier, p['id'])
|
64
|
+
end
|
65
|
+
|
66
|
+
return if @order.payments.sum(:amount) < @order.amount || @order.state == 'complete'
|
67
|
+
|
68
|
+
@order.state = 'confirm'
|
69
|
+
@order.save!
|
70
|
+
@order.state = 'complete'
|
71
|
+
@order.save!
|
72
|
+
end
|
73
|
+
|
74
|
+
def payment_method_id
|
75
|
+
@payment_method_id ||= Spree::PaymentMethod.find_by(active: true, type: 'Spree::Gateway::FlowIo').id
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
module Webhooks
|
5
|
+
class CaptureUpsertedV2
|
6
|
+
attr_reader :errors
|
7
|
+
alias full_messages errors
|
8
|
+
|
9
|
+
def self.process(data)
|
10
|
+
new(data).process
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(data)
|
14
|
+
@data = data
|
15
|
+
@errors = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def process
|
19
|
+
errors << { message: 'Capture param missing' } && (return self) unless (capture = @data['capture']&.to_hash)
|
20
|
+
|
21
|
+
order_number = capture.dig('authorization', 'order', 'number')
|
22
|
+
errors << { message: 'Order number param missing' } && (return self) unless order_number
|
23
|
+
|
24
|
+
if (order = Spree::Order.find_by(number: order_number))
|
25
|
+
upsert_order_captures(order, capture)
|
26
|
+
payments = order.flow_io_payments
|
27
|
+
map_payment_captures_to_spree(order, payments) if payments.present?
|
28
|
+
order
|
29
|
+
else
|
30
|
+
errors << { message: "Order #{order_number} not found" }
|
31
|
+
self
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def upsert_order_captures(order, capture)
|
38
|
+
order.flow_data ||= {}
|
39
|
+
order.flow_data['captures'] ||= []
|
40
|
+
order_captures = order.flow_data['captures']
|
41
|
+
order_captures.delete_if { |c| c['id'] == capture['id'] }
|
42
|
+
order_captures << capture
|
43
|
+
order.update_column(:meta, order.meta.to_json)
|
44
|
+
end
|
45
|
+
|
46
|
+
def map_payment_captures_to_spree(order, payments)
|
47
|
+
order.flow_data['captures']&.each do |c|
|
48
|
+
next unless (payment = captured_payment(payments, c))
|
49
|
+
|
50
|
+
payment.capture_events.create!(amount: c['amount'], meta: { 'flow_data' => { 'id' => c['id'] } })
|
51
|
+
return if payment.completed? || payment.capture_events.sum(:amount) < payment.amount
|
52
|
+
|
53
|
+
payment.complete
|
54
|
+
end
|
55
|
+
|
56
|
+
return if order.completed?
|
57
|
+
return unless order.flow_io_captures_sum >= order.flow_io_total_amount && order.flow_io_balance_amount <= 0
|
58
|
+
|
59
|
+
FlowcommerceSpree::OrderUpdater.new(order: order).finalize_order
|
60
|
+
end
|
61
|
+
|
62
|
+
def captured_payment(flow_order_payments, capture)
|
63
|
+
return unless capture['status'] == 'succeeded'
|
64
|
+
|
65
|
+
auth = capture.dig('authorization', 'id')
|
66
|
+
return unless flow_order_payments&.find { |p| p['reference'] == auth }
|
67
|
+
|
68
|
+
return unless (payment = Spree::Payment.find_by(response_code: auth))
|
69
|
+
|
70
|
+
return if Spree::PaymentCaptureEvent.where("meta -> 'flow_data' ->> 'id' = ?", capture['id']).exists?
|
71
|
+
|
72
|
+
payment
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
module Webhooks
|
5
|
+
class CardAuthorizationUpsertedV2
|
6
|
+
attr_reader :errors
|
7
|
+
alias full_messages errors
|
8
|
+
|
9
|
+
def self.process(data)
|
10
|
+
new(data).process
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(data)
|
14
|
+
@data = data['authorization']&.to_hash
|
15
|
+
@data&.[]('method')&.delete('images')
|
16
|
+
@errors = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def process
|
20
|
+
errors << { message: 'Authorization param missing' } && (return self) unless @data
|
21
|
+
|
22
|
+
errors << { message: 'Card param missing' } && (return self) unless (flow_io_card = @data.delete('card'))
|
23
|
+
|
24
|
+
if (order_number = @data.dig('order', 'number'))
|
25
|
+
if (order = Spree::Order.find_by(number: order_number))
|
26
|
+
card = upsert_card(flow_io_card, order)
|
27
|
+
|
28
|
+
order.payments.where(response_code: @data['id'])
|
29
|
+
.update_all(source_id: card.id, source_type: 'Spree::CreditCard')
|
30
|
+
|
31
|
+
return card
|
32
|
+
else
|
33
|
+
errors << { message: "Order #{order_number} not found" }
|
34
|
+
end
|
35
|
+
else
|
36
|
+
errors << { message: 'Order number param missing' }
|
37
|
+
end
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def upsert_card(flow_io_card, order)
|
45
|
+
flow_io_card_expiration = flow_io_card.delete('expiration')
|
46
|
+
|
47
|
+
card = Spree::CreditCard.find_or_initialize_by(month: flow_io_card_expiration['month'].to_s,
|
48
|
+
year: flow_io_card_expiration['year'].to_s,
|
49
|
+
cc_type: flow_io_card.delete('type'),
|
50
|
+
last_digits: flow_io_card.delete('last4'),
|
51
|
+
name: flow_io_card.delete('name'),
|
52
|
+
user_id: order.user&.id)
|
53
|
+
card.flow_data ||= {}
|
54
|
+
if card.new_record?
|
55
|
+
card.flow_data.merge!(flow_io_card.except('discriminator'))
|
56
|
+
card.imported = true
|
57
|
+
end
|
58
|
+
|
59
|
+
card.push_authorization(@data.except('discriminator'))
|
60
|
+
card.new_record? ? card.save : card.update_column(:meta, card.meta.to_json)
|
61
|
+
|
62
|
+
card
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
module Webhooks
|
5
|
+
class ExperienceUpsertedV2
|
6
|
+
attr_accessor :errors
|
7
|
+
alias full_messages errors
|
8
|
+
|
9
|
+
def self.process(data, opts = {})
|
10
|
+
new(data, opts).process
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(data, opts = {})
|
14
|
+
@data = data
|
15
|
+
@opts = opts
|
16
|
+
@errors = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def process
|
20
|
+
experience = @data['experience']
|
21
|
+
Spree::Zones::Product.find_or_initialize_by(name: experience['key'].titleize).store_flow_io_data(experience)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
module Webhooks
|
5
|
+
class FraudStatusChanged
|
6
|
+
attr_accessor :errors
|
7
|
+
alias full_messages errors
|
8
|
+
|
9
|
+
def self.process(data, opts = {})
|
10
|
+
new(data, opts).process
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(data, opts = {})
|
14
|
+
@data = data
|
15
|
+
@opts = opts
|
16
|
+
@errors = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def process
|
20
|
+
order_number = @data.dig('order', 'number')
|
21
|
+
errors << { message: 'Order number param missing' } && (return self) unless order_number
|
22
|
+
|
23
|
+
order = Spree::Order.find_by(number: order_number)
|
24
|
+
errors << { message: "Order #{order_number} not found" } && (return self) unless order
|
25
|
+
|
26
|
+
if @data['status'] == 'declined'
|
27
|
+
order.update_columns(fraudulent: true)
|
28
|
+
order.cancel!
|
29
|
+
end
|
30
|
+
|
31
|
+
order
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
module Webhooks
|
5
|
+
class LocalItemUpserted
|
6
|
+
attr_accessor :errors
|
7
|
+
alias full_messages errors
|
8
|
+
|
9
|
+
def self.process(data, opts = {})
|
10
|
+
new(data, opts).process
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(data, opts = {})
|
14
|
+
@data = data
|
15
|
+
@opts = opts
|
16
|
+
@errors = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def process
|
20
|
+
errors << { message: 'Local item param missing' } && (return self) unless (local_item = @data['local_item'])
|
21
|
+
|
22
|
+
errors << { message: 'SKU param missing' } && (return self) unless (flow_sku = local_item.dig('item', 'number'))
|
23
|
+
|
24
|
+
if (variant = Spree::Variant.find_by(sku: flow_sku))
|
25
|
+
variant.add_flow_io_experience_data(
|
26
|
+
local_item.dig('experience', 'key'),
|
27
|
+
'prices' => [local_item.dig('pricing', 'price')], 'status' => local_item['status']
|
28
|
+
)
|
29
|
+
|
30
|
+
variant.update_column(:meta, variant.meta.to_json)
|
31
|
+
return variant
|
32
|
+
else
|
33
|
+
errors << { message: "Variant with sku [#{flow_sku}] not found!" }
|
34
|
+
end
|
35
|
+
|
36
|
+
self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<fieldset data-hook="credit_card">
|
2
|
+
<legend align="center"><%= Spree.t(:credit_card) %></legend>
|
3
|
+
|
4
|
+
<div class="row">
|
5
|
+
<div class="alpha six columns">
|
6
|
+
<dl>
|
7
|
+
<dt><%= Spree.t(:name_on_card) %>:</dt>
|
8
|
+
<dd><%= payment.source&.name %></dd>
|
9
|
+
|
10
|
+
<dt><%= Spree.t(:card_type) %>:</dt>
|
11
|
+
<dd><%= payment.source&.cc_type %></dd>
|
12
|
+
|
13
|
+
<dt><%= Spree.t(:card_number) %>:</dt>
|
14
|
+
<dd><%= payment.source&.display_number %></dd>
|
15
|
+
|
16
|
+
<dt><%= Spree.t(:expiration) %>:</dt>
|
17
|
+
<dd><%= payment.source&.month %>/<%= payment.source&.year %></dd>
|
18
|
+
</dl>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</fieldset>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
class ImportItemWorker
|
5
|
+
include Sidekiq::Worker
|
6
|
+
sidekiq_options retry: 3, queue: :flow_io
|
7
|
+
|
8
|
+
sidekiq_retries_exhausted do |message, exception|
|
9
|
+
Rails.logger.warn("[!] FlowcommerceSpree::ImportItemWorker max attempts reached: #{message} - #{exception}")
|
10
|
+
notification_setting = FlowcommerceSpree::Config.notification_setting
|
11
|
+
return unless notification_setting[:slack].present?
|
12
|
+
|
13
|
+
slack_message = "[#{Rails.env}] #{message}"
|
14
|
+
Slack_client.chat_postMessage(channel: notification_setting[:slack][:channel], text: slack_message)
|
15
|
+
end
|
16
|
+
|
17
|
+
def perform(variant_sku)
|
18
|
+
variant = Spree::Variant.find_by sku: variant_sku
|
19
|
+
return unless variant
|
20
|
+
|
21
|
+
FlowcommerceSpree::ImportItem.run(variant)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
FlowcommerceSpree::Engine.routes.draw do
|
4
|
-
post '/event-target', to: 'webhooks#
|
4
|
+
post '/event-target', to: 'webhooks#handle_flow_io_event'
|
5
|
+
get '/order-completed', to: 'orders#order_completed'
|
6
|
+
post '/online-stock-availability', to: 'inventory#online_stock_availability'
|
5
7
|
end
|
@@ -5,13 +5,15 @@ class AddMetaToSpreeTables < ActiveRecord::Migration
|
|
5
5
|
add_column :spree_orders, :meta, :jsonb, default: '{}' unless column_exists?(:spree_orders, :meta)
|
6
6
|
add_column :spree_promotions, :meta, :jsonb, default: '{}' unless column_exists?(:spree_promotions, :meta)
|
7
7
|
add_column :spree_credit_cards, :meta, :jsonb, default: '{}' unless column_exists?(:spree_credit_cards, :meta)
|
8
|
+
add_column :spree_payment_capture_events, :meta, :jsonb, default: '{}' unless column_exists?(:spree_payment_capture_events, :meta)
|
8
9
|
end
|
9
10
|
|
10
11
|
def down
|
11
|
-
remove_column :
|
12
|
-
remove_column :spree_variants, :meta if column_exists?(:spree_variants, :meta)
|
13
|
-
remove_column :spree_orders, :meta if column_exists?(:spree_orders, :meta)
|
14
|
-
remove_column :spree_promotions, :meta if column_exists?(:spree_promotions, :meta)
|
12
|
+
remove_column :spree_payment_capture_events, :meta if column_exists?(:spree_payment_capture_events, :meta)
|
15
13
|
remove_column :spree_credit_cards, :meta if column_exists?(:spree_credit_cards, :meta)
|
14
|
+
remove_column :spree_promotions, :meta if column_exists?(:spree_promotions, :meta)
|
15
|
+
remove_column :spree_orders, :meta if column_exists?(:spree_orders, :meta)
|
16
|
+
remove_column :spree_variants, :meta if column_exists?(:spree_variants, :meta)
|
17
|
+
remove_column :spree_products, :meta if column_exists?(:spree_products, :meta)
|
16
18
|
end
|
17
19
|
end
|
data/lib/flow/simple_gateway.rb
CHANGED
@@ -34,42 +34,6 @@ module Flow
|
|
34
34
|
error_response(e)
|
35
35
|
end
|
36
36
|
|
37
|
-
# capture authorised funds
|
38
|
-
def cc_capture
|
39
|
-
# GET /:organization/authorizations, order_number: abc
|
40
|
-
data = @order.flow_data['authorization']
|
41
|
-
|
42
|
-
raise ArgumentError, 'No Authorization data, please authorize first' unless data
|
43
|
-
|
44
|
-
capture_form = ::Io::Flow::V0::Models::CaptureForm.new(data)
|
45
|
-
response = FlowcommerceSpree.client.captures.post(FlowcommerceSpree::ORGANIZATION, capture_form)
|
46
|
-
|
47
|
-
return ActiveMerchant::Billing::Response.new false, 'error', response: response unless response.id
|
48
|
-
|
49
|
-
@order.update_column :flow_data, @order.flow_data.merge('capture': response.to_hash)
|
50
|
-
@order.flow_finalize!
|
51
|
-
|
52
|
-
ActiveMerchant::Billing::Response.new true, 'success', response: response
|
53
|
-
rescue StandardError => e
|
54
|
-
error_response(e)
|
55
|
-
end
|
56
|
-
|
57
|
-
def cc_refund
|
58
|
-
raise ArgumentError, 'capture info is not available' unless @order.flow_data['capture']
|
59
|
-
|
60
|
-
# we allways have capture ID, so we use it
|
61
|
-
refund_data = { capture_id: @order.flow_data['capture']['id'] }
|
62
|
-
refund_form = ::Io::Flow::V0::Models::RefundForm.new(refund_data)
|
63
|
-
response = FlowcommerceSpree.client.refunds.post(FlowcommerceSpree::ORGANIZATION, refund_form)
|
64
|
-
|
65
|
-
return ActiveMerchant::Billing::Response.new false, 'error', response: response unless response.id
|
66
|
-
|
67
|
-
@order.update_column :flow_data, @order.flow_data.merge('refund': response.to_hash)
|
68
|
-
ActiveMerchant::Billing::Response.new true, 'success', response: response
|
69
|
-
rescue StandardError => e
|
70
|
-
error_response(e)
|
71
|
-
end
|
72
|
-
|
73
37
|
private
|
74
38
|
|
75
39
|
# if order is not in flow, we use local Spree settings
|