idnow 1.0.0 → 2.3.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 +5 -5
- data/.github/workflows/gem-push.yml +67 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -14
- data/.travis.yml +4 -2
- data/CODE_OF_CONDUCT.md +13 -0
- data/Dockerfile +9 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/Makefile +12 -1
- data/README.md +57 -12
- data/examples/idnow_automated_testing.rb +3 -1
- data/examples/idnow_download_identification.rb +3 -1
- data/examples/idnow_get_identification.rb +3 -1
- data/examples/idnow_upload_download_default_document.rb +3 -1
- data/idnow-client.gemspec +12 -10
- data/lib/idnow.rb +28 -9
- data/lib/idnow/API/authentication.rb +2 -0
- data/lib/idnow/API/automated_testing.rb +5 -3
- data/lib/idnow/API/document_definitions.rb +10 -7
- data/lib/idnow/API/download_documents.rb +4 -2
- data/lib/idnow/API/request_identifications.rb +3 -1
- data/lib/idnow/API/retrieve_identifications.rb +9 -6
- data/lib/idnow/API/upload_documents.rb +5 -2
- data/lib/idnow/client.rb +14 -9
- data/lib/idnow/configuration.rb +5 -8
- data/lib/idnow/exception.rb +2 -0
- data/lib/idnow/get_request.rb +2 -0
- data/lib/idnow/helpers.rb +3 -1
- data/lib/idnow/http_client.rb +12 -9
- data/lib/idnow/json_response.rb +3 -1
- data/lib/idnow/models/contact_data.rb +2 -0
- data/lib/idnow/models/document_definition.rb +2 -0
- data/lib/idnow/models/identification.rb +5 -2
- data/lib/idnow/models/identification_data.rb +20 -13
- data/lib/idnow/models/identification_document.rb +11 -18
- data/lib/idnow/models/identification_process.rb +4 -2
- data/lib/idnow/models/identification_request.rb +2 -0
- data/lib/idnow/models/login.rb +2 -0
- data/lib/idnow/models/login_data.rb +3 -1
- data/lib/idnow/models/user_data.rb +7 -0
- data/lib/idnow/modules/jsonable.rb +4 -1
- data/lib/idnow/post_binary_request.rb +2 -0
- data/lib/idnow/post_json_request.rb +2 -0
- data/lib/idnow/raw_response.rb +5 -3
- data/lib/idnow/sftp_client.rb +15 -3
- metadata +41 -37
- data/circle.yml +0 -7
@@ -1,18 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
module API
|
3
5
|
module AutomatedTesting
|
4
|
-
HOST = 'https://api.test.idnow.de'
|
6
|
+
HOST = 'https://api.test.idnow.de'
|
5
7
|
|
6
8
|
def testing_start(transaction_number:)
|
7
9
|
path = full_path_for("identifications/#{transaction_number}/start")
|
8
10
|
request = Idnow::PostJsonRequest.new(path, {})
|
9
|
-
execute(request, 'X-API_KEY' => @api_key, http_client: automated_testing_http_client)
|
11
|
+
execute(request, { 'X-API_KEY' => @api_key }, http_client: automated_testing_http_client)
|
10
12
|
end
|
11
13
|
|
12
14
|
def testing_request_video_chat(transaction_number:)
|
13
15
|
path = full_path_for("identifications/#{transaction_number}/requestVideoChat")
|
14
16
|
request = Idnow::PostJsonRequest.new(path, {})
|
15
|
-
execute(request, 'X-API_KEY' => @api_key, http_client: automated_testing_http_client)
|
17
|
+
execute(request, { 'X-API_KEY' => @api_key }, http_client: automated_testing_http_client)
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
@@ -1,28 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
module API
|
3
5
|
module DocumentDefinitions
|
4
6
|
def create_document_definition(document_data)
|
5
|
-
|
7
|
+
raise Idnow::AuthenticationException if @auth_token.nil?
|
6
8
|
|
7
9
|
path = full_path_for('documentdefinitions')
|
8
10
|
request = Idnow::PostJsonRequest.new(path, document_data)
|
9
|
-
execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
11
|
+
execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
|
10
12
|
end
|
11
13
|
|
12
14
|
def list_document_definitions
|
13
|
-
|
15
|
+
raise Idnow::AuthenticationException if @auth_token.nil?
|
14
16
|
|
15
17
|
path = full_path_for('documentdefinitions')
|
16
18
|
request = Idnow::GetRequest.new(path)
|
17
|
-
response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
19
|
+
response = execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
|
18
20
|
response.data.map do |data|
|
19
21
|
Idnow::DocumentDefinition.new(data)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
def list_cached_document_definitions(refresh = false)
|
24
|
-
return @
|
25
|
-
|
25
|
+
def list_cached_document_definitions(refresh = false) # rubocop:disable Style/OptionalBooleanParameter
|
26
|
+
return @list_cached_document_definitions = list_document_definitions if refresh
|
27
|
+
|
28
|
+
@list_cached_document_definitions ||= list_document_definitions
|
26
29
|
end
|
27
30
|
end
|
28
31
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
module API
|
3
5
|
module DownloadDocuments
|
4
6
|
def download_default_document(document_definition_identifier)
|
5
|
-
|
7
|
+
raise Idnow::AuthenticationException if @auth_token.nil?
|
6
8
|
|
7
9
|
path = full_path_for("documentdefinitions/#{document_definition_identifier}/data")
|
8
10
|
request = Idnow::GetRequest.new(path, '')
|
9
|
-
execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
11
|
+
execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
module API
|
3
5
|
module RequestIdentifications
|
4
6
|
def request_identification(transaction_number:, identification_data:)
|
5
7
|
path = full_path_for("identifications/#{transaction_number}/start")
|
6
8
|
request = Idnow::PostJsonRequest.new(path, identification_data)
|
7
|
-
response = execute(request, 'X-API-KEY' => @api_key)
|
9
|
+
response = execute(request, { 'X-API-KEY' => @api_key })
|
8
10
|
Idnow::IdentificationRequest.new(response.data, transaction_number, @target_host, @company_id)
|
9
11
|
end
|
10
12
|
end
|
@@ -1,29 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
module API
|
3
5
|
module RetrieveIdentifications
|
4
|
-
IDENTIFICATION_STATUSES = %w
|
6
|
+
IDENTIFICATION_STATUSES = %w[pending failed].freeze
|
5
7
|
|
6
8
|
def list_identifications(status: nil)
|
7
|
-
|
9
|
+
raise Idnow::AuthenticationException if @auth_token.nil?
|
8
10
|
|
9
11
|
unless status.nil? || IDENTIFICATION_STATUSES.include?(status)
|
10
|
-
|
12
|
+
raise Idnow::InvalidArguments, "Status #{status} not defined, possible options are: #{IDENTIFICATION_STATUSES.join(',')}"
|
11
13
|
end
|
14
|
+
|
12
15
|
partial_path = status.nil? ? 'identifications' : "identifications?#{status}=true"
|
13
16
|
path = full_path_for(partial_path)
|
14
17
|
request = Idnow::GetRequest.new(path)
|
15
|
-
response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
18
|
+
response = execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
|
16
19
|
response.data['identifications'].map do |data|
|
17
20
|
Idnow::Identification.new(data)
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
21
24
|
def get_identification(transaction_number:)
|
22
|
-
|
25
|
+
raise Idnow::AuthenticationException if @auth_token.nil?
|
23
26
|
|
24
27
|
path = full_path_for("identifications/#{transaction_number}")
|
25
28
|
request = Idnow::GetRequest.new(path)
|
26
|
-
response = execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
29
|
+
response = execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
|
27
30
|
Idnow::Identification.new(response.data)
|
28
31
|
end
|
29
32
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
module API
|
3
5
|
module UploadDocuments
|
@@ -14,9 +16,10 @@ module Idnow
|
|
14
16
|
private
|
15
17
|
|
16
18
|
def upload_document(file_data, request_path)
|
17
|
-
|
19
|
+
raise Idnow::AuthenticationException if @auth_token.nil?
|
20
|
+
|
18
21
|
request = Idnow::PostBinaryRequest.new(request_path, file_data)
|
19
|
-
execute(request, 'X-API-LOGIN-TOKEN' => @auth_token)
|
22
|
+
execute(request, { 'X-API-LOGIN-TOKEN' => @auth_token })
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|
data/lib/idnow/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'idnow/API/authentication'
|
2
4
|
require 'idnow/API/automated_testing' # shouldn't be included by default
|
3
5
|
require 'idnow/API/request_identifications'
|
@@ -16,21 +18,24 @@ module Idnow
|
|
16
18
|
include Idnow::API::UploadDocuments
|
17
19
|
include Idnow::API::DownloadDocuments
|
18
20
|
|
19
|
-
API_VERSION = 'v1'
|
21
|
+
API_VERSION = 'v1'
|
20
22
|
|
21
23
|
attr_reader :host
|
22
24
|
|
23
|
-
def initialize(env:, company_id:, api_key:)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@
|
25
|
+
def initialize(env:, company_id:, api_key:, timeout: nil, sftp_options: {})
|
26
|
+
raise 'Please set env to :test or :live' unless Idnow::ENVIRONMENTS.keys.include?(env)
|
27
|
+
raise 'Please set your company_id' if company_id.nil?
|
28
|
+
raise 'Please set your api_key' if api_key.nil?
|
29
|
+
|
30
|
+
@host = Idnow.endpoint(env, :host)
|
31
|
+
@target_host = Idnow.endpoint(env, :target_host)
|
29
32
|
@company_id = company_id
|
30
33
|
@api_key = api_key
|
31
34
|
|
32
35
|
@http_client = HttpClient.new(host: @host)
|
33
|
-
|
36
|
+
|
37
|
+
sftp_options[:timeout] = timeout if timeout
|
38
|
+
@sftp_client = SftpClient.new(host: @host, username: @company_id, password: @api_key, options: sftp_options)
|
34
39
|
end
|
35
40
|
|
36
41
|
private
|
@@ -45,7 +50,7 @@ module Idnow
|
|
45
50
|
end
|
46
51
|
|
47
52
|
response.tap do |r|
|
48
|
-
|
53
|
+
raise Idnow::ResponseException, r.errors if r.errors?
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
data/lib/idnow/configuration.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
class Configuration
|
3
5
|
# TODO: This class is not being used right now, but its aim is to be able for the developers
|
@@ -8,18 +10,13 @@ module Idnow
|
|
8
10
|
# config.company_id = company_id
|
9
11
|
# end
|
10
12
|
|
11
|
-
attr_accessor :api_key
|
12
|
-
|
13
|
-
attr_accessor :company_id
|
13
|
+
attr_accessor :api_key, :company_id, :host, :api_version
|
14
14
|
|
15
15
|
module Idnow
|
16
16
|
module Host
|
17
|
-
TEST = 'https://gateway.test.idnow.de'
|
18
|
-
PRODUCTION = 'https://gateway.idnow.de'
|
17
|
+
TEST = 'https://gateway.test.idnow.de'
|
18
|
+
PRODUCTION = 'https://gateway.idnow.de'
|
19
19
|
end
|
20
20
|
end
|
21
|
-
attr_accessor :host
|
22
|
-
|
23
|
-
attr_accessor :api_version
|
24
21
|
end
|
25
22
|
end
|
data/lib/idnow/exception.rb
CHANGED
data/lib/idnow/get_request.rb
CHANGED
data/lib/idnow/helpers.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
module Helpers
|
3
5
|
PROJECT_ROOT = File.dirname(File.dirname(File.dirname(__FILE__)))
|
4
6
|
|
5
7
|
module Factories
|
6
|
-
Dir[File.join(PROJECT_ROOT, 'spec', 'support', 'factories', '*.rb')].each { |file| require(file) }
|
8
|
+
Dir[File.join(PROJECT_ROOT, 'spec', 'support', 'factories', '*.rb')].sort.each { |file| require(file) }
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
data/lib/idnow/http_client.rb
CHANGED
@@ -1,26 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
class HttpClient
|
3
|
-
def initialize(host:)
|
4
|
-
@uri
|
5
|
+
def initialize(host:, read_timout_sec: 30)
|
6
|
+
@uri = URI.parse(host)
|
7
|
+
@read_timeout = read_timout_sec
|
5
8
|
end
|
6
9
|
|
7
10
|
def execute(request, headers = {})
|
8
11
|
headers.each do |k, v|
|
9
12
|
request[k] = v
|
10
13
|
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
14
|
+
|
15
|
+
client.request(request)
|
16
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
17
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
18
|
+
raise Idnow::ConnectionException, e
|
17
19
|
end
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
23
|
def client
|
22
24
|
Net::HTTP.new(@uri.host, @uri.port).tap do |http|
|
23
|
-
http.
|
25
|
+
http.read_timeout = @read_timeout
|
26
|
+
http.use_ssl = @uri.scheme == 'https'
|
24
27
|
end
|
25
28
|
end
|
26
29
|
end
|
data/lib/idnow/json_response.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
class JsonResponse < RawResponse
|
3
5
|
attr_reader :data
|
4
6
|
|
5
7
|
def initialize(raw_response)
|
6
8
|
super
|
7
|
-
raw_response =
|
9
|
+
raw_response = raw_response == '' ? '{}' : raw_response
|
8
10
|
@data = JSON.parse(raw_response)
|
9
11
|
end
|
10
12
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable'
|
2
|
-
|
4
|
+
|
3
5
|
module Idnow
|
4
6
|
class Identification
|
5
7
|
extend Forwardable
|
6
8
|
include Idnow::Jsonable
|
7
9
|
|
8
10
|
attr_accessor :identification_process, :contact_data, :user_data,
|
9
|
-
:identification_document, :attachments, :esigning
|
11
|
+
:identification_document, :attachments, :esigning, :raw_data
|
10
12
|
|
11
13
|
def initialize(data)
|
12
14
|
@identification_process = IdentificationProcess.new(data['identificationprocess'])
|
@@ -15,6 +17,7 @@ module Idnow
|
|
15
17
|
@identification_document = IdentificationDocument.new(data.fetch('identificationdocument', {}))
|
16
18
|
@attachments = data['attachments']
|
17
19
|
@esigning = data['esigning']
|
20
|
+
@raw_data = data
|
18
21
|
end
|
19
22
|
|
20
23
|
def esigning?
|
@@ -1,25 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module Idnow
|
4
6
|
class IdentificationData
|
5
7
|
module Gender
|
6
|
-
MALE = 'MALE'
|
7
|
-
FEMALE = 'FEMALE'
|
8
|
+
MALE = 'MALE'
|
9
|
+
FEMALE = 'FEMALE'
|
8
10
|
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
:
|
12
|
+
# rubocop:disable Naming/MethodName
|
13
|
+
attr_accessor :birthplace, :birthname, :city, :custom1,
|
14
|
+
:custom2, :custom3, :custom4, :custom5, :trackingid, :email, :firstname,
|
15
|
+
:lastname, :mobilephone, :nationality, :street, :streetnumber, :title, :zipcode,
|
16
|
+
:preferredLang
|
17
|
+
# rubocop:enable Naming/MethodName
|
18
|
+
|
19
|
+
attr_reader :country, :gender
|
13
20
|
|
14
21
|
def initialize(params = {})
|
15
|
-
params.
|
16
|
-
|
22
|
+
params.each_key do |key|
|
23
|
+
raise ArgumentError, "Attribute #{key} is not supported!" unless respond_to?(key.to_sym)
|
17
24
|
|
18
25
|
send("#{key}=", params[key])
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
|
-
def to_json
|
29
|
+
def to_json(*_args)
|
23
30
|
result = {}
|
24
31
|
instance_variables.each do |attribute|
|
25
32
|
result[attribute.to_s.delete('@')] = instance_variable_get(attribute)
|
@@ -30,7 +37,7 @@ module Idnow
|
|
30
37
|
########### Getter / Setter ############
|
31
38
|
|
32
39
|
def birthday
|
33
|
-
@birthday
|
40
|
+
@birthday&.strftime('%Y-%m-%d')
|
34
41
|
end
|
35
42
|
|
36
43
|
def birthday=(birthday)
|
@@ -42,18 +49,18 @@ module Idnow
|
|
42
49
|
end
|
43
50
|
|
44
51
|
def country=(country)
|
45
|
-
|
52
|
+
raise ArgumentError, 'Country must be ISO 3166 two letter country code' unless country.instance_of?(String) && country.size == 2
|
46
53
|
|
47
54
|
@country = country.upcase
|
48
55
|
end
|
49
56
|
|
50
57
|
def gender=(gender)
|
51
|
-
if %w
|
58
|
+
if %w[M MALE].include?(gender.to_s.strip.upcase)
|
52
59
|
@gender = Gender::MALE
|
53
|
-
elsif %w
|
60
|
+
elsif %w[F FEMALE].include?(gender.to_s.strip.upcase)
|
54
61
|
@gender = Gender::FEMALE
|
55
62
|
else
|
56
|
-
|
63
|
+
raise ArgumentError, 'Provide valid value for gender: MALE or FEMALE'
|
57
64
|
end
|
58
65
|
end
|
59
66
|
end
|
@@ -1,15 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Idnow
|
2
4
|
class IdentificationDocument
|
3
5
|
include Idnow::Jsonable
|
4
6
|
|
5
|
-
attr_accessor :country, :number, :issued_by, :
|
7
|
+
attr_accessor :country, :number, :issued_by, :type
|
8
|
+
attr_writer :date_issued, :valid_until
|
9
|
+
|
6
10
|
def initialize(data)
|
7
|
-
@country
|
8
|
-
@number
|
9
|
-
@issued_by
|
10
|
-
@date_issued
|
11
|
-
@type
|
12
|
-
@valid_until
|
11
|
+
@country = data.dig('country', 'value')
|
12
|
+
@number = data.dig('number', 'value')
|
13
|
+
@issued_by = data.dig('issuedby', 'value')
|
14
|
+
@date_issued = data.dig('dateissued', 'value')
|
15
|
+
@type = data.dig('type', 'value')
|
16
|
+
@valid_until = data.dig('validuntil', 'value')
|
13
17
|
end
|
14
18
|
|
15
19
|
def date_issued
|
@@ -19,16 +23,5 @@ module Idnow
|
|
19
23
|
def valid_until
|
20
24
|
Date.parse(@valid_until) if @valid_until
|
21
25
|
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def dig_value(*keys, data)
|
26
|
-
# TODO: use ruby 2.3 and dig
|
27
|
-
result = data
|
28
|
-
keys.each do |key|
|
29
|
-
result = result.fetch(key, {})
|
30
|
-
end
|
31
|
-
result['value']
|
32
|
-
end
|
33
26
|
end
|
34
27
|
end
|