minfraud 1.0.0 → 1.1.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 (66) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +20 -3
  4. data/CHANGELOG.md +42 -0
  5. data/CODE_OF_CONDUCT.md +4 -4
  6. data/Gemfile +9 -2
  7. data/LICENSE.txt +2 -1
  8. data/README.dev.md +4 -0
  9. data/README.md +109 -39
  10. data/lib/maxmind/geoip2/model/city.rb +99 -0
  11. data/lib/maxmind/geoip2/model/country.rb +94 -0
  12. data/lib/maxmind/geoip2/model/insights.rb +38 -0
  13. data/lib/maxmind/geoip2/record/abstract.rb +46 -0
  14. data/lib/maxmind/geoip2/record/city.rb +62 -0
  15. data/lib/maxmind/geoip2/record/continent.rb +61 -0
  16. data/lib/maxmind/geoip2/record/country.rb +78 -0
  17. data/lib/maxmind/geoip2/record/location.rb +97 -0
  18. data/lib/maxmind/geoip2/record/maxmind.rb +41 -0
  19. data/lib/maxmind/geoip2/record/place.rb +52 -0
  20. data/lib/maxmind/geoip2/record/postal.rb +54 -0
  21. data/lib/maxmind/geoip2/record/represented_country.rb +47 -0
  22. data/lib/maxmind/geoip2/record/subdivision.rb +72 -0
  23. data/lib/maxmind/geoip2/record/traits.rb +224 -0
  24. data/lib/minfraud.rb +6 -4
  25. data/lib/minfraud/assessments.rb +32 -13
  26. data/lib/minfraud/components/account.rb +2 -2
  27. data/lib/minfraud/components/addressable.rb +2 -2
  28. data/lib/minfraud/components/base.rb +26 -4
  29. data/lib/minfraud/components/credit_card.rb +6 -1
  30. data/lib/minfraud/components/custom_inputs.rb +14 -0
  31. data/lib/minfraud/components/device.rb +11 -0
  32. data/lib/minfraud/components/event.rb +14 -9
  33. data/lib/minfraud/components/order.rb +1 -0
  34. data/lib/minfraud/components/payment.rb +125 -13
  35. data/lib/minfraud/components/report/transaction.rb +69 -0
  36. data/lib/minfraud/components/shipping.rb +1 -5
  37. data/lib/minfraud/components/shopping_cart.rb +2 -1
  38. data/lib/minfraud/enum.rb +8 -4
  39. data/lib/minfraud/error_handler.rb +37 -17
  40. data/lib/minfraud/http_service.rb +1 -2
  41. data/lib/minfraud/http_service/request.rb +1 -1
  42. data/lib/minfraud/http_service/response.rb +38 -10
  43. data/lib/minfraud/model/abstract.rb +20 -0
  44. data/lib/minfraud/model/address.rb +52 -0
  45. data/lib/minfraud/model/billing_address.rb +11 -0
  46. data/lib/minfraud/model/credit_card.rb +75 -0
  47. data/lib/minfraud/model/device.rb +54 -0
  48. data/lib/minfraud/model/disposition.rb +35 -0
  49. data/lib/minfraud/model/email.rb +54 -0
  50. data/lib/minfraud/model/email_domain.rb +24 -0
  51. data/lib/minfraud/model/error.rb +28 -0
  52. data/lib/minfraud/model/factors.rb +24 -0
  53. data/lib/minfraud/model/geoip2_location.rb +25 -0
  54. data/lib/minfraud/model/insights.rb +68 -0
  55. data/lib/minfraud/model/ip_address.rb +82 -0
  56. data/lib/minfraud/model/issuer.rb +49 -0
  57. data/lib/minfraud/model/score.rb +76 -0
  58. data/lib/minfraud/model/score_ip_address.rb +23 -0
  59. data/lib/minfraud/model/shipping_address.rb +30 -0
  60. data/lib/minfraud/model/subscores.rb +156 -0
  61. data/lib/minfraud/model/warning.rb +63 -0
  62. data/lib/minfraud/report.rb +38 -0
  63. data/lib/minfraud/resolver.rb +4 -3
  64. data/lib/minfraud/version.rb +1 -1
  65. data/minfraud.gemspec +18 -15
  66. metadata +68 -19
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Minfraud
4
+ module Components
5
+ module Report
6
+ # Contains all of the fields which are used in the report transaction API
7
+ class Transaction < Base
8
+ include ::Minfraud::Enum
9
+
10
+ # @!attribute ip_address
11
+ # @return [String, nil] The IP address of the customer placing the order. This
12
+ # should be passed as a string like "44.55.66.77" or "2001:db8::2:1".
13
+ attr_accessor :ip_address
14
+
15
+ # @!attribute tag
16
+ # This may be one of +:chargeback+, +:not_fraud+, +:spam_or_abuse+ or +:suspected_fraud+
17
+ # @return [Symbol, nil] A symbol indicating the likelihood that a transaction
18
+ # may be fraudulent.
19
+ enum_accessor :tag, [:chargeback, :not_fraud, :spam_or_abuse, :suspected_fraud]
20
+
21
+ # @attribute chargeback_code
22
+ # @return [String, nil] A string which is provided by your payment processor
23
+ # indicating the reason for the chargeback.
24
+ attr_accessor :chargeback_code
25
+
26
+ # @attribute maxmind_id
27
+ # @return [String, nil] A unique eight character string identifying a minFraud
28
+ # Standard or Premium request. These IDs are returned in the maxmindID
29
+ # field of a response for a successful minFraud request. This field is
30
+ # not required, but you are encouraged to provide it, if possible.
31
+ attr_accessor :maxmind_id
32
+
33
+ # @attribute minfraud_id
34
+ # @return [String, nil] A UUID that identifies a minFraud Score, minFraud
35
+ # Insights, or minFraud Factors request. This ID is returned at /id in
36
+ # the response. This field is not required, but you are encouraged to
37
+ # provide it if the request was made to one of these services.
38
+ attr_accessor :minfraud_id
39
+
40
+ # @attribute notes
41
+ # @return [String, nil] Your notes on the fraud tag associated with the
42
+ # transaction. We manually review many reported transactions to improve
43
+ # our scoring for you so any additional details to help us understand
44
+ # context are helpful.
45
+ attr_accessor :notes
46
+
47
+ # @attribute transaction_id
48
+ # @return [String, nil] The transaction ID you originally passed to minFraud.
49
+ # This field is not required, but you are encouraged to provide it or
50
+ # the transaction's maxmind_id or minfraud_id
51
+ attr_accessor :transaction_id
52
+
53
+ # Creates Minfraud::Components::Report::Transaction instance
54
+ # @param [Hash] params hash of parameters
55
+ # @return [Minfraud::Components::Report::Transaction] a Report::Transaction
56
+ # instance
57
+ def initialize(params = {})
58
+ @ip_address = params[:ip_address]
59
+ @chargeback_code = params[:chargeback_code]
60
+ @maxmind_id = params[:maxmind_id]
61
+ @minfraud_id = params[:minfraud_id]
62
+ @notes = params[:notes]
63
+ @transaction_id = params[:transaction_id]
64
+ self.tag = params[:tag]
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -4,17 +4,13 @@ module Minfraud
4
4
  include ::Minfraud::Enum
5
5
  # @attribute delivery_speed
6
6
  # @return [String] The shipping delivery speed for the order. The valid values are:
7
- # => same_day
8
- # => overnight
9
- # => expedited
10
- # => standard
11
7
  enum_accessor :delivery_speed, [:same_day, :overnight, :expedited, :standard]
12
8
 
13
9
  # Creates Minfraud::Components::Shipping instance
14
10
  # @param [Hash] params hash of parameters
15
11
  # @return [Minfraud::Components::Shipping] Shipping instance
16
12
  def initialize(params = {})
17
- @delivery_speed = params[:delivery_speed]
13
+ self.delivery_speed = params[:delivery_speed]
18
14
  super
19
15
  end
20
16
  end
@@ -20,9 +20,10 @@ module Minfraud
20
20
  private
21
21
 
22
22
  # @param [Hash] params hash of parameters for Minfraud::Components::ShoppingCartItem
23
+ # or Minfraud::Components::ShoppingCartItem instance
23
24
  # @return [Minfraud::Components::ShoppingCart] ShoppingCart instance
24
25
  def resolve(params)
25
- ShoppingCartItem.new(params)
26
+ params.is_a?(ShoppingCartItem) ? params : ShoppingCartItem.new(params)
26
27
  end
27
28
  end
28
29
  end
@@ -5,12 +5,17 @@ module Minfraud
5
5
  end
6
6
 
7
7
  module ClassMethods
8
+ # Returns a hash with in the following format: attribute_name => permitted_values
9
+ # @return [Hash] mapping
8
10
  def mapping
9
11
  @mapping ||= {}
10
12
  end
11
13
 
14
+ # Creates a set of methods for enum-like behaviour of the attribute
15
+ # @param [Symbol] attribute attribute name
16
+ # @param [Array] assignable_values a set of values which are permitted
12
17
  def enum_accessor(attribute, assignable_values)
13
- mapping[attribute] = assignable_values.map(&:to_s)
18
+ mapping[attribute] = assignable_values.map(&:intern)
14
19
 
15
20
  self.class.instance_eval do
16
21
  define_method("#{attribute}_values") { mapping[attribute] }
@@ -18,10 +23,9 @@ module Minfraud
18
23
 
19
24
  self.class_eval do
20
25
  define_method("#{attribute}") { instance_variable_get("@#{attribute}") }
21
-
22
26
  define_method "#{attribute}=" do |value|
23
- raise NotEnumValueError, 'Value is not permitted' unless self.class.mapping[attribute].include?(value.to_s)
24
- instance_variable_set("@#{attribute}", value.to_s)
27
+ raise NotEnumValueError, 'Value is not permitted' if value && !self.class.mapping[attribute].include?(value.intern)
28
+ instance_variable_set("@#{attribute}", value ? value.intern : nil)
25
29
  end
26
30
  end
27
31
  end
@@ -1,45 +1,65 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Minfraud
2
4
  module ErrorHandler
3
5
  class << self
4
- # Returns a response if status code is 200, rises an error otherwise
6
+ # Returns a response if status code is 2xx, raises an error otherwise
5
7
  # @param [Minfraud::HTTPService::Response] response
6
8
  # @return [Minfraud::HTTPService::Response] if status code is 200
7
- def inspect(response)
8
- return response if response.status == 200
9
+ def examine(response)
10
+ return response if response.status > 199 && response.status < 300
9
11
 
10
- raise *STATUS_CODES.fetch(response.code&.intern, [ServerError, 'Service not available'])
12
+ raise *STATUS_CODES.fetch(response.code, [ServerError, 'Server error'])
11
13
  end
12
14
 
13
15
  # A hash that maps status codes returned by minFraud with errors & messages
14
16
  STATUS_CODES = {
15
- IP_ADDRESS_INVALID: [
16
- ClientError, 'You have no supplied a valid IPv4 or IPv6 address'
17
+ IP_ADDRESS_INVALID: [
18
+ ClientError, 'You have not supplied a valid IPv4 or IPv6 address'
17
19
  ],
18
- IP_ADDRESS_REQUIRED: [
19
- ClientError, 'You have not supplied an IP address which is required filed'
20
+ IP_ADDRESS_REQUIRED: [
21
+ ClientError, 'You have not supplied an IP address which is a required field'
20
22
  ],
21
- IP_ADDRESS_RESERVED: [
23
+ IP_ADDRESS_RESERVED: [
22
24
  ClientError, 'You have supplied an IP address which is reserved'
23
25
  ],
24
- JSON_INVALID: [
26
+ JSON_INVALID: [
25
27
  ClientError, 'JSON body cannot be decoded'
26
28
  ],
29
+ MAXMIND_ID_INVALID: [
30
+ ClientError, 'You have not supplied a valid maxmind_id'
31
+ ],
32
+ MINFRAUD_ID_INVALID: [
33
+ ClientError, 'You have not supplied a valid minfraud_id'
34
+ ],
35
+ PARAMETER_UNKNOWN: [
36
+ ClientError, 'You have supplied an unknown parameter'
37
+ ],
38
+ TAG_REQUIRED: [
39
+ ClientError, 'You have not supplied a tag, which is a required field'
40
+ ],
41
+ TAG_INVALID: [
42
+ ClientError, 'You have not supplied a valid tag'
43
+ ],
44
+ ACCOUNT_ID_REQUIRED: [
45
+ AuthorizationError, 'You have not supplied a account ID'
46
+ ],
27
47
  AUTHORIZATION_INVALID: [
28
- AuthorizationError, 'Invalid license key and / or user id'
48
+ AuthorizationError, 'Invalid license key and / or account ID'
29
49
  ],
30
- LICENSE_KEY_REQUIRED: [
50
+ LICENSE_KEY_REQUIRED: [
31
51
  AuthorizationError, 'You have not supplied a license key'
32
52
  ],
33
- USER_ID_REQUIRED: [
34
- AuthorizationError, 'You have not supplied a user id'
53
+ USER_ID_REQUIRED: [
54
+ AuthorizationError, 'You have not supplied a account id'
35
55
  ],
36
- INSUFFICIENT_FUNDS: [
56
+ INSUFFICIENT_FUNDS: [
37
57
  ClientError, 'The license key you have provided does not have a sufficient funds to use this service'
38
58
  ],
39
- PERMISSION_REQUIRED: [
59
+ PERMISSION_REQUIRED: [
40
60
  ClientError, 'You do not have permission to use this service'
41
61
  ]
42
- }
62
+ }.freeze
43
63
  end
44
64
  end
45
65
  end
@@ -19,13 +19,12 @@ module Minfraud
19
19
 
20
20
  builder.basic_auth *::Minfraud.configuration.values
21
21
 
22
- builder.response :mashify
23
22
  builder.response :json, content_type: /\bjson$/
24
23
 
25
24
  builder.adapter Faraday.default_adapter
26
25
  end
27
26
 
28
27
  # Minfraud default server
29
- DEFAULT_SERVER = 'https://minfraud.maxmind.com/minfraud/v2.0'
28
+ DEFAULT_SERVER = 'https://minfraud.maxmind.com/minfraud/v2.0'.freeze
30
29
  end
31
30
  end
@@ -14,7 +14,7 @@ module Minfraud
14
14
  # Creates Minfraud::HTTPService::Request instance
15
15
  # @param [Hash] params hash of parameters
16
16
  # @return [Minfraud::HTTPService::Request] Request instance
17
- def initialize(params)
17
+ def initialize(params = {})
18
18
  @middleware = params[:middleware]
19
19
  @server = params[:server]
20
20
  end
@@ -1,36 +1,64 @@
1
+ require 'minfraud/model/error'
2
+ require 'minfraud/model/factors'
3
+ require 'minfraud/model/insights'
4
+ require 'minfraud/model/score'
5
+
1
6
  module Minfraud
2
7
  module HTTPService
8
+ # Response class for HTTP requests
3
9
  class Response
4
10
  # @attribute status
5
11
  # @return [Integer] HTTP response status
6
12
  attr_reader :status
7
13
 
8
14
  # @attribute body
9
- # @return [Hash] HTTP response body
15
+ # @return [Minfraud::Model::Score, Minfraud::Model::Insights,
16
+ # Minfraud::Model::Factors] HTTP response body
10
17
  attr_reader :body
11
18
 
12
19
  # @attribute headers
13
20
  # @return [Hash] HTTP response headers
14
21
  attr_reader :headers
15
22
 
16
- # @attribute code
17
- # @return [String] minFraud specific HTTP response code
18
- attr_reader :code
19
-
20
23
  # Creates Minfraud::HTTPService::Response instance
21
24
  # @param [Hash] params hash of parameters
22
25
  # @return [Minfraud::HTTPService::Response] Response instance
23
- def initialize(params)
26
+ def initialize(params = {})
24
27
  @status = params[:status]
25
- @body = params[:body]
28
+ @body = make_body(
29
+ params[:endpoint],
30
+ params[:body],
31
+ params[:locales]
32
+ )
26
33
  @headers = params[:headers]
27
34
  end
28
35
 
29
- # Returns minFraud specific response code
30
- # @return [String] minFraud specific request code
36
+ # Returns minFraud-specific response code
37
+ # @return [Symbol, nil] minFraud specific request code
31
38
  def code
32
- body.code if body.respond_to?(:code)
39
+ return nil if body.nil?
40
+
41
+ body.code.intern if body.respond_to?(:code) && body.code
33
42
  end
43
+
44
+ private
45
+
46
+ def make_body(endpoint, body, locales)
47
+ if @status != 200
48
+ # Won't be a Hash when the body is not JSON.
49
+ return nil unless body.is_a?(Hash)
50
+
51
+ return Minfraud::Model::Error.new(body)
52
+ end
53
+
54
+ ENDPOINT_TO_CLASS[endpoint].new(body, locales)
55
+ end
56
+
57
+ ENDPOINT_TO_CLASS = {
58
+ factors: Minfraud::Model::Factors,
59
+ insights: Minfraud::Model::Insights,
60
+ score: Minfraud::Model::Score
61
+ }.freeze
34
62
  end
35
63
  end
36
64
  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