flowcommerce_spree 0.0.4 → 0.0.9
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/README.md +35 -6
- data/app/controllers/concerns/current_zone_loader_decorator.rb +7 -12
- data/app/controllers/flowcommerce_spree/orders_controller.rb +3 -1
- data/app/controllers/flowcommerce_spree/webhooks_controller.rb +16 -18
- data/app/models/flowcommerce_spree/settings.rb +1 -0
- data/app/models/spree/calculator/flow_io.rb +23 -11
- data/app/models/spree/calculator/shipping/flow_io.rb +5 -2
- data/app/models/spree/flow_io_order_decorator.rb +29 -58
- 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 +22 -11
- 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/services/flowcommerce_spree/import_experience_items.rb +0 -20
- data/app/services/flowcommerce_spree/import_item.rb +45 -0
- data/app/services/flowcommerce_spree/order_sync.rb +39 -82
- data/app/services/flowcommerce_spree/order_updater.rb +3 -1
- 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/workers/flowcommerce_spree/import_item_worker.rb +24 -0
- data/config/routes.rb +1 -1
- data/lib/flowcommerce_spree.rb +3 -1
- data/lib/flowcommerce_spree/engine.rb +5 -0
- data/lib/flowcommerce_spree/experience_service.rb +1 -27
- data/lib/flowcommerce_spree/session.rb +5 -7
- data/lib/flowcommerce_spree/version.rb +1 -1
- data/lib/tasks/flowcommerce_spree.rake +4 -1
- metadata +74 -16
- data/app/mailers/spree/spree_order_mailer_decorator.rb +0 -24
- 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 -154
- data/lib/simple_csv_writer.rb +0 -44
@@ -21,7 +21,7 @@ module Spree
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def payment_profiles_supported?
|
24
|
-
|
24
|
+
false
|
25
25
|
end
|
26
26
|
|
27
27
|
def method_type
|
@@ -43,14 +43,18 @@ module Spree
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def refund(payment, amount, _options = {})
|
46
|
-
request_refund_store_result(payment.order, amount)
|
46
|
+
response = request_refund_store_result(payment.order, amount)
|
47
|
+
map_refund_to_payment(response, payment.order) if response.success?
|
48
|
+
response
|
47
49
|
rescue StandardError => e
|
48
50
|
ActiveMerchant::Billing::Response.new(false, e.to_s, {}, {})
|
49
51
|
end
|
50
52
|
|
51
53
|
def cancel(authorization)
|
52
54
|
original_payment = Spree::Payment.find_by(response_code: authorization)
|
53
|
-
request_refund_store_result(original_payment.order, original_payment.amount)
|
55
|
+
response = request_refund_store_result(original_payment.order, original_payment.amount)
|
56
|
+
map_refund_to_payment(response, original_payment.order) if response.success?
|
57
|
+
response
|
54
58
|
rescue StandardError => e
|
55
59
|
ActiveMerchant::Billing::Response.new(false, e.to_s, {}, {})
|
56
60
|
end
|
@@ -72,6 +76,12 @@ module Spree
|
|
72
76
|
create_flow_cc_profile!
|
73
77
|
end
|
74
78
|
|
79
|
+
def credit(payment, credit_amount)
|
80
|
+
request_refund_store_result(payment.order, credit_amount)
|
81
|
+
rescue StandardError => e
|
82
|
+
ActiveMerchant::Billing::Response.new(false, e.to_s, {}, {})
|
83
|
+
end
|
84
|
+
|
75
85
|
private
|
76
86
|
|
77
87
|
def request_refund_store_result(order, amount)
|
@@ -82,8 +92,10 @@ module Spree
|
|
82
92
|
response_status = response.status.value
|
83
93
|
if response_status == REFUND_SUCCESS
|
84
94
|
add_refund_to_order(response, order)
|
85
|
-
|
86
|
-
|
95
|
+
ActiveMerchant::Billing::Response.new(true,
|
96
|
+
REFUND_SUCCESS,
|
97
|
+
response.to_hash,
|
98
|
+
authorization: response.authorization.id)
|
87
99
|
else
|
88
100
|
msg = "Partial refund fail. Details: #{response_status}"
|
89
101
|
ActiveMerchant::Billing::Response.new(false, msg, {}, {})
|
@@ -100,18 +112,17 @@ module Spree
|
|
100
112
|
end
|
101
113
|
|
102
114
|
def map_refund_to_payment(response, order)
|
103
|
-
original_payment = Spree::Payment.find_by(response_code: response.authorization
|
115
|
+
original_payment = Spree::Payment.find_by(response_code: response.authorization)
|
104
116
|
payment = order.payments.create!(state: 'completed',
|
105
|
-
response_code: response.authorization
|
117
|
+
response_code: response.authorization,
|
106
118
|
payment_method_id: original_payment&.payment_method_id,
|
107
|
-
amount: - response.amount,
|
108
|
-
|
109
|
-
source_type: original_payment&.source_type)
|
119
|
+
amount: - response.params['amount'].to_f,
|
120
|
+
source: original_payment)
|
110
121
|
|
111
122
|
# For now this additional update is overwriting the generated identifier with flow.io payment identifier.
|
112
123
|
# TODO: Check and possibly refactor in Spree 3.0, where the `before_create :set_unique_identifier`
|
113
124
|
# has been removed.
|
114
|
-
payment.update_column(:identifier, response.id)
|
125
|
+
payment.update_column(:identifier, response.params['id'])
|
115
126
|
end
|
116
127
|
|
117
128
|
# hard inject Flow as payment method unless defined
|
@@ -28,6 +28,10 @@ module Spree
|
|
28
28
|
flow_data&.[]('key').present? && flow_data['status'] == 'active'
|
29
29
|
end
|
30
30
|
|
31
|
+
def flow_io_active_or_archiving_experience?
|
32
|
+
flow_data&.[]('key').present? && %w[active archiving].include?(flow_data['status'])
|
33
|
+
end
|
34
|
+
|
31
35
|
def update_on_flow; end
|
32
36
|
|
33
37
|
def remove_on_flow_io
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: 'spree/admin/shared/_order_tabs',
|
3
|
+
name: 'spree_admin_order_additional_information_flow_message',
|
4
|
+
insert_top: '.additional-info',
|
5
|
+
text: '
|
6
|
+
<% if FlowcommerceSpree::ORGANIZATION.present? && @order.flow_order.present? %>
|
7
|
+
<div style="text-align: center">
|
8
|
+
<%= link_to "See Flow Order",
|
9
|
+
"https://console.flow.io/#{FlowcommerceSpree::ORGANIZATION}/orders/#{@order.number}",
|
10
|
+
target: "_blank", class: "button" %>
|
11
|
+
</div>
|
12
|
+
<% end %>'
|
13
|
+
)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: 'spree/admin/prices/index',
|
3
|
+
name: 'spree_admin_prices_flow_mesage',
|
4
|
+
insert_top: '.no-border-top',
|
5
|
+
text: "
|
6
|
+
<div class='spree-admin-info' >
|
7
|
+
To check localized pricing, please click <a href='#{"https://console.flow.io/#{ENV['FLOW_ORGANIZATION']}/price-books"}' target='_blank'>here</a>.
|
8
|
+
</div>"
|
9
|
+
)
|
@@ -33,14 +33,6 @@ module FlowcommerceSpree
|
|
33
33
|
item_hash = item.to_hash
|
34
34
|
next unless (variant = Spree::Variant.find_by(sku: item_hash.delete(:number)))
|
35
35
|
|
36
|
-
status_in_experience = item_hash.dig(:local, :status)
|
37
|
-
|
38
|
-
if status_in_experience != 'included'
|
39
|
-
log_str << "[#{status_in_experience.red}]:"
|
40
|
-
else # If at least a variant is included in experience, include the product too
|
41
|
-
adjust_product_zone(variant)
|
42
|
-
end
|
43
|
-
|
44
36
|
variant.flow_import_item(item_hash, experience_key: @experience_key)
|
45
37
|
|
46
38
|
log_str << "#{variant.sku}, "
|
@@ -60,17 +52,5 @@ module FlowcommerceSpree
|
|
60
52
|
@organization = organization
|
61
53
|
@zone = zone
|
62
54
|
end
|
63
|
-
|
64
|
-
def adjust_product_zone(variant)
|
65
|
-
return unless (product = variant.product)
|
66
|
-
|
67
|
-
zone_ids = product.zone_ids || []
|
68
|
-
zone_id_string = @zone.id.to_s
|
69
|
-
return if zone_ids.include?(zone_id_string)
|
70
|
-
|
71
|
-
zone_ids << zone_id_string
|
72
|
-
product.zone_ids = zone_ids
|
73
|
-
product.update_columns(meta: product.meta.to_json)
|
74
|
-
end
|
75
55
|
end
|
76
56
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FlowcommerceSpree
|
4
|
+
# A service object to import the data for product variants belonging to a flow.io Experience
|
5
|
+
class ImportItem
|
6
|
+
def self.run(variant, client: FlowcommerceSpree.client, organization: ORGANIZATION)
|
7
|
+
new(variant, client: client, organization: organization).run
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
@client.experiences.get(@organization, status: 'active').each do |experience|
|
12
|
+
experience_key = experience.key
|
13
|
+
zone = Spree::Zones::Product.find_by(name: experience_key.titleize)
|
14
|
+
next unless zone
|
15
|
+
|
16
|
+
import_data(zone)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def initialize(variant, client:, organization:)
|
23
|
+
@client = client
|
24
|
+
@logger = client.instance_variable_get(:@http_handler).logger
|
25
|
+
@organization = organization
|
26
|
+
@variant = variant
|
27
|
+
end
|
28
|
+
|
29
|
+
def import_data(zone)
|
30
|
+
experience_key = zone.flow_io_experience
|
31
|
+
item = begin
|
32
|
+
@client.experiences.get_items_by_number(@organization, @variant.sku, experience: experience_key)
|
33
|
+
rescue Io::Flow::V0::HttpClient::PreconditionException, Io::Flow::V0::HttpClient::ServerError => e
|
34
|
+
@logger.info "flow.io API error: #{e.message}"
|
35
|
+
end
|
36
|
+
return unless item
|
37
|
+
|
38
|
+
item_hash = item.to_hash
|
39
|
+
|
40
|
+
@variant.flow_import_item(item_hash, experience_key: @experience_key)
|
41
|
+
|
42
|
+
@logger.info "[#{@variant.sku}][#{experience_key}] Variant experience imported successfully."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -2,58 +2,40 @@
|
|
2
2
|
|
3
3
|
module FlowcommerceSpree
|
4
4
|
# represents flow.io order syncing service
|
5
|
-
|
6
|
-
# - flow experience
|
7
|
-
# - spree order
|
8
|
-
# - current customer, if present as @order.user
|
9
|
-
#
|
10
|
-
# example:
|
11
|
-
# flow_order = FlowcommerceSpree::OrderSync.new # init flow-order object
|
12
|
-
# order: Spree::Order.last,
|
13
|
-
# experience: @flow_session.experience
|
14
|
-
# customer: @order.user
|
15
|
-
# flow_order.build_flow_request # builds json body to be posted to flow.io api
|
16
|
-
# flow_order.synchronize! # sends order to flow
|
17
|
-
class OrderSync # rubocop:disable Metrics/ClassLength
|
5
|
+
class OrderSync
|
18
6
|
FLOW_CENTER = 'default'
|
19
7
|
|
20
8
|
attr_reader :order, :response
|
21
9
|
|
22
|
-
|
23
|
-
|
10
|
+
# @param [Object] order
|
11
|
+
# @param [String] flow_session_id
|
24
12
|
def initialize(order:, flow_session_id:)
|
25
|
-
raise(ArgumentError, 'Experience not defined or not active') unless order
|
13
|
+
raise(ArgumentError, 'Experience not defined or not active') unless order&.zone&.flow_io_active_experience?
|
26
14
|
|
27
15
|
@experience = order.flow_io_experience_key
|
28
16
|
@flow_session_id = flow_session_id
|
29
17
|
@order = order
|
30
|
-
@client = FlowcommerceSpree.client(
|
18
|
+
@client = FlowcommerceSpree.client(default_headers: { "Authorization": "Session #{flow_session_id}" },
|
19
|
+
authorization: nil)
|
31
20
|
end
|
32
21
|
|
33
22
|
# helper method to send complete order from Spree to flow.io
|
34
23
|
def synchronize!
|
35
|
-
return unless @order.
|
24
|
+
return unless @order.state == 'cart' && @order.line_items.size > 0
|
36
25
|
|
37
26
|
sync_body!
|
38
|
-
|
27
|
+
write_response_to_order
|
39
28
|
|
40
29
|
@order.update_columns(total: @order.total, meta: @order.meta.to_json)
|
41
30
|
refresh_checkout_token
|
42
|
-
@checkout_token
|
43
|
-
end
|
44
|
-
|
45
|
-
def error
|
46
|
-
@response['messages'].join(', ')
|
47
|
-
end
|
48
|
-
|
49
|
-
def error_code
|
50
|
-
@response['code']
|
51
31
|
end
|
52
32
|
|
53
33
|
def error?
|
54
34
|
@response&.[]('code') && @response&.[]('messages') ? true : false
|
55
35
|
end
|
56
36
|
|
37
|
+
private
|
38
|
+
|
57
39
|
# builds object that can be sent to api.flow.io to sync order data
|
58
40
|
def build_flow_request
|
59
41
|
@opts = { experience: @experience, expand: ['experience'] }
|
@@ -71,24 +53,21 @@ module FlowcommerceSpree
|
|
71
53
|
@body[:discount] = { amount: @order.adjustment_total, currency: @order.currency } if @order.adjustment_total != 0
|
72
54
|
end
|
73
55
|
|
74
|
-
private
|
75
|
-
|
76
56
|
def refresh_checkout_token
|
77
|
-
root_url = url_helpers.root_url
|
57
|
+
root_url = Rails.application.routes.url_helpers.root_url
|
78
58
|
order_number = @order.number
|
79
59
|
confirmation_url = "#{root_url}flow/order-completed?order=#{order_number}&t=#{@order.guest_token}"
|
80
|
-
@checkout_token = FlowcommerceSpree.client.checkout_tokens.post_checkout_and_tokens_by_organization(
|
81
|
-
FlowcommerceSpree::ORGANIZATION,
|
82
|
-
discriminator: 'checkout_token_reference_form',
|
83
|
-
order_number: order_number,
|
84
|
-
session_id: @flow_session_id,
|
85
|
-
urls: { continue_shopping: root_url,
|
86
|
-
confirmation: confirmation_url,
|
87
|
-
invalid_checkout: root_url }
|
88
|
-
)&.id
|
89
|
-
|
90
60
|
@order.flow_io_attribute_add('flow_return_url', confirmation_url)
|
91
61
|
@order.flow_io_attribute_add('checkout_continue_shopping_url', root_url)
|
62
|
+
|
63
|
+
FlowcommerceSpree.client.checkout_tokens.post_checkout_and_tokens_by_organization(
|
64
|
+
FlowcommerceSpree::ORGANIZATION, discriminator: 'checkout_token_reference_form',
|
65
|
+
order_number: order_number,
|
66
|
+
session_id: @flow_session_id,
|
67
|
+
urls: { continue_shopping: root_url,
|
68
|
+
confirmation: confirmation_url,
|
69
|
+
invalid_checkout: root_url }
|
70
|
+
)&.id
|
92
71
|
end
|
93
72
|
|
94
73
|
# if customer is defined, add customer info
|
@@ -100,13 +79,14 @@ module FlowcommerceSpree
|
|
100
79
|
customer_ship_address = customer.ship_address
|
101
80
|
address = customer_ship_address if customer_ship_address&.country&.iso3 == @order.zone.flow_io_experience_country
|
102
81
|
|
82
|
+
customer_profile = customer.user_profile
|
103
83
|
unless address
|
104
|
-
user_profile_address =
|
84
|
+
user_profile_address = customer_profile&.address
|
105
85
|
address = user_profile_address if user_profile_address&.country&.iso3 == @order.zone.flow_io_experience_country
|
106
86
|
end
|
107
87
|
|
108
|
-
@body[:customer] = { name: { first: address&.firstname,
|
109
|
-
last: address&.lastname },
|
88
|
+
@body[:customer] = { name: { first: address&.firstname || customer_profile&.first_name,
|
89
|
+
last: address&.lastname || customer_profile&.last_name },
|
110
90
|
email: customer.email,
|
111
91
|
number: customer.flow_number,
|
112
92
|
phone: address&.phone }
|
@@ -116,14 +96,14 @@ module FlowcommerceSpree
|
|
116
96
|
|
117
97
|
def add_customer_address(address)
|
118
98
|
streets = []
|
119
|
-
streets.push address.address1 if address
|
120
|
-
streets.push address.address2 if address
|
99
|
+
streets.push address.address1 if address.address1.present?
|
100
|
+
streets.push address.address2 if address.address2.present?
|
121
101
|
|
122
102
|
@body[:destination] = { streets: streets,
|
123
|
-
city: address
|
124
|
-
province: address
|
125
|
-
postal: address
|
126
|
-
country: (address
|
103
|
+
city: address.city,
|
104
|
+
province: address.state_name,
|
105
|
+
postal: address.zipcode,
|
106
|
+
country: (address.country&.iso3 || ''),
|
127
107
|
contact: @body[:customer] }
|
128
108
|
|
129
109
|
@body[:destination].delete_if { |_k, v| v.nil? }
|
@@ -132,20 +112,8 @@ module FlowcommerceSpree
|
|
132
112
|
def sync_body!
|
133
113
|
build_flow_request
|
134
114
|
|
135
|
-
@
|
136
|
-
|
137
|
-
# use get if order is completed and closed
|
138
|
-
@use_get = true if @order.flow_data.dig('order', 'submitted_at').present? || @order.state == 'complete'
|
139
|
-
|
140
|
-
# do not use get if there is no local order cache
|
141
|
-
@use_get = false unless @order.flow_data['order']
|
142
|
-
|
143
|
-
if @use_get
|
144
|
-
@response ||= @client.orders.get_by_number(ORGANIZATION, @order.number).to_hash
|
145
|
-
else
|
146
|
-
@response = @client.orders.put_by_number(ORGANIZATION, @order.number,
|
147
|
-
Io::Flow::V0::Models::OrderPutForm.new(@body), @opts).to_hash
|
148
|
-
end
|
115
|
+
@response = @client.orders.put_by_number(ORGANIZATION, @order.number,
|
116
|
+
Io::Flow::V0::Models::OrderPutForm.new(@body), @opts).to_hash
|
149
117
|
end
|
150
118
|
|
151
119
|
def add_item(line_item)
|
@@ -156,27 +124,16 @@ module FlowcommerceSpree
|
|
156
124
|
{ center: FLOW_CENTER,
|
157
125
|
number: variant.sku,
|
158
126
|
quantity: line_item.quantity,
|
159
|
-
price: { amount: price_root['amount'] || variant.
|
127
|
+
price: { amount: price_root['amount'] || variant.price,
|
160
128
|
currency: price_root['currency'] || variant.cost_currency } }
|
161
129
|
end
|
162
130
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
response_total = @response[:total]
|
170
|
-
response_total_label = response_total&.[](:label)
|
171
|
-
cache_total = @order.flow_data.dig('order', 'total', 'label')
|
172
|
-
|
173
|
-
# return if total is not changed, no products removed or added
|
174
|
-
return if @use_get && response_total_label == cache_total
|
175
|
-
|
176
|
-
# update local order
|
177
|
-
@order.total = response_total&.[](:amount)
|
178
|
-
@order.flow_data.merge!('order' => @response)
|
179
|
-
end
|
131
|
+
def write_response_to_order
|
132
|
+
return @order.flow_data.delete('order') if !@response || error?
|
133
|
+
|
134
|
+
# update local order
|
135
|
+
@order.total = @response[:total]&.[](:amount)
|
136
|
+
@order.flow_data.merge!('order' => @response)
|
180
137
|
end
|
181
138
|
end
|
182
139
|
end
|
@@ -3,7 +3,9 @@
|
|
3
3
|
module FlowcommerceSpree
|
4
4
|
class OrderUpdater
|
5
5
|
def initialize(order:)
|
6
|
-
|
6
|
+
unless order&.zone&.flow_io_active_or_archiving_experience?
|
7
|
+
raise(ArgumentError, 'Experience not defined or not active')
|
8
|
+
end
|
7
9
|
|
8
10
|
@experience = order.flow_io_experience_key
|
9
11
|
@order = order
|
@@ -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
|