workarea-kount 3.3.0
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 +7 -0
- data/.editorconfig +20 -0
- data/.eslintrc +24 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/ci.yml +58 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +212 -0
- data/CODE_OF_CONDUCT.md +3 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +17 -0
- data/LICENSE.md +3 -0
- data/README.md +98 -0
- data/Rakefile +53 -0
- data/app/controllers/workarea/admin/orders_controller.decorator +5 -0
- data/app/controllers/workarea/storefront/checkout/place_order_controller.decorator +11 -0
- data/app/controllers/workarea/storefront/kount_controller.rb +19 -0
- data/app/controllers/workarea/storefront/kount_orders_controller.rb +40 -0
- data/app/lib/active_shipping/rate_estimate.decorator +10 -0
- data/app/mailers/workarea/storefront/order_mailer.decorator +14 -0
- data/app/models/workarea/checkout.decorator +37 -0
- data/app/models/workarea/checkout/fraud/kount_analyzer.rb +71 -0
- data/app/models/workarea/kount/ens_event.rb +13 -0
- data/app/models/workarea/kount/order.rb +14 -0
- data/app/models/workarea/order.decorator +62 -0
- data/app/models/workarea/order/fraud_decision.decorator +9 -0
- data/app/models/workarea/order/item.decorator +8 -0
- data/app/models/workarea/order/status/review.rb +13 -0
- data/app/models/workarea/payment/credit_card.decorator +13 -0
- data/app/models/workarea/payment/payment.decorator +11 -0
- data/app/models/workarea/payment/status/kount_declined.rb +13 -0
- data/app/models/workarea/payment/status/kount_review.rb +13 -0
- data/app/models/workarea/payment/tender/credit_card.decorator +10 -0
- data/app/models/workarea/search/admin.decorator +12 -0
- data/app/models/workarea/search/admin/order.decorator +7 -0
- data/app/models/workarea/shipping/rate_lookup.decorator +26 -0
- data/app/models/workarea/shipping/service.decorator +9 -0
- data/app/models/workarea/shipping/service_selection.decorator +7 -0
- data/app/models/workarea/shipping_option.decorator +27 -0
- data/app/services/workarea/kount/cancel_order_under_review.rb +28 -0
- data/app/services/workarea/kount/event.rb +43 -0
- data/app/services/workarea/kount/event/dmc_event.rb +9 -0
- data/app/services/workarea/kount/event/risk_change_event.rb +21 -0
- data/app/services/workarea/kount/event/special_alert_event.rb +21 -0
- data/app/services/workarea/kount/event/workflow_event.rb +25 -0
- data/app/services/workarea/kount/event_batch.rb +37 -0
- data/app/services/workarea/kount/order_fraud_update_service.rb +42 -0
- data/app/services/workarea/kount/ris_inquiry.rb +120 -0
- data/app/services/workarea/kount/ris_inquiry/product.rb +53 -0
- data/app/services/workarea/kount/ris_request.rb +84 -0
- data/app/services/workarea/kount/ris_update.rb +39 -0
- data/app/view_models/workarea/admin/order_view_model.decorator +35 -0
- data/app/view_models/workarea/storefront/order_view_model.decorator +11 -0
- data/app/views/workarea/admin/orders/_kount.html.haml +28 -0
- data/app/views/workarea/admin/orders/kount.html.haml +46 -0
- data/app/views/workarea/storefront/checkouts/_kount_data_collector.html.haml +4 -0
- data/app/views/workarea/storefront/order_mailer/hold_denial.html.haml +14 -0
- data/app/workers/workarea/kount/process_review_order.rb +75 -0
- data/app/workers/workarea/kount/update_ris_inquiry.rb +31 -0
- data/bin/rails +18 -0
- data/config/initializers/appends.rb +11 -0
- data/config/initializers/workarea.rb +26 -0
- data/config/locales/en.yml +26 -0
- data/config/routes.rb +14 -0
- data/doc/Kount Technical Specification Guide 5.5.5.pdf +0 -0
- data/lib/workarea/kount.rb +87 -0
- data/lib/workarea/kount/address.rb +39 -0
- data/lib/workarea/kount/bogus_gateway.rb +415 -0
- data/lib/workarea/kount/engine.rb +8 -0
- data/lib/workarea/kount/errors.rb +2 -0
- data/lib/workarea/kount/gateway.rb +50 -0
- data/lib/workarea/kount/mappings.rb +195 -0
- data/lib/workarea/kount/payment_types.rb +50 -0
- data/lib/workarea/kount/response.rb +141 -0
- data/lib/workarea/kount/security_mash.rb +79 -0
- data/lib/workarea/kount/user_defined_fields.rb +16 -0
- data/lib/workarea/kount/version.rb +5 -0
- data/lib/workarea/mailer_previews/storefront/order_mailer_preview.rb +10 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +34 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +9 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +56 -0
- data/test/dummy/config/environments/production.rb +86 -0
- data/test/dummy/config/environments/test.rb +44 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/puma.rb +47 -0
- data/test/dummy/config/routes.rb +6 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/db/seeds.rb +2 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/test/dummy/public/apple-touch-icon.png +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/factories/kount.rb +164 -0
- data/test/integration/workarea/api/admin/payment_transactions_integration_test.decorator +29 -0
- data/test/integration/workarea/kount_moneris_integration_test.rb +37 -0
- data/test/integration/workarea/storefront/kount_integration_test.rb +37 -0
- data/test/integration/workarea/storefront/kount_orders_integration_test.rb +89 -0
- data/test/lib/workarea/kount/response_test.rb +95 -0
- data/test/lib/workarea/kount/security_mash_test.rb +62 -0
- data/test/models/workarea/checkout/fraud/kount_analyzer_test.rb +44 -0
- data/test/models/workarea/checkout_test.decorator +22 -0
- data/test/models/workarea/order/queries_test.decorator +28 -0
- data/test/models/workarea/order_test.decorator +25 -0
- data/test/models/workarea/payment/payment_test.rb +106 -0
- data/test/models/workarea/payment/saved_credit_card_test.rb +24 -0
- data/test/models/workarea/payment_test.decorator +54 -0
- data/test/models/workarea/shipping_option_test.rb +29 -0
- data/test/services/workarea/kount/event_batch_test.rb +95 -0
- data/test/services/workarea/kount/event_test.rb +51 -0
- data/test/services/workarea/kount/order_fraud_update_service_test.rb +48 -0
- data/test/support/workarea/kount_api_config.rb +27 -0
- data/test/system/workarea/kount_system_test.rb +72 -0
- data/test/system/workarea/storefront/kount_guest_checkout_system_test.rb +32 -0
- data/test/system/workarea/storefront/kount_logged_in_checkout_system_test.rb +102 -0
- data/test/test_helper.rb +16 -0
- data/test/vcr_cassettes/kount/basic_fraud_test.yml +43 -0
- data/test/vcr_cassettes/kount/integration/moneris_new_credit_card.yml +84 -0
- data/test/vcr_cassettes/kount/integration/moneris_saved_credit_card.yml +84 -0
- data/test/vcr_cassettes/kount/order_fraud_update.yml +82 -0
- data/test/workers/workarea/kount/clean_orders_test.rb +40 -0
- data/test/workers/workarea/kount/process_review_order_test.rb +100 -0
- data/workarea-kount.gemspec +17 -0
- metadata +238 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
module Kount
|
|
3
|
+
class RisInquiry::Product
|
|
4
|
+
attr_reader :order_item
|
|
5
|
+
|
|
6
|
+
def initialize(order_item)
|
|
7
|
+
@order_item = order_item
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def item
|
|
11
|
+
order_item.sku
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def type
|
|
15
|
+
catalog_product.name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def description
|
|
19
|
+
"#{catalog_product.name} - #{variant_description}".truncate(255)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def quantity
|
|
23
|
+
order_item.quantity
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def price
|
|
27
|
+
order_item.unit_price_cents.floor
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def catalog_product
|
|
33
|
+
@catalog_product ||=
|
|
34
|
+
if order_item.product_attributes.present?
|
|
35
|
+
Mongoid::Factory.from_db(Catalog::Product, order_item.product_attributes)
|
|
36
|
+
else
|
|
37
|
+
Catalog::Product.find_by_sku(order_item.sku)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def variant
|
|
42
|
+
catalog_product.variants.where(sku: order_item.sku).first
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def variant_description
|
|
46
|
+
variant
|
|
47
|
+
.details
|
|
48
|
+
.map { |key, value| "#{key}: #{value.join(',')}" }
|
|
49
|
+
.flatten.join(', ')
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
module Kount
|
|
3
|
+
class RisRequest
|
|
4
|
+
attr_reader :order, :payment, :mode
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def base_fields
|
|
9
|
+
{
|
|
10
|
+
MACK: 'Y',
|
|
11
|
+
AUTH: 'A',
|
|
12
|
+
SESS: order.kount_session_id,
|
|
13
|
+
MODE: mode
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def authorization_transaction
|
|
18
|
+
@authorization_transaction ||= payment
|
|
19
|
+
.credit_card
|
|
20
|
+
.transactions
|
|
21
|
+
.authorizes
|
|
22
|
+
.successful
|
|
23
|
+
.first
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def avs_response
|
|
27
|
+
return {} unless authorization_transaction.present? && payment.uses_credit_card?
|
|
28
|
+
|
|
29
|
+
avs_code = authorization_transaction.response.avs_result
|
|
30
|
+
case avs_code
|
|
31
|
+
when 'A', 'B', 'O'
|
|
32
|
+
street = 'M'
|
|
33
|
+
zip = 'N'
|
|
34
|
+
when 'L', 'P', 'W', 'Z'
|
|
35
|
+
street = 'N'
|
|
36
|
+
zip = 'M'
|
|
37
|
+
when 'C', 'I', 'K', 'N', '4'
|
|
38
|
+
street = 'N'
|
|
39
|
+
zip = 'N'
|
|
40
|
+
when 'D', 'M', 'H', 'V', 'X', 'Y', '3'
|
|
41
|
+
street = 'M'
|
|
42
|
+
zip = 'M'
|
|
43
|
+
when 'E', 'G', 'R', 'S', 'U', '1', '2'
|
|
44
|
+
street = 'X'
|
|
45
|
+
zip = 'X'
|
|
46
|
+
when 'F'
|
|
47
|
+
street = 'X'
|
|
48
|
+
zip = 'M'
|
|
49
|
+
when 'T'
|
|
50
|
+
street = 'M'
|
|
51
|
+
zip = 'X'
|
|
52
|
+
else
|
|
53
|
+
Kount.log_error "KOUNT WARNING: Unsupported AVS Code: #{avs_code} does not have a corresponding value in Kount. Marking as Unsupported/Unavailable."
|
|
54
|
+
street = 'X'
|
|
55
|
+
zip = 'X'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
"AVST": street,
|
|
60
|
+
"AVSZ": zip
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def cvv_response
|
|
65
|
+
return {} unless authorization_transaction.present? && payment.uses_credit_card?
|
|
66
|
+
|
|
67
|
+
cv_code = authorization_transaction.response.cvv_result
|
|
68
|
+
kount_cv_code =
|
|
69
|
+
case cv_code
|
|
70
|
+
when 'M'
|
|
71
|
+
'M' # match
|
|
72
|
+
when 'N'
|
|
73
|
+
'N' # no match
|
|
74
|
+
when 'D', 'I', 'P', 'S', 'U', 'X', '1', '2', '3'
|
|
75
|
+
'X' # unsupported or unavailable
|
|
76
|
+
else
|
|
77
|
+
Kount.log_error "KOUNT WARNING: Unsupported CV Code: #{cv_code} does not have a corresponding value in Kount. Marking as Unsupported/Unavailable."
|
|
78
|
+
'X'
|
|
79
|
+
end
|
|
80
|
+
{ CVVR: kount_cv_code }
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
module Kount
|
|
3
|
+
class RisUpdate < RisRequest
|
|
4
|
+
attr_reader :options
|
|
5
|
+
|
|
6
|
+
def initialize(order:, payment:, mode: 'U', options: {})
|
|
7
|
+
@order = order
|
|
8
|
+
@payment = payment
|
|
9
|
+
@mode = mode
|
|
10
|
+
@options = options
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_h
|
|
14
|
+
@to_h ||= [
|
|
15
|
+
base_fields,
|
|
16
|
+
kount_transaction_id,
|
|
17
|
+
avs_response,
|
|
18
|
+
cvv_response
|
|
19
|
+
].reduce(&:merge)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def payment_transaction
|
|
23
|
+
@payment_transaction = options[:payment_transaction] ||
|
|
24
|
+
authorization_transaction
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def kount_order
|
|
30
|
+
@kount_order ||= options[:kount_order] ||
|
|
31
|
+
Workarea::Kount::Order.find(order.id)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def kount_transaction_id
|
|
35
|
+
{ TRAN: kount_order.response.transaction_id }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
decorate Admin::OrderViewModel, with: :kount do
|
|
3
|
+
def kount_order
|
|
4
|
+
@kount_order ||= Workarea::Kount::Order.find model.id rescue nil
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def kount_order_success?
|
|
8
|
+
kount_order&.response&.success?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def kount_score
|
|
12
|
+
kount_order&.response&.score
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def kount_credit_cards
|
|
16
|
+
kount_order&.response&.credit_cards
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def kount_email_addresses
|
|
20
|
+
kount_order&.response&.email_addresses
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def kount_devices
|
|
24
|
+
kount_order&.response&.devices
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def kount_rules
|
|
28
|
+
kount_order&.response&.triggered_rules
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def kount_order_url
|
|
32
|
+
"#{Kount.kount_order_url_base}#{kount_order.response.transaction_id}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
- if order.kount_order_success?
|
|
2
|
+
.grid__cell
|
|
3
|
+
.card{ class: card_classes(:kount, local_assigns[:active]) }
|
|
4
|
+
= link_to kount_order_path(order), class: 'card__header' do
|
|
5
|
+
%span.card__header-text= t('workarea.admin.orders.cards.kount.title')
|
|
6
|
+
= inline_svg 'workarea/admin/icons/link.svg', class: 'card__icon'
|
|
7
|
+
|
|
8
|
+
- if local_assigns[:active].blank?
|
|
9
|
+
.card__body
|
|
10
|
+
%ul.list-reset
|
|
11
|
+
%li
|
|
12
|
+
%strong= t('workarea.admin.orders.cards.kount.decision')
|
|
13
|
+
#{order.kount_decision.to_s}
|
|
14
|
+
%li
|
|
15
|
+
%strong= t('workarea.admin.orders.cards.kount.score')
|
|
16
|
+
#{order.kount_score}
|
|
17
|
+
%li
|
|
18
|
+
%strong= t('workarea.admin.orders.cards.kount.credit_cards')
|
|
19
|
+
#{order.kount_credit_cards}
|
|
20
|
+
%li
|
|
21
|
+
%strong= t('workarea.admin.orders.cards.kount.email_addresses')
|
|
22
|
+
#{order.kount_email_addresses}
|
|
23
|
+
%li
|
|
24
|
+
%strong= t('workarea.admin.orders.cards.kount.devices')
|
|
25
|
+
#{order.kount_devices}
|
|
26
|
+
|
|
27
|
+
= link_to kount_order_path(order), class: 'card__button' do
|
|
28
|
+
%span.button.button--small= t('workarea.admin.orders.cards.kount.button')
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
- @page_title = t('workarea.admin.orders.kount.title', name: @order.name)
|
|
2
|
+
|
|
3
|
+
.view
|
|
4
|
+
.view__header
|
|
5
|
+
.grid.grid--middle.grid--right
|
|
6
|
+
.grid__cell.grid__cell--50
|
|
7
|
+
.view__heading
|
|
8
|
+
= link_to_index_for(@order)
|
|
9
|
+
%h1= link_to @order.name, url_for(@order)
|
|
10
|
+
.grid__cell.grid__cell--25
|
|
11
|
+
= render_aux_navigation_for(@order)
|
|
12
|
+
|
|
13
|
+
.view__container
|
|
14
|
+
= render_cards_for(@order, :flow)
|
|
15
|
+
|
|
16
|
+
.view__container.view__container--narrow
|
|
17
|
+
.grid
|
|
18
|
+
.grid__cell.grid__cell--50
|
|
19
|
+
%h2= t('workarea.admin.orders.kount.rules_triggered')
|
|
20
|
+
- if @order.kount_rules.present?
|
|
21
|
+
%ul.list-reset
|
|
22
|
+
- @order.kount_rules.each do |rule|
|
|
23
|
+
%li= rule[:rule_description]
|
|
24
|
+
- else
|
|
25
|
+
%span= t('workarea.admin.orders.kount.no_rules_triggered')
|
|
26
|
+
.grid__cell.grid__cell--50
|
|
27
|
+
%ul.list-reset
|
|
28
|
+
%li
|
|
29
|
+
%strong= t('workarea.admin.orders.cards.kount.decision')
|
|
30
|
+
#{@order.kount_decision.to_s}
|
|
31
|
+
%li
|
|
32
|
+
%strong= t('workarea.admin.orders.cards.kount.score')
|
|
33
|
+
#{@order.kount_score}
|
|
34
|
+
%li
|
|
35
|
+
%strong= t('workarea.admin.orders.cards.kount.credit_cards')
|
|
36
|
+
#{@order.kount_credit_cards}
|
|
37
|
+
%li
|
|
38
|
+
%strong= t('workarea.admin.orders.cards.kount.email_addresses')
|
|
39
|
+
#{@order.kount_email_addresses}
|
|
40
|
+
%li
|
|
41
|
+
%strong= t('workarea.admin.orders.cards.kount.devices')
|
|
42
|
+
#{@order.kount_devices}
|
|
43
|
+
|
|
44
|
+
.workflow-bar
|
|
45
|
+
.grid.grid--auto.grid--right.grid--middle
|
|
46
|
+
.grid__cell= link_to t('workarea.admin.orders.kount.view_order_in_kount'), @order.kount_order_url, target: :_blank, class: 'workflow-bar__button'
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
- unless Rails.env.test? || @kount_data_collector_already_appended
|
|
2
|
+
- @kount_data_collector_already_appended = true
|
|
3
|
+
%iframe{ width: 1, height: 1, frameborder: 0, scrolling: 'no', style: 'display:none;', src: kount_data_collector_htm_url }
|
|
4
|
+
%img{ width: 1, height: 1, src: kount_data_collector_gif_url }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
= append_partials('storefront.hold_denial_mailer.top')
|
|
2
|
+
%tr
|
|
3
|
+
%td
|
|
4
|
+
%table
|
|
5
|
+
%tr
|
|
6
|
+
%td
|
|
7
|
+
%h1= t('workarea.storefront.email.hold_denial.heading', order_id: @order.id)
|
|
8
|
+
%p= t('workarea.storefront.email.hold_denial.info_html').html_safe
|
|
9
|
+
|
|
10
|
+
= render 'summary', order: @order
|
|
11
|
+
|
|
12
|
+
= render 'workarea/storefront/mailers/recommendations', recommendations: @recommendations
|
|
13
|
+
|
|
14
|
+
= append_partials('storefront.hold_denial_mailer.bottom')
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
module Kount
|
|
3
|
+
class ProcessReviewOrder
|
|
4
|
+
include Sidekiq::Worker
|
|
5
|
+
|
|
6
|
+
sidekiq_options queue: 'high'
|
|
7
|
+
attr_reader :order
|
|
8
|
+
|
|
9
|
+
def perform(order_id, approved, event_string)
|
|
10
|
+
@order = Workarea::Order.find(order_id)
|
|
11
|
+
return unless order.under_review?
|
|
12
|
+
|
|
13
|
+
Workarea::Kount::Order.find(order.id).tap do |kount_order|
|
|
14
|
+
kount_order.ens_events.create!(xml: event_string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
with_order_lock do
|
|
18
|
+
if approved
|
|
19
|
+
order.update_attributes(kount_decision: :approve)
|
|
20
|
+
place_order
|
|
21
|
+
else
|
|
22
|
+
order.update_attributes(kount_decision: :decline)
|
|
23
|
+
cancel_order
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def with_order_lock
|
|
31
|
+
order.lock!
|
|
32
|
+
yield
|
|
33
|
+
ensure
|
|
34
|
+
order.unlock!
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def checkout
|
|
38
|
+
@checkout ||= Workarea::Checkout.new(order)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def place_order
|
|
42
|
+
if checkout.handle_kount_approved
|
|
43
|
+
place_order_side_effects
|
|
44
|
+
else
|
|
45
|
+
write_comment
|
|
46
|
+
cancel_order
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def place_order_side_effects
|
|
51
|
+
Workarea::Storefront::OrderMailer.confirmation(order.id).deliver_now
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def write_comment
|
|
55
|
+
transaction = Workarea::Payment::Transaction
|
|
56
|
+
.where(payment_id: order.id)
|
|
57
|
+
.order(:updated_at.desc)
|
|
58
|
+
.first
|
|
59
|
+
|
|
60
|
+
body =
|
|
61
|
+
if transaction
|
|
62
|
+
"Kount review order approved but payment declined: #{transaction.message}"
|
|
63
|
+
else
|
|
64
|
+
'Kount review order approved but failed without a payment transaction.'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
order.comments.create(body: body)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def cancel_order
|
|
71
|
+
Kount::CancelOrderUnderReview.new(order).cancel!
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
module Kount
|
|
3
|
+
class UpdateRisInquiry
|
|
4
|
+
include Sidekiq::Worker
|
|
5
|
+
include Sidekiq::CallbacksWorker
|
|
6
|
+
|
|
7
|
+
self.inlined = true
|
|
8
|
+
sidekiq_options(
|
|
9
|
+
enqueue_on: { Workarea::Payment::Transaction => :save },
|
|
10
|
+
queue: 'high'
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
def perform(transaction_id)
|
|
14
|
+
transaction = Workarea::Payment::Transaction.find(transaction_id)
|
|
15
|
+
payment = transaction.payment
|
|
16
|
+
order = Workarea::Order.find(payment.id)
|
|
17
|
+
kount_order = Kount::Order.find(payment.id) rescue nil
|
|
18
|
+
|
|
19
|
+
return unless kount_order.present? && payment.credit_card? && transaction.authorize?
|
|
20
|
+
|
|
21
|
+
Workarea::Kount::OrderFraudUpdateService.new(
|
|
22
|
+
order: order,
|
|
23
|
+
payment: payment,
|
|
24
|
+
options: {
|
|
25
|
+
payment_transaction: transaction
|
|
26
|
+
}
|
|
27
|
+
).perform!
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/bin/rails
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# This command will automatically be run when you run 'rails' with Rails gems
|
|
3
|
+
# installed from the root of your application.
|
|
4
|
+
|
|
5
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
|
6
|
+
ENGINE_PATH = File.expand_path('../../lib/kount/engine', __FILE__)
|
|
7
|
+
|
|
8
|
+
# Set up gems listed in the Gemfile.
|
|
9
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
|
10
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
|
11
|
+
|
|
12
|
+
require 'action_controller/railtie'
|
|
13
|
+
require 'action_view/railtie'
|
|
14
|
+
require 'action_mailer/railtie'
|
|
15
|
+
require 'rails/test_unit/railtie'
|
|
16
|
+
require 'sprockets/railtie'
|
|
17
|
+
|
|
18
|
+
require 'rails/engine/commands'
|