minfraud 1.0.2 → 1.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.
Files changed (75) hide show
  1. checksums.yaml +5 -13
  2. data/.github/workflows/test.yml +46 -0
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +108 -0
  5. data/.travis.yml +19 -3
  6. data/CHANGELOG.md +65 -1
  7. data/CODE_OF_CONDUCT.md +4 -4
  8. data/Gemfile +11 -2
  9. data/LICENSE.txt +2 -1
  10. data/README.dev.md +4 -0
  11. data/README.md +245 -59
  12. data/Rakefile +18 -3
  13. data/bin/console +4 -3
  14. data/lib/maxmind/geoip2/model/city.rb +99 -0
  15. data/lib/maxmind/geoip2/model/country.rb +94 -0
  16. data/lib/maxmind/geoip2/model/insights.rb +38 -0
  17. data/lib/maxmind/geoip2/record/abstract.rb +46 -0
  18. data/lib/maxmind/geoip2/record/city.rb +62 -0
  19. data/lib/maxmind/geoip2/record/continent.rb +61 -0
  20. data/lib/maxmind/geoip2/record/country.rb +78 -0
  21. data/lib/maxmind/geoip2/record/location.rb +97 -0
  22. data/lib/maxmind/geoip2/record/maxmind.rb +41 -0
  23. data/lib/maxmind/geoip2/record/place.rb +52 -0
  24. data/lib/maxmind/geoip2/record/postal.rb +54 -0
  25. data/lib/maxmind/geoip2/record/represented_country.rb +47 -0
  26. data/lib/maxmind/geoip2/record/subdivision.rb +72 -0
  27. data/lib/maxmind/geoip2/record/traits.rb +233 -0
  28. data/lib/minfraud.rb +48 -8
  29. data/lib/minfraud/assessments.rb +118 -49
  30. data/lib/minfraud/components/account.rb +31 -9
  31. data/lib/minfraud/components/addressable.rb +73 -26
  32. data/lib/minfraud/components/base.rb +35 -11
  33. data/lib/minfraud/components/billing.rb +5 -0
  34. data/lib/minfraud/components/credit_card.rb +67 -18
  35. data/lib/minfraud/components/custom_inputs.rb +25 -0
  36. data/lib/minfraud/components/device.rb +51 -10
  37. data/lib/minfraud/components/email.rb +29 -7
  38. data/lib/minfraud/components/event.rb +60 -13
  39. data/lib/minfraud/components/order.rb +60 -22
  40. data/lib/minfraud/components/payment.rb +165 -21
  41. data/lib/minfraud/components/report/transaction.rb +80 -0
  42. data/lib/minfraud/components/shipping.rb +14 -5
  43. data/lib/minfraud/components/shopping_cart.rb +19 -12
  44. data/lib/minfraud/components/shopping_cart_item.rb +42 -13
  45. data/lib/minfraud/enum.rb +22 -8
  46. data/lib/minfraud/error_handler.rb +45 -12
  47. data/lib/minfraud/errors.rb +22 -2
  48. data/lib/minfraud/http_service.rb +22 -8
  49. data/lib/minfraud/http_service/request.rb +19 -18
  50. data/lib/minfraud/http_service/response.rb +49 -12
  51. data/lib/minfraud/model/abstract.rb +20 -0
  52. data/lib/minfraud/model/address.rb +52 -0
  53. data/lib/minfraud/model/billing_address.rb +11 -0
  54. data/lib/minfraud/model/credit_card.rb +75 -0
  55. data/lib/minfraud/model/device.rb +54 -0
  56. data/lib/minfraud/model/disposition.rb +35 -0
  57. data/lib/minfraud/model/email.rb +54 -0
  58. data/lib/minfraud/model/email_domain.rb +24 -0
  59. data/lib/minfraud/model/error.rb +28 -0
  60. data/lib/minfraud/model/factors.rb +24 -0
  61. data/lib/minfraud/model/geoip2_location.rb +25 -0
  62. data/lib/minfraud/model/insights.rb +68 -0
  63. data/lib/minfraud/model/ip_address.rb +82 -0
  64. data/lib/minfraud/model/issuer.rb +49 -0
  65. data/lib/minfraud/model/score.rb +76 -0
  66. data/lib/minfraud/model/score_ip_address.rb +23 -0
  67. data/lib/minfraud/model/shipping_address.rb +30 -0
  68. data/lib/minfraud/model/subscores.rb +178 -0
  69. data/lib/minfraud/model/warning.rb +63 -0
  70. data/lib/minfraud/report.rb +58 -0
  71. data/lib/minfraud/resolver.rb +25 -16
  72. data/lib/minfraud/validates.rb +187 -0
  73. data/lib/minfraud/version.rb +4 -1
  74. data/minfraud.gemspec +23 -18
  75. metadata +123 -48
@@ -1,36 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
 
3
5
  module Minfraud
4
6
  module HTTPService
7
+ # Request performs HTTP requests.
5
8
  class Request
6
- # @attribute middleware
7
- # @return [Proc] A proc containing Faraday configuration
9
+ # A proc containing Faraday configuration.
10
+ #
11
+ # @return [Proc, nil]
8
12
  attr_reader :middleware
9
13
 
10
- # @attribute server
11
- # @return [String] an API endpoint
14
+ # The API endpoint.
15
+ #
16
+ # @return [String, nil]
12
17
  attr_reader :server
13
18
 
14
- # Creates Minfraud::HTTPService::Request instance
15
- # @param [Hash] params hash of parameters
16
- # @return [Minfraud::HTTPService::Request] Request instance
19
+ # @param params [Hash] Hash of parameters. Each key/value should
20
+ # correspond to one of the available attributes.
17
21
  def initialize(params = {})
18
22
  @middleware = params[:middleware]
19
23
  @server = params[:server]
20
24
  end
21
25
 
22
- # Performs an HTTP request to the specified endpoint with given body
23
- # @param [Hash] params hash of parameters.
24
- # @return [Farday::Response] Faraday::Response instance
26
+ # Perform an HTTP request to the specified endpoint with given body.
27
+ #
28
+ # @param params [Hash] Hash of parameters, including +:verb+,
29
+ # +:endpoint+, and +:body+.
30
+ #
31
+ # @return [Farday::Response]
25
32
  def perform(params)
26
- adapter.send(*params.values_at(:verb, :endpoint, :body))
27
- end
28
-
29
- private
30
- # Creates memoized Faraday::Connection instance
31
- # @return [Faraday::Connection] Faraday::Connection instance
32
- def adapter
33
- @adapter ||= Faraday.new(server, {}, &middleware)
33
+ connection = Minfraud.connection
34
+ connection.send(*params.values_at(:verb, :endpoint, :body))
34
35
  end
35
36
  end
36
37
  end
@@ -1,32 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/error'
4
+ require 'minfraud/model/factors'
5
+ require 'minfraud/model/insights'
6
+ require 'minfraud/model/score'
7
+
1
8
  module Minfraud
2
9
  module HTTPService
10
+ # Response class for HTTP requests.
3
11
  class Response
4
- # @attribute status
5
- # @return [Integer] HTTP response status
12
+ # HTTP response status.
13
+ #
14
+ # @return [Integer, nil]
6
15
  attr_reader :status
7
16
 
8
- # @attribute body
9
- # @return [Hash] HTTP response body
17
+ # HTTP response model.
18
+ #
19
+ # @return [Minfraud::Model::Score, Minfraud::Model::Insights,
20
+ # Minfraud::Model::Factors, nil]
10
21
  attr_reader :body
11
22
 
12
- # @attribute headers
13
- # @return [Hash] HTTP response headers
23
+ # HTTP response headers.
24
+ #
25
+ # @return [Hash, nil]
14
26
  attr_reader :headers
15
27
 
16
- # Creates Minfraud::HTTPService::Response instance
17
- # @param [Hash] params hash of parameters
18
- # @return [Minfraud::HTTPService::Response] Response instance
28
+ # @param params [Hash] Hash of parameters. +:status+, +:endpoint+,
29
+ # +:body+, +:locales+, and +:headers+ are used.
19
30
  def initialize(params = {})
20
31
  @status = params[:status]
21
- @body = params[:body]
32
+ @body = make_body(
33
+ params[:endpoint],
34
+ params[:body],
35
+ params[:locales]
36
+ )
22
37
  @headers = params[:headers]
23
38
  end
24
39
 
25
- # Returns minFraud specific response code
26
- # @return [Symbol] minFraud specific request code
40
+ # Return the minFraud-specific response code.
41
+ #
42
+ # @return [Symbol, nil]
27
43
  def code
44
+ return nil if body.nil?
45
+
28
46
  body.code.intern if body.respond_to?(:code) && body.code
29
47
  end
48
+
49
+ private
50
+
51
+ def make_body(endpoint, body, locales)
52
+ if @status != 200
53
+ # Won't be a Hash when the body is not JSON.
54
+ return nil unless body.is_a?(Hash)
55
+
56
+ return Minfraud::Model::Error.new(body)
57
+ end
58
+
59
+ ENDPOINT_TO_CLASS[endpoint].new(body, locales)
60
+ end
61
+
62
+ ENDPOINT_TO_CLASS = {
63
+ factors: Minfraud::Model::Factors,
64
+ insights: Minfraud::Model::Insights,
65
+ score: Minfraud::Model::Score
66
+ }.freeze
30
67
  end
31
68
  end
32
69
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Minfraud
4
+ module Model
5
+ # @!visibility private
6
+ class Abstract
7
+ def initialize(record)
8
+ @record = record
9
+ end
10
+
11
+ protected
12
+
13
+ def get(key)
14
+ return nil if @record.nil? || !@record.key?(key)
15
+
16
+ @record[key]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/abstract'
4
+
5
+ module Minfraud
6
+ module Model
7
+ # Abstract model for a postal address.
8
+ class Address < Abstract
9
+ # The distance in kilometers from the address to the IP location.
10
+ #
11
+ # @return [Integer, nil]
12
+ attr_reader :distance_to_ip_location
13
+
14
+ # This property is true if the address is in the IP country. The property
15
+ # is false when the address is not in the IP country. If the address
16
+ # could not be parsed or was not provided or if the IP address could not
17
+ # be geolocated, the property will be nil.
18
+ #
19
+ # @return [Boolean, nil]
20
+ attr_reader :is_in_ip_country
21
+
22
+ # This property is true if the postal code provided with the address is
23
+ # in the city for the address. The property is false when the postal code
24
+ # is not in the city. If the address was not provided or could not be
25
+ # parsed, the property will be nil.
26
+ #
27
+ # @return [Boolean, nil]
28
+ attr_reader :is_postal_in_city
29
+
30
+ # The latitude associated with the address.
31
+ #
32
+ # @return [Float, nil]
33
+ attr_reader :latitude
34
+
35
+ # The longitude associated with the address.
36
+ #
37
+ # @return [Float, nil]
38
+ attr_reader :longitude
39
+
40
+ # @!visibility private
41
+ def initialize(record)
42
+ super(record)
43
+
44
+ @distance_to_ip_location = get('distance_to_ip_location')
45
+ @is_in_ip_country = get('is_in_ip_country')
46
+ @is_postal_in_city = get('is_postal_in_city')
47
+ @latitude = get('latitude')
48
+ @longitude = get('longitude')
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/address'
4
+
5
+ module Minfraud
6
+ module Model
7
+ # Model containing information about the billing address.
8
+ class BillingAddress < Address
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/abstract'
4
+ require 'minfraud/model/issuer'
5
+
6
+ module Minfraud
7
+ module Model
8
+ # Model with details about the credit card used.
9
+ class CreditCard < Abstract
10
+ # The card brand, such as "Visa", "Discover", "American Express", etc.
11
+ #
12
+ # @return [String, nil]
13
+ attr_reader :brand
14
+
15
+ # This property contains the two letter ISO 3166-1 alpha-2 country code
16
+ # (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) associated with the
17
+ # location of the majority of customers using this credit card as
18
+ # determined by their billing address. In cases where the location of
19
+ # customers is highly mixed, this defaults to the country of the bank
20
+ # issuing the card.
21
+ #
22
+ # @return [String, nil]
23
+ attr_reader :country
24
+
25
+ # This property is true if the card is a business card.
26
+ #
27
+ # @return [Boolean, nil]
28
+ attr_reader :is_business
29
+
30
+ # This property is true if the country of the billing address matches the
31
+ # country of the majority of customers using this credit card. In cases
32
+ # where the location of customers is highly mixed, the match is to the
33
+ # country of the bank issuing the card.
34
+ #
35
+ # @return [Boolean, nil]
36
+ attr_reader :is_issued_in_billing_address_country
37
+
38
+ # This property is true if the card is a prepaid card.
39
+ #
40
+ # @return [Boolean, nil]
41
+ attr_reader :is_prepaid
42
+
43
+ # This property is true if the card is a virtual card.
44
+ #
45
+ # @return [Boolean, nil]
46
+ attr_reader :is_virtual
47
+
48
+ # An object containing information about the credit card issuer.
49
+ #
50
+ # @return [Minfraud::Model::Issuer]
51
+ attr_reader :issuer
52
+
53
+ # The card's type. The valid values are: charge, credit, debit.
54
+ #
55
+ # @return [String, nil]
56
+ attr_reader :type
57
+
58
+ # @!visibility private
59
+ def initialize(record)
60
+ super(record)
61
+
62
+ @brand = get('brand')
63
+ @country = get('country')
64
+ @is_business = get('is_business')
65
+ @is_issued_in_billing_address_country = get(
66
+ 'is_issued_in_billing_address_country'
67
+ )
68
+ @is_prepaid = get('is_prepaid')
69
+ @is_virtual = get('is_virtual')
70
+ @issuer = Minfraud::Model::Issuer.new(get('issuer'))
71
+ @type = get('type')
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/abstract'
4
+
5
+ module Minfraud
6
+ module Model
7
+ # Model with information about the device.
8
+ #
9
+ # In order to receive device output from minFraud Insights or minFraud
10
+ # Factors, you must be using the Device Tracking Add-on
11
+ # (https://dev.maxmind.com/minfraud/device/).
12
+ class Device < Abstract
13
+ # This number represents our confidence that the device_id refers to a
14
+ # unique device as opposed to a cluster of similar devices. A confidence
15
+ # of 0.01 indicates very low confidence that the device is unique,
16
+ # whereas 99 indicates very high confidence.
17
+ #
18
+ # @return [Float, nil]
19
+ attr_reader :confidence
20
+
21
+ # A UUID that MaxMind uses for the device associated with this IP
22
+ # address. Note that many devices cannot be uniquely identified because
23
+ # they are too common (for example, all iPhones of a given model and OS
24
+ # release). In these cases, the minFraud service will simply not return a
25
+ # UUID for that device.
26
+ #
27
+ # @return [String, nil]
28
+ attr_reader :id
29
+
30
+ # This is the date and time of the last sighting of the device. This is
31
+ # an RFC 3339 date-time.
32
+ #
33
+ # @return [String, nil]
34
+ attr_reader :last_seen
35
+
36
+ # This is the local date and time of the transaction in the time zone of
37
+ # the device. This is determined by using the UTC offset associated with
38
+ # the device. This is an RFC 3339 date-time
39
+ #
40
+ # @return [String, nil]
41
+ attr_reader :local_time
42
+
43
+ # @!visibility private
44
+ def initialize(record)
45
+ super(record)
46
+
47
+ @confidence = get('confidence')
48
+ @id = get('id')
49
+ @last_seen = get('last_seen')
50
+ @local_time = get('local_time')
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/abstract'
4
+
5
+ module Minfraud
6
+ module Model
7
+ # Model with the disposition set by custom rules.
8
+ #
9
+ # In order to receive a disposition, you must be using minFraud custom
10
+ # rules.
11
+ class Disposition < Abstract
12
+ # The action to take on the transaction as defined by your custom rules.
13
+ # The current set of values are "accept", "manual_review", and "reject".
14
+ # If you do not have custom rules set up, this will be nil.
15
+ #
16
+ # @return [String, nil]
17
+ attr_reader :action
18
+
19
+ # The reason for the action. The current possible values are
20
+ # "custom_rule", "block_list", and "default". If you do not have custom
21
+ # rules set up, this will be nil.
22
+ #
23
+ # @return [String, nil]
24
+ attr_reader :reason
25
+
26
+ # @!visibility private
27
+ def initialize(record)
28
+ super(record)
29
+
30
+ @action = get('action')
31
+ @reason = get('reason')
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/abstract'
4
+ require 'minfraud/model/email_domain'
5
+
6
+ module Minfraud
7
+ module Model
8
+ # Model containing information about the email address.
9
+ class Email < Abstract
10
+ # An object containing information about the email domain.
11
+ #
12
+ # @return [Minfraud::Model::EmailDomain]
13
+ attr_reader :domain
14
+
15
+ # A date string (e.g. 2017-04-24) to identify the date an email address
16
+ # was first seen by MaxMind. This is expressed using the ISO 8601 date
17
+ # format.
18
+ #
19
+ # @return [String, nil]
20
+ attr_reader :first_seen
21
+
22
+ # Whether this email address is from a disposable email provider. The
23
+ # value will be nil when no email address or email domain has been passed
24
+ # as an input.
25
+ #
26
+ # @return [Boolean, nil]
27
+ attr_reader :is_disposable
28
+
29
+ # This property is true if MaxMind believes that this email is hosted by
30
+ # a free email provider such as Gmail or Yahoo! Mail.
31
+ #
32
+ # @return [Boolean, nil]
33
+ attr_reader :is_free
34
+
35
+ # This field is true if MaxMind believes that this email is likely to be
36
+ # used for fraud. Note that this is also factored into the overall
37
+ # risk_score in the response as well.
38
+ #
39
+ # @return [Boolean, nil]
40
+ attr_reader :is_high_risk
41
+
42
+ # @!visibility private
43
+ def initialize(record)
44
+ super(record)
45
+
46
+ @domain = Minfraud::Model::EmailDomain.new(get('domain'))
47
+ @first_seen = get('first_seen')
48
+ @is_disposable = get('is_disposable')
49
+ @is_free = get('is_free')
50
+ @is_high_risk = get('is_high_risk')
51
+ end
52
+ end
53
+ end
54
+ end