flowcommerce_spree 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +91 -0
- data/Rakefile +33 -0
- data/SPREE_FLOW.md +134 -0
- data/app/assets/javascripts/flowcommerce_spree/application.js +13 -0
- data/app/assets/stylesheets/flowcommerce_spree/application.css +15 -0
- data/app/controllers/concerns/current_zone_loader_decorator.rb +49 -0
- data/app/controllers/flowcommerce_spree/webhooks_controller.rb +25 -0
- data/app/helpers/flowcommerce_spree/application_helper.rb +6 -0
- data/app/helpers/spree/admin/orders_helper_decorator.rb +17 -0
- data/app/helpers/spree/core/controller_helpers/flow_io_order_helper_decorator.rb +53 -0
- data/app/mailers/spree/spree_order_mailer_decorator.rb +24 -0
- data/app/models/flowcommerce_spree/settings.rb +8 -0
- data/app/models/spree/credit_card_decorator.rb +9 -0
- data/app/models/spree/flow_io_product_decorator.rb +91 -0
- data/app/models/spree/flow_io_variant_decorator.rb +205 -0
- data/app/models/spree/gateway/spree_flow_gateway.rb +116 -0
- data/app/models/spree/line_item_decorator.rb +15 -0
- data/app/models/spree/order_decorator.rb +179 -0
- data/app/models/spree/promotion_decorator.rb +10 -0
- data/app/models/spree/promotion_handler/coupon_decorator.rb +30 -0
- data/app/models/spree/spree_user_decorator.rb +15 -0
- data/app/models/spree/taxon_decorator.rb +37 -0
- data/app/models/spree/zone_decorator.rb +7 -0
- data/app/models/spree/zones/flow_io_product_zone_decorator.rb +55 -0
- data/app/services/flowcommerce_spree/import_experience_items.rb +76 -0
- data/app/services/flowcommerce_spree/import_experiences.rb +37 -0
- data/app/services/flowcommerce_spree/order_sync.rb +231 -0
- data/app/views/layouts/flowcommerce_spree/application.html.erb +14 -0
- data/app/views/spree/admin/payments/index.html.erb +28 -0
- data/app/views/spree/admin/promotions/edit.html.erb +57 -0
- data/app/views/spree/admin/shared/_order_summary.html.erb +44 -0
- data/app/views/spree/admin/shared/_order_summary_flow.html.erb +13 -0
- data/app/views/spree/order_mailer/confirm_email.html.erb +86 -0
- data/app/views/spree/order_mailer/confirm_email.text.erb +38 -0
- data/config/initializers/flowcommerce_spree.rb +7 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20201021160159_add_type_and_meta_to_spree_zone.rb +23 -0
- data/db/migrate/20201021755957_add_meta_to_spree_tables.rb +17 -0
- data/db/migrate/20201022173210_add_zone_type_to_spree_zone_members.rb +24 -0
- data/db/migrate/20201022174252_add_kind_to_zone.rb +22 -0
- data/lib/flow/error.rb +73 -0
- data/lib/flow/pay_pal.rb +25 -0
- data/lib/flow/simple_gateway.rb +115 -0
- data/lib/flowcommerce_spree.rb +31 -0
- data/lib/flowcommerce_spree/api.rb +48 -0
- data/lib/flowcommerce_spree/engine.rb +27 -0
- data/lib/flowcommerce_spree/experience_service.rb +65 -0
- data/lib/flowcommerce_spree/logging_http_client.rb +43 -0
- data/lib/flowcommerce_spree/logging_http_handler.rb +15 -0
- data/lib/flowcommerce_spree/refresher.rb +81 -0
- data/lib/flowcommerce_spree/session.rb +71 -0
- data/lib/flowcommerce_spree/version.rb +5 -0
- data/lib/flowcommerce_spree/webhook_service.rb +98 -0
- data/lib/simple_csv_writer.rb +44 -0
- data/lib/tasks/flowcommerce_spree.rake +289 -0
- metadata +220 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
<%= Spree.t('order_mailer.confirm_email.dear_customer') %>
|
2
|
+
|
3
|
+
<%= Spree.t('order_mailer.confirm_email.instructions') %>
|
4
|
+
|
5
|
+
============================================================
|
6
|
+
<%= Spree.t('order_mailer.confirm_email.order_summary') %>
|
7
|
+
============================================================
|
8
|
+
<% @order.line_items.each do |item| %>
|
9
|
+
<%= item.variant.sku %> <%= raw(item.variant.product.name) %> <%= raw(item.variant.options_text) -%> (<%=item.quantity%>) @ <%= item.single_money %> = <%= @order.flow_line_item_price(line_item, :with_quantity) %>
|
10
|
+
<% end %>
|
11
|
+
============================================================
|
12
|
+
<%= Spree.t('order_mailer.confirm_email.subtotal', :subtotal => @order.display_item_total) %>
|
13
|
+
<% if @order.line_item_adjustments.exists? %>
|
14
|
+
<% if @order.all_adjustments.promotion.eligible.exists? %>
|
15
|
+
<% @order.all_adjustments.promotion.eligible.group_by(&:label).each do |label, adjustments| %>
|
16
|
+
<%= Spree.t(:promotion) %>: <%= label %> <%= Spree::Money.new(adjustments.sum(&:amount), currency: @order.currency) %>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<% @order.shipments.group_by { |s| s.selected_shipping_rate.try(:name) }.each do |name, shipments| %>
|
22
|
+
<%= Spree.t(:shipping) %>: <%= name %> <%= Spree::Money.new(shipments.sum(&:discounted_cost), currency: @order.currency) %>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<% if @order.all_adjustments.eligible.tax.exists? %>
|
26
|
+
<% @order.all_adjustments.eligible.tax.group_by(&:label).each do |label, adjustments| %>
|
27
|
+
<%= Spree.t(:tax) %>: <%= label %> <%= Spree::Money.new(adjustments.sum(&:amount), currency: @order.currency) %>
|
28
|
+
<% end %>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% @order.adjustments.eligible.each do |adjustment| %>
|
32
|
+
<% next if (adjustment.source_type == 'Spree::TaxRate') and (adjustment.amount == 0) %>
|
33
|
+
<%= adjustment.label %> <%= adjustment.display_amount %>
|
34
|
+
<% end %>
|
35
|
+
============================================================
|
36
|
+
<%= Spree.t('order_mailer.confirm_email.total', :total => @order.display_total) %>
|
37
|
+
|
38
|
+
<%= Spree.t('order_mailer.confirm_email.thanks') %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
class AddTypeAndMetaToSpreeZone < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
add_column :spree_zones, :klass, :text unless column_exists?(:spree_zones, :klass)
|
4
|
+
add_column :spree_zones, :status, :text unless column_exists?(:spree_zones, :status)
|
5
|
+
add_column :spree_zones, :meta, :jsonb, default: '{}' unless column_exists?(:spree_zones, :meta)
|
6
|
+
|
7
|
+
add_index :spree_zones, :meta, using: :gin unless index_exists?(:spree_zones, :meta)
|
8
|
+
add_index :spree_zones, %i[id klass] unless index_exists?(:spree_zones, %i[id klass])
|
9
|
+
add_index :spree_zones, %i[klass name], unique: true unless index_exists?(:spree_zones, %i[klass name])
|
10
|
+
add_index :spree_zones, :status unless index_exists?(:spree_zones, :status)
|
11
|
+
end
|
12
|
+
|
13
|
+
def down
|
14
|
+
remove_index :spree_zones, :status if index_exists?(:spree_zones, :status)
|
15
|
+
remove_index :spree_zones, %i[klass name] if index_exists?(:spree_zones, %i[klass name])
|
16
|
+
remove_index :spree_zones, %i[id klass] if index_exists?(:spree_zones, %i[id klass])
|
17
|
+
remove_index :spree_zones, :meta if index_exists?(:spree_zones, :meta)
|
18
|
+
|
19
|
+
remove_column :spree_zones, :meta if column_exists?(:spree_zones, :meta)
|
20
|
+
remove_column :spree_zones, :status if column_exists?(:spree_zones, :status)
|
21
|
+
remove_column :spree_zones, :klass if column_exists?(:spree_zones, :klass)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class AddMetaToSpreeTables < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
add_column :spree_products, :meta, :jsonb, default: '{}' unless column_exists?(:spree_products, :meta)
|
4
|
+
add_column :spree_variants, :meta, :jsonb, default: '{}' unless column_exists?(:spree_variants, :meta)
|
5
|
+
add_column :spree_orders, :meta, :jsonb, default: '{}' unless column_exists?(:spree_orders, :meta)
|
6
|
+
add_column :spree_promotions, :meta, :jsonb, default: '{}' unless column_exists?(:spree_promotions, :meta)
|
7
|
+
add_column :spree_credit_cards, :meta, :jsonb, default: '{}' unless column_exists?(:spree_credit_cards, :meta)
|
8
|
+
end
|
9
|
+
|
10
|
+
def down
|
11
|
+
remove_column :spree_products, :meta if column_exists?(:spree_products, :meta)
|
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)
|
15
|
+
remove_column :spree_credit_cards, :meta if column_exists?(:spree_credit_cards, :meta)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class AddZoneTypeToSpreeZoneMembers < ActiveRecord::Migration
|
2
|
+
def up
|
3
|
+
add_column :spree_zone_members, :zone_type, :text unless column_exists?(:spree_zone_members, :zone_type)
|
4
|
+
|
5
|
+
unless index_exists?(:spree_zone_members, %i[zone_id zone_type])
|
6
|
+
add_index :spree_zone_members, %i[zone_id zone_type],
|
7
|
+
name: "index_spree_zone_members_on_zone_id_and_zone_type", using: :btree
|
8
|
+
end
|
9
|
+
|
10
|
+
if index_exists?(:spree_zone_members, name: "index_spree_zone_members_on_zone_id")
|
11
|
+
remove_index :spree_zone_members, name: "index_spree_zone_members_on_zone_id"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def down
|
16
|
+
add_index :spree_zone_members, :zone_id unless index_exists?(:spree_zone_members, :zone_id)
|
17
|
+
|
18
|
+
if index_exists?(:spree_zone_members, %i[zone_id zone_type])
|
19
|
+
remove_index :spree_zone_members, name: "index_spree_zone_members_on_zone_id_and_zone_type"
|
20
|
+
end
|
21
|
+
|
22
|
+
remove_column :spree_zone_members, :zone_type if column_exists?(:spree_zone_members, :zone_type)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# This is from Spree 3.0
|
2
|
+
# https://github.com/spree/spree/commit/f9509a511def39de9d98199ddbf35f35c8580ca4#diff-984b308f2dc59ffb6e47183ac28b9895cfaa58bb26fb6f6e56a6afbe888fdece
|
3
|
+
class AddKindToZone < ActiveRecord::Migration
|
4
|
+
def up
|
5
|
+
unless column_exists?(:spree_zones, :kind)
|
6
|
+
add_column :spree_zones, :kind, :string
|
7
|
+
add_index :spree_zones, :kind
|
8
|
+
|
9
|
+
Spree::Zone.find_each do |zone|
|
10
|
+
last_type = zone.members.where.not(zoneable_type: nil).pluck(:zoneable_type).last
|
11
|
+
zone.update_column :kind, last_type.demodulize.underscore if last_type
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index :spree_zones, :kind unless index_exists?(:spree_zones, :kind)
|
16
|
+
end
|
17
|
+
|
18
|
+
def down
|
19
|
+
remove_index :spree_zones, :kind if index_exists?(:spree_zones, :kind)
|
20
|
+
remove_column :spree_zones, :kind if column_exists?(:spree_zones, :kind)
|
21
|
+
end
|
22
|
+
end
|
data/lib/flow/error.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Flow (2017)
|
4
|
+
# api error logger and formater
|
5
|
+
|
6
|
+
require 'digest/sha1'
|
7
|
+
|
8
|
+
class Flow::Error < StandardError
|
9
|
+
# logs error to file for easy discovery and fix
|
10
|
+
def self.log(exception, request)
|
11
|
+
history = exception.backtrace.reject { |el| el.index('/gems/') }.map { |el| el.sub(Rails.root.to_s, '') }.join($/)
|
12
|
+
|
13
|
+
msg = "#{exception.class} in #{request.url}"
|
14
|
+
data = [msg, exception.message, history].join("\n\n")
|
15
|
+
key = Digest::SHA1.hexdigest(exception.backtrace.first.split(' ').first)
|
16
|
+
|
17
|
+
folder = Rails.root.join('log/exceptions').to_s
|
18
|
+
Dir.mkdir(folder) unless Dir.exist?(folder)
|
19
|
+
|
20
|
+
folder += "/#{exception.class.to_s.tableize.gsub('/', '-')}"
|
21
|
+
Dir.mkdir(folder) unless Dir.exist?(folder)
|
22
|
+
|
23
|
+
"#{folder}/#{key}.txt".tap do |path|
|
24
|
+
File.write(path, data)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.format_message(exception)
|
29
|
+
# format Flow errors in a special way
|
30
|
+
# Io::Flow::V0::HttpClient::ServerError - 422 Unprocessable Entity:
|
31
|
+
# {"code":"invalid_number","messages":["Card number is not valid"]}
|
32
|
+
# hash['code'] = 'invalid_number'
|
33
|
+
# hash['message'] = 'Card number is not valid'
|
34
|
+
# hash['title'] = '422 Unprocessable Entity'
|
35
|
+
# hash['klass'] = 'Io::Flow::V0::HttpClient::ServerError'
|
36
|
+
if exception.class == Io::Flow::V0::HttpClient::ServerError
|
37
|
+
parts = exception.message.split(': ', 2)
|
38
|
+
hash = Oj.load(parts[1])
|
39
|
+
|
40
|
+
hash[:message] = hash['messages'].join(', ')
|
41
|
+
hash[:title] = parts[0]
|
42
|
+
hash[:klass] = exception.class
|
43
|
+
hash[:code] = hash['code']
|
44
|
+
else
|
45
|
+
msg = exception.message.is_a?(Array) ? exception.message.join(' - ') : exception.message
|
46
|
+
|
47
|
+
hash = {}
|
48
|
+
hash[:message] = msg
|
49
|
+
hash[:title] = '-'
|
50
|
+
hash[:klass] = exception.class
|
51
|
+
hash[:code] = '-'
|
52
|
+
end
|
53
|
+
|
54
|
+
hash
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.format_order_message(order)
|
58
|
+
message = if order['messages']
|
59
|
+
msg = order['messages'].join(', ')
|
60
|
+
msg += " (#{Spree::Variant.where(id: order['numbers']).map(&:name).join(', ')})" if order['numbers']
|
61
|
+
msg
|
62
|
+
else
|
63
|
+
'Order not properly localized (sync issue)'
|
64
|
+
end
|
65
|
+
|
66
|
+
# sub_info = 'Flow.io'
|
67
|
+
# sub_info += ' - %s' % flow_experience.key[0, 15] if flow_experience
|
68
|
+
|
69
|
+
# '%s (%s)' % [message, sub_info]
|
70
|
+
|
71
|
+
message
|
72
|
+
end
|
73
|
+
end
|
data/lib/flow/pay_pal.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Flow.io (2017)
|
4
|
+
# communicates with flow api to synchronize Spree order with PayPal
|
5
|
+
|
6
|
+
module Flow::PayPal
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def get_id(order)
|
10
|
+
raise 'PayPal only supported while using flow' unless order.flow_order
|
11
|
+
|
12
|
+
# get PayPal ID using Flow api
|
13
|
+
body = {
|
14
|
+
# discriminator: 'merchant_of_record_payment_form',
|
15
|
+
method: 'paypal',
|
16
|
+
order_number: order.number,
|
17
|
+
amount: order.flow_order.total.amount,
|
18
|
+
currency: order.flow_order.total.currency
|
19
|
+
}
|
20
|
+
|
21
|
+
# FlowcommerceSpree::Api.run :post, '/:organization/payments', {}, body
|
22
|
+
form = ::Io::Flow::V0::Models::MerchantOfRecordPaymentForm.new body
|
23
|
+
FlowcommerceSpree.client.payments.post FlowcommerceSpree::ORGANIZATION, form
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Flow.io (2017)
|
4
|
+
# communicates with Flow payments API, easy access to session
|
5
|
+
# to basic shop frontend and backend needs
|
6
|
+
module Flow
|
7
|
+
class SimpleGateway
|
8
|
+
cattr_accessor :clear_zero_amount_payments
|
9
|
+
|
10
|
+
def initialize(order)
|
11
|
+
@order = order
|
12
|
+
end
|
13
|
+
|
14
|
+
# authorises credit card and prepares for capture
|
15
|
+
def cc_authorization
|
16
|
+
response = FlowcommerceSpree.client.authorizations.post(FlowcommerceSpree::ORGANIZATION, build_authorization_form)
|
17
|
+
status_message = response.result.status.value
|
18
|
+
status = status_message == ::Io::Flow::V0::Models::AuthorizationStatus.authorized.value
|
19
|
+
|
20
|
+
store = { key: response.key,
|
21
|
+
amount: response.amount,
|
22
|
+
currency: response.currency,
|
23
|
+
authorization_id: response.id }
|
24
|
+
|
25
|
+
@order.flow_data['authorization'] = store
|
26
|
+
@order.update_column(:meta, @order.meta.to_json)
|
27
|
+
|
28
|
+
if self.class.clear_zero_amount_payments
|
29
|
+
@order.payments.where(amount: 0, state: %w[invalid processing pending]).map(&:destroy)
|
30
|
+
end
|
31
|
+
|
32
|
+
ActiveMerchant::Billing::Response.new(status, status_message, { response: response }, authorization: store)
|
33
|
+
rescue Io::Flow::V0::HttpClient::ServerError => e
|
34
|
+
error_response(e)
|
35
|
+
end
|
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
|
+
private
|
74
|
+
|
75
|
+
# if order is not in flow, we use local Spree settings
|
76
|
+
def in_flow?
|
77
|
+
@order.flow_order ? true : false
|
78
|
+
end
|
79
|
+
|
80
|
+
def build_authorization_form
|
81
|
+
if in_flow?
|
82
|
+
# we have order id so we allways use MerchantOfRecordAuthorizationForm
|
83
|
+
::Io::Flow::V0::Models::MerchantOfRecordAuthorizationForm.new('order_number': @order.flow_number,
|
84
|
+
'currency': @order.flow_order.total.currency,
|
85
|
+
'amount': @order.flow_order.total.amount,
|
86
|
+
'token': cc_get_token)
|
87
|
+
else
|
88
|
+
# when not using Flow, we fall back to Spree default
|
89
|
+
::Io::Flow::V0::Models::DirectAuthorizationForm.new('currency': @order.currency,
|
90
|
+
'amount': @order.total,
|
91
|
+
'token': cc_get_token)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# gets credit card token
|
96
|
+
def cc_get_token
|
97
|
+
cards = @order.credit_cards.select(&:gateway_customer_profile_id)
|
98
|
+
raise StandardError, 'Credit card with token not found' unless cards.first
|
99
|
+
|
100
|
+
cards.first.gateway_customer_profile_id
|
101
|
+
end
|
102
|
+
|
103
|
+
# we want to return errors in standardized format
|
104
|
+
def error_response(exception_object)
|
105
|
+
message = if exception_object.respond_to?(:body) && exception_object.body.length > 0
|
106
|
+
description = Oj.load(exception_object.body)['messages'].to_sentence
|
107
|
+
"#{exception_object.details}: #{description} (#{exception_object.code})"
|
108
|
+
else
|
109
|
+
exception_object.message
|
110
|
+
end
|
111
|
+
|
112
|
+
ActiveMerchant::Billing::Response.new(false, message, exception: exception_object)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'flowcommerce'
|
4
|
+
require 'flowcommerce_spree/api'
|
5
|
+
require 'flowcommerce_spree/refresher'
|
6
|
+
require 'flowcommerce_spree/engine'
|
7
|
+
require 'flowcommerce_spree/logging_http_client'
|
8
|
+
require 'flowcommerce_spree/logging_http_handler'
|
9
|
+
require 'flowcommerce_spree/webhook_service'
|
10
|
+
require 'flowcommerce_spree/session'
|
11
|
+
require 'flow/simple_gateway'
|
12
|
+
|
13
|
+
module FlowcommerceSpree
|
14
|
+
def self.client(logger: FlowcommerceSpree.logger, **opts)
|
15
|
+
FlowCommerce.instance(http_handler: LoggingHttpHandler.new(logger: logger), **opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.configure
|
19
|
+
yield self if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.logger
|
23
|
+
logger = ActiveSupport::Logger.new(STDOUT, 3, 10_485_760)
|
24
|
+
|
25
|
+
# Broadcast the log into the file besides STDOUT, if `log` folder exists
|
26
|
+
if Dir.exist?('log')
|
27
|
+
logger.extend(ActiveSupport::Logger.broadcast(ActiveSupport::Logger.new('log/flowcommerce_spree.log')))
|
28
|
+
end
|
29
|
+
logger
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# module for communication and customization based on Flow API
|
4
|
+
# for now all in same class
|
5
|
+
module FlowcommerceSpree
|
6
|
+
module Api
|
7
|
+
extend self
|
8
|
+
|
9
|
+
# builds curl command and gets remote data
|
10
|
+
def run(action, path, params = {}, body = nil)
|
11
|
+
body ||= params.delete(:BODY)
|
12
|
+
|
13
|
+
remote_params = URI.encode_www_form params
|
14
|
+
remote_path = debug_path = path.sub('%o', ORGANIZATION).sub(':organization', ORGANIZATION)
|
15
|
+
remote_path += "?#{remote_params}" unless remote_params.blank?
|
16
|
+
|
17
|
+
curl = ['curl -s']
|
18
|
+
curl.push "-X #{action.to_s.upcase}"
|
19
|
+
curl.push "-u #{API_KEY}:"
|
20
|
+
|
21
|
+
if body
|
22
|
+
body = body.to_json unless body.is_a?(Array)
|
23
|
+
curl.push '-H "Content-Type: application/json"'
|
24
|
+
curl.push "-d '#{body.gsub(%['], %['"'"'])}'" if body
|
25
|
+
end
|
26
|
+
|
27
|
+
curl.push "\"https://api.flow.io#{remote_path}\""
|
28
|
+
command = curl.join(' ')
|
29
|
+
|
30
|
+
puts command if defined?(Rails::Console)
|
31
|
+
|
32
|
+
dir = Rails.root.join('log/api')
|
33
|
+
Dir.mkdir(dir) unless Dir.exist?(dir)
|
34
|
+
debug_file = "#{dir}/#{debug_path.gsub(/[^\w]+/, '_')}.bash"
|
35
|
+
File.write debug_file, command + "\n"
|
36
|
+
|
37
|
+
JSON.load `#{command}`
|
38
|
+
end
|
39
|
+
|
40
|
+
def logger
|
41
|
+
@logger ||= Logger.new('./log/flow.log') # or nil for no logging
|
42
|
+
end
|
43
|
+
|
44
|
+
def format_default_price(amount)
|
45
|
+
format('$%<price>.2f', amount)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|