onfido 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +161 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +14 -0
- data/LICENSE +22 -0
- data/LICENSE.txt +22 -0
- data/README.md +154 -0
- data/Rakefile +2 -0
- data/lib/onfido.rb +23 -0
- data/lib/onfido/address.rb +10 -0
- data/lib/onfido/api.rb +18 -0
- data/lib/onfido/applicant.rb +18 -0
- data/lib/onfido/check.rb +21 -0
- data/lib/onfido/configuration.rb +35 -0
- data/lib/onfido/document.rb +13 -0
- data/lib/onfido/null_logger.rb +6 -0
- data/lib/onfido/report.rb +11 -0
- data/lib/onfido/request_error.rb +23 -0
- data/lib/onfido/requestable.rb +12 -0
- data/lib/onfido/resource.rb +48 -0
- data/lib/onfido/response_handler.rb +38 -0
- data/lib/onfido/version.rb +3 -0
- data/onfido.gemspec +25 -0
- data/spec/integrations/4xx_response_spec.rb +35 -0
- data/spec/integrations/address_spec.rb +10 -0
- data/spec/integrations/applicant_spec.rb +73 -0
- data/spec/integrations/check_spec.rb +36 -0
- data/spec/integrations/document_spec.rb +27 -0
- data/spec/integrations/report_spec.rb +20 -0
- data/spec/onfido/request_error_spec.rb +39 -0
- data/spec/onfido/resource_spec.rb +63 -0
- data/spec/onfido/response_handler_spec.rb +79 -0
- data/spec/onfido_spec.rb +55 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/fake_onfido_api.rb +55 -0
- data/spec/support/fixtures/4xx_response.json +14 -0
- data/spec/support/fixtures/addresses.json +24 -0
- data/spec/support/fixtures/applicant.json +44 -0
- data/spec/support/fixtures/applicants.json +12 -0
- data/spec/support/fixtures/check.json +30 -0
- data/spec/support/fixtures/checks.json +34 -0
- data/spec/support/fixtures/document.json +10 -0
- data/spec/support/fixtures/report.json +10 -0
- data/spec/support/fixtures/reports.json +24 -0
- metadata +151 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module Onfido
|
2
|
+
class Applicant < Resource
|
3
|
+
def create(payload)
|
4
|
+
post(
|
5
|
+
url: url_for('applicants'),
|
6
|
+
payload: payload
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
def find(applicant_id)
|
11
|
+
get(url: url_for("applicants/#{applicant_id}"), payload: {})
|
12
|
+
end
|
13
|
+
|
14
|
+
def all
|
15
|
+
get(url: url_for("applicants"), payload: {})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/onfido/check.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Onfido
|
2
|
+
class Check < Resource
|
3
|
+
def create(applicant_id, payload)
|
4
|
+
post(
|
5
|
+
url: url_for("applicants/#{applicant_id}/checks"),
|
6
|
+
payload: payload
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
def find(applicant_id, check_id)
|
11
|
+
get(
|
12
|
+
url: url_for("applicants/#{applicant_id}/checks/#{check_id}"),
|
13
|
+
payload: {}
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def all(applicant_id)
|
18
|
+
get(url: url_for("applicants/#{applicant_id}/checks"), payload: {})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Onfido
|
2
|
+
module Configuration
|
3
|
+
attr_accessor :api_key, :throws_exceptions
|
4
|
+
|
5
|
+
def self.extended(base)
|
6
|
+
base.reset
|
7
|
+
end
|
8
|
+
|
9
|
+
def configure
|
10
|
+
yield self
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset
|
14
|
+
self.api_key = nil
|
15
|
+
self.throws_exceptions = true
|
16
|
+
RestClient.log = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def logger=(log)
|
20
|
+
if log.respond_to?(:<<)
|
21
|
+
RestClient.log = log
|
22
|
+
else
|
23
|
+
raise "#{log.class} doesn't seem to behave like a logger!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger
|
28
|
+
RestClient.log ||= NullLogger.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def endpoint
|
32
|
+
'https://api.onfido.com/v1/'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Onfido
|
2
|
+
class Document < Resource
|
3
|
+
# with open-uri the file can be a link or an actual file
|
4
|
+
|
5
|
+
def create(applicant_id, payload)
|
6
|
+
payload[:file] = open(payload.fetch(:file), 'r')
|
7
|
+
post(
|
8
|
+
url: url_for("applicants/#{applicant_id}/documents"),
|
9
|
+
payload: payload
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
=begin
|
2
|
+
The class will handle response failures coming from Onfido
|
3
|
+
It's main purpose is to produce meaningful error messages to the user e.g.
|
4
|
+
|
5
|
+
RequestError: Authorization error: please re-check your credentials
|
6
|
+
|
7
|
+
Users can also rescue the error and insect its type and affected fields as
|
8
|
+
specified in the Onfido documentation e.g.
|
9
|
+
|
10
|
+
begin
|
11
|
+
# error being raised
|
12
|
+
rescue Onfido::RequestError => e
|
13
|
+
e.type
|
14
|
+
e.fields
|
15
|
+
end
|
16
|
+
|
17
|
+
=end
|
18
|
+
|
19
|
+
module Onfido
|
20
|
+
class RequestError < StandardError
|
21
|
+
attr_accessor :type, :fields, :response_code
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Onfido
|
2
|
+
module Requestable
|
3
|
+
def make_request(options)
|
4
|
+
url = options.fetch(:url)
|
5
|
+
payload = options.fetch(:payload)
|
6
|
+
method = options.fetch(:method)
|
7
|
+
RestClient::Request.execute(url: url, payload: payload, method: method, headers: headers) do |response, *|
|
8
|
+
ResponseHandler.new(response).parse!
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Onfido
|
2
|
+
class Resource
|
3
|
+
VALID_HTTP_METHODS = %i(get post)
|
4
|
+
|
5
|
+
include Requestable
|
6
|
+
|
7
|
+
def url_for(path)
|
8
|
+
Onfido.endpoint + path
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method, *args)
|
12
|
+
if VALID_HTTP_METHODS.include?(method.to_sym)
|
13
|
+
make_request(
|
14
|
+
url: args.first.fetch(:url),
|
15
|
+
payload: build_query(args.first.fetch(:payload)),
|
16
|
+
method: method.to_sym
|
17
|
+
)
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def respond_to_missing?(method, include_private = false)
|
24
|
+
VALID_HTTP_METHODS.include?(method.to_sym) || super
|
25
|
+
end
|
26
|
+
|
27
|
+
def headers
|
28
|
+
{
|
29
|
+
'Authorization' => "Token token=#{Onfido.api_key}",
|
30
|
+
'Accept' => "application/json"
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# There seems to be a serialization issue with the HTTP client
|
37
|
+
# which does not serialize the payload properly.
|
38
|
+
# Have a look here https://gist.github.com/PericlesTheo/cb35139c57107ab3c84a
|
39
|
+
|
40
|
+
def build_query(payload)
|
41
|
+
if payload[:file]
|
42
|
+
payload
|
43
|
+
else
|
44
|
+
Rack::Utils.build_nested_query(payload)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Onfido
|
2
|
+
class ResponseHandler
|
3
|
+
attr_reader :response
|
4
|
+
|
5
|
+
def initialize(response)
|
6
|
+
@response = response
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse!
|
10
|
+
if Onfido.throws_exceptions && parsed_response["error"]
|
11
|
+
raise request_error
|
12
|
+
else
|
13
|
+
parsed_response
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def parsed_response
|
20
|
+
@parsed_response ||=
|
21
|
+
begin
|
22
|
+
JSON.parse(response)
|
23
|
+
rescue JSON::ParserError
|
24
|
+
{
|
25
|
+
'error' => {"message" => "Unparseable response: #{response}"}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def request_error
|
31
|
+
RequestError.new(parsed_response['error']['message']).tap do |error|
|
32
|
+
error.type = parsed_response['error']["type"]
|
33
|
+
error.fields = parsed_response['error']["fields"]
|
34
|
+
error.response_code = response.code if response.respond_to?(:code)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/onfido.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'onfido/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'onfido'
|
8
|
+
spec.version = Onfido::VERSION
|
9
|
+
spec.authors = ['Pericles Theodorou']
|
10
|
+
spec.email = ['periclestheo@gmail.com']
|
11
|
+
spec.summary = %q{A wrapper for Onfido API 1.0}
|
12
|
+
spec.description = %q{A wrapper for Onfido API 1.0}
|
13
|
+
spec.homepage = 'http://github.com/hvssle/onfido'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
|
24
|
+
spec.add_dependency 'rest-client', '~> 1.8.0'
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
describe Onfido::Resource do
|
2
|
+
let(:resource) { described_class.new }
|
3
|
+
let(:url) { Onfido.endpoint + path }
|
4
|
+
let(:api_key) { 'some_key' }
|
5
|
+
let(:payload) { {postcode: 'SE1 4NG'} }
|
6
|
+
|
7
|
+
|
8
|
+
before do
|
9
|
+
allow(Onfido).to receive(:api_key).and_return(api_key)
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when a response is a 4xx' do
|
13
|
+
let(:path) { '4xx_response' }
|
14
|
+
|
15
|
+
context "when 'throws_exceptions' is true" do
|
16
|
+
it 'raises a custom error' do
|
17
|
+
expect {
|
18
|
+
resource.get({url: url, payload: payload})
|
19
|
+
}.to raise_error(
|
20
|
+
Onfido::RequestError, 'Something went wrong')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when 'throws_exceptions' is false" do
|
25
|
+
before do
|
26
|
+
allow(Onfido).to receive(:throws_exceptions).and_return(false)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns the body as a hash' do
|
30
|
+
response = resource.get({url: url, payload: payload})
|
31
|
+
expect(response['error']).not_to be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
describe Onfido::Applicant do
|
2
|
+
subject(:applicant) { described_class.new }
|
3
|
+
let(:params) do
|
4
|
+
{
|
5
|
+
'title' => 'Mr',
|
6
|
+
'first_name' => 'Chandler',
|
7
|
+
'last_name' => 'Bing',
|
8
|
+
'gender' => 'male',
|
9
|
+
'middle_name' => 'Muriel',
|
10
|
+
'dob' => '1968-04-08',
|
11
|
+
'telephone' => '555555555',
|
12
|
+
'mobile' => '77777777',
|
13
|
+
'email' => 'chandler_bing_6@friends.com',
|
14
|
+
'addresses' => [
|
15
|
+
{
|
16
|
+
'flat_number' => '4',
|
17
|
+
'building_number' => '100',
|
18
|
+
'building_name' => 'Awesome Building',
|
19
|
+
'street' => 'Main Street',
|
20
|
+
'sub_street' => 'A sub street',
|
21
|
+
'town' => 'London',
|
22
|
+
'postcode' => 'SW4 6EH',
|
23
|
+
'country' => 'GBR'
|
24
|
+
},
|
25
|
+
{
|
26
|
+
'flat_number' => '1',
|
27
|
+
'building_number' => '10',
|
28
|
+
'building_name' => 'Great Building',
|
29
|
+
'street' => 'Old Street',
|
30
|
+
'sub_street' => 'Sub Street',
|
31
|
+
'town' => 'London',
|
32
|
+
'postcode' => 'SW1 4NG',
|
33
|
+
'country' => 'GBR'
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#create' do
|
40
|
+
# Need to find a better way of testing that the request is not malformed.
|
41
|
+
# Currently this runs for every feature spec. The fact that it's under here
|
42
|
+
# is only for semantic reasons
|
43
|
+
|
44
|
+
it 'serializes the payload correctly' do
|
45
|
+
WebMock.after_request do |request_signature, response|
|
46
|
+
if request_signature.uri.path == 'v1/applicants'
|
47
|
+
expect(Rack::Utils.parse_nested_query(request_signature.body)).to eq(params)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'creates an applicant' do
|
53
|
+
response = applicant.create(params)
|
54
|
+
expect(response['id']).not_to be_nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#find' do
|
59
|
+
let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
|
60
|
+
|
61
|
+
it 'returns the applicant' do
|
62
|
+
response = applicant.find(applicant_id)
|
63
|
+
expect(response['id']).to eq(applicant_id)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#all' do
|
68
|
+
it 'returns all the applicants' do
|
69
|
+
response = applicant.all
|
70
|
+
expect(response['applicants'].size).to eq(2)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
describe Onfido::Check do
|
2
|
+
subject(:check) { described_class.new }
|
3
|
+
let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
|
4
|
+
|
5
|
+
describe '#create' do
|
6
|
+
let(:params) do
|
7
|
+
{
|
8
|
+
type: 'express',
|
9
|
+
reports: [{name: 'identity'}]
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'creates a new check for an applicant' do
|
14
|
+
response = check.create(applicant_id, params)
|
15
|
+
expect(response['id']).not_to be_nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#find' do
|
20
|
+
let(:check_id) { '8546921-123123-123123' }
|
21
|
+
|
22
|
+
it 'returns an existing check for the applicant' do
|
23
|
+
response = check.find(applicant_id, check_id)
|
24
|
+
expect(response['id']).to eq(check_id)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#all' do
|
29
|
+
let(:check_id) { '8546921-123123-123123' }
|
30
|
+
|
31
|
+
it 'returns all existing checks for the applicant' do
|
32
|
+
response = check.all(applicant_id)
|
33
|
+
expect(response['checks'].size).to eq(1)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
describe Onfido::Document do
|
4
|
+
subject(:document) { described_class.new }
|
5
|
+
|
6
|
+
describe '#create' do
|
7
|
+
after do
|
8
|
+
file.close
|
9
|
+
file.unlink
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:file) { Tempfile.new(['passport', '.jpg']) }
|
13
|
+
let(:params) do
|
14
|
+
{
|
15
|
+
type: 'passport',
|
16
|
+
side: 'back',
|
17
|
+
file: file
|
18
|
+
}
|
19
|
+
let(:applicant_id) { '1030303-123123-123123' }
|
20
|
+
|
21
|
+
it 'creates a new document' do
|
22
|
+
response = document.create('foobar', params)
|
23
|
+
expect(response['id']).not_to be_nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|