maxmind-rb 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +21 -0
- data/README.markdown +106 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/examples/example.rb +41 -0
- data/lib/maxmind.rb +8 -0
- data/lib/maxmind/request.rb +145 -0
- data/lib/maxmind/response.rb +102 -0
- data/test/fixtures/response.txt +1 -0
- data/test/maxmind_test.rb +131 -0
- data/test/test_helper.rb +14 -0
- metadata +105 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2009 Adam
|
2
|
+
Copyright (c) 2010 t.e.morgan
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
maxmind-rb
|
2
|
+
==========
|
3
|
+
|
4
|
+
A wrapper around MaxMind's minFraud anti-fraud service.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
sudo gem install maxmind-rb
|
9
|
+
|
10
|
+
|
11
|
+
Dependencies
|
12
|
+
------------
|
13
|
+
* active_support
|
14
|
+
* [shoulda](http://github.com/thoughtbot/shoulda/) (used in tests only)
|
15
|
+
* [matchy](http://github.com/jeremymcanally/matchy/) (used in tests only)
|
16
|
+
|
17
|
+
|
18
|
+
Usage
|
19
|
+
-----
|
20
|
+
|
21
|
+
### Minimum Required ###
|
22
|
+
These are the only required fields to acquire a response from MaxMind.
|
23
|
+
|
24
|
+
require 'maxmind'
|
25
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
26
|
+
request = Maxmind::Request.new(
|
27
|
+
:client_ip => '24.24.24.24',
|
28
|
+
:city => 'New York',
|
29
|
+
:region => 'NY',
|
30
|
+
:postal => '11434',
|
31
|
+
:country => 'US'
|
32
|
+
)
|
33
|
+
|
34
|
+
response = request.process!
|
35
|
+
|
36
|
+
|
37
|
+
### Recommended ###
|
38
|
+
For increased accuracy, these are the recommended fields to submit to MaxMind. The additional
|
39
|
+
fields here are optional and can be all or none.
|
40
|
+
|
41
|
+
require 'maxmind'
|
42
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
43
|
+
request = Maxmind::Request.new(
|
44
|
+
:client_ip => '24.24.24.24',
|
45
|
+
:city => 'New York',
|
46
|
+
:region => 'NY',
|
47
|
+
:postal => '11434',
|
48
|
+
:country => 'US',
|
49
|
+
:domain => 'yahoo.com',
|
50
|
+
:bin => '549099',
|
51
|
+
:forwarded_ip => '24.24.24.25',
|
52
|
+
:email => 'test@test.com',
|
53
|
+
:username => 'test_carder_username',
|
54
|
+
:password => 'test_carder_password'
|
55
|
+
)
|
56
|
+
|
57
|
+
response = request.process!
|
58
|
+
|
59
|
+
### Thorough ###
|
60
|
+
This is every field available.
|
61
|
+
|
62
|
+
require 'maxmind'
|
63
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
64
|
+
request = Maxmind::Request.new(
|
65
|
+
:client_ip => '24.24.24.24',
|
66
|
+
:city => 'New York',
|
67
|
+
:region => 'NY',
|
68
|
+
:postal => '11434',
|
69
|
+
:country => 'US',
|
70
|
+
:domain => 'yahoo.com',
|
71
|
+
:bin => '549099',
|
72
|
+
:forwarded_ip => '24.24.24.25',
|
73
|
+
:email => 'test@test.com',
|
74
|
+
:username => 'test_carder_username',
|
75
|
+
:password => 'test_carder_password'
|
76
|
+
:bin_name => 'MBNA America Bank',
|
77
|
+
:bin_phone => '800-421-2110',
|
78
|
+
:cust_phone => '212-242',
|
79
|
+
:request_type => 'premium',
|
80
|
+
:shipping_address => '145-50 157th Street',
|
81
|
+
:shipping_city => 'Jamaica',
|
82
|
+
:shipping_region => 'NY',
|
83
|
+
:shipping_postal => '11434',
|
84
|
+
:shipping_country => 'US',
|
85
|
+
:transaction_id => '1234',
|
86
|
+
:session_id => 'abcd9876',
|
87
|
+
:user_agent => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1',
|
88
|
+
:accept_language => 'en-us'
|
89
|
+
)
|
90
|
+
|
91
|
+
response = request.process!
|
92
|
+
|
93
|
+
|
94
|
+
Also see examples/example.rb
|
95
|
+
|
96
|
+
|
97
|
+
Reference
|
98
|
+
---------
|
99
|
+
[minFraud API Reference](http://www.maxmind.com/app/ccv)
|
100
|
+
|
101
|
+
|
102
|
+
Copyright
|
103
|
+
---------
|
104
|
+
Copyright (c) 2009 Adam.
|
105
|
+
Copyright (c) 2010 t.e.morgan.
|
106
|
+
See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "maxmind-rb"
|
8
|
+
gem.summary = "Wrapper for MaxMind's minFraud service"
|
9
|
+
gem.description = <<-EOF
|
10
|
+
A wrapper around MaxMind's minFraud anti-fraud service.
|
11
|
+
|
12
|
+
http://www.maxmind.com/app/ccv_overview
|
13
|
+
EOF
|
14
|
+
gem.email = "tm@iprog.com"
|
15
|
+
gem.homepage = "http://github.com/zarqman/maxmind"
|
16
|
+
gem.authors = ["Adam Daniels", "Tinu Cleatus", 't.e.morgan']
|
17
|
+
gem.add_dependency 'activesupport', '>= 2.3'
|
18
|
+
gem.add_development_dependency('shoulda')
|
19
|
+
gem.add_development_dependency('matchy')
|
20
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
21
|
+
end
|
22
|
+
Jeweler::GemcutterTasks.new
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new(:test) do |test|
|
29
|
+
test.libs << 'lib' << 'test'
|
30
|
+
test.pattern = 'test/**/*_test.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/*_test.rb'
|
39
|
+
test.verbose = true
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
task :rcov do
|
43
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
task :default => :test
|
49
|
+
|
50
|
+
require 'rake/rdoctask'
|
51
|
+
Rake::RDocTask.new do |rdoc|
|
52
|
+
if File.exist?('VERSION.yml')
|
53
|
+
config = YAML.load(File.read('VERSION.yml'))
|
54
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
55
|
+
else
|
56
|
+
version = ""
|
57
|
+
end
|
58
|
+
|
59
|
+
rdoc.rdoc_dir = 'rdoc'
|
60
|
+
rdoc.title = "maxmind-rb #{version}"
|
61
|
+
rdoc.rdoc_files.include('README*')
|
62
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
63
|
+
end
|
64
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.0
|
data/examples/example.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib/maxmind')
|
3
|
+
|
4
|
+
required_fields = {
|
5
|
+
:client_ip => '24.24.24.24',
|
6
|
+
:city => 'New York',
|
7
|
+
:region => 'NY',
|
8
|
+
:postal => '11434',
|
9
|
+
:country => 'US'
|
10
|
+
}
|
11
|
+
|
12
|
+
recommended_fields = {
|
13
|
+
:domain => 'yahoo.com',
|
14
|
+
:bin => '549099',
|
15
|
+
:forwarded_ip => '24.24.24.25',
|
16
|
+
:email => 'test@test.com',
|
17
|
+
:username => 'test_carder_username',
|
18
|
+
:password => 'test_carder_password'
|
19
|
+
}
|
20
|
+
|
21
|
+
optional_fields = {
|
22
|
+
:bin_name => 'MBNA America Bank',
|
23
|
+
:bin_phone => '800-421-2110',
|
24
|
+
:cust_phone => '212-242',
|
25
|
+
:request_type => 'premium',
|
26
|
+
:shipping_address => '145-50 157th Street',
|
27
|
+
:shipping_city => 'Jamaica',
|
28
|
+
:shipping_region => 'NY',
|
29
|
+
:shipping_postal => '11434',
|
30
|
+
:shipping_country => 'US',
|
31
|
+
:transaction_id => '1234',
|
32
|
+
:session_id => 'abcd9876',
|
33
|
+
:user_agent => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1',
|
34
|
+
:accept_language => 'en-us'
|
35
|
+
}
|
36
|
+
|
37
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
38
|
+
Maxmind::Request.default_request_type = 'standard'
|
39
|
+
request = Maxmind::Request.new(required_fields.merge(recommended_fields).merge(optional_fields))
|
40
|
+
response = request.process!
|
41
|
+
pp response
|
data/lib/maxmind.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
module Maxmind
|
2
|
+
# Your license key
|
3
|
+
mattr_accessor :license_key
|
4
|
+
|
5
|
+
class Request
|
6
|
+
# optionally set a default request type (one of 'standard' or 'premium')
|
7
|
+
# Maxmind's default behavior is to use premium if you have credits, else use standard
|
8
|
+
mattr_accessor :default_request_type
|
9
|
+
|
10
|
+
|
11
|
+
# Required Fields
|
12
|
+
attr_accessor :client_ip, :city, :region, :postal, :country
|
13
|
+
|
14
|
+
# Optional Fields
|
15
|
+
attr_accessor :domain, :bin, :bin_name, :bin_phone, :cust_phone, :request_type,
|
16
|
+
:forwarded_ip, :email, :username, :password, :transaction_id, :session_id,
|
17
|
+
:shipping_address, :shipping_city, :shipping_region, :shipping_postal,
|
18
|
+
:shipping_country, :user_agent, :accept_language
|
19
|
+
|
20
|
+
def initialize(attrs={})
|
21
|
+
self.attributes = attrs
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def attributes=(attrs={})
|
26
|
+
attrs.each do |k, v|
|
27
|
+
self.send("#{k}=", v)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# email domain ... if a full email is provided, take just the domain portion
|
33
|
+
def domain=(email)
|
34
|
+
@domain = if email =~ /@(.+)/
|
35
|
+
$1
|
36
|
+
else
|
37
|
+
email
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# customer email ... sends just an MD5 hash of the email.
|
42
|
+
# also sets the email domain at the same time.
|
43
|
+
def email=(email)
|
44
|
+
@email = Digest::MD5.hexdigest(email.downcase)
|
45
|
+
self.domain = email unless domain
|
46
|
+
end
|
47
|
+
|
48
|
+
def username=(username)
|
49
|
+
@username = Digest::MD5.hexdigest(username.downcase)
|
50
|
+
end
|
51
|
+
|
52
|
+
def password=(password)
|
53
|
+
@password = Digest::MD5.hexdigest(password.downcase)
|
54
|
+
end
|
55
|
+
|
56
|
+
# if a full card number is passed, grab just the first 6 digits (which is the bank id number)
|
57
|
+
def bin=(bin)
|
58
|
+
@bin = bin ? bin[0,6] : nil
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def process!
|
63
|
+
resp = post(query)
|
64
|
+
Maxmind::Response.new(resp)
|
65
|
+
end
|
66
|
+
|
67
|
+
def process
|
68
|
+
process!
|
69
|
+
rescue Exception => e
|
70
|
+
false
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def query
|
77
|
+
validate
|
78
|
+
|
79
|
+
required_fields = {
|
80
|
+
:i => @client_ip,
|
81
|
+
:city => @city,
|
82
|
+
:region => @region,
|
83
|
+
:postal => @postal,
|
84
|
+
:country => @country,
|
85
|
+
:license_key => Maxmind::license_key
|
86
|
+
}
|
87
|
+
|
88
|
+
optional_fields = {
|
89
|
+
:domain => @domain,
|
90
|
+
:bin => @bin,
|
91
|
+
:binName => @bin_name,
|
92
|
+
:binPhone => @bin_phone,
|
93
|
+
:custPhone => @cust_phone,
|
94
|
+
:requested_type => @request_type || @@default_request_type,
|
95
|
+
:forwardedIP => @forwarded_ip,
|
96
|
+
:emailMD5 => @email,
|
97
|
+
:usernameMD5 => @username,
|
98
|
+
:passwordMD5 => @password,
|
99
|
+
:shipAddr => @shipping_address,
|
100
|
+
:shipCity => @shipping_city,
|
101
|
+
:shipRegion => @shipping_region,
|
102
|
+
:shipPostal => @shipping_postal,
|
103
|
+
:shipCountry => @shipping_country,
|
104
|
+
:txnID => @transaction_id,
|
105
|
+
:sessionID => @session_id,
|
106
|
+
:user_agent => @user_agent,
|
107
|
+
:accept_language => @accept_langage
|
108
|
+
}
|
109
|
+
|
110
|
+
field_set = required_fields.merge(optional_fields)
|
111
|
+
field_set.reject {|k, v| v.nil? }#.to_query
|
112
|
+
end
|
113
|
+
|
114
|
+
# Upon a failure at the first URL, will automatically retry with the second one before finally raising an exception
|
115
|
+
def post(query_params)
|
116
|
+
servers ||= ["https://minfraud1.maxmind.com/app/ccv2r", "https://minfraud3.maxmind.com/app/ccv2r"]
|
117
|
+
url = URI.parse(servers.shift)
|
118
|
+
|
119
|
+
# req = Net::HTTP::Get.new("#{url.path}?#{query_string}")
|
120
|
+
req = Net::HTTP::Post.new("#{url.path}")
|
121
|
+
req.set_form_data(query_params)
|
122
|
+
h = Net::HTTP.new(url.host, url.port)
|
123
|
+
h.use_ssl = true
|
124
|
+
h.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
125
|
+
response = h.start { |http| http.request(req) }
|
126
|
+
response.body
|
127
|
+
|
128
|
+
rescue Exception => e
|
129
|
+
retry if servers.size > 0
|
130
|
+
raise e
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
protected
|
136
|
+
def validate
|
137
|
+
raise ArgumentError, 'License key is required' unless Maxmind::license_key
|
138
|
+
raise ArgumentError, 'IP address is required' unless client_ip
|
139
|
+
raise ArgumentError, 'City is required' unless city
|
140
|
+
raise ArgumentError, 'Region is required' unless region
|
141
|
+
raise ArgumentError, 'Postal code is required' unless postal
|
142
|
+
raise ArgumentError, 'Country is required' unless country
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Maxmind
|
2
|
+
class Response
|
3
|
+
attr_accessor :country_match, :country_code, :high_risk_country, :distance,
|
4
|
+
:ip_region, :ip_city, :ip_latitude, :ip_longitude, :ip_isp, :ip_org,
|
5
|
+
:anonymous_proxy, :proxy_score, :is_transparent_proxy,
|
6
|
+
:free_mail, :carder_email, :high_risk_username, :high_risk_password,
|
7
|
+
:bin_match, :bin_country, :bin_name_match, :bin_name, :bin_phone_match,
|
8
|
+
:bin_phone, :phone_in_billing_location, :ship_forward, :city_postal_match,
|
9
|
+
:ship_city_postal_match, :score, :explanation, :risk_score, :queries_remaining,
|
10
|
+
:maxmind_id, :error, :response
|
11
|
+
|
12
|
+
def initialize(response = nil)
|
13
|
+
raise ArgumentError, 'Missing response string' unless response
|
14
|
+
|
15
|
+
parse(response)
|
16
|
+
@attributes = attributes_from_response
|
17
|
+
end
|
18
|
+
|
19
|
+
def attributes_from_response
|
20
|
+
hash_to_return = {}
|
21
|
+
self.instance_variables.each do |var|
|
22
|
+
hash_to_return[var.gsub("@","")] = self.instance_variable_get(var)
|
23
|
+
end
|
24
|
+
return hash_to_return
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse(response)
|
28
|
+
response.split(';').each do |parameter|
|
29
|
+
k, v = parameter.split('=')
|
30
|
+
|
31
|
+
case k
|
32
|
+
when 'err'
|
33
|
+
set_attribute('error', v)
|
34
|
+
when 'custPhoneInBillingLoc'
|
35
|
+
set_attribute('phone_in_billing_location', v)
|
36
|
+
when 'maxmindID'
|
37
|
+
set_attribute('maxmind_id', v)
|
38
|
+
when 'isTransProxy'
|
39
|
+
set_attribute('is_transparent_proxy', v)
|
40
|
+
when 'explanation'
|
41
|
+
@explanation = v
|
42
|
+
else
|
43
|
+
set_attribute(k.gsub(/([A-Z])/, '_\1').downcase, v)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
alias_method :country_match?, :country_match
|
49
|
+
alias_method :high_risk_country?, :high_risk_country
|
50
|
+
alias_method :anonymous_proxy?, :anonymous_proxy
|
51
|
+
alias_method :is_transparent_proxy?, :is_transparent_proxy
|
52
|
+
alias_method :free_mail?, :free_mail
|
53
|
+
alias_method :carder_email?, :carder_email
|
54
|
+
alias_method :high_risk_username?, :high_risk_username
|
55
|
+
alias_method :high_risk_password?, :high_risk_password
|
56
|
+
alias_method :city_postal_match?, :city_postal_match
|
57
|
+
alias_method :ship_city_postal_match?, :ship_city_postal_match
|
58
|
+
alias_method :bin_match?, :bin_match
|
59
|
+
|
60
|
+
# Returns an array of names for the attributes available on this object sorted alphabetically.
|
61
|
+
def attribute_names
|
62
|
+
@attributes.keys.sort
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
|
66
|
+
def attributes
|
67
|
+
attrs = self.attribute_names.inject({}) do |attrs, name|
|
68
|
+
attrs[name] = read_attribute(name)
|
69
|
+
attrs
|
70
|
+
end
|
71
|
+
attrs.symbolize_keys
|
72
|
+
end
|
73
|
+
|
74
|
+
def read_attribute(attr_name)
|
75
|
+
attr_name = attr_name.to_s
|
76
|
+
if !(value = @attributes[attr_name]).nil?
|
77
|
+
value
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
def set_attribute(k, v)
|
85
|
+
if v.nil?
|
86
|
+
self.instance_variable_set("@#{k}", nil)
|
87
|
+
return
|
88
|
+
end
|
89
|
+
|
90
|
+
v = Integer(v) rescue Float(v) rescue v;
|
91
|
+
|
92
|
+
case v
|
93
|
+
when /[Yy]es/
|
94
|
+
self.instance_variable_set("@#{k}", true)
|
95
|
+
when /[Nn]o/
|
96
|
+
self.instance_variable_set("@#{k}", false)
|
97
|
+
else
|
98
|
+
self.instance_variable_set("@#{k}", v)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +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 Runner;ip_org=Road Runner;binNameMatch=Yes;binPhoneMatch=Yes;binPhone=;custPhoneInBillingLoc=No;highRiskCountry=No;queriesRemaining=955;cityPostalMatch=No;shipCityPostalMatch=Yes;maxmindID=9VSOSDE2;isTransProxy=No;carderEmail=No;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,131 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
REQUIRED_FIELDS = {
|
4
|
+
:client_ip => '24.24.24.24',
|
5
|
+
:city => 'New York',
|
6
|
+
:region => 'NY',
|
7
|
+
:postal => '11434',
|
8
|
+
:country => 'US'
|
9
|
+
}
|
10
|
+
|
11
|
+
RECOMMENDED_FIELDS = {
|
12
|
+
:domain => 'yahoo.com',
|
13
|
+
:bin => '549099',
|
14
|
+
:forwarded_ip => '24.24.24.25',
|
15
|
+
:email => 'test@test.com',
|
16
|
+
:username => 'test_carder_username',
|
17
|
+
:password => 'test_carder_password'
|
18
|
+
}
|
19
|
+
|
20
|
+
OPTIONAL_FIELDS = {
|
21
|
+
:bin_name => 'MBNA America Bank',
|
22
|
+
:bin_phone => '800-421-2110',
|
23
|
+
:cust_phone => '212-242',
|
24
|
+
:request_type => 'premium',
|
25
|
+
:shipping_address => '145-50 157th Street',
|
26
|
+
:shipping_city => 'Jamaica',
|
27
|
+
:shipping_region => 'NY',
|
28
|
+
:shipping_postal => '11434',
|
29
|
+
:shipping_country => 'US',
|
30
|
+
:transaction_id => '1234',
|
31
|
+
:session_id => 'abcd9876',
|
32
|
+
:user_agent => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1',
|
33
|
+
:accept_language => 'en-us'
|
34
|
+
}
|
35
|
+
|
36
|
+
class MaxmindTest < Test::Unit::TestCase
|
37
|
+
context "New Request object" do
|
38
|
+
setup do
|
39
|
+
Maxmind.license_key = 'key'
|
40
|
+
@request = Maxmind::Request.new(REQUIRED_FIELDS)
|
41
|
+
end
|
42
|
+
|
43
|
+
should "require a key" do
|
44
|
+
Maxmind.license_key = nil
|
45
|
+
lambda { @request.send(:validate) }.should raise_error(ArgumentError)
|
46
|
+
Maxmind.license_key = 'key'
|
47
|
+
end
|
48
|
+
|
49
|
+
should "require client IP" do
|
50
|
+
lambda { @request.client_ip = nil; @request.send(:validate) }.should raise_error(ArgumentError)
|
51
|
+
end
|
52
|
+
|
53
|
+
should "require city" do
|
54
|
+
lambda { @request.city = nil; @request.send(:validate) }.should raise_error(ArgumentError)
|
55
|
+
end
|
56
|
+
|
57
|
+
should "require region" do
|
58
|
+
lambda { @request.region = nil; @request.send(:validate) }.should raise_error(ArgumentError)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "require postal" do
|
62
|
+
lambda { @request.postal = nil; @request.send(:validate) }.should raise_error(ArgumentError)
|
63
|
+
end
|
64
|
+
|
65
|
+
should "require country" do
|
66
|
+
lambda { @request.country = nil; @request.send(:validate) }.should raise_error(ArgumentError)
|
67
|
+
end
|
68
|
+
|
69
|
+
should "convert username to MD5" do
|
70
|
+
@request.username = 'testuser'
|
71
|
+
@request.username.should == '5d9c68c6c50ed3d02a2fcf54f63993b6'
|
72
|
+
end
|
73
|
+
|
74
|
+
should "convert password to MD5" do
|
75
|
+
@request.password = 'testpassword'
|
76
|
+
@request.password.should == 'e16b2ab8d12314bf4efbd6203906ea6c'
|
77
|
+
end
|
78
|
+
|
79
|
+
should "convert email to MD5" do
|
80
|
+
@request.email = 'test@test.com'
|
81
|
+
@request.email.should == 'b642b4217b34b1e8d3bd915fc65c4452'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#context "Requesting" do
|
86
|
+
# setup do
|
87
|
+
# request = Maxmind::Request.new('LICENSE_KEY', REQUIRED_FIELDS.merge(RECOMMENDED_FIELDS).merge(OPTIONAL_FIELDS))
|
88
|
+
# FakeWeb.register_uri(:get, "http://minfraud3.maxmind.com/app/ccv2r?" + request.query(true), :string => File.read(File.join(File.dirname(__FILE__), "fixtures/basic.txt")))
|
89
|
+
#
|
90
|
+
# @response = Maxmind::Response.new(request)
|
91
|
+
# end
|
92
|
+
#end
|
93
|
+
|
94
|
+
context "Response" do
|
95
|
+
setup do
|
96
|
+
Maxmind.license_key = 'LICENSE_KEY'
|
97
|
+
request = Maxmind::Request.new(REQUIRED_FIELDS.merge(RECOMMENDED_FIELDS).merge(OPTIONAL_FIELDS))
|
98
|
+
FakeWeb.register_uri(:post, "https://minfraud1.maxmind.com/app/ccv2r", :body => File.read(File.join(File.dirname(__FILE__), "fixtures/response.txt")))
|
99
|
+
|
100
|
+
@response = request.process!
|
101
|
+
end
|
102
|
+
|
103
|
+
should "require a response" do
|
104
|
+
lambda { Maxmind::Response.new }.should raise_error(ArgumentError)
|
105
|
+
end
|
106
|
+
|
107
|
+
should "have a distance" do
|
108
|
+
@response.distance.should == 329
|
109
|
+
end
|
110
|
+
|
111
|
+
should "have a maxmind ID" do
|
112
|
+
@response.maxmind_id.should == '9VSOSDE2'
|
113
|
+
end
|
114
|
+
|
115
|
+
should "have a risk score" do
|
116
|
+
@response.risk_score.should == 2.0
|
117
|
+
end
|
118
|
+
|
119
|
+
should "have a score" do
|
120
|
+
@response.score.should == 7.66
|
121
|
+
end
|
122
|
+
|
123
|
+
should "have queries remaining" do
|
124
|
+
@response.queries_remaining.should == 955
|
125
|
+
end
|
126
|
+
|
127
|
+
should "have an explanation" do
|
128
|
+
@response.explanation.should_not == nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'matchy'
|
5
|
+
require 'fakeweb'
|
6
|
+
|
7
|
+
FakeWeb.allow_net_connect = false
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
10
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
11
|
+
require 'maxmind'
|
12
|
+
|
13
|
+
class Test::Unit::TestCase
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: maxmind-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Daniels
|
8
|
+
- Tinu Cleatus
|
9
|
+
- t.e.morgan
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
|
14
|
+
date: 2010-03-06 00:00:00 -07:00
|
15
|
+
default_executable:
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: activesupport
|
19
|
+
type: :runtime
|
20
|
+
version_requirement:
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: "2.3"
|
26
|
+
version:
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: shoulda
|
29
|
+
type: :development
|
30
|
+
version_requirement:
|
31
|
+
version_requirements: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
version:
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: matchy
|
39
|
+
type: :development
|
40
|
+
version_requirement:
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
description: |
|
48
|
+
A wrapper around MaxMind's minFraud anti-fraud service.
|
49
|
+
|
50
|
+
http://www.maxmind.com/app/ccv_overview
|
51
|
+
|
52
|
+
email: tm@iprog.com
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files:
|
58
|
+
- LICENSE
|
59
|
+
- README.markdown
|
60
|
+
files:
|
61
|
+
- .document
|
62
|
+
- .gitignore
|
63
|
+
- LICENSE
|
64
|
+
- README.markdown
|
65
|
+
- Rakefile
|
66
|
+
- VERSION
|
67
|
+
- examples/example.rb
|
68
|
+
- lib/maxmind.rb
|
69
|
+
- lib/maxmind/request.rb
|
70
|
+
- lib/maxmind/response.rb
|
71
|
+
- test/fixtures/response.txt
|
72
|
+
- test/maxmind_test.rb
|
73
|
+
- test/test_helper.rb
|
74
|
+
has_rdoc: true
|
75
|
+
homepage: http://github.com/zarqman/maxmind
|
76
|
+
licenses: []
|
77
|
+
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options:
|
80
|
+
- --charset=UTF-8
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
version:
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
version:
|
95
|
+
requirements: []
|
96
|
+
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.3.4
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Wrapper for MaxMind's minFraud service
|
102
|
+
test_files:
|
103
|
+
- test/maxmind_test.rb
|
104
|
+
- test/test_helper.rb
|
105
|
+
- examples/example.rb
|