yoti 1.6.1 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE.md +17 -0
- data/.gitignore +1 -0
- data/CONTRIBUTING.md +1 -30
- data/README.md +23 -224
- data/Rakefile +9 -8
- data/lib/yoti.rb +50 -1
- data/lib/yoti/activity_details.rb +1 -0
- data/lib/yoti/client.rb +13 -4
- data/lib/yoti/configuration.rb +7 -2
- data/lib/yoti/data_type/age_verification.rb +1 -1
- data/lib/yoti/data_type/base_profile.rb +1 -1
- data/lib/yoti/data_type/document_details.rb +5 -13
- data/lib/yoti/data_type/image.rb +4 -12
- data/lib/yoti/data_type/image_jpeg.rb +2 -0
- data/lib/yoti/data_type/image_png.rb +2 -0
- data/lib/yoti/data_type/media.rb +19 -0
- data/lib/yoti/doc_scan/client.rb +163 -0
- data/lib/yoti/doc_scan/constants.rb +28 -0
- data/lib/yoti/doc_scan/session/create/create_session_result.rb +50 -0
- data/lib/yoti/doc_scan/session/create/document_filter.rb +31 -0
- data/lib/yoti/doc_scan/session/create/document_restrictions_filter.rb +140 -0
- data/lib/yoti/doc_scan/session/create/notification_config.rb +142 -0
- data/lib/yoti/doc_scan/session/create/orthogonal_restrictions_filter.rb +150 -0
- data/lib/yoti/doc_scan/session/create/requested_check.rb +39 -0
- data/lib/yoti/doc_scan/session/create/requested_document_authenticity_check.rb +53 -0
- data/lib/yoti/doc_scan/session/create/requested_face_match_check.rb +95 -0
- data/lib/yoti/doc_scan/session/create/requested_liveness_check.rb +108 -0
- data/lib/yoti/doc_scan/session/create/requested_task.rb +39 -0
- data/lib/yoti/doc_scan/session/create/requested_text_extraction_task.rb +94 -0
- data/lib/yoti/doc_scan/session/create/required_document.rb +31 -0
- data/lib/yoti/doc_scan/session/create/required_id_document.rb +53 -0
- data/lib/yoti/doc_scan/session/create/sdk_config.rb +221 -0
- data/lib/yoti/doc_scan/session/create/session_specification.rb +203 -0
- data/lib/yoti/doc_scan/session/retrieve/authenticity_check_response.rb +12 -0
- data/lib/yoti/doc_scan/session/retrieve/breakdown_response.rb +38 -0
- data/lib/yoti/doc_scan/session/retrieve/check_response.rb +63 -0
- data/lib/yoti/doc_scan/session/retrieve/details_response.rb +28 -0
- data/lib/yoti/doc_scan/session/retrieve/document_fields_response.rb +21 -0
- data/lib/yoti/doc_scan/session/retrieve/face_map_response.rb +21 -0
- data/lib/yoti/doc_scan/session/retrieve/face_match_check_response.rb +12 -0
- data/lib/yoti/doc_scan/session/retrieve/frame_response.rb +21 -0
- data/lib/yoti/doc_scan/session/retrieve/generated_check_response.rb +28 -0
- data/lib/yoti/doc_scan/session/retrieve/generated_media.rb +28 -0
- data/lib/yoti/doc_scan/session/retrieve/generated_text_data_check_response.rb +12 -0
- data/lib/yoti/doc_scan/session/retrieve/get_session_result.rb +113 -0
- data/lib/yoti/doc_scan/session/retrieve/id_document_resource_response.rb +52 -0
- data/lib/yoti/doc_scan/session/retrieve/liveness_check_response.rb +12 -0
- data/lib/yoti/doc_scan/session/retrieve/liveness_resource_response.rb +24 -0
- data/lib/yoti/doc_scan/session/retrieve/media_response.rb +38 -0
- data/lib/yoti/doc_scan/session/retrieve/page_response.rb +27 -0
- data/lib/yoti/doc_scan/session/retrieve/recommendation_response.rb +34 -0
- data/lib/yoti/doc_scan/session/retrieve/report_response.rb +31 -0
- data/lib/yoti/doc_scan/session/retrieve/resource_container.rb +50 -0
- data/lib/yoti/doc_scan/session/retrieve/resource_response.rb +39 -0
- data/lib/yoti/doc_scan/session/retrieve/task_response.rb +87 -0
- data/lib/yoti/doc_scan/session/retrieve/text_data_check_response.rb +12 -0
- data/lib/yoti/doc_scan/session/retrieve/text_extraction_task_response.rb +18 -0
- data/lib/yoti/doc_scan/session/retrieve/zoom_liveness_resource_response.rb +33 -0
- data/lib/yoti/doc_scan/support/supported_documents.rb +60 -0
- data/lib/yoti/dynamic_share_service/extension/thirdparty_attribute_extension.rb +62 -11
- data/lib/yoti/dynamic_share_service/policy/dynamic_policy.rb +17 -17
- data/lib/yoti/dynamic_share_service/share_url.rb +28 -33
- data/lib/yoti/errors.rb +17 -2
- data/lib/yoti/http/aml_check_request.rb +12 -6
- data/lib/yoti/http/payloads/aml_address.rb +4 -0
- data/lib/yoti/http/payloads/aml_profile.rb +7 -1
- data/lib/yoti/http/profile_request.rb +11 -6
- data/lib/yoti/http/request.rb +221 -18
- data/lib/yoti/http/signed_request.rb +13 -4
- data/lib/yoti/protobuf/main.rb +1 -1
- data/lib/yoti/ssl.rb +3 -2
- data/lib/yoti/util/anchor_processor.rb +1 -1
- data/lib/yoti/util/validation.rb +41 -0
- data/lib/yoti/version.rb +1 -1
- data/rubocop.yml +9 -1
- data/yoti.gemspec +5 -8
- metadata +53 -63
- data/lib/yoti/sandbox.rb +0 -5
- data/lib/yoti/sandbox/anchor.rb +0 -49
- data/lib/yoti/sandbox/attribute.rb +0 -52
- data/lib/yoti/sandbox/profile.rb +0 -171
- data/lib/yoti/sandbox/sandbox.rb +0 -105
- data/lib/yoti/sandbox/sandbox_client.rb +0 -45
- data/login_flow.png +0 -0
@@ -16,8 +16,8 @@ module Yoti
|
|
16
16
|
false
|
17
17
|
end
|
18
18
|
|
19
|
-
def to_json(*
|
20
|
-
as_json.to_json
|
19
|
+
def to_json(*_args)
|
20
|
+
as_json.to_json
|
21
21
|
end
|
22
22
|
|
23
23
|
def as_json(*_args)
|
@@ -105,19 +105,19 @@ module Yoti
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def with_family_name(options = {})
|
108
|
-
with_wanted_attribute_by_name Attribute::FAMILY_NAME, options
|
108
|
+
with_wanted_attribute_by_name Attribute::FAMILY_NAME, **options
|
109
109
|
end
|
110
110
|
|
111
111
|
def with_given_names(options = {})
|
112
|
-
with_wanted_attribute_by_name Attribute::GIVEN_NAMES, options
|
112
|
+
with_wanted_attribute_by_name Attribute::GIVEN_NAMES, **options
|
113
113
|
end
|
114
114
|
|
115
115
|
def with_full_name(options = {})
|
116
|
-
with_wanted_attribute_by_name Attribute::FULL_NAME, options
|
116
|
+
with_wanted_attribute_by_name Attribute::FULL_NAME, **options
|
117
117
|
end
|
118
118
|
|
119
119
|
def with_date_of_birth(options = {})
|
120
|
-
with_wanted_attribute_by_name Attribute::DATE_OF_BIRTH, options
|
120
|
+
with_wanted_attribute_by_name Attribute::DATE_OF_BIRTH, **options
|
121
121
|
end
|
122
122
|
|
123
123
|
#
|
@@ -135,45 +135,45 @@ module Yoti
|
|
135
135
|
end
|
136
136
|
|
137
137
|
#
|
138
|
-
# @param [Integer]
|
138
|
+
# @param [Integer] age
|
139
139
|
#
|
140
140
|
def with_age_over(age, options = {})
|
141
|
-
with_age_derived_attribute(Attribute::AGE_OVER + age.to_s, options)
|
141
|
+
with_age_derived_attribute(Attribute::AGE_OVER + age.to_s, **options)
|
142
142
|
end
|
143
143
|
|
144
144
|
#
|
145
|
-
# @param [Integer]
|
145
|
+
# @param [Integer] age
|
146
146
|
#
|
147
147
|
def with_age_under(age, options = {})
|
148
|
-
with_age_derived_attribute(Attribute::AGE_UNDER + age.to_s, options)
|
148
|
+
with_age_derived_attribute(Attribute::AGE_UNDER + age.to_s, **options)
|
149
149
|
end
|
150
150
|
|
151
151
|
def with_gender(options = {})
|
152
|
-
with_wanted_attribute_by_name Attribute::GENDER, options
|
152
|
+
with_wanted_attribute_by_name Attribute::GENDER, **options
|
153
153
|
end
|
154
154
|
|
155
155
|
def with_postal_address(options = {})
|
156
|
-
with_wanted_attribute_by_name(Attribute::POSTAL_ADDRESS, options)
|
156
|
+
with_wanted_attribute_by_name(Attribute::POSTAL_ADDRESS, **options)
|
157
157
|
end
|
158
158
|
|
159
159
|
def with_structured_postal_address(options = {})
|
160
|
-
with_wanted_attribute_by_name(Attribute::STRUCTURED_POSTAL_ADDRESS, options)
|
160
|
+
with_wanted_attribute_by_name(Attribute::STRUCTURED_POSTAL_ADDRESS, **options)
|
161
161
|
end
|
162
162
|
|
163
163
|
def with_nationality(options = {})
|
164
|
-
with_wanted_attribute_by_name(Attribute::NATIONALITY, options)
|
164
|
+
with_wanted_attribute_by_name(Attribute::NATIONALITY, **options)
|
165
165
|
end
|
166
166
|
|
167
167
|
def with_phone_number(options = {})
|
168
|
-
with_wanted_attribute_by_name(Attribute::PHONE_NUMBER, options)
|
168
|
+
with_wanted_attribute_by_name(Attribute::PHONE_NUMBER, **options)
|
169
169
|
end
|
170
170
|
|
171
171
|
def with_selfie(options = {})
|
172
|
-
with_wanted_attribute_by_name(Attribute::SELFIE, options)
|
172
|
+
with_wanted_attribute_by_name(Attribute::SELFIE, **options)
|
173
173
|
end
|
174
174
|
|
175
175
|
def with_email(options = {})
|
176
|
-
with_wanted_attribute_by_name(Attribute::EMAIL_ADDRESS, options)
|
176
|
+
with_wanted_attribute_by_name(Attribute::EMAIL_ADDRESS, **options)
|
177
177
|
end
|
178
178
|
|
179
179
|
def with_document_details
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'securerandom'
|
4
|
+
|
3
5
|
module Yoti
|
4
6
|
module DynamicSharingService
|
5
7
|
class Share
|
@@ -11,50 +13,33 @@ module Yoti
|
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
14
|
-
def self.create_share_url_endpoint
|
15
|
-
"/qrcodes/apps/#{Yoti.configuration.client_sdk_id}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.create_share_url_query
|
19
|
-
"?nonce=#{SecureRandom.uuid}×tamp=#{Time.now.to_i}"
|
20
|
-
end
|
21
|
-
|
22
16
|
def self.create_share_url(scenario)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
yoti_request = Yoti::Request
|
18
|
+
.builder
|
19
|
+
.with_http_method('POST')
|
20
|
+
.with_base_url(Yoti.configuration.api_endpoint)
|
21
|
+
.with_endpoint("qrcodes/apps/#{Yoti.configuration.client_sdk_id}")
|
22
|
+
.with_query_param('appId', Yoti.configuration.client_sdk_id)
|
23
|
+
.with_payload(scenario)
|
24
|
+
.build
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
).sign
|
26
|
+
begin
|
27
|
+
create_share_url_parse_response yoti_request.execute
|
28
|
+
rescue Yoti::RequestError => e
|
29
|
+
raise if e.response.nil?
|
34
30
|
|
35
|
-
|
36
|
-
uri.hostname,
|
37
|
-
uri.port,
|
38
|
-
use_ssl: true
|
39
|
-
) do |http|
|
40
|
-
http.request signed_request
|
41
|
-
end
|
42
|
-
|
43
|
-
create_share_url_parse_response response
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.create_share_url_parse_response(response)
|
47
|
-
if response.code.to_i < 200 || response.code.to_i >= 300
|
48
|
-
case response.code
|
31
|
+
case e.response.code
|
49
32
|
when '400'
|
50
33
|
raise InvalidDataError
|
51
34
|
when '404'
|
52
35
|
raise ApplicationNotFoundError
|
53
36
|
else
|
54
|
-
raise UnknownHTTPError, response.code
|
37
|
+
raise UnknownHTTPError, e.response.code
|
55
38
|
end
|
56
39
|
end
|
40
|
+
end
|
57
41
|
|
42
|
+
def self.create_share_url_parse_response(response)
|
58
43
|
Share.new JSON.parse response.body
|
59
44
|
end
|
60
45
|
|
@@ -76,5 +61,15 @@ module Yoti
|
|
76
61
|
super msg
|
77
62
|
end
|
78
63
|
end
|
64
|
+
|
65
|
+
# @deprecated no longer used - will be removed in 2.0.0
|
66
|
+
def self.create_share_url_query
|
67
|
+
"?nonce=#{SecureRandom.uuid}×tamp=#{Time.now.to_i}"
|
68
|
+
end
|
69
|
+
|
70
|
+
# @deprecated no longer used - will be removed in 2.0.0
|
71
|
+
def self.create_share_url_endpoint
|
72
|
+
"/qrcodes/apps/#{Yoti.configuration.client_sdk_id}"
|
73
|
+
end
|
79
74
|
end
|
80
75
|
end
|
data/lib/yoti/errors.rb
CHANGED
@@ -3,12 +3,27 @@ module Yoti
|
|
3
3
|
class ProtobufError < StandardError; end
|
4
4
|
|
5
5
|
# Raises exceptions related to API requests
|
6
|
-
class RequestError < StandardError
|
6
|
+
class RequestError < StandardError
|
7
|
+
attr_reader :response
|
8
|
+
|
9
|
+
def initialize(message, response = nil)
|
10
|
+
super(append_response_message(message, response))
|
11
|
+
@response = response
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def append_response_message(message, response)
|
17
|
+
return message if response.nil? || response.body.empty?
|
18
|
+
|
19
|
+
"#{message}: #{response.body}"
|
20
|
+
end
|
21
|
+
end
|
7
22
|
|
8
23
|
# Raises exceptions related to OpenSSL actions
|
9
24
|
class SslError < StandardError; end
|
10
25
|
|
11
|
-
# Raises exceptions
|
26
|
+
# Raises exceptions related to an incorrect gem configuration value
|
12
27
|
class ConfigurationError < StandardError; end
|
13
28
|
|
14
29
|
# Raises exceptions related to AML actions
|
@@ -1,13 +1,16 @@
|
|
1
1
|
module Yoti
|
2
2
|
# Manage the API's AML check requests
|
3
3
|
class AmlCheckRequest
|
4
|
+
#
|
5
|
+
# @param [AmlProfile] aml_profile
|
6
|
+
#
|
4
7
|
def initialize(aml_profile)
|
5
8
|
@aml_profile = aml_profile
|
6
9
|
@payload = aml_profile.payload
|
7
10
|
@request = request
|
8
11
|
end
|
9
12
|
|
10
|
-
# @return [
|
13
|
+
# @return [Hash] a JSON representation of the AML check response
|
11
14
|
def response
|
12
15
|
JSON.parse(@request.body)
|
13
16
|
end
|
@@ -15,11 +18,14 @@ module Yoti
|
|
15
18
|
private
|
16
19
|
|
17
20
|
def request
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
Yoti::Request
|
22
|
+
.builder
|
23
|
+
.with_http_method('POST')
|
24
|
+
.with_base_url(Yoti.configuration.api_endpoint)
|
25
|
+
.with_endpoint('aml-check')
|
26
|
+
.with_query_param('appId', Yoti.configuration.client_sdk_id)
|
27
|
+
.with_payload(@payload)
|
28
|
+
.build
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
@@ -7,6 +7,10 @@ module Yoti
|
|
7
7
|
# @return [String] the postcode required for USA, optional otherwise
|
8
8
|
attr_accessor :post_code
|
9
9
|
|
10
|
+
#
|
11
|
+
# @param [String] country
|
12
|
+
# @param [String] post_code
|
13
|
+
#
|
10
14
|
def initialize(country, post_code = nil)
|
11
15
|
raise AmlError, 'AmlAddress requires a country.' if country.to_s.empty?
|
12
16
|
|
@@ -1,6 +1,12 @@
|
|
1
1
|
module Yoti
|
2
2
|
# Manages the AML check Profile object
|
3
3
|
class AmlProfile
|
4
|
+
#
|
5
|
+
# @param [String] given_names
|
6
|
+
# @param [String] family_name
|
7
|
+
# @param [AmlAddress] aml_address
|
8
|
+
# @param [String] ssn
|
9
|
+
#
|
4
10
|
def initialize(given_names, family_name, aml_address, ssn = nil)
|
5
11
|
@given_names = given_names
|
6
12
|
@family_name = family_name
|
@@ -11,7 +17,7 @@ module Yoti
|
|
11
17
|
raise AmlError, 'Request for USA require a valid SSN and postcode.' if usa_invalid
|
12
18
|
end
|
13
19
|
|
14
|
-
# @return [
|
20
|
+
# @return [Hash] the AML check request body
|
15
21
|
def payload
|
16
22
|
{
|
17
23
|
given_names: @given_names,
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Yoti
|
2
2
|
# Manage the API's profile requests
|
3
3
|
class ProfileRequest
|
4
|
+
#
|
5
|
+
# @param [String] encrypted_connect_token
|
6
|
+
#
|
4
7
|
def initialize(encrypted_connect_token)
|
5
8
|
@encrypted_connect_token = encrypted_connect_token
|
6
9
|
@request = request
|
@@ -14,12 +17,14 @@ module Yoti
|
|
14
17
|
private
|
15
18
|
|
16
19
|
def request
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
Yoti::Request
|
21
|
+
.builder
|
22
|
+
.with_http_method('GET')
|
23
|
+
.with_base_url(Yoti.configuration.api_endpoint)
|
24
|
+
.with_endpoint("profile/#{Yoti::SSL.decrypt_token(@encrypted_connect_token)}")
|
25
|
+
.with_query_param('appId', Yoti.configuration.client_sdk_id)
|
26
|
+
.with_header('X-Yoti-Auth-Key', Yoti::SSL.auth_key_from_pem)
|
27
|
+
.build
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
data/lib/yoti/http/request.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'cgi'
|
3
|
+
|
1
4
|
module Yoti
|
2
5
|
# Manage the API's HTTPS requests
|
3
6
|
class Request
|
7
|
+
# @deprecated will be removed in 2.0.0 - token is now provided with the endpoint
|
4
8
|
# @return [String] the URL token received from Yoti Connect
|
5
9
|
attr_accessor :encrypted_connect_token
|
6
10
|
|
11
|
+
# @return [String] the base URL
|
12
|
+
attr_writer :base_url
|
13
|
+
|
14
|
+
# @return [Hash] query params to add to the request
|
15
|
+
attr_accessor :query_params
|
16
|
+
|
7
17
|
# @return [String] the HTTP method used for the request
|
8
18
|
# The allowed methods are: GET, DELETE, POST, PUT, PATCH
|
9
19
|
attr_accessor :http_method
|
@@ -11,36 +21,93 @@ module Yoti
|
|
11
21
|
# @return [String] the API endpoint for the request
|
12
22
|
attr_accessor :endpoint
|
13
23
|
|
14
|
-
# @return [
|
24
|
+
# @return [#to_json,String] the body sent with the request
|
15
25
|
attr_accessor :payload
|
16
26
|
|
17
27
|
def initialize
|
18
28
|
@headers = {}
|
19
29
|
end
|
20
30
|
|
31
|
+
#
|
32
|
+
# @return [RequestBuilder]
|
33
|
+
#
|
34
|
+
def self.builder
|
35
|
+
RequestBuilder.new
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
21
39
|
# Adds a HTTP header to the request
|
40
|
+
#
|
41
|
+
# @param [String] header
|
42
|
+
# @param [String] value
|
43
|
+
#
|
22
44
|
def add_header(header, value)
|
23
45
|
@headers[header] = value
|
24
46
|
end
|
25
47
|
|
48
|
+
#
|
26
49
|
# Makes a HTTP request after signing the headers
|
27
|
-
#
|
28
|
-
|
50
|
+
#
|
51
|
+
# @return [HTTPResponse]
|
52
|
+
#
|
53
|
+
def execute
|
29
54
|
raise RequestError, 'The request requires a HTTP method.' unless @http_method
|
30
|
-
raise RequestError, 'The payload needs to be a hash.' unless @payload.to_s.empty? || @payload.is_a?(Hash)
|
31
55
|
|
32
|
-
|
56
|
+
http_res = Net::HTTP.start(uri.hostname, Yoti.configuration.api_port, use_ssl: https_uri?) do |http|
|
33
57
|
signed_request = SignedRequest.new(unsigned_request, path, @payload).sign
|
34
58
|
http.request(signed_request)
|
35
59
|
end
|
36
60
|
|
37
|
-
raise RequestError
|
61
|
+
raise RequestError.new("Unsuccessful Yoti API call: #{http_res.message}", http_res) unless response_is_success(http_res)
|
38
62
|
|
39
|
-
|
63
|
+
http_res
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Makes a HTTP request and returns the body after signing the headers
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
#
|
71
|
+
def body
|
72
|
+
execute.body
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# @return [String] the base URL
|
77
|
+
#
|
78
|
+
def base_url
|
79
|
+
@base_url ||= Yoti.configuration.api_endpoint
|
40
80
|
end
|
41
81
|
|
42
82
|
private
|
43
83
|
|
84
|
+
#
|
85
|
+
# @param [Net::HTTPResponse] http_res
|
86
|
+
#
|
87
|
+
# @return [Boolean]
|
88
|
+
#
|
89
|
+
def response_is_success(http_res)
|
90
|
+
http_res.code.to_i >= 200 && http_res.code.to_i < 300
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Adds payload to provided HTTP request
|
95
|
+
#
|
96
|
+
# @param [Net::HTTPRequest] http_req
|
97
|
+
#
|
98
|
+
def add_payload(http_req)
|
99
|
+
return if @payload.to_s.empty?
|
100
|
+
|
101
|
+
if @payload.is_a?(String)
|
102
|
+
http_req.body = @payload
|
103
|
+
elsif @payload.respond_to?(:to_json)
|
104
|
+
http_req.body = @payload.to_json
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# @return [Net::HTTPRequest] the unsigned HTTP request
|
110
|
+
#
|
44
111
|
def unsigned_request
|
45
112
|
case @http_method
|
46
113
|
when 'GET'
|
@@ -49,13 +116,13 @@ module Yoti
|
|
49
116
|
http_req = Net::HTTP::Delete.new(uri)
|
50
117
|
when 'POST'
|
51
118
|
http_req = Net::HTTP::Post.new(uri)
|
52
|
-
http_req
|
119
|
+
add_payload(http_req)
|
53
120
|
when 'PUT'
|
54
121
|
http_req = Net::HTTP::Put.new(uri)
|
55
|
-
http_req
|
122
|
+
add_payload(http_req)
|
56
123
|
when 'PATCH'
|
57
124
|
http_req = Net::HTTP::Patch.new(uri)
|
58
|
-
http_req
|
125
|
+
add_payload(http_req)
|
59
126
|
else
|
60
127
|
raise RequestError, "Request method not allowed: #{@http_method}"
|
61
128
|
end
|
@@ -67,22 +134,27 @@ module Yoti
|
|
67
134
|
http_req
|
68
135
|
end
|
69
136
|
|
137
|
+
#
|
138
|
+
# @return [URI] the full request URI
|
139
|
+
#
|
70
140
|
def uri
|
71
|
-
@uri ||= URI(
|
141
|
+
@uri ||= URI(base_url + path)
|
72
142
|
end
|
73
143
|
|
144
|
+
#
|
145
|
+
# @return [String] the path with query string
|
146
|
+
#
|
74
147
|
def path
|
75
148
|
@path ||= begin
|
76
|
-
|
77
|
-
timestamp = Time.now.to_i
|
78
|
-
|
79
|
-
"/#{@endpoint}/#{token}"\
|
80
|
-
"?nonce=#{nonce}"\
|
81
|
-
"×tamp=#{timestamp}"\
|
82
|
-
"&appId=#{Yoti.configuration.client_sdk_id}"
|
149
|
+
"/#{@endpoint}/#{token}".chomp('/') + "?#{query_string}"
|
83
150
|
end
|
84
151
|
end
|
85
152
|
|
153
|
+
#
|
154
|
+
# @deprecated will be removed in 2.0.0 - token is now provided with the endpoint
|
155
|
+
#
|
156
|
+
# @return [String] the decrypted connect token
|
157
|
+
#
|
86
158
|
def token
|
87
159
|
return '' unless @encrypted_connect_token
|
88
160
|
|
@@ -92,5 +164,136 @@ module Yoti
|
|
92
164
|
def https_uri?
|
93
165
|
uri.scheme == 'https'
|
94
166
|
end
|
167
|
+
|
168
|
+
#
|
169
|
+
# Builds query string including nonce and timestamp
|
170
|
+
#
|
171
|
+
# @return [String]
|
172
|
+
#
|
173
|
+
def query_string
|
174
|
+
params = {
|
175
|
+
nonce: SecureRandom.uuid,
|
176
|
+
timestamp: Time.now.to_i
|
177
|
+
}
|
178
|
+
|
179
|
+
if @query_params.nil?
|
180
|
+
# @deprecated this default will be removed in 2.0.0
|
181
|
+
# Append appId when no custom query params are provided.
|
182
|
+
params.merge!(appId: Yoti.configuration.client_sdk_id)
|
183
|
+
else
|
184
|
+
Validation.assert_is_a(Hash, @query_params, 'query_params')
|
185
|
+
params.merge!(@query_params)
|
186
|
+
end
|
187
|
+
|
188
|
+
params.map do |k, v|
|
189
|
+
CGI.escape(k.to_s) + '=' + CGI.escape(v.to_s)
|
190
|
+
end.join('&')
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
# Builder for {Request}
|
196
|
+
#
|
197
|
+
class RequestBuilder
|
198
|
+
def initialize
|
199
|
+
@headers = {}
|
200
|
+
@query_params = {}
|
201
|
+
end
|
202
|
+
|
203
|
+
#
|
204
|
+
# Sets the base URL
|
205
|
+
#
|
206
|
+
# @param [String] base_url
|
207
|
+
#
|
208
|
+
# @return [self]
|
209
|
+
#
|
210
|
+
def with_base_url(base_url)
|
211
|
+
Validation.assert_is_a(String, base_url, 'base_url')
|
212
|
+
@base_url = base_url
|
213
|
+
self
|
214
|
+
end
|
215
|
+
|
216
|
+
#
|
217
|
+
# Adds a HTTP header to the request
|
218
|
+
#
|
219
|
+
# @param [String] header
|
220
|
+
# @param [String] value
|
221
|
+
#
|
222
|
+
# @return [self]
|
223
|
+
#
|
224
|
+
def with_header(header, value)
|
225
|
+
Validation.assert_is_a(String, header, 'header')
|
226
|
+
Validation.assert_is_a(String, value, 'value')
|
227
|
+
@headers[header] = value
|
228
|
+
self
|
229
|
+
end
|
230
|
+
|
231
|
+
#
|
232
|
+
# Adds a query parameter to the request
|
233
|
+
#
|
234
|
+
# @param [String] key
|
235
|
+
# @param [String] value
|
236
|
+
#
|
237
|
+
# @return [self]
|
238
|
+
#
|
239
|
+
def with_query_param(key, value)
|
240
|
+
Validation.assert_is_a(String, key, 'key')
|
241
|
+
Validation.assert_is_a(String, value, 'value')
|
242
|
+
@query_params[key] = value
|
243
|
+
self
|
244
|
+
end
|
245
|
+
|
246
|
+
#
|
247
|
+
# Sets the HTTP method
|
248
|
+
#
|
249
|
+
# @param [String] http_method
|
250
|
+
#
|
251
|
+
# @return [self]
|
252
|
+
#
|
253
|
+
def with_http_method(http_method)
|
254
|
+
Validation.assert_is_a(String, http_method, 'http_method')
|
255
|
+
@http_method = http_method
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
#
|
260
|
+
# Sets the API endpoint for the request
|
261
|
+
#
|
262
|
+
# @param [String] endpoint
|
263
|
+
#
|
264
|
+
# @return [self]
|
265
|
+
#
|
266
|
+
def with_endpoint(endpoint)
|
267
|
+
Validation.assert_is_a(String, endpoint, 'endpoint')
|
268
|
+
@endpoint = endpoint
|
269
|
+
self
|
270
|
+
end
|
271
|
+
|
272
|
+
#
|
273
|
+
# Sets the body sent with the request
|
274
|
+
#
|
275
|
+
# @param [#to_json,String] payload
|
276
|
+
#
|
277
|
+
# @return [self]
|
278
|
+
#
|
279
|
+
def with_payload(payload)
|
280
|
+
Validation.assert_respond_to(:to_json, payload, 'payload') unless payload.is_a?(String)
|
281
|
+
@payload = payload
|
282
|
+
self
|
283
|
+
end
|
284
|
+
|
285
|
+
#
|
286
|
+
# @return [Request]
|
287
|
+
#
|
288
|
+
def build
|
289
|
+
request = Request.new
|
290
|
+
request.base_url = @base_url
|
291
|
+
request.endpoint = @endpoint
|
292
|
+
request.query_params = @query_params
|
293
|
+
request.http_method = @http_method
|
294
|
+
request.payload = @payload
|
295
|
+
@headers.map { |k, v| request.add_header(k, v) }
|
296
|
+
request
|
297
|
+
end
|
95
298
|
end
|
96
299
|
end
|