workarea-kount 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/LICENSE.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Workarea Kount
|
2
|
+
|
3
|
+
Kount plugin for the Workarea platform.
|
4
|
+
|
5
|
+
## Kount Response Codes
|
6
|
+
|
7
|
+
Kount's Risk Inquiry Services will return one of three values.
|
8
|
+
|
9
|
+
Approved - the order is not suspected as fraud
|
10
|
+
|
11
|
+
Decline - the order is fraud
|
12
|
+
|
13
|
+
Hold for manager review - the order is suspected fraud
|
14
|
+
|
15
|
+
## Kount Order Flow
|
16
|
+
|
17
|
+
### In Checkout
|
18
|
+
|
19
|
+
The Kount plugin sends the credit card and paypal orders to Kount before payment
|
20
|
+
is captured. Based on the response from Kount different actions will be taken.
|
21
|
+
|
22
|
+
#### Approved - The order is not fraud
|
23
|
+
|
24
|
+
The order is placed.
|
25
|
+
|
26
|
+
#### Decline - The order is fraud
|
27
|
+
|
28
|
+
An error is shown to the customer and redirected back to the payment step.
|
29
|
+
|
30
|
+
#### Hold for manager review - the order is suspected fraud
|
31
|
+
|
32
|
+
The credit card is tokenized and inventory is captured but the payment is not
|
33
|
+
authorized/purchased. The customer is shown the order confirmation as if the
|
34
|
+
order is placed. A Kount admin user needs to use approve or decline the order
|
35
|
+
via the Kount admin.
|
36
|
+
|
37
|
+
The Kount Event Notificaion System (ENS) will post the data back to Workarea.
|
38
|
+
|
39
|
+
If the admin declines the order in Kount, the order is canceled and the customer
|
40
|
+
recieves a cancelation email.
|
41
|
+
|
42
|
+
If the admin approves the order, the payment is attemped to be captured. If the
|
43
|
+
payment captures successfully the order is placed. If the payment fails
|
44
|
+
authorization/purchase, the order is canceled and the customer recives a
|
45
|
+
cancelation email.
|
46
|
+
|
47
|
+
## Configuration
|
48
|
+
|
49
|
+
Add values for `merchant_id`, `version`, `key`, and `ksalt` to your application secrets
|
50
|
+
|
51
|
+
```yaml
|
52
|
+
kount:
|
53
|
+
merchant_id:
|
54
|
+
version:
|
55
|
+
key:
|
56
|
+
ksalt:
|
57
|
+
ens_username: username for basic auth for ENS
|
58
|
+
ens_password: password for basic auth for ENS
|
59
|
+
kount_site: <site name for ENS>
|
60
|
+
```
|
61
|
+
|
62
|
+
### Event Notification System Configuration
|
63
|
+
|
64
|
+
The Kount ENS requires configuration in Workarea to match configuration in Kount.
|
65
|
+
If the ENS is not configured properly, Kount review decisions will not be
|
66
|
+
received by Workarea.
|
67
|
+
|
68
|
+
Workarea uses basic auth credentials `ens_username:ens_password` to authenticate
|
69
|
+
requests from the Kount ENS. If your application is behind basic_auth (e.g. in
|
70
|
+
staging or QA) you should configure these credentials to match your basic auth
|
71
|
+
credentials for the environment. If your application is not behind basic auth
|
72
|
+
these credentials can be anything you want, as long as they are secure.
|
73
|
+
|
74
|
+
#### Kount Site
|
75
|
+
|
76
|
+
The `kount_site` configuration is used by kount ENS to determine which endpoint
|
77
|
+
events should be sent to. If no `kount_site` is provided the DEFAULT site will
|
78
|
+
be used. `kount_site` can be used to configure different ENS endpoints for
|
79
|
+
testing inQA and Staging, or for multi-site implementations.
|
80
|
+
|
81
|
+
#### Configure ENS in Kount
|
82
|
+
|
83
|
+
In the Kount admin navigate to: Fraud Control -> Websites -> Add Website
|
84
|
+
|
85
|
+
The ENS Api URL should look like `https://ENS_USERNAME:ENS_PASSWORD@WEBSITE_DOMAIN/kount_orders`
|
86
|
+
|
87
|
+
Example: `https://kount:aksjei8243d8@www.example.com/kount_orders`
|
88
|
+
|
89
|
+
## Workarea Platform Documentation
|
90
|
+
|
91
|
+
See [http://developer.workarea.com](http://developer.workarea.com) for Workarea
|
92
|
+
platform documentation.
|
93
|
+
|
94
|
+
## Copyright & Licensing
|
95
|
+
|
96
|
+
Copyright WebLinc 2018. All rights reserved.
|
97
|
+
|
98
|
+
For licensing, contact sales@weblinc.com.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'rdoc/task'
|
9
|
+
|
10
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
11
|
+
rdoc.rdoc_dir = 'rdoc'
|
12
|
+
rdoc.title = 'Tasker'
|
13
|
+
rdoc.options << '--line-numbers'
|
14
|
+
rdoc.rdoc_files.include('README.md')
|
15
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
16
|
+
end
|
17
|
+
|
18
|
+
APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
|
19
|
+
load 'rails/tasks/engine.rake'
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
load 'workarea/changelog.rake'
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
|
25
|
+
Rake::TestTask.new(:test) do |t|
|
26
|
+
t.libs << 'lib'
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
33
|
+
|
34
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
35
|
+
require 'workarea/kount/version'
|
36
|
+
|
37
|
+
desc "Release version #{Workarea::Kount::VERSION} of the gem"
|
38
|
+
task :release do
|
39
|
+
host = "https://#{ENV['BUNDLE_GEMS__WORKAREA__COM']}@gems.workarea.com"
|
40
|
+
|
41
|
+
Rake::Task['workarea:changelog'].execute
|
42
|
+
system 'git add CHANGELOG.md'
|
43
|
+
system 'git commit -m "Update CHANGELOG"'
|
44
|
+
system 'git push origin HEAD'
|
45
|
+
|
46
|
+
system "git tag -a v#{Workarea::Kount::VERSION} -m 'Tagging #{Workarea::Kount::VERSION}'"
|
47
|
+
system 'git push --tags'
|
48
|
+
|
49
|
+
system 'gem build workarea-kount.gemspec'
|
50
|
+
system "gem push workarea-kount-#{Workarea::Kount::VERSION}.gem"
|
51
|
+
system "gem push workarea-kount-#{Workarea::Kount::VERSION}.gem --host #{host}"
|
52
|
+
system "rm workarea-kount-#{Workarea::Kount::VERSION}.gem"
|
53
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Storefront::Checkout::PlaceOrderController, with: :kount do
|
3
|
+
def try_place_order
|
4
|
+
if current_checkout.place_order || current_checkout.handle_kount_review
|
5
|
+
completed_place_order
|
6
|
+
else
|
7
|
+
incomplete_place_order
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
class KountController < Workarea::Storefront::ApplicationController
|
4
|
+
def data_collector
|
5
|
+
current_order.update_attributes(kount_session_id: kount_session_id)
|
6
|
+
|
7
|
+
params = { merchant_id: Workarea::Kount.merchant_id, s: kount_session_id }
|
8
|
+
|
9
|
+
redirect_to "#{Workarea::Kount.data_collector_url}logo.htm?#{params.to_query}", status: 302
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def kount_session_id
|
15
|
+
@kount_session_id ||= "#{current_order.id}#{Time.now.to_i}R#{rand(10000..99999)}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
class KountOrdersController < ApplicationController
|
4
|
+
skip_before_action :verify_authenticity_token, only: [:bulk]
|
5
|
+
before_action :authenticate
|
6
|
+
|
7
|
+
def bulk
|
8
|
+
event_batch = Kount::EventBatch.new(request.raw_post)
|
9
|
+
|
10
|
+
if event_batch.valid?
|
11
|
+
event_batch.process!
|
12
|
+
successful_response
|
13
|
+
else
|
14
|
+
unsuccessful_response
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def authenticate
|
21
|
+
authenticated = authenticate_with_http_basic do |username, password|
|
22
|
+
Kount.credentials[:ens_username].present? &&
|
23
|
+
Kount.credentials[:ens_password].present? &&
|
24
|
+
username == Kount.credentials[:ens_username] &&
|
25
|
+
password == Kount.credentials[:ens_password]
|
26
|
+
end
|
27
|
+
|
28
|
+
unsuccessful_response unless authenticated
|
29
|
+
end
|
30
|
+
|
31
|
+
def successful_response
|
32
|
+
render json: { status: 200 }
|
33
|
+
end
|
34
|
+
|
35
|
+
def unsuccessful_response
|
36
|
+
head :bad_request
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Storefront::OrderMailer, with: :kount do
|
3
|
+
def hold_denial(order_id)
|
4
|
+
order = Order.find(order_id)
|
5
|
+
@order = Storefront::OrderViewModel.new(order)
|
6
|
+
@recommendations = Storefront::EmailRecommendationsViewModel.wrap(order)
|
7
|
+
|
8
|
+
mail(
|
9
|
+
to: @order.email,
|
10
|
+
subject: t('workarea.storefront.email.hold_denial.subject', order_id: @order.id)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Checkout, with: :kount do
|
3
|
+
def handle_kount_review
|
4
|
+
return false unless order.under_review?
|
5
|
+
return false unless complete?
|
6
|
+
return false unless shippable?
|
7
|
+
return false unless payable?
|
8
|
+
|
9
|
+
inventory.purchase
|
10
|
+
return false unless inventory.captured?
|
11
|
+
|
12
|
+
return true unless payment.uses_credit_card?
|
13
|
+
store_credit_card
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_kount_approved
|
17
|
+
unless payment_collection.purchase
|
18
|
+
captured_inventory&.rollback
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
result = order.place
|
23
|
+
place_order_side_effects if result
|
24
|
+
result
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def captured_inventory
|
30
|
+
@captured_inventory ||= Inventory::Transaction.captured_for_order(order.id)
|
31
|
+
end
|
32
|
+
|
33
|
+
def store_credit_card
|
34
|
+
Payment::StoreCreditCard.new(payment.credit_card).save!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Workarea
|
4
|
+
class Checkout
|
5
|
+
module Fraud
|
6
|
+
class KountAnalyzer < Analyzer
|
7
|
+
# This is the `:mode` value used in the RIS Inquiry request to
|
8
|
+
# Kount. It tells Kount that this is a new order, and not an
|
9
|
+
# update to an existing order as used in the updater service
|
10
|
+
# class.
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
MODE_Q = 'Q'
|
14
|
+
|
15
|
+
delegate :gateway, to: Workarea::Kount
|
16
|
+
delegate :kount_mode, :kount_request_user_defined_fields, to: :checkout
|
17
|
+
delegate :decision, to: :kount_response
|
18
|
+
|
19
|
+
# Tell Kount about the order and record its response.
|
20
|
+
#
|
21
|
+
# @return [Workarea::Order::FraudDecision]
|
22
|
+
def make_decision
|
23
|
+
kount_order.update_attributes!(response: kount_response)
|
24
|
+
|
25
|
+
Workarea::Order::FraudDecision.new(
|
26
|
+
decision: decision,
|
27
|
+
message: message
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Data for this Order from Kount.
|
32
|
+
#
|
33
|
+
# @return [Workarea::Kount::Order]
|
34
|
+
def kount_order
|
35
|
+
@kount_order ||= Workarea::Kount::Order.find_or_initialize_by(id: order.id)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Build the RIS inquiry request.
|
41
|
+
#
|
42
|
+
# @private
|
43
|
+
# @return [Hash]
|
44
|
+
def inquiry
|
45
|
+
Workarea::Kount::RisInquiry.new(
|
46
|
+
order: order,
|
47
|
+
payment: payment,
|
48
|
+
shippings: shippings,
|
49
|
+
mode: MODE_Q
|
50
|
+
).to_h
|
51
|
+
end
|
52
|
+
|
53
|
+
# Response for the Kount RIS inquiry request.
|
54
|
+
#
|
55
|
+
# @private
|
56
|
+
# @return [Workarea::Kount::Response]
|
57
|
+
def kount_response
|
58
|
+
@kount_response ||= gateway.call(inquiry)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Translated message for the Kount decision.
|
62
|
+
#
|
63
|
+
# @private
|
64
|
+
# @return [String]
|
65
|
+
def message
|
66
|
+
I18n.t(decision, scope: 'workarea.storefront.fraud.kount')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Kount
|
3
|
+
class Order
|
4
|
+
include ApplicationDocument
|
5
|
+
|
6
|
+
field :response, type: Workarea::Kount::Response
|
7
|
+
field :update_response, type: Workarea::Kount::Response
|
8
|
+
|
9
|
+
embeds_many :ens_events, class_name: 'Workarea::Kount::EnsEvent'
|
10
|
+
|
11
|
+
index(created_at: -1)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Workarea
|
2
|
+
decorate Order, with: :kount do
|
3
|
+
decorated do
|
4
|
+
field :kount_session_id, type: String
|
5
|
+
field :kount_decision, type: Symbol
|
6
|
+
|
7
|
+
scope :not_under_review, -> { where(:kount_decision.ne => :review) }
|
8
|
+
|
9
|
+
before_save :set_kount_decision, if: :fraud_decision?
|
10
|
+
end
|
11
|
+
|
12
|
+
class_methods do
|
13
|
+
# Query for orders which have expired in checkout, meaning they have been
|
14
|
+
# not been placed or updated for longer than the
|
15
|
+
# +Workarea.config.order_expiration_period+, but have started
|
16
|
+
# checkout. Contrast this with +Order.expired+, which does not
|
17
|
+
# factor in orders that have started checkout.
|
18
|
+
#
|
19
|
+
# Doesn't include orders under review or declined by kount
|
20
|
+
#
|
21
|
+
# @return [Mongoid::Criteria]
|
22
|
+
def expired_in_checkout
|
23
|
+
super.nin(kount_decision: [:review, :decline])
|
24
|
+
end
|
25
|
+
|
26
|
+
# Overriding method from core/models/order/queries.rb module
|
27
|
+
def need_reminding
|
28
|
+
super.where(kount_decision: nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Find a current cart for a session. Returns a new order if one cannot be found.
|
32
|
+
#
|
33
|
+
# @param params [Hash]
|
34
|
+
# @return [Order]
|
35
|
+
#
|
36
|
+
def find_current(params = {})
|
37
|
+
if params[:id].present?
|
38
|
+
Order.not_placed.not_under_review.find(params[:id].to_s)
|
39
|
+
elsif params[:user_id].present?
|
40
|
+
Order.recently_updated.not_placed.not_under_review.find_by(params.slice(:user_id))
|
41
|
+
else
|
42
|
+
Order.new(user_id: params[:user_id])
|
43
|
+
end
|
44
|
+
rescue Mongoid::Errors::DocumentNotFound
|
45
|
+
Order.new(user_id: params[:user_id])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Whether the FraudDecision#decision is `:review`.
|
50
|
+
def under_review?
|
51
|
+
!placed? && !canceled? && kount_decision == :review
|
52
|
+
end
|
53
|
+
|
54
|
+
def abandoned?
|
55
|
+
super && kount_decision.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_kount_decision
|
59
|
+
self.kount_decision = fraud_decision.decision
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|