minfraud 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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