Skip to content

Commit

Permalink
Added Chargeback Service support
Browse files Browse the repository at this point in the history
  • Loading branch information
darksheik committed Mar 23, 2013
1 parent 51df9d0 commit 27f3795
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 3 deletions.
46 changes: 43 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ This is every field available.

response = request.process!


Also see examples/example.rb

TODO
----
* Improve specs (eg, test server failover)
Expand All @@ -115,6 +112,48 @@ Reference
---------
[minFraud API Reference](http://www.maxmind.com/app/ccv)

Also see examples/example.rb

Chargeback Service
------------------

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.

Chargeback Service Usage
------------------------

### Minimum Required ###
These are the only required fields to acquire a response from MaxMind.

require 'maxmind'
Maxmind.license_key = 'LICENSE_KEY'
Maxmind.user_id = 'MAXMIND_USER_ID'
request = Maxmind::ChargebackRequest.new(
:client_ip => '24.24.24.24'
)

response = request.process!


### Recommended ###
For increased accuracy, these are the recommended fields to submit to MaxMind. The additional
fields here are optional and can be all or none.

require 'maxmind'
Maxmind.license_key = 'LICENSE_KEY'
Maxmind.user_id = 'MAXMIND_USER_ID'
request = Maxmind::ChargebackRequest.new(
:client_ip => '24.24.24.24',
:chargeback_code => 'Fraud',
:fraud_score => 'suspected_fraud',
:maxmind_id => 'KW36L83C',
:transaction_id => '12345'
)

response = request.process!

[minFraud Chargeback reference](http://dev.maxmind.com/minfraud/chargeback)

Contributors
------------
* Sam Oliver <sam@samoliver.com>
Expand All @@ -124,6 +163,7 @@ Contributors
* Tom Blomfield
* Thomas Morgan
* Tinu Cleatus <tinu.cleatus@me.com>
* Don Pflaster <dpflaster@gmail.com>

Thanks to all :)

Expand Down
20 changes: 20 additions & 0 deletions examples/chargeback_example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'pp'
require File.join(File.dirname(__FILE__), '..', 'lib/maxmind')

required_fields = {
:client_ip => '24.24.24.24'
}

recommended_fields = {
:client_ip => '24.24.24.24',
:chargeback_code => 'Fraud',
:fraud_score => 'suspected_fraud',
:maxmind_id => 'KW36L83C',
:transaction_id => '12345'
}

Maxmind.license_key = 'LICENSE_KEY'
Maxmind.user_id = 'MAXMIND_USER_ID'
request = Maxmind::ChargebackRequest.new(required_fields.merge(recommended_fields))
response = request.process!
pp response
3 changes: 3 additions & 0 deletions lib/maxmind.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

require 'maxmind/version'
require 'maxmind/request'
require 'maxmind/chargeback_request'
require 'maxmind/chargeback_response'
require 'maxmind/response'

module Maxmind
SERVERS = %w(minfraud.maxmind.com minfraud-us-east.maxmind.com minfraud-us-west.maxmind.com)

class << self
attr_accessor :license_key
attr_accessor :user_id
end
end
93 changes: 93 additions & 0 deletions lib/maxmind/chargeback_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
module Maxmind
class ChargebackRequest
DefaultTimeout = 60

# optionally set a default request type (one of 'standard' or 'premium')
# Maxmind's default behavior is to use premium if you have credits, else use standard
class << self
attr_accessor :default_request_type
attr_accessor :timeout
end

# Required Fields
attr_accessor :client_ip

# Optional Fields
attr_accessor :chargeback_code, :fraud_score, :maxmind_id, :transaction_id

def initialize(attrs={})
self.attributes = attrs
end

def attributes=(attrs={})
attrs.each do |k, v|
self.send("#{k}=", v)
end
end

def process!
resp = post(query)
Maxmind::ChargebackResponse.new(resp.message,resp.code)
end

def process
process!
rescue Exception => e
false
end

def query
validate

required_fields = {
:ip_address => @client_ip,
}

optional_fields = {
:chargeback_code => @chargeback_code,
:fraud_score => @fraud_score,
:maxmind_id => @maxmind_id,
:transaction_id => @transaction_id
}

field_set = required_fields.merge(optional_fields)
field_set.reject {|k, v| v.nil? }.to_json
end

private

# Upon a failure at the first URL, will automatically retry with the
# second & third ones before finally raising an exception
# Returns an HTTPResponse object
def post(query_params)
servers ||= SERVERS.map{|hostname| "https://#{hostname}/minfraud/chargeback"}
url = URI.parse(servers.shift)

req = Net::HTTP::Post.new(url.path, initheader = {'Content-Type' =>'application/json'})
req.basic_auth Maxmind::user_id, Maxmind::license_key
req.body = query_params

h = Net::HTTP.new(url.host, url.port)
h.use_ssl = true
h.verify_mode = OpenSSL::SSL::VERIFY_NONE

# set some timeouts
h.open_timeout = 60 # this blocks forever by default, lets be a bit less crazy.
h.read_timeout = self.class.timeout || DefaultTimeout
h.ssl_timeout = self.class.timeout || DefaultTimeout

h.start { |http| http.request(req) }

rescue Exception => e
retry if servers.size > 0
raise e
end

protected
def validate
raise ArgumentError, 'License key is required' unless Maxmind::license_key
raise ArgumentError, 'User ID is required' unless Maxmind::user_id
raise ArgumentError, 'IP address is required' unless client_ip
end
end
end
12 changes: 12 additions & 0 deletions lib/maxmind/chargeback_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Maxmind
class ChargebackResponse
attr_accessor :attributes
attr_reader :response, :http_code

def initialize(response = nil, http_code = nil)
raise ArgumentError, 'Missing response string' unless response
@response = response
@http_code = http_code.to_i if http_code
end
end
end

0 comments on commit 27f3795

Please sign in to comment.