onfido 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|