maxmind 0.4.2 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +6 -0
- data/Gemfile +9 -2
- data/Guardfile +22 -0
- data/LICENSE +1 -1
- data/README.md +52 -12
- data/examples/chargeback_example.rb +20 -0
- data/lib/maxmind.rb +15 -8
- data/lib/maxmind/chargeback_request.rb +94 -0
- data/lib/maxmind/chargeback_response.rb +12 -0
- data/lib/maxmind/request.rb +23 -22
- data/lib/maxmind/response.rb +12 -8
- data/lib/maxmind/version.rb +2 -2
- data/maxmind.gemspec +11 -18
- data/spec/data/response.txt +1 -1
- data/spec/maxmind/chargeback_request_spec.rb +26 -0
- data/spec/maxmind/chargeback_response_spec.rb +25 -0
- data/spec/maxmind/request_spec.rb +21 -1
- data/spec/maxmind/response_spec.rb +17 -9
- data/spec/spec_helper.rb +5 -14
- metadata +19 -85
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 86e1f00f56877745ccb1a9abb4def3a574ab5e39
|
4
|
+
data.tar.gz: 6cb391c94e902c903a4231c3760e49e0c1e45fe3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa6c8d0f6338fdf40e435fad867ac08d882bc96cdc547a25f393f59ffdf5359df1a5677c0eea7b53b8e51640b169afd953abbfbefda1264db6d3c301f3496930
|
7
|
+
data.tar.gz: 1ceffa7a4b3c2bac93c89f36a8912a85e39c2290cda325cc4438b6f3ca0033a1379924e2bbfe630e42c9f80182575cc1998f7a31933db2fbc4225621200c4c94
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -4,3 +4,25 @@ guard 'rspec', :version => 2, :cli => '--color --format doc' do
|
|
4
4
|
watch('lib/eventricle.rb') { "spec/eventricle.rb" }
|
5
5
|
watch('spec/spec_helper.rb') { "spec" }
|
6
6
|
end
|
7
|
+
|
8
|
+
guard :rspec do
|
9
|
+
watch(%r{^spec/.+_spec\.rb$})
|
10
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
11
|
+
watch('spec/spec_helper.rb') { "spec" }
|
12
|
+
|
13
|
+
# Rails example
|
14
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
15
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
16
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
17
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
18
|
+
watch('config/routes.rb') { "spec/routing" }
|
19
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
20
|
+
|
21
|
+
# Capybara features specs
|
22
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
23
|
+
|
24
|
+
# Turnip features and steps
|
25
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
26
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
27
|
+
end
|
28
|
+
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Tests
|
|
15
15
|
------------
|
16
16
|
|
17
17
|
bundle install
|
18
|
-
guard
|
18
|
+
bundle exec guard
|
19
19
|
|
20
20
|
Dependencies
|
21
21
|
------------
|
@@ -27,7 +27,7 @@ Running Tests
|
|
27
27
|
|
28
28
|
Run `bundle install` to make sure you have all the dependencies. Once that's done, run:
|
29
29
|
|
30
|
-
rake
|
30
|
+
rake spec
|
31
31
|
|
32
32
|
Usage
|
33
33
|
-----
|
@@ -104,9 +104,6 @@ This is every field available.
|
|
104
104
|
|
105
105
|
response = request.process!
|
106
106
|
|
107
|
-
|
108
|
-
Also see examples/example.rb
|
109
|
-
|
110
107
|
TODO
|
111
108
|
----
|
112
109
|
* Improve specs (eg, test server failover)
|
@@ -115,15 +112,58 @@ Reference
|
|
115
112
|
---------
|
116
113
|
[minFraud API Reference](http://www.maxmind.com/app/ccv)
|
117
114
|
|
115
|
+
Also see examples/example.rb
|
116
|
+
|
117
|
+
Chargeback Service
|
118
|
+
------------------
|
119
|
+
|
120
|
+
You can help improve the Minfraud service by reporting instances of fraud. Only the IP address of a suspected fraudulent order is required, but you can pass additional information. Note that your Maxmind User ID is required in addition to your license key.
|
121
|
+
|
122
|
+
Chargeback Service Usage
|
123
|
+
------------------------
|
124
|
+
|
125
|
+
### Minimum Required ###
|
126
|
+
These are the only required fields to acquire a response from MaxMind.
|
127
|
+
|
128
|
+
require 'maxmind'
|
129
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
130
|
+
Maxmind.user_id = 'MAXMIND_USER_ID'
|
131
|
+
request = Maxmind::ChargebackRequest.new(
|
132
|
+
:client_ip => '24.24.24.24'
|
133
|
+
)
|
134
|
+
|
135
|
+
response = request.process!
|
136
|
+
|
137
|
+
|
138
|
+
### Recommended ###
|
139
|
+
For increased accuracy, these are the recommended fields to submit to MaxMind. The additional
|
140
|
+
fields here are optional and can be all or none.
|
141
|
+
|
142
|
+
require 'maxmind'
|
143
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
144
|
+
Maxmind.user_id = 'MAXMIND_USER_ID'
|
145
|
+
request = Maxmind::ChargebackRequest.new(
|
146
|
+
:client_ip => '24.24.24.24',
|
147
|
+
:chargeback_code => 'Fraud',
|
148
|
+
:fraud_score => 'suspected_fraud',
|
149
|
+
:maxmind_id => 'KW36L83C',
|
150
|
+
:transaction_id => '12345'
|
151
|
+
)
|
152
|
+
|
153
|
+
response = request.process!
|
154
|
+
|
155
|
+
[minFraud Chargeback reference](http://dev.maxmind.com/minfraud/chargeback)
|
156
|
+
|
118
157
|
Contributors
|
119
158
|
------------
|
120
|
-
Sam Oliver <sam@samoliver.com>
|
121
|
-
Nick Wilson <nick@di.fm>
|
122
|
-
Wolfram Arnold <wolfram@rubyfocus.biz>
|
123
|
-
Jonathan Lim <snowblink@gmail.com>
|
124
|
-
Tom Blomfield
|
125
|
-
Thomas Morgan
|
126
|
-
Tinu Cleatus <tinu.cleatus@me.com>
|
159
|
+
* Sam Oliver <sam@samoliver.com>
|
160
|
+
* Nick Wilson <nick@di.fm>
|
161
|
+
* Wolfram Arnold <wolfram@rubyfocus.biz>
|
162
|
+
* Jonathan Lim <snowblink@gmail.com>
|
163
|
+
* Tom Blomfield
|
164
|
+
* Thomas Morgan
|
165
|
+
* Tinu Cleatus <tinu.cleatus@me.com>
|
166
|
+
* Don Pflaster <dpflaster@gmail.com>
|
127
167
|
|
128
168
|
Thanks to all :)
|
129
169
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib/maxmind')
|
3
|
+
|
4
|
+
required_fields = {
|
5
|
+
:client_ip => '24.24.24.24'
|
6
|
+
}
|
7
|
+
|
8
|
+
recommended_fields = {
|
9
|
+
:client_ip => '24.24.24.24',
|
10
|
+
:chargeback_code => 'Fraud',
|
11
|
+
:fraud_score => 'suspected_fraud',
|
12
|
+
:maxmind_id => 'KW36L83C',
|
13
|
+
:transaction_id => '12345'
|
14
|
+
}
|
15
|
+
|
16
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
17
|
+
Maxmind.user_id = 'MAXMIND_USER_ID'
|
18
|
+
request = Maxmind::ChargebackRequest.new(required_fields.merge(recommended_fields))
|
19
|
+
response = request.process!
|
20
|
+
pp response
|
data/lib/maxmind.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
unless Module.respond_to?(:mattr_accessor)
|
3
|
-
require 'active_support/core_ext/module/attribute_accessors'# rescue nil # this may be needed for ActiveSupport versions >= 3.x
|
4
|
-
end
|
5
|
-
require 'active_support/core_ext/hash'
|
6
|
-
require 'net/http'
|
7
1
|
require 'net/https'
|
8
2
|
require 'uri'
|
9
3
|
require 'digest/md5'
|
10
|
-
|
11
|
-
require
|
4
|
+
|
5
|
+
require 'maxmind/version'
|
6
|
+
require 'maxmind/request'
|
7
|
+
require 'maxmind/chargeback_request'
|
8
|
+
require 'maxmind/chargeback_response'
|
9
|
+
require 'maxmind/response'
|
10
|
+
|
11
|
+
module Maxmind
|
12
|
+
SERVERS = %w(minfraud.maxmind.com minfraud-us-east.maxmind.com minfraud-us-west.maxmind.com)
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :license_key
|
16
|
+
attr_accessor :user_id
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Maxmind
|
2
|
+
class ChargebackRequest
|
3
|
+
DefaultTimeout = 60
|
4
|
+
|
5
|
+
# optionally set a default request type (one of 'standard' or 'premium')
|
6
|
+
# Maxmind's default behavior is to use premium if you have credits, else use standard
|
7
|
+
class << self
|
8
|
+
attr_accessor :default_request_type
|
9
|
+
attr_accessor :timeout
|
10
|
+
end
|
11
|
+
|
12
|
+
# Required Fields
|
13
|
+
attr_accessor :client_ip
|
14
|
+
|
15
|
+
# Optional Fields
|
16
|
+
attr_accessor :chargeback_code, :fraud_score, :maxmind_id, :transaction_id
|
17
|
+
|
18
|
+
def initialize(attrs={})
|
19
|
+
self.attributes = attrs
|
20
|
+
end
|
21
|
+
|
22
|
+
def attributes=(attrs={})
|
23
|
+
attrs.each do |k, v|
|
24
|
+
self.send("#{k}=", v)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def process!
|
29
|
+
resp = post(query)
|
30
|
+
Maxmind::ChargebackResponse.new(resp.message, resp.code)
|
31
|
+
end
|
32
|
+
|
33
|
+
def process
|
34
|
+
process!
|
35
|
+
rescue Exception => e
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def query
|
40
|
+
validate
|
41
|
+
|
42
|
+
required_fields = {
|
43
|
+
:ip_address => @client_ip,
|
44
|
+
}
|
45
|
+
|
46
|
+
optional_fields = {
|
47
|
+
:chargeback_code => @chargeback_code,
|
48
|
+
:fraud_score => @fraud_score,
|
49
|
+
:maxmind_id => @maxmind_id,
|
50
|
+
:transaction_id => @transaction_id
|
51
|
+
}
|
52
|
+
|
53
|
+
field_set = required_fields.merge(optional_fields)
|
54
|
+
field_set.reject {|k, v| v.nil? }.to_json
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Upon a failure at the first URL, will automatically retry with the
|
60
|
+
# second & third ones before finally raising an exception
|
61
|
+
# Returns an HTTPResponse object
|
62
|
+
def post(query_params)
|
63
|
+
servers ||= SERVERS.map{|hostname| "https://#{hostname}/minfraud/chargeback"}
|
64
|
+
url = URI.parse(servers.shift)
|
65
|
+
|
66
|
+
req = Net::HTTP::Post.new(url.path, initheader = {'Content-Type' =>'application/json'})
|
67
|
+
req.basic_auth Maxmind::user_id, Maxmind::license_key
|
68
|
+
req.body = query_params
|
69
|
+
|
70
|
+
h = Net::HTTP.new(url.host, url.port)
|
71
|
+
h.use_ssl = true
|
72
|
+
h.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
73
|
+
|
74
|
+
# set some timeouts
|
75
|
+
h.open_timeout = 60 # this blocks forever by default, lets be a bit less crazy.
|
76
|
+
h.read_timeout = self.class.timeout || DefaultTimeout
|
77
|
+
h.ssl_timeout = self.class.timeout || DefaultTimeout
|
78
|
+
|
79
|
+
h.start { |http| http.request(req) }
|
80
|
+
|
81
|
+
rescue Exception => e
|
82
|
+
retry if servers.size > 0
|
83
|
+
raise e
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def validate
|
89
|
+
raise ArgumentError, 'License key is required' unless Maxmind::license_key
|
90
|
+
raise ArgumentError, 'User ID is required' unless Maxmind::user_id
|
91
|
+
raise ArgumentError, 'IP address is required' unless client_ip
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Maxmind
|
2
|
+
class ChargebackResponse
|
3
|
+
attr_accessor :attributes
|
4
|
+
attr_reader :response, :http_code
|
5
|
+
|
6
|
+
def initialize(response = nil, http_code = nil)
|
7
|
+
raise ArgumentError, 'Missing response string' unless response
|
8
|
+
@response = response
|
9
|
+
@http_code = http_code.to_i if http_code
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/maxmind/request.rb
CHANGED
@@ -1,11 +1,4 @@
|
|
1
1
|
module Maxmind
|
2
|
-
# Your license key
|
3
|
-
class << self
|
4
|
-
attr_accessor :license_key
|
5
|
-
end
|
6
|
-
|
7
|
-
SERVERS = %w(minfraud.maxmind.com minfraud-us-east.maxmind.com minfraud-us-west.maxmind.com)
|
8
|
-
|
9
2
|
class Request
|
10
3
|
DefaultTimeout = 60
|
11
4
|
|
@@ -16,7 +9,6 @@ module Maxmind
|
|
16
9
|
attr_accessor :timeout
|
17
10
|
end
|
18
11
|
|
19
|
-
|
20
12
|
# Required Fields
|
21
13
|
attr_accessor :client_ip, :city, :region, :postal, :country
|
22
14
|
|
@@ -25,20 +17,18 @@ module Maxmind
|
|
25
17
|
:forwarded_ip, :email, :username, :password, :transaction_id, :session_id,
|
26
18
|
:shipping_address, :shipping_city, :shipping_region, :shipping_postal,
|
27
19
|
:shipping_country, :user_agent, :accept_language, :order_amount,
|
28
|
-
:order_currency
|
20
|
+
:order_currency, :avs_result, :cvv_result, :txn_type
|
29
21
|
|
30
22
|
def initialize(attrs={})
|
31
23
|
self.attributes = attrs
|
32
24
|
end
|
33
25
|
|
34
|
-
|
35
26
|
def attributes=(attrs={})
|
36
27
|
attrs.each do |k, v|
|
37
28
|
self.send("#{k}=", v)
|
38
29
|
end
|
39
30
|
end
|
40
31
|
|
41
|
-
|
42
32
|
# email domain ... if a full email is provided, take just the domain portion
|
43
33
|
def domain=(email)
|
44
34
|
@domain = if email =~ /@(.+)/
|
@@ -51,16 +41,16 @@ module Maxmind
|
|
51
41
|
# customer email ... sends just an MD5 hash of the email.
|
52
42
|
# also sets the email domain at the same time.
|
53
43
|
def email=(email)
|
54
|
-
@email =
|
44
|
+
@email = md5_digest(email)
|
55
45
|
self.domain = email unless domain
|
56
46
|
end
|
57
47
|
|
58
48
|
def username=(username)
|
59
|
-
@username =
|
49
|
+
@username = md5_digest(username)
|
60
50
|
end
|
61
51
|
|
62
52
|
def password=(password)
|
63
|
-
@password =
|
53
|
+
@password = md5_digest(password)
|
64
54
|
end
|
65
55
|
|
66
56
|
# if a full card number is passed, grab just the first 6 digits (which is the bank id number)
|
@@ -68,10 +58,10 @@ module Maxmind
|
|
68
58
|
@bin = bin ? bin[0,6] : nil
|
69
59
|
end
|
70
60
|
|
71
|
-
|
72
61
|
def process!
|
73
62
|
resp = post(query)
|
74
|
-
|
63
|
+
resp.body.encode!("utf-8", "iso-8859-1") if resp.body.respond_to?(:encode!)
|
64
|
+
Maxmind::Response.new(resp.body, resp.code)
|
75
65
|
end
|
76
66
|
|
77
67
|
def process
|
@@ -80,9 +70,6 @@ module Maxmind
|
|
80
70
|
false
|
81
71
|
end
|
82
72
|
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
73
|
def query
|
87
74
|
validate
|
88
75
|
|
@@ -114,15 +101,22 @@ module Maxmind
|
|
114
101
|
:txnID => @transaction_id,
|
115
102
|
:sessionID => @session_id,
|
116
103
|
:user_agent => @user_agent,
|
117
|
-
:accept_language => @
|
104
|
+
:accept_language => @accept_language,
|
105
|
+
:avs_result => @avs_result,
|
106
|
+
:cvv_result => @cvv_result,
|
107
|
+
:txn_type => @txn_type,
|
108
|
+
:order_amount => @order_amount
|
118
109
|
}
|
119
110
|
|
120
111
|
field_set = required_fields.merge(optional_fields)
|
121
112
|
field_set.reject {|k, v| v.nil? }
|
122
113
|
end
|
123
114
|
|
115
|
+
private
|
116
|
+
|
124
117
|
# Upon a failure at the first URL, will automatically retry with the
|
125
118
|
# second & third ones before finally raising an exception
|
119
|
+
# Returns an HTTPResponse object
|
126
120
|
def post(query_params)
|
127
121
|
servers ||= SERVERS.map{|hostname| "https://#{hostname}/app/ccv2r"}
|
128
122
|
url = URI.parse(servers.shift)
|
@@ -139,13 +133,20 @@ module Maxmind
|
|
139
133
|
h.read_timeout = self.class.timeout || DefaultTimeout
|
140
134
|
h.ssl_timeout = self.class.timeout || DefaultTimeout
|
141
135
|
|
142
|
-
|
143
|
-
response.body
|
136
|
+
h.start { |http| http.request(req) }
|
144
137
|
|
145
138
|
rescue Exception => e
|
146
139
|
retry if servers.size > 0
|
147
140
|
raise e
|
148
141
|
end
|
142
|
+
|
143
|
+
def md5_digest(value)
|
144
|
+
if value =~ /^[0-9a-f]{32}$/i
|
145
|
+
value
|
146
|
+
else
|
147
|
+
Digest::MD5.hexdigest(value.downcase)
|
148
|
+
end
|
149
|
+
end
|
149
150
|
|
150
151
|
protected
|
151
152
|
def validate
|
data/lib/maxmind/response.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
module Maxmind
|
2
2
|
class Response
|
3
3
|
attr_accessor :attributes
|
4
|
+
attr_reader :body, :http_code
|
4
5
|
|
5
6
|
ATTRIBUTE_MAP = {
|
6
7
|
'custPhoneInBillingLoc' => 'phone_in_billing_location',
|
7
8
|
'maxmindID' => 'maxmind_id',
|
8
9
|
'isTransProxy' => 'is_transparent_proxy',
|
9
|
-
'err' => 'error'
|
10
|
+
'err' => 'error',
|
11
|
+
'carderEmail' => 'high_risk_email'
|
10
12
|
}
|
11
13
|
|
12
|
-
def initialize(response = nil)
|
14
|
+
def initialize(response = nil, http_code = nil)
|
13
15
|
raise ArgumentError, 'Missing response string' unless response
|
16
|
+
@body = response
|
17
|
+
@http_code = http_code.to_i if http_code
|
14
18
|
@attributes = {}
|
15
19
|
parse(response)
|
16
20
|
end
|
@@ -34,8 +38,8 @@ module Maxmind
|
|
34
38
|
end
|
35
39
|
|
36
40
|
def method_missing(meth, *args)
|
37
|
-
if meth.to_s[-1] == '?'
|
38
|
-
send(meth[0..-2])
|
41
|
+
if meth.to_s[-1, 1] == '?'
|
42
|
+
send(meth.to_s[0..-2])
|
39
43
|
elsif attributes.has_key?(meth)
|
40
44
|
attributes[meth]
|
41
45
|
else
|
@@ -44,7 +48,7 @@ module Maxmind
|
|
44
48
|
end
|
45
49
|
|
46
50
|
def respond_to?(meth)
|
47
|
-
if meth.to_s[-1] == '?'
|
51
|
+
if meth.to_s[-1, 1] == '?'
|
48
52
|
respond_to? meth[0..-2]
|
49
53
|
else
|
50
54
|
super
|
@@ -64,13 +68,13 @@ module Maxmind
|
|
64
68
|
v = Integer(v) rescue Float(v) rescue v;
|
65
69
|
|
66
70
|
case v
|
67
|
-
when
|
71
|
+
when 'Yes', 'yes'
|
68
72
|
attributes[k] = true
|
69
|
-
when
|
73
|
+
when 'No', 'no'
|
70
74
|
attributes[k] = false
|
71
75
|
else
|
72
76
|
attributes[k] = v
|
73
77
|
end
|
74
78
|
end
|
75
79
|
end
|
76
|
-
end
|
80
|
+
end
|
data/lib/maxmind/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Maxmind
|
2
|
-
VERSION = '0.4.
|
3
|
-
end
|
2
|
+
VERSION = '0.4.5'
|
3
|
+
end
|
data/maxmind.gemspec
CHANGED
@@ -3,28 +3,21 @@ $:.push File.expand_path('../lib', __FILE__)
|
|
3
3
|
require 'maxmind/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name
|
7
|
-
s.version
|
6
|
+
s.name = "maxmind"
|
7
|
+
s.version = Maxmind::VERSION
|
8
8
|
|
9
|
-
s.authors
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.email = "adam@mediadrive.ca"
|
9
|
+
s.authors = ["Adam Daniels"]
|
10
|
+
s.description = "A wrapper around MaxMind's minFraud anti-fraud service. \n\nhttp://www.maxmind.com/app/ccv_overview\n"
|
11
|
+
s.email = "adam@mediadrive.ca"
|
13
12
|
s.extra_rdoc_files = [
|
14
13
|
"LICENSE",
|
15
14
|
"README.md"
|
16
15
|
]
|
17
|
-
|
18
|
-
s.files = `git ls-files`.split("\n")
|
19
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
-
s.homepage = "http://github.com/adam12/maxmind"
|
21
|
-
s.require_paths = ["lib"]
|
22
|
-
s.summary = "Wrapper for MaxMind's minFraud service"
|
23
16
|
|
24
|
-
s.
|
25
|
-
s.
|
26
|
-
s.
|
27
|
-
|
28
|
-
s.
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.homepage = "http://github.com/adam12/maxmind"
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.summary = "Wrapper for MaxMind's minFraud service"
|
22
|
+
s.license = 'MIT'
|
29
23
|
end
|
30
|
-
|
data/spec/data/response.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
distance=329;countryMatch=Yes;countryCode=US;freeMail=Yes;anonymousProxy=No;score=7.66;binMatch=Yes;binCountry=US;err=;proxyScore=0.00;ip_region=NY;ip_city=Syracuse;ip_latitude=43.0514;ip_longitude=-76.1495;binName=;ip_isp=Road
|
1
|
+
distance=329;countryMatch=Yes;countryCode=US;freeMail=Yes;anonymousProxy=No;score=7.66;binMatch=Yes;binCountry=US;err=;proxyScore=0.00;ip_region=NY;ip_city=Syracuse;ip_latitude=43.0514;ip_longitude=-76.1495;binName=;ip_isp=Road Runnere�;ip_org=Road Runner;binNameMatch=Yes;binPhoneMatch=Yes;binPhone=;custPhoneInBillingLoc=No;highRiskCountry=No;queriesRemaining=955;cityPostalMatch=No;shipCityPostalMatch=Yes;maxmindID=9VSOSDE2;isTransProxy=No;carderEmail=Yes;shipForward=Yes;highRiskUsername=No;highRiskPassword=No;riskScore=2.00;explanation=This order is very high risk, and we suggest you not accept it. This order is considered to be very slightly higher risk because the distance between the billing address and the user's actual location is larger than expected. The order is slightly riskier because the e-mail domain, yahoo.com, is a free e-mail provider. The order is slightly riskier because the phone number supplied by the user is not located within the zip code of the billing address for the credit card. The order is riskier because the shipping address given is a mail forwarding address, so there is no way to know where the products are actually going
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Maxmind::ChargebackRequest do
|
4
|
+
before do
|
5
|
+
Maxmind.user_id = 'user'
|
6
|
+
Maxmind.license_key = 'key'
|
7
|
+
@request = Maxmind::ChargebackRequest.new(:client_ip => '198.51.100.2')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "requires a License Key" do
|
11
|
+
Maxmind.license_key = nil
|
12
|
+
expect { @request.send(:validate) }.to raise_error(ArgumentError)
|
13
|
+
Maxmind.license_key = 'key'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "requires a User ID" do
|
17
|
+
Maxmind.user_id = nil
|
18
|
+
expect { @request.send(:validate) }.to raise_error(ArgumentError)
|
19
|
+
Maxmind.user_id = 'user'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "requires a client IP" do
|
23
|
+
@request.client_ip = nil
|
24
|
+
expect { @request.send(:validate) }.to raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Maxmind::ChargebackResponse do
|
4
|
+
before do
|
5
|
+
Maxmind.user_id = 'USER_ID'
|
6
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
7
|
+
|
8
|
+
request = Maxmind::ChargebackRequest.new(:client_ip => '198.51.100.2')
|
9
|
+
stub_request(:post, "https://USER_ID:LICENSE_KEY@minfraud.maxmind.com/minfraud/chargeback").
|
10
|
+
to_return(:body => '', :status => 200)
|
11
|
+
@response = request.process!
|
12
|
+
end
|
13
|
+
|
14
|
+
it "requires a response" do
|
15
|
+
expect { Maxmind::ChargebackResponse.new }.to raise_exception(ArgumentError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "exposes the http response code" do
|
19
|
+
expect(@response.http_code).to eq 200
|
20
|
+
end
|
21
|
+
|
22
|
+
it "exposes the http response" do
|
23
|
+
expect(@response.response).to_not be_nil
|
24
|
+
end
|
25
|
+
end
|
@@ -47,4 +47,24 @@ describe Maxmind::Request do
|
|
47
47
|
@request.email = 'test@test.com'
|
48
48
|
@request.email.should == 'b642b4217b34b1e8d3bd915fc65c4452'
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
|
+
it "does not double convert an md5 username" do
|
52
|
+
@request.username = 'b642b4217b34b1e8d3bd915fc65c4452'
|
53
|
+
@request.username.should == 'b642b4217b34b1e8d3bd915fc65c4452'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "does not double convert an md5 password" do
|
57
|
+
@request.password = 'b642b4217b34b1e8d3bd915fc65c4452'
|
58
|
+
@request.password.should == 'b642b4217b34b1e8d3bd915fc65c4452'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "does not double convert an md5 email" do
|
62
|
+
@request.email = 'b642b4217b34b1e8d3bd915fc65c4452'
|
63
|
+
@request.email.should == 'b642b4217b34b1e8d3bd915fc65c4452'
|
64
|
+
end
|
65
|
+
|
66
|
+
it "exposes the query parameters" do
|
67
|
+
@request.query.should be_a Hash
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -1,11 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
REQUIRED_FIELDS =
|
4
|
-
|
5
|
-
RECOMMENDED_FIELDS =
|
6
|
-
|
7
|
-
OPTIONAL_FIELDS =
|
8
|
-
|
9
3
|
describe Maxmind::Response do
|
10
4
|
before do
|
11
5
|
Maxmind.license_key = 'LICENSE_KEY'
|
@@ -14,10 +8,12 @@ describe Maxmind::Response do
|
|
14
8
|
recommended_fields = JSON.parse(load_fixture("recommended_fields.json"))
|
15
9
|
optional_fields = JSON.parse(load_fixture("optional_fields.json"))
|
16
10
|
all_fields = required_fields.merge(recommended_fields).merge(optional_fields)
|
11
|
+
@response_body = load_fixture("response.txt")
|
12
|
+
@response_body.encode!("utf-8", "iso-8859-1") if @response_body.respond_to?(:encode!)
|
17
13
|
|
18
14
|
request = Maxmind::Request.new(all_fields)
|
19
15
|
stub_request(:post, "https://minfraud.maxmind.com/app/ccv2r").
|
20
|
-
to_return(:body =>
|
16
|
+
to_return(:body => @response_body, :status => 200)
|
21
17
|
@response = request.process!
|
22
18
|
end
|
23
19
|
|
@@ -28,6 +24,14 @@ describe Maxmind::Response do
|
|
28
24
|
it "exposes its attributes" do
|
29
25
|
@response.attributes.should be_a Hash
|
30
26
|
end
|
27
|
+
|
28
|
+
it "exposes the raw response body" do
|
29
|
+
@response.body.should == @response_body
|
30
|
+
end
|
31
|
+
|
32
|
+
it "exposes the http response code" do
|
33
|
+
@response.http_code.should == 200
|
34
|
+
end
|
31
35
|
|
32
36
|
it "has a distance" do
|
33
37
|
@response.distance.should == 329
|
@@ -50,7 +54,7 @@ describe Maxmind::Response do
|
|
50
54
|
end
|
51
55
|
|
52
56
|
it "has an explanation" do
|
53
|
-
@response.explanation.
|
57
|
+
@response.explanation.should be_a String
|
54
58
|
end
|
55
59
|
|
56
60
|
it "has a country match" do
|
@@ -69,4 +73,8 @@ describe Maxmind::Response do
|
|
69
73
|
it "has a phone in billing location ? method" do
|
70
74
|
@response.phone_in_billing_location?.should == false
|
71
75
|
end
|
72
|
-
|
76
|
+
|
77
|
+
it "has a high risk email" do
|
78
|
+
@response.high_risk_email.should == true
|
79
|
+
end
|
80
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
require '
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'mocha/api'
|
2
5
|
require 'maxmind'
|
3
6
|
require 'json'
|
4
7
|
require 'webmock/rspec'
|
@@ -7,24 +10,12 @@ RSpec.configure do |config|
|
|
7
10
|
|
8
11
|
config.before(:suite) do
|
9
12
|
# Disable all live HTTP requests
|
10
|
-
WebMock.disable_net_connect!(allow_localhost
|
13
|
+
WebMock.disable_net_connect!(:allow_localhost => true)
|
11
14
|
end
|
12
15
|
|
13
16
|
config.mock_with :mocha
|
14
17
|
end
|
15
18
|
|
16
|
-
# Constants (classes, etc) defined within a block passed to this method
|
17
|
-
# will be removed from the global namespace after the block as run.
|
18
|
-
def isolate_constants
|
19
|
-
existing_constants = Object.constants
|
20
|
-
yield
|
21
|
-
ensure
|
22
|
-
(Object.constants - existing_constants).each do |constant|
|
23
|
-
Object.send(:remove_const, constant)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
19
|
def load_fixture(*filename)
|
29
20
|
File.open(File.join('spec', 'data', *filename)).read
|
30
21
|
end
|
metadata
CHANGED
@@ -1,84 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maxmind
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.5
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Adam Daniels
|
9
|
-
- Tinu Cleatus
|
10
|
-
- t.e.morgan
|
11
|
-
- Sam Oliver
|
12
8
|
autorequire:
|
13
9
|
bindir: bin
|
14
10
|
cert_chain: []
|
15
|
-
date:
|
16
|
-
dependencies:
|
17
|
-
-
|
18
|
-
name: rspec
|
19
|
-
requirement: !ruby/object:Gem::Requirement
|
20
|
-
none: false
|
21
|
-
requirements:
|
22
|
-
- - ! '>='
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: '0'
|
25
|
-
type: :development
|
26
|
-
prerelease: false
|
27
|
-
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
|
-
requirements:
|
30
|
-
- - ! '>='
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '0'
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: mocha
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
none: false
|
37
|
-
requirements:
|
38
|
-
- - ! '>='
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
type: :development
|
42
|
-
prerelease: false
|
43
|
-
version_requirements: !ruby/object:Gem::Requirement
|
44
|
-
none: false
|
45
|
-
requirements:
|
46
|
-
- - ! '>='
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: '0'
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: webmock
|
51
|
-
requirement: !ruby/object:Gem::Requirement
|
52
|
-
none: false
|
53
|
-
requirements:
|
54
|
-
- - ! '>='
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: '0'
|
57
|
-
type: :development
|
58
|
-
prerelease: false
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
60
|
-
none: false
|
61
|
-
requirements:
|
62
|
-
- - ! '>='
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
version: '0'
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
|
-
name: active_support
|
67
|
-
requirement: !ruby/object:Gem::Requirement
|
68
|
-
none: false
|
69
|
-
requirements:
|
70
|
-
- - ! '>='
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: 3.0.0
|
73
|
-
type: :runtime
|
74
|
-
prerelease: false
|
75
|
-
version_requirements: !ruby/object:Gem::Requirement
|
76
|
-
none: false
|
77
|
-
requirements:
|
78
|
-
- - ! '>='
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: 3.0.0
|
81
|
-
description: ! "A wrapper around MaxMind's minFraud anti-fraud service. \n\nhttp://www.maxmind.com/app/ccv_overview\n"
|
11
|
+
date: 2013-09-27 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: "A wrapper around MaxMind's minFraud anti-fraud service. \n\nhttp://www.maxmind.com/app/ccv_overview\n"
|
82
14
|
email: adam@mediadrive.ca
|
83
15
|
executables: []
|
84
16
|
extensions: []
|
@@ -87,13 +19,17 @@ extra_rdoc_files:
|
|
87
19
|
- README.md
|
88
20
|
files:
|
89
21
|
- .gitignore
|
22
|
+
- .travis.yml
|
90
23
|
- Gemfile
|
91
24
|
- Guardfile
|
92
25
|
- LICENSE
|
93
26
|
- README.md
|
94
27
|
- Rakefile
|
28
|
+
- examples/chargeback_example.rb
|
95
29
|
- examples/example.rb
|
96
30
|
- lib/maxmind.rb
|
31
|
+
- lib/maxmind/chargeback_request.rb
|
32
|
+
- lib/maxmind/chargeback_response.rb
|
97
33
|
- lib/maxmind/request.rb
|
98
34
|
- lib/maxmind/response.rb
|
99
35
|
- lib/maxmind/version.rb
|
@@ -102,44 +38,42 @@ files:
|
|
102
38
|
- spec/data/recommended_fields.json
|
103
39
|
- spec/data/required_fields.json
|
104
40
|
- spec/data/response.txt
|
41
|
+
- spec/maxmind/chargeback_request_spec.rb
|
42
|
+
- spec/maxmind/chargeback_response_spec.rb
|
105
43
|
- spec/maxmind/request_spec.rb
|
106
44
|
- spec/maxmind/response_spec.rb
|
107
45
|
- spec/spec_helper.rb
|
108
46
|
homepage: http://github.com/adam12/maxmind
|
109
|
-
licenses:
|
47
|
+
licenses:
|
48
|
+
- MIT
|
49
|
+
metadata: {}
|
110
50
|
post_install_message:
|
111
51
|
rdoc_options: []
|
112
52
|
require_paths:
|
113
53
|
- lib
|
114
54
|
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
55
|
requirements:
|
117
|
-
- -
|
56
|
+
- - '>='
|
118
57
|
- !ruby/object:Gem::Version
|
119
58
|
version: '0'
|
120
|
-
segments:
|
121
|
-
- 0
|
122
|
-
hash: -1867686245011996081
|
123
59
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
-
none: false
|
125
60
|
requirements:
|
126
|
-
- -
|
61
|
+
- - '>='
|
127
62
|
- !ruby/object:Gem::Version
|
128
63
|
version: '0'
|
129
|
-
segments:
|
130
|
-
- 0
|
131
|
-
hash: -1867686245011996081
|
132
64
|
requirements: []
|
133
65
|
rubyforge_project:
|
134
|
-
rubygems_version:
|
66
|
+
rubygems_version: 2.0.7
|
135
67
|
signing_key:
|
136
|
-
specification_version:
|
68
|
+
specification_version: 4
|
137
69
|
summary: Wrapper for MaxMind's minFraud service
|
138
70
|
test_files:
|
139
71
|
- spec/data/optional_fields.json
|
140
72
|
- spec/data/recommended_fields.json
|
141
73
|
- spec/data/required_fields.json
|
142
74
|
- spec/data/response.txt
|
75
|
+
- spec/maxmind/chargeback_request_spec.rb
|
76
|
+
- spec/maxmind/chargeback_response_spec.rb
|
143
77
|
- spec/maxmind/request_spec.rb
|
144
78
|
- spec/maxmind/response_spec.rb
|
145
79
|
- spec/spec_helper.rb
|