idnow 1.0.0
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 +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +43 -0
- data/.travis.yml +4 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/Makefile +2 -0
- data/README.md +142 -0
- data/circle.yml +7 -0
- data/docs/IDnow_API.pdf +0 -0
- data/examples/idnow_automated_testing.rb +35 -0
- data/examples/idnow_download_identification.rb +16 -0
- data/examples/idnow_get_identification.rb +16 -0
- data/examples/idnow_upload_download_default_document.rb +33 -0
- data/idnow-client.gemspec +30 -0
- data/lib/idnow.rb +68 -0
- data/lib/idnow/API/authentication.rb +13 -0
- data/lib/idnow/API/automated_testing.rb +19 -0
- data/lib/idnow/API/document_definitions.rb +29 -0
- data/lib/idnow/API/download_documents.rb +13 -0
- data/lib/idnow/API/request_identifications.rb +12 -0
- data/lib/idnow/API/retrieve_identifications.rb +36 -0
- data/lib/idnow/API/upload_documents.rb +23 -0
- data/lib/idnow/client.rb +60 -0
- data/lib/idnow/configuration.rb +25 -0
- data/lib/idnow/exception.rb +25 -0
- data/lib/idnow/get_request.rb +10 -0
- data/lib/idnow/helpers.rb +9 -0
- data/lib/idnow/http_client.rb +27 -0
- data/lib/idnow/json_response.rb +11 -0
- data/lib/idnow/models/contact_data.rb +12 -0
- data/lib/idnow/models/document_definition.rb +15 -0
- data/lib/idnow/models/identification.rb +25 -0
- data/lib/idnow/models/identification_data.rb +60 -0
- data/lib/idnow/models/identification_document.rb +34 -0
- data/lib/idnow/models/identification_process.rb +29 -0
- data/lib/idnow/models/identification_request.rb +16 -0
- data/lib/idnow/models/login.rb +9 -0
- data/lib/idnow/models/login_data.rb +13 -0
- data/lib/idnow/models/user_data.rb +39 -0
- data/lib/idnow/modules/jsonable.rb +28 -0
- data/lib/idnow/post_binary_request.rb +11 -0
- data/lib/idnow/post_json_request.rb +12 -0
- data/lib/idnow/raw_response.rb +31 -0
- data/lib/idnow/sftp_client.rb +24 -0
- metadata +187 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
module Idnow
|
2
|
+
module API
|
3
|
+
module Authentication
|
4
|
+
def login
|
5
|
+
path = full_path_for('login')
|
6
|
+
login_data = Idnow::LoginData.new(@api_key)
|
7
|
+
request = Idnow::PostJsonRequest.new(path, login_data)
|
8
|
+
response = execute(request)
|
9
|
+
@auth_token = Idnow::Login.new(response.data).auth_token
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Idnow
|
2
|
+
module API
|
3
|
+
module AutomatedTesting
|
4
|
+
HOST = 'https://api.test.idnow.de'.freeze
|
5
|
+
|
6
|
+
def testing_start(transaction_number:)
|
7
|
+
path = full_path_for("identifications/#{transaction_number}/start")
|
8
|
+
request = Idnow::PostJsonRequest.new(path, {})
|
9
|
+
execute(request, 'X-API_KEY' => @api_key, http_client: automated_testing_http_client)
|
10
|
+
end
|
11
|
+
|
12
|
+
def testing_request_video_chat(transaction_number:)
|
13
|
+
path = full_path_for("identifications/#{transaction_number}/requestVideoChat")
|
14
|
+
request = Idnow::PostJsonRequest.new(path, {})
|
15
|
+
execute(request, 'X-API_KEY' => @api_key, http_client: automated_testing_http_client)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Idnow
|
2
|
+
module API
|
3
|
+
module DocumentDefinitions
|
4
|
+
def create_document_definition(document_data)
|
5
|
+
fail Idnow::AuthenticationException if @auth_token.nil?
|
6
|
+
|
7
|
+
path = full_path_for('documentdefinitions')
|
8
|
+
request = Idnow::PostJsonRequest.new(path, document_data)
|
9
|
+
execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
10
|
+
end
|
11
|
+
|
12
|
+
def list_document_definitions
|
13
|
+
fail Idnow::AuthenticationException if @auth_token.nil?
|
14
|
+
|
15
|
+
path = full_path_for('documentdefinitions')
|
16
|
+
request = Idnow::GetRequest.new(path)
|
17
|
+
response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
18
|
+
response.data.map do |data|
|
19
|
+
Idnow::DocumentDefinition.new(data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def list_cached_document_definitions(refresh = false)
|
24
|
+
return @document_definitions = list_document_definitions if refresh
|
25
|
+
@document_definitions ||= list_document_definitions
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Idnow
|
2
|
+
module API
|
3
|
+
module DownloadDocuments
|
4
|
+
def download_default_document(document_definition_identifier)
|
5
|
+
fail Idnow::AuthenticationException if @auth_token.nil?
|
6
|
+
|
7
|
+
path = full_path_for("documentdefinitions/#{document_definition_identifier}/data")
|
8
|
+
request = Idnow::GetRequest.new(path, '')
|
9
|
+
execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Idnow
|
2
|
+
module API
|
3
|
+
module RequestIdentifications
|
4
|
+
def request_identification(transaction_number:, identification_data:)
|
5
|
+
path = full_path_for("identifications/#{transaction_number}/start")
|
6
|
+
request = Idnow::PostJsonRequest.new(path, identification_data)
|
7
|
+
response = execute(request, 'X-API-KEY' => @api_key)
|
8
|
+
Idnow::IdentificationRequest.new(response.data, transaction_number, @target_host, @company_id)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Idnow
|
2
|
+
module API
|
3
|
+
module RetrieveIdentifications
|
4
|
+
IDENTIFICATION_STATUSES = %w(pending failed).freeze
|
5
|
+
|
6
|
+
def list_identifications(status: nil)
|
7
|
+
fail Idnow::AuthenticationException if @auth_token.nil?
|
8
|
+
|
9
|
+
unless status.nil? || IDENTIFICATION_STATUSES.include?(status)
|
10
|
+
fail Idnow::InvalidArguments, "Status #{status} not defined, possible options are: #{IDENTIFICATION_STATUSES.join(',')}"
|
11
|
+
end
|
12
|
+
partial_path = status.nil? ? 'identifications' : "identifications?#{status}=true"
|
13
|
+
path = full_path_for(partial_path)
|
14
|
+
request = Idnow::GetRequest.new(path)
|
15
|
+
response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
16
|
+
response.data['identifications'].map do |data|
|
17
|
+
Idnow::Identification.new(data)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_identification(transaction_number:)
|
22
|
+
fail Idnow::AuthenticationException if @auth_token.nil?
|
23
|
+
|
24
|
+
path = full_path_for("identifications/#{transaction_number}")
|
25
|
+
request = Idnow::GetRequest.new(path)
|
26
|
+
response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
27
|
+
Idnow::Identification.new(response.data)
|
28
|
+
end
|
29
|
+
|
30
|
+
def download_identification(transaction_number:)
|
31
|
+
path = "#{transaction_number}.zip"
|
32
|
+
@sftp_client.download(path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Idnow
|
2
|
+
module API
|
3
|
+
module UploadDocuments
|
4
|
+
def upload_identification_document(transaction_number, document_definition_identifier, file_data)
|
5
|
+
request_path = full_path_for("identifications/#{transaction_number}/documents/#{document_definition_identifier}/data")
|
6
|
+
upload_document(file_data, request_path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def upload_default_document(document_definition_identifier, file_data)
|
10
|
+
request_path = full_path_for("documentdefinitions/#{document_definition_identifier}/data")
|
11
|
+
upload_document(file_data, request_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def upload_document(file_data, request_path)
|
17
|
+
fail Idnow::AuthenticationException if @auth_token.nil?
|
18
|
+
request = Idnow::PostBinaryRequest.new(request_path, file_data)
|
19
|
+
execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/idnow/client.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'idnow/API/authentication'
|
2
|
+
require 'idnow/API/automated_testing' # shouldn't be included by default
|
3
|
+
require 'idnow/API/request_identifications'
|
4
|
+
require 'idnow/API/retrieve_identifications'
|
5
|
+
require 'idnow/API/document_definitions'
|
6
|
+
require 'idnow/API/upload_documents'
|
7
|
+
require 'idnow/API/download_documents'
|
8
|
+
|
9
|
+
module Idnow
|
10
|
+
class Client
|
11
|
+
include Idnow::API::Authentication
|
12
|
+
include Idnow::API::RetrieveIdentifications
|
13
|
+
include Idnow::API::RequestIdentifications
|
14
|
+
include Idnow::API::AutomatedTesting
|
15
|
+
include Idnow::API::DocumentDefinitions
|
16
|
+
include Idnow::API::UploadDocuments
|
17
|
+
include Idnow::API::DownloadDocuments
|
18
|
+
|
19
|
+
API_VERSION = 'v1'.freeze
|
20
|
+
|
21
|
+
attr_reader :host
|
22
|
+
|
23
|
+
def initialize(env:, company_id:, api_key:)
|
24
|
+
fail 'Please set env to :test or :live' unless Idnow::ENVIRONMENTS.keys.include?(env)
|
25
|
+
fail 'Please set your company_id' if company_id.nil?
|
26
|
+
fail 'Please set your api_key' if api_key.nil?
|
27
|
+
@host = Idnow::ENVIRONMENTS[env][:host]
|
28
|
+
@target_host = Idnow::ENVIRONMENTS[env][:target_host]
|
29
|
+
@company_id = company_id
|
30
|
+
@api_key = api_key
|
31
|
+
|
32
|
+
@http_client = HttpClient.new(host: @host)
|
33
|
+
@sftp_client = SftpClient.new(host: @host, username: @company_id, password: @api_key)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def execute(request, headers = {}, http_client: @http_client)
|
39
|
+
http_response = http_client.execute(request, headers)
|
40
|
+
|
41
|
+
response = if request.content_type == 'application/json'
|
42
|
+
Idnow::JsonResponse.new(http_response.body)
|
43
|
+
else
|
44
|
+
Idnow::RawResponse.new(http_response.body)
|
45
|
+
end
|
46
|
+
|
47
|
+
response.tap do |r|
|
48
|
+
fail Idnow::ResponseException, r.errors if r.errors?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def full_path_for(partial_path)
|
53
|
+
File.join('/api', API_VERSION, @company_id, partial_path)
|
54
|
+
end
|
55
|
+
|
56
|
+
def automated_testing_http_client
|
57
|
+
@automated_testing_http_client ||= HttpClient.new(host: Idnow::API::AutomatedTesting::HOST)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Idnow
|
2
|
+
class Configuration
|
3
|
+
# TODO: This class is not being used right now, but its aim is to be able for the developers
|
4
|
+
# using the gem to set its configuration with something like
|
5
|
+
# Idnow.config do |config|
|
6
|
+
# config.url = Idnow::TEST_SERVER
|
7
|
+
# config.env = :test
|
8
|
+
# config.company_id = company_id
|
9
|
+
# end
|
10
|
+
|
11
|
+
attr_accessor :api_key
|
12
|
+
|
13
|
+
attr_accessor :company_id
|
14
|
+
|
15
|
+
module Idnow
|
16
|
+
module Host
|
17
|
+
TEST = 'https://gateway.test.idnow.de'.freeze
|
18
|
+
PRODUCTION = 'https://gateway.idnow.de'.freeze
|
19
|
+
end
|
20
|
+
end
|
21
|
+
attr_accessor :host
|
22
|
+
|
23
|
+
attr_accessor :api_version
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Idnow
|
2
|
+
class Exception < StandardError
|
3
|
+
def initialize(message)
|
4
|
+
super("Request to IDnow failed: #{message}")
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class ConnectionException < Idnow::Exception
|
9
|
+
def initialize(exception)
|
10
|
+
super("#{exception.class}, #{exception.message}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ResponseException < Idnow::Exception
|
15
|
+
end
|
16
|
+
|
17
|
+
class AuthenticationException < Idnow::Exception
|
18
|
+
def initialize
|
19
|
+
super('Not authenticaton token found, please log in first')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class InvalidArguments < Idnow::Exception
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Idnow
|
2
|
+
class HttpClient
|
3
|
+
def initialize(host:)
|
4
|
+
@uri = URI.parse(host)
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute(request, headers = {})
|
8
|
+
headers.each do |k, v|
|
9
|
+
request[k] = v
|
10
|
+
end
|
11
|
+
begin
|
12
|
+
client.request(request)
|
13
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
14
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
15
|
+
raise Idnow::ConnectionException, e
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def client
|
22
|
+
Net::HTTP.new(@uri.host, @uri.port).tap do |http|
|
23
|
+
http.use_ssl = true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Idnow
|
2
|
+
class DocumentDefinition
|
3
|
+
include Idnow::Jsonable
|
4
|
+
|
5
|
+
attr_accessor :optional, :name, :identifier, :mime_type, :sort_order
|
6
|
+
|
7
|
+
def initialize(data)
|
8
|
+
@optional = data['optional']
|
9
|
+
@name = data['name']
|
10
|
+
@identifier = data['identifier']
|
11
|
+
@mime_type = data['mimeType']
|
12
|
+
@sort_order = data['sortOrder']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'pry'
|
3
|
+
module Idnow
|
4
|
+
class Identification
|
5
|
+
extend Forwardable
|
6
|
+
include Idnow::Jsonable
|
7
|
+
|
8
|
+
attr_accessor :identification_process, :contact_data, :user_data,
|
9
|
+
:identification_document, :attachments, :esigning
|
10
|
+
|
11
|
+
def initialize(data)
|
12
|
+
@identification_process = IdentificationProcess.new(data['identificationprocess'])
|
13
|
+
@contact_data = ContactData.new(data['contactdata'])
|
14
|
+
@user_data = UserData.new(data['userdata'])
|
15
|
+
@identification_document = IdentificationDocument.new(data.fetch('identificationdocument', {}))
|
16
|
+
@attachments = data['attachments']
|
17
|
+
@esigning = data['esigning']
|
18
|
+
end
|
19
|
+
|
20
|
+
def esigning?
|
21
|
+
!@esigning.nil?
|
22
|
+
end
|
23
|
+
def_delegators :identification_process, :successful?, :result, :reason, :id, :transaction_number, :review_pending?
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Idnow
|
4
|
+
class IdentificationData
|
5
|
+
module Gender
|
6
|
+
MALE = 'MALE'.freeze
|
7
|
+
FEMALE = 'FEMALE'.freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :birthplace, :birthname, :city, :country, :custom1,
|
11
|
+
:custom2, :custom3, :custom4, :custom5, :trackingid, :email, :firstname, :gender,
|
12
|
+
:lastname, :mobilephone, :nationality, :street, :streetnumber, :title, :zipcode
|
13
|
+
|
14
|
+
def initialize(params = {})
|
15
|
+
params.keys.each do |key|
|
16
|
+
fail ArgumentError, "Attribute #{key} is not supported!" unless respond_to?(key.to_sym)
|
17
|
+
|
18
|
+
send("#{key}=", params[key])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json
|
23
|
+
result = {}
|
24
|
+
instance_variables.each do |attribute|
|
25
|
+
result[attribute.to_s.delete('@')] = instance_variable_get(attribute)
|
26
|
+
end
|
27
|
+
result.to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
########### Getter / Setter ############
|
31
|
+
|
32
|
+
def birthday
|
33
|
+
@birthday.strftime('%Y-%m-%d') if @birthday
|
34
|
+
end
|
35
|
+
|
36
|
+
def birthday=(birthday)
|
37
|
+
@birthday = if birthday.instance_of?(Date) || birthday.instance_of?(DateTime)
|
38
|
+
birthday
|
39
|
+
else
|
40
|
+
Date.parse(birthday)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def country=(country)
|
45
|
+
fail ArgumentError, 'Country must be ISO 3166 two letter country code' unless country.instance_of?(String) && country.size == 2
|
46
|
+
|
47
|
+
@country = country.upcase
|
48
|
+
end
|
49
|
+
|
50
|
+
def gender=(gender)
|
51
|
+
if %w(M MALE).include?(gender.to_s.strip.upcase)
|
52
|
+
@gender = Gender::MALE
|
53
|
+
elsif %w(F FEMALE).include?(gender.to_s.strip.upcase)
|
54
|
+
@gender = Gender::FEMALE
|
55
|
+
else
|
56
|
+
fail ArgumentError, 'Provide valid value for gender: MALE or FEMALE'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|