minfraud 1.4.0 → 2.0.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +7 -0
  3. data/.github/workflows/rubocop.yml +1 -1
  4. data/.github/workflows/test.yml +1 -4
  5. data/.rubocop.yml +4 -25
  6. data/CHANGELOG.md +82 -1
  7. data/Gemfile +0 -9
  8. data/LICENSE.txt +1 -1
  9. data/README.dev.md +1 -1
  10. data/README.md +13 -12
  11. data/lib/minfraud/assessments.rb +21 -16
  12. data/lib/minfraud/components/account.rb +1 -1
  13. data/lib/minfraud/components/billing.rb +1 -1
  14. data/lib/minfraud/components/credit_card.rb +21 -9
  15. data/lib/minfraud/components/custom_inputs.rb +1 -1
  16. data/lib/minfraud/components/device.rb +1 -1
  17. data/lib/minfraud/components/email.rb +93 -4
  18. data/lib/minfraud/components/event.rb +11 -11
  19. data/lib/minfraud/components/order.rb +1 -1
  20. data/lib/minfraud/components/payment.rb +152 -133
  21. data/lib/minfraud/components/report/transaction.rb +2 -2
  22. data/lib/minfraud/components/shipping.rb +2 -2
  23. data/lib/minfraud/components/shopping_cart.rb +2 -2
  24. data/lib/minfraud/components/shopping_cart_item.rb +3 -3
  25. data/lib/minfraud/http_service/response.rb +28 -21
  26. data/lib/minfraud/model/device.rb +1 -1
  27. data/lib/minfraud/model/disposition.rb +13 -6
  28. data/lib/minfraud/model/ip_address.rb +20 -44
  29. data/lib/minfraud/model/ip_risk_reason.rb +48 -0
  30. data/lib/minfraud/model/score.rb +1 -1
  31. data/lib/minfraud/model/subscores.rb +0 -22
  32. data/lib/minfraud/report.rb +19 -11
  33. data/lib/minfraud/validates.rb +2 -2
  34. data/lib/minfraud/version.rb +1 -1
  35. data/lib/minfraud.rb +18 -24
  36. data/minfraud.gemspec +10 -6
  37. metadata +40 -51
  38. data/lib/maxmind/geoip2/model/city.rb +0 -99
  39. data/lib/maxmind/geoip2/model/country.rb +0 -94
  40. data/lib/maxmind/geoip2/model/insights.rb +0 -38
  41. data/lib/maxmind/geoip2/record/abstract.rb +0 -46
  42. data/lib/maxmind/geoip2/record/city.rb +0 -62
  43. data/lib/maxmind/geoip2/record/continent.rb +0 -61
  44. data/lib/maxmind/geoip2/record/country.rb +0 -78
  45. data/lib/maxmind/geoip2/record/location.rb +0 -97
  46. data/lib/maxmind/geoip2/record/maxmind.rb +0 -41
  47. data/lib/maxmind/geoip2/record/place.rb +0 -52
  48. data/lib/maxmind/geoip2/record/postal.rb +0 -54
  49. data/lib/maxmind/geoip2/record/represented_country.rb +0 -47
  50. data/lib/maxmind/geoip2/record/subdivision.rb +0 -72
  51. data/lib/maxmind/geoip2/record/traits.rb +0 -233
  52. data/lib/minfraud/http_service/request.rb +0 -38
  53. data/lib/minfraud/http_service.rb +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b1e4e92365857b6d5d5be13e1d31a863b4c89bc9b845df4e54faebd0ffd4104
4
- data.tar.gz: 0d320caef5e7ce0bbb751c1d5a7e1ec60c6c0d97d4d683649c19c84e16b2b733
3
+ metadata.gz: 4e3c2e76357a683ceda7350bde7dc4c89cc6055d473b771ee74041d4371f05f7
4
+ data.tar.gz: 60aacbf2435a51f65c9d9702e209ddab469d21dd672ba8d5baf34dae807deb2f
5
5
  SHA512:
6
- metadata.gz: 2fd31f60de5693ec4248852f4bbd8c73d5e5e86cadc6648028b3fcac794c4e66fd4b1a002eef8e24bffdc4a3100cd14965a093f9e1c0bfaacfd220611087708f
7
- data.tar.gz: c183a0bd27ad2710f34e04b33f3a0e46f8abfbd573faafdbbcdbc8533a634a59e111d59fc14b23c7984da4ee5af1911b6a4c7f70a103ae8a7bc9448ca3f162de
6
+ metadata.gz: ebdccdbdb2d97665faabbf8486cdeb029e1a1d372a09a1ffeff226f5f900d99887e6e370e01515543983c46f86d4083fa347e557d82c5dde265b079e055adddc
7
+ data.tar.gz: 61f65f9cc64dd1e0c205c5c2f8df5acfb621dc1ae80b828d5df27e0616964ac0c0a1315b609a4a3228b1f9ecce78dd31411b66513c25eb4311532b3b9f71d775
@@ -0,0 +1,7 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ open-pull-requests-limit: 10
@@ -7,6 +7,6 @@ jobs:
7
7
  - uses: actions/checkout@v2
8
8
  - uses: ruby/setup-ruby@v1
9
9
  with:
10
- ruby-version: 2.7
10
+ ruby-version: '3.0'
11
11
  - run: bundle install
12
12
  - run: bundle exec rake -t rubocop
@@ -9,13 +9,10 @@ jobs:
9
9
  os: [ubuntu-latest, windows-latest, macos-latest]
10
10
  version:
11
11
  [
12
- 2.1,
13
- 2.2,
14
- 2.3,
15
- 2.4,
16
12
  2.5,
17
13
  2.6,
18
14
  2.7,
15
+ '3.0',
19
16
  jruby,
20
17
  ]
21
18
  exclude:
data/.rubocop.yml CHANGED
@@ -1,5 +1,6 @@
1
- Gemspec/RequiredRubyVersion:
2
- Enabled: false # We support 2.1+, but rubocop supports 2.4+.
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+ NewCops: enable
3
4
 
4
5
  # Metrics.
5
6
 
@@ -39,7 +40,7 @@ Layout/IndentationStyle:
39
40
  # Style.
40
41
 
41
42
  Style/HashSyntax:
42
- EnforcedStyle: ruby19_no_mixed_keys # Default is ruby19.
43
+ EnforcedStyle: ruby19_no_mixed_keys # Default is ruby19. This one is better.
43
44
 
44
45
  Style/CollectionMethods:
45
46
  Enabled: true # Default is false.
@@ -53,9 +54,6 @@ Style/NegatedIf: # I disagree with this.
53
54
  Style/IfUnlessModifier: # This doesn't always make sense.
54
55
  Enabled: false
55
56
 
56
- Style/SymbolArray:
57
- EnforcedStyle: brackets # Default is percent, but 1.9 doesn't support that.
58
-
59
57
  # Trailing commas are often good.
60
58
  Style/TrailingCommaInArguments:
61
59
  Enabled: false
@@ -64,9 +62,6 @@ Style/TrailingCommaInArrayLiteral:
64
62
  Style/TrailingCommaInHashLiteral:
65
63
  Enabled: false
66
64
 
67
- Style/SafeNavigation:
68
- Enabled: false # Default is true, but this 1.9 doesn't support it.
69
-
70
65
  # Default is both which is probably fine, but it changes code and I don't want
71
66
  # to investigate any possible behavior change right now.
72
67
  Style/EmptyElse:
@@ -75,25 +70,12 @@ Style/EmptyElse:
75
70
  Style/ConditionalAssignment:
76
71
  Enabled: false # This produces kind of strange results.
77
72
 
78
- Style/Dir:
79
- Enabled: false # This is good, but not supported on 1.9.
80
-
81
- Style/ExpandPathArguments:
82
- Enabled: false # This causes us to use __dir__ which 1.9 doesn't support.
83
-
84
73
  Style/GuardClause:
85
74
  Enabled: false # Doesn't always make sense.
86
75
 
87
- Style/Documentation:
88
- Enabled: false # We should enable this, but allow for pre-existing code.
89
-
90
76
  Style/FormatStringToken:
91
77
  Enabled: false # Seems unnecessary.
92
78
 
93
- # Asks to use x.negative? instead of x < 0. But this isn't available until 2.3.
94
- Style/NumericPredicate:
95
- Enabled: false
96
-
97
79
  # Seems unnecessary. Asks us to call super in a bunch of places when there's no
98
80
  # need.
99
81
  Lint/MissingSuper:
@@ -103,6 +85,3 @@ Lint/MissingSuper:
103
85
 
104
86
  Naming/VariableNumber:
105
87
  Enabled: false # Doesn't always make sense.
106
-
107
- AllCops:
108
- NewCops: enable
data/CHANGELOG.md CHANGED
@@ -1,4 +1,84 @@
1
- # Minfraud Changelog
1
+ # Changelog
2
+
3
+ ## v2.0.0 (2021-12-06)
4
+
5
+ * Breaking change from 1.x: Removed deprecated methods
6
+ `is_in_european_union`, `is_anonymous`, `is_anonymous_vpn`,
7
+ `is_hosting_provider`, `is_public_proxy`, and `is_tor_exit_node`. The
8
+ non-deprecated equivalents are `in_european_union?`, `anonymous?`,
9
+ `anonymous_vpn?`, `hosting_provider?`, `public_proxy?`, and
10
+ `tor_exit_node?`.
11
+ * Breaking change from 1.x: Removed deprecated methods for deprecated
12
+ subscores: `email_tenure` and `ip_tenure`. For `email_tenure`, please use
13
+ the `email_address` subscore instead. For `ip_tenure`, please use
14
+ `risk_score` instead.
15
+ * Breaking change from 1.x: Removed deprecated method for deprecated
16
+ attribute `ip_address.country.is_high_risk`.
17
+ * Breaking change from 1.x: Switches HTTP client from faraday to http.rb.
18
+ There should be no behavior change for most users, but this is
19
+ technically a breaking change from the perspective of semver. Most users
20
+ should not be affected as the changes are limited to attributes and
21
+ classes that would not normally be accessed outside the gem.
22
+ * Breaking change from 1.x: `user_id` is no longer supported as a way to
23
+ configure your MaxMind account ID. Use `account_id` instead.
24
+ * Breaking change from 1.x: Removed the `Minfraud.configuration` method.
25
+ * Breaking change from 1.x: Localized names are no longer exposed via
26
+ methods on `names` objects, only as hash keys. For example, use
27
+ `response.ip_address.country.names['en']` instead of
28
+ `response.ip_address.country.names.en`. The latter was deprecated.
29
+ * Adds mobile country code (MCC) and mobile network code (MNC) to minFraud
30
+ Insights and Factors responses. These are available at
31
+ `response.ip_address.traits.mobile_country_code` and
32
+ `response.ip_address.traits.mobile_network_code`. We expect this data to
33
+ be available by late January, 2022.
34
+ * Adds the following new processors to `Minfraud::Components::Payment`:
35
+ * `:boacompra`
36
+ * `:boku`
37
+ * `:coregateway`
38
+ * `:fiserv`
39
+ * `:neopay`
40
+ * `:neosurf`
41
+ * `:openbucks`
42
+ * `:paysera`
43
+ * `:payvision`
44
+ * `:trustly`
45
+ * Depend on the `maxmind-geoip2` gem. This allows us to delete classes from
46
+ that gem that we previously had included in this gem. There is no
47
+ functional difference.
48
+
49
+ ## v1.6.0 (2021-08-19)
50
+
51
+ * Adds new processor to `Minfraud::Components::Payment`: `:cardknox`,
52
+ `:creditguard`, `:credorax`, `:datacap`, `:dlocal`, `:onpay`, and
53
+ `:safecharge`.
54
+ * Adds `rule_label` to minFraud output `/disposition`.
55
+ * Adds support for the `/credit_card/was_3d_secure_successful` input. This is
56
+ available by setting the `was_3d_secure_successful` attribute on
57
+ `Minfraud::Components::CreditCard`.
58
+ * Ruby 2.5+ is now required. If you're using Ruby 2.1, 2.2, 2.3, or 2.4,
59
+ please use version 1.5.0 of this gem.
60
+
61
+ ## v1.5.0 (2021-02-02)
62
+
63
+ * Add the `hash_address` attribute to `Minfraud::Components::Email`. If
64
+ this is `true`, the MD5 hash of the `address` will be sent instead of the
65
+ plain text `address`. Use this if you prefer to send the hash of the
66
+ `address` rather than the plain text. Note that this normalizes the
67
+ `address`, so we recommend using it as opposed to hashing the `address`
68
+ manually.
69
+ * The email `domain` input is now automatically set if the email `address`
70
+ input is set but the `domain` is not.
71
+ * Adds new payment processors `:apple_pay` and `:aps_payments` to
72
+ `Minfraud::Components::Payment`.
73
+ * Added support for the IP address risk reasons in the minFraud Insights
74
+ and Factors responses. This is available at `.ip_address.risk_reasons`.
75
+ It is an array of `IPRiskReason` objects.
76
+
77
+ ## v1.4.1 (2020-12-01)
78
+
79
+ * Do not throw an exception if the response does not include IP address
80
+ information. Previously we would incorrectly try to retrieve fields from
81
+ `nil`, leading to a `NoMethodError`.
2
82
 
3
83
  ## v1.4.0 (2020-10-13)
4
84
 
@@ -69,6 +149,7 @@
69
149
  * Adds `amount` attribute to the `Minfraud::Components::Order` instances
70
150
 
71
151
  ## v1.0.3 (2016-11-24)
152
+
72
153
  * Adds `token` attribute to the `Minfraud::Components::CreditCard` instances
73
154
  according to the MinFraud Release Notes introduced on November 17, 2016
74
155
 
data/Gemfile CHANGED
@@ -2,13 +2,4 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- # coveralls fails on Ruby 1.9. My understanding is we don't need to run this on
6
- # more than one version anyway, so restrict to the current latest.
7
- version_pieces = RUBY_VERSION.split('.')
8
- major_version = version_pieces[0]
9
- minor_version = version_pieces[1]
10
- if major_version == '2' && minor_version == '7'
11
- gem 'coveralls', require: false
12
- end
13
-
14
5
  gemspec
data/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  The MIT License (MIT)
2
2
 
3
3
  Copyright (c) 2016-2020 kushnir.yb
4
- Copyright (c) 2020 MaxMind, Inc.
4
+ Copyright (c) 2020-2021 MaxMind, Inc.
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
data/README.dev.md CHANGED
@@ -1,4 +1,4 @@
1
1
  # How to release
2
2
 
3
3
  See
4
- [here](https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/master/README.dev.md).
4
+ [here](https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/main/README.dev.md).
data/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  ## Description
4
4
 
5
5
  This package provides an API for the [MaxMind minFraud web
6
- services](https://dev.maxmind.com/minfraud/). This includes minFraud Score,
6
+ services](https://dev.maxmind.com/minfraud?lang=en). This includes minFraud Score,
7
7
  Insights, and Factors. It also includes our [minFraud Report Transaction
8
- API](https://dev.maxmind.com/minfraud/report-transaction/).
8
+ API](https://dev.maxmind.com/minfraud/report-a-transaction?lang=en).
9
9
 
10
10
  The legacy minFraud Standard and Premium services are not supported by this
11
11
  API.
@@ -122,14 +122,15 @@ assessment = Minfraud::Assessments.new(
122
122
  decline_code: 'invalid number',
123
123
  },
124
124
  credit_card: {
125
- issuer_id_number: '411111',
126
- last_4_digits: '7643',
127
- bank_name: 'Bank of No Hope',
128
- bank_phone_country_code: '1',
129
- bank_phone_number: '123-456-1234',
130
- token: 'abcd',
131
- avs_result: 'Y',
132
- cvv_result: 'N',
125
+ issuer_id_number: '411111',
126
+ last_4_digits: '7643',
127
+ bank_name: 'Bank of No Hope',
128
+ bank_phone_country_code: '1',
129
+ bank_phone_number: '123-456-1234',
130
+ token: 'abcd',
131
+ avs_result: 'Y',
132
+ cvv_result: 'N',
133
+ was_3d_secure_successful: true,
133
134
  },
134
135
  order: {
135
136
  amount: 323.21,
@@ -264,7 +265,7 @@ to the client API, please see
264
265
 
265
266
  ## Requirements
266
267
 
267
- This gem works with Ruby 2.1 and above.
268
+ This gem works with Ruby 2.5 and above.
268
269
 
269
270
  ## Contributing
270
271
 
@@ -282,7 +283,7 @@ This API uses [Semantic Versioning](https://semver.org/).
282
283
 
283
284
  Copyright (c) 2016-2020 kushnir.yb.
284
285
 
285
- Copyright (c) 2020 MaxMind, Inc.
286
+ Copyright (c) 2020-2021 MaxMind, Inc.
286
287
 
287
288
  The gem is available as open source under the terms of the [MIT
288
289
  License](https://opensource.org/licenses/MIT).
@@ -4,9 +4,8 @@ module Minfraud
4
4
  # Assessments is used to perform minFraud Score, Insights, and Factors
5
5
  # requests.
6
6
  #
7
- # @see https://dev.maxmind.com/minfraud/
7
+ # @see https://dev.maxmind.com/minfraud?lang=en
8
8
  class Assessments
9
- include ::Minfraud::HTTPService
10
9
  include ::Minfraud::Resolver
11
10
 
12
11
  # The Account component.
@@ -82,6 +81,8 @@ module Minfraud
82
81
  #
83
82
  # @return [Minfraud::HTTPService::Response]
84
83
  #
84
+ # @raise [JSON::ParserError] if there was invalid JSON in the response.
85
+ #
85
86
  # @raise [Minfraud::AuthorizationError] If there was an authentication
86
87
  # problem.
87
88
  #
@@ -98,6 +99,8 @@ module Minfraud
98
99
  #
99
100
  # @return [Minfraud::HTTPService::Response]
100
101
  #
102
+ # @raise [JSON::ParserError] if there was invalid JSON in the response.
103
+ #
101
104
  # @raise [Minfraud::AuthorizationError] If there was an authentication
102
105
  # problem.
103
106
  #
@@ -114,6 +117,8 @@ module Minfraud
114
117
  #
115
118
  # @return [Minfraud::HTTPService::Response]
116
119
  #
120
+ # @raise [JSON::ParserError] if there was invalid JSON in the response.
121
+ #
117
122
  # @raise [Minfraud::AuthorizationError] If there was an authentication
118
123
  # problem.
119
124
  #
@@ -129,18 +134,22 @@ module Minfraud
129
134
  private
130
135
 
131
136
  def perform_request(endpoint)
132
- raw = request.perform(
133
- verb: :post,
134
- endpoint: endpoint.to_s,
135
- body: request_body,
136
- )
137
+ response = nil
138
+ body = nil
139
+ Minfraud.connection_pool.with do |client|
140
+ response = client.post(
141
+ "/minfraud/v2.0/#{endpoint}",
142
+ json: request_body,
143
+ )
144
+
145
+ body = response.to_s
146
+ end
137
147
 
138
148
  response = ::Minfraud::HTTPService::Response.new(
139
- endpoint: endpoint,
140
- locales: @locales,
141
- status: raw.status.to_i,
142
- body: raw.body,
143
- headers: raw.headers
149
+ endpoint,
150
+ @locales,
151
+ response,
152
+ body,
144
153
  )
145
154
 
146
155
  ::Minfraud::ErrorHandler.examine(response)
@@ -153,9 +162,5 @@ module Minfraud
153
162
  mem.merge!(e.to_s => value.to_json)
154
163
  end
155
164
  end
156
-
157
- def request
158
- @request ||= Request.new(::Minfraud::HTTPService.configuration)
159
- end
160
165
  end
161
166
  end
@@ -4,7 +4,7 @@ module Minfraud
4
4
  module Components
5
5
  # Account corresponds to the account object of a minFraud request.
6
6
  #
7
- # @see https://dev.maxmind.com/minfraud/#Account_(/account)
7
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--account
8
8
  class Account < Base
9
9
  include Minfraud::Validates
10
10
 
@@ -4,7 +4,7 @@ module Minfraud
4
4
  module Components
5
5
  # Billing corresponds to the billing object of a minFraud request.
6
6
  #
7
- # @see https://dev.maxmind.com/minfraud/#Billing_(/billing)
7
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--billing
8
8
  class Billing < Addressable; end
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ module Minfraud
4
4
  module Components
5
5
  # CreditCard corresponds to the credit_card object of a minFraud request.
6
6
  #
7
- # @see https://dev.maxmind.com/minfraud/#Credit_Card_(/creditcard)
7
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--credit-card
8
8
  class CreditCard < Base
9
9
  include Minfraud::Validates
10
10
 
@@ -62,17 +62,28 @@ module Minfraud
62
62
  # @return [String, nil]
63
63
  attr_accessor :cvv_result
64
64
 
65
+ # Whether the outcome of 3-D Secure verification (e.g. Safekey,
66
+ # SecureCode, Verified by Visa) was successful. +true+ if customer
67
+ # verification was successful, or +false+ if the customer failed
68
+ # verification. If 3-D Secure verification was not used, was unavailable,
69
+ # or resulted in an outcome other than success or failure, do not
70
+ # include this field.
71
+ #
72
+ # @return [Boolean, nil]
73
+ attr_accessor :was_3d_secure_successful
74
+
65
75
  # @param params [Hash] Hash of parameters. Each key/value should
66
76
  # correspond to one of the available attributes.
67
77
  def initialize(params = {})
68
- @bank_phone_country_code = params[:bank_phone_country_code]
69
- @issuer_id_number = params[:issuer_id_number]
70
- @last_4_digits = params[:last_4_digits]
71
- @bank_name = params[:bank_name]
72
- @bank_phone_number = params[:bank_phone_number]
73
- @avs_result = params[:avs_result]
74
- @cvv_result = params[:cvv_result]
75
- @token = params[:token]
78
+ @bank_phone_country_code = params[:bank_phone_country_code]
79
+ @issuer_id_number = params[:issuer_id_number]
80
+ @last_4_digits = params[:last_4_digits]
81
+ @bank_name = params[:bank_name]
82
+ @bank_phone_number = params[:bank_phone_number]
83
+ @avs_result = params[:avs_result]
84
+ @cvv_result = params[:cvv_result]
85
+ @token = params[:token]
86
+ @was_3d_secure_successful = params[:was_3d_secure_successful]
76
87
 
77
88
  validate
78
89
  end
@@ -90,6 +101,7 @@ module Minfraud
90
101
  validate_string('avs_result', 1, @avs_result)
91
102
  validate_string('cvv_result', 1, @cvv_result)
92
103
  validate_credit_card_token('token', @token)
104
+ validate_boolean('was_3d_secure_successful', @was_3d_secure_successful)
93
105
  end
94
106
  end
95
107
  end
@@ -5,7 +5,7 @@ module Minfraud
5
5
  # CustomInputs corresponds to the custom_inputs object of a minFraud
6
6
  # request.
7
7
  #
8
- # @see https://dev.maxmind.com/minfraud/#Custom_Inputs_(/custominputs)
8
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--custom-inputs
9
9
  class CustomInputs < Base
10
10
  include Minfraud::Validates
11
11
 
@@ -4,7 +4,7 @@ module Minfraud
4
4
  module Components
5
5
  # Device corresponds to the device object of a minFraud request.
6
6
  #
7
- # @see https://dev.maxmind.com/minfraud/#Device_(/device)
7
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--device
8
8
  class Device < Base
9
9
  include Minfraud::Validates
10
10
 
@@ -1,17 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'digest/md5'
4
+ require 'simpleidn'
5
+
3
6
  module Minfraud
4
7
  module Components
5
8
  # Email corresponds to the email object of a minFraud request.
6
9
  #
7
- # @see https://dev.maxmind.com/minfraud/#Email_(/email)
10
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--email
8
11
  class Email < Base
9
12
  include Minfraud::Validates
10
13
 
11
14
  # This field must be either be a valid email address or an MD5 of the
12
15
  # lowercased email used in the transaction. Important: if using the MD5
13
16
  # hash, please be sure to convert the email address to lowercase before
14
- # calculating its MD5 hash.
17
+ # calculating its MD5 hash. Instead of converting an address to an MD5
18
+ # hash yourself, please use the hash_address attribute in this class.
15
19
  #
16
20
  # @return [String, nil]
17
21
  attr_accessor :address
@@ -21,15 +25,46 @@ module Minfraud
21
25
  # @return [String, nil]
22
26
  attr_accessor :domain
23
27
 
28
+ # By default, the address will be sent in plain text. If this is set
29
+ # true, the address will instead be sent as an MD5 hash.
30
+ #
31
+ # @return [Boolean, nil]
32
+ attr_accessor :hash_address
33
+
24
34
  # @param params [Hash] Hash of parameters. Each key/value should
25
35
  # correspond to one of the available attributes.
26
36
  def initialize(params = {})
27
- @address = params[:address]
28
- @domain = params[:domain]
37
+ @address = params[:address]
38
+ @domain = params[:domain]
39
+ @hash_address = params[:hash_address]
29
40
 
30
41
  validate
31
42
  end
32
43
 
44
+ # A JSON representation of Minfraud::Components::Email.
45
+ #
46
+ # @return [Hash]
47
+ def to_json(*_args)
48
+ json = super
49
+
50
+ if json['address'] && !json['domain']
51
+ _, domain = address.split('@', 2)
52
+ if domain
53
+ domain = clean_domain(domain)
54
+ json['domain'] = domain if domain
55
+ end
56
+ end
57
+
58
+ if json.delete('hash_address') && json['address']
59
+ hash = hash_email_address(json['address'])
60
+
61
+ # We could consider clearing the key if !hash.
62
+ json['address'] = hash if hash
63
+ end
64
+
65
+ json
66
+ end
67
+
33
68
  private
34
69
 
35
70
  def validate
@@ -38,6 +73,60 @@ module Minfraud
38
73
  validate_email('email', @address)
39
74
  validate_string('domain', 255, @domain)
40
75
  end
76
+
77
+ def hash_email_address(address)
78
+ address = clean_email_address(address)
79
+ return nil if !address
80
+
81
+ Digest::MD5.hexdigest(address)
82
+ end
83
+
84
+ def clean_email_address(address)
85
+ address = address.strip
86
+ address.downcase!
87
+
88
+ local_part, domain = address.split('@', 2)
89
+ return nil if !local_part || !domain
90
+
91
+ domain = clean_domain(domain)
92
+
93
+ if domain == 'yahoo.com'
94
+ local_part.sub!(/\A([^-]+)-.*\z/, '\1')
95
+ else
96
+ local_part.sub!(/\A([^+]+)\+.*\z/, '\1')
97
+ end
98
+
99
+ "#{local_part}@#{domain}"
100
+ end
101
+
102
+ TYPO_DOMAINS = {
103
+ # gmail.com
104
+ '35gmai.com' => 'gmail.com',
105
+ '636gmail.com' => 'gmail.com',
106
+ 'gamil.com' => 'gmail.com',
107
+ 'gmail.comu' => 'gmail.com',
108
+ 'gmial.com' => 'gmail.com',
109
+ 'gmil.com' => 'gmail.com',
110
+ 'yahoogmail.com' => 'gmail.com',
111
+ # outlook.com
112
+ 'putlook.com' => 'outlook.com',
113
+ }.freeze
114
+ private_constant :TYPO_DOMAINS
115
+
116
+ def clean_domain(domain)
117
+ domain = domain.strip
118
+
119
+ # We could use delete_suffix!, but that is in Ruby 2.5+ only.
120
+ domain.sub!(/\.\z/, '')
121
+
122
+ domain = SimpleIDN.to_ascii(domain)
123
+
124
+ if TYPO_DOMAINS.key?(domain)
125
+ domain = TYPO_DOMAINS[domain]
126
+ end
127
+
128
+ domain
129
+ end
41
130
  end
42
131
  end
43
132
  end
@@ -4,7 +4,7 @@ module Minfraud
4
4
  module Components
5
5
  # Event corresponds to the event object of a minFraud request.
6
6
  #
7
- # @see https://dev.maxmind.com/minfraud/#Event_(/event)
7
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--event
8
8
  class Event < Base
9
9
  include ::Minfraud::Enum
10
10
  include Minfraud::Validates
@@ -43,16 +43,16 @@ module Minfraud
43
43
  #
44
44
  # @return [Symbol, nil]
45
45
  enum_accessor :type,
46
- [
47
- :account_creation,
48
- :account_login,
49
- :email_change,
50
- :password_reset,
51
- :payout_change,
52
- :purchase,
53
- :recurring_purchase,
54
- :referral,
55
- :survey,
46
+ %i[
47
+ account_creation
48
+ account_login
49
+ email_change
50
+ password_reset
51
+ payout_change
52
+ purchase
53
+ recurring_purchase
54
+ referral
55
+ survey
56
56
  ]
57
57
 
58
58
  # @param params [Hash] Hash of parameters. Each key/value should
@@ -4,7 +4,7 @@ module Minfraud
4
4
  module Components
5
5
  # Order corresponds to the order object of a minFraud request.
6
6
  #
7
- # @see https://dev.maxmind.com/minfraud/#Order_(/order)
7
+ # @see https://dev.maxmind.com/minfraud/api-documentation/requests?lang=en#schema--request--order
8
8
  class Order < Base
9
9
  include Minfraud::Validates
10
10