sumsub-ruby-sdk 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +13 -0
- data/.editorconfig +20 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +105 -0
- data/LICENSE.txt +21 -0
- data/README.md +88 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/sumsub.rb +40 -0
- data/lib/sumsub/configuration.rb +11 -0
- data/lib/sumsub/message_signer.rb +17 -0
- data/lib/sumsub/parser.rb +18 -0
- data/lib/sumsub/request.rb +204 -0
- data/lib/sumsub/struct/address.rb +20 -0
- data/lib/sumsub/struct/applicant.rb +16 -0
- data/lib/sumsub/struct/applicant_update.rb +16 -0
- data/lib/sumsub/struct/base_struct.rb +11 -0
- data/lib/sumsub/struct/document_metadata.rb +20 -0
- data/lib/sumsub/struct/error_response.rb +14 -0
- data/lib/sumsub/struct/info.rb +25 -0
- data/lib/sumsub/version.rb +5 -0
- data/lib/types.rb +39 -0
- data/sumsub-ruby-sdk.gemspec +45 -0
- metadata +171 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 507bfecc21b02884373eeaaf2ef76729711b710b348a7d6de2b289349b5cb1ae
|
4
|
+
data.tar.gz: e943a0860aa49188e629a87a43a8b09ecac65079cacd76e7ffb601c1b4d4aec9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 22eb29cf663da0995ae277ca39263b2c9e38a937c1b02a3ba7b750246b1292de7592ec336a772511555c34823e617506f8d4a9cc821560aed46dfc9be75695f7
|
7
|
+
data.tar.gz: 5a3c8f478845385fc6a6f326b9d13043d6dc20930a2353d555cd3853f9fa0f5118500e3b8bc43f42cb9d8aa9aaaabb358a65c91833590b12c0bca32e2e64d063
|
data/.editorconfig
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# top-most EditorConfig file
|
2
|
+
root = true
|
3
|
+
|
4
|
+
# Unix-style newlines with a newline ending every file
|
5
|
+
[*]
|
6
|
+
end_of_line = lf
|
7
|
+
insert_final_newline = true
|
8
|
+
|
9
|
+
# Set default charset
|
10
|
+
charset = utf-8
|
11
|
+
|
12
|
+
# General identation style
|
13
|
+
[*]
|
14
|
+
indent_style = space
|
15
|
+
indent_size = 2
|
16
|
+
|
17
|
+
# Makefile's only accept tab identations
|
18
|
+
[Makefile]
|
19
|
+
indent_style = tab
|
20
|
+
indent_size = 2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sumsub-ruby-sdk (0.1.1)
|
5
|
+
dry-struct (~> 1.4.0)
|
6
|
+
http (~> 5.0.0)
|
7
|
+
mime-types (~> 3.3.1)
|
8
|
+
pry (~> 0.14.1)
|
9
|
+
rspec (~> 3.10.0)
|
10
|
+
timecop (~> 0.9.4)
|
11
|
+
webmock (~> 3.13.0)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
addressable (2.7.0)
|
17
|
+
public_suffix (>= 2.0.2, < 5.0)
|
18
|
+
coderay (1.1.3)
|
19
|
+
concurrent-ruby (1.1.8)
|
20
|
+
crack (0.4.5)
|
21
|
+
rexml
|
22
|
+
diff-lcs (1.4.4)
|
23
|
+
domain_name (0.5.20190701)
|
24
|
+
unf (>= 0.0.5, < 1.0.0)
|
25
|
+
dry-configurable (0.12.1)
|
26
|
+
concurrent-ruby (~> 1.0)
|
27
|
+
dry-core (~> 0.5, >= 0.5.0)
|
28
|
+
dry-container (0.7.2)
|
29
|
+
concurrent-ruby (~> 1.0)
|
30
|
+
dry-configurable (~> 0.1, >= 0.1.3)
|
31
|
+
dry-core (0.5.0)
|
32
|
+
concurrent-ruby (~> 1.0)
|
33
|
+
dry-inflector (0.2.0)
|
34
|
+
dry-logic (1.2.0)
|
35
|
+
concurrent-ruby (~> 1.0)
|
36
|
+
dry-core (~> 0.5, >= 0.5)
|
37
|
+
dry-struct (1.4.0)
|
38
|
+
dry-core (~> 0.5, >= 0.5)
|
39
|
+
dry-types (~> 1.5)
|
40
|
+
ice_nine (~> 0.11)
|
41
|
+
dry-types (1.5.1)
|
42
|
+
concurrent-ruby (~> 1.0)
|
43
|
+
dry-container (~> 0.3)
|
44
|
+
dry-core (~> 0.5, >= 0.5)
|
45
|
+
dry-inflector (~> 0.1, >= 0.1.2)
|
46
|
+
dry-logic (~> 1.0, >= 1.0.2)
|
47
|
+
ffi (1.15.0)
|
48
|
+
ffi-compiler (1.0.1)
|
49
|
+
ffi (>= 1.0.0)
|
50
|
+
rake
|
51
|
+
hashdiff (1.0.1)
|
52
|
+
http (5.0.0)
|
53
|
+
addressable (~> 2.3)
|
54
|
+
http-cookie (~> 1.0)
|
55
|
+
http-form_data (~> 2.2)
|
56
|
+
llhttp-ffi (~> 0.0.1)
|
57
|
+
http-cookie (1.0.3)
|
58
|
+
domain_name (~> 0.5)
|
59
|
+
http-form_data (2.3.0)
|
60
|
+
ice_nine (0.11.2)
|
61
|
+
llhttp-ffi (0.0.1)
|
62
|
+
ffi-compiler (~> 1.0)
|
63
|
+
rake (~> 13.0)
|
64
|
+
method_source (1.0.0)
|
65
|
+
mime-types (3.3.1)
|
66
|
+
mime-types-data (~> 3.2015)
|
67
|
+
mime-types-data (3.2021.0225)
|
68
|
+
pry (0.14.1)
|
69
|
+
coderay (~> 1.1)
|
70
|
+
method_source (~> 1.0)
|
71
|
+
public_suffix (4.0.6)
|
72
|
+
rake (13.0.3)
|
73
|
+
rexml (3.2.5)
|
74
|
+
rspec (3.10.0)
|
75
|
+
rspec-core (~> 3.10.0)
|
76
|
+
rspec-expectations (~> 3.10.0)
|
77
|
+
rspec-mocks (~> 3.10.0)
|
78
|
+
rspec-core (3.10.1)
|
79
|
+
rspec-support (~> 3.10.0)
|
80
|
+
rspec-expectations (3.10.1)
|
81
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
82
|
+
rspec-support (~> 3.10.0)
|
83
|
+
rspec-mocks (3.10.2)
|
84
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
85
|
+
rspec-support (~> 3.10.0)
|
86
|
+
rspec-support (3.10.2)
|
87
|
+
timecop (0.9.4)
|
88
|
+
unf (0.1.4)
|
89
|
+
unf_ext
|
90
|
+
unf_ext (0.0.7.7)
|
91
|
+
webmock (3.13.0)
|
92
|
+
addressable (>= 2.3.6)
|
93
|
+
crack (>= 0.3.2)
|
94
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
95
|
+
|
96
|
+
PLATFORMS
|
97
|
+
x86_64-linux
|
98
|
+
|
99
|
+
DEPENDENCIES
|
100
|
+
rake (~> 13.0)
|
101
|
+
rspec (~> 3.0)
|
102
|
+
sumsub-ruby-sdk!
|
103
|
+
|
104
|
+
BUNDLED WITH
|
105
|
+
2.2.17
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Rodrigo W. Ehresmann
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# SumSub Ruby SDK
|
2
|
+
|
3
|
+
This gem is an unnoficial SDK for the [SumSub API](https://developers.sumsub.com/api-reference/).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'sumsub-ruby-sdk', '~> 0.1.1', require: 'sumsub'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
## Configuration and Usage
|
18
|
+
|
19
|
+
You can configure your credentials using `Sumsub::Configure` block. There are three keys you can inform: *token*, *secret_key* and *production*. The token and secret key you need to generate from your SumSub account, and *production* is a boolean value where you specify if you wanna use SumSub production or test environtment. To use the test environment, just set production as `false`.
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
Sumsub.configure do |config|
|
23
|
+
config.token = your_token
|
24
|
+
config.secret_key = your_secret_key
|
25
|
+
config.production = false # is true by default
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
Use the `Sumsub::Request` to call the methods that access SumSub API endpoints. Check it out the [implemented methods](https://github.com/rwehresmann/sumsub-ruby-sdk/blob/master/lib/sumsub/request.rb) to know what is already available to be used.
|
30
|
+
|
31
|
+
For requests where you need to inform full objects in the request's body, `Sumsub::Struct` have some models you can use to easily fill the necessary data for the request. Check it out the models available [here](https://github.com/rwehresmann/sumsub-ruby-sdk/tree/master/lib/sumsub/struct).
|
32
|
+
|
33
|
+
**Note:** To use `Sumsub::Struct` or not is up to you. A simple [ruby hash](https://ruby-doc.org/core-3.0.1/Hash.html) is a viable option too. Under the hood we call `to_json` to serialize it, so just ensure that this method is available and does what we expect of him: transform your object in a json string.
|
34
|
+
|
35
|
+
Usage example:
|
36
|
+
|
37
|
+
An applicant is an user that will go into the KYC process.
|
38
|
+
|
39
|
+
- Create the applicant;
|
40
|
+
- Add an ID document to it;
|
41
|
+
- Retrieve the current applicant's status.
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
request = Sumsub::Request.new
|
45
|
+
|
46
|
+
# If you didn't set your configurations on Sumsub.configure block,
|
47
|
+
# you have the option to inform it in the Request constructor, like this:
|
48
|
+
#
|
49
|
+
# request = Sumsub::Request.new(
|
50
|
+
# token: your_token,
|
51
|
+
# secret_key: your_secret_key,
|
52
|
+
# production: false
|
53
|
+
# )
|
54
|
+
|
55
|
+
applicant = Sumsub::Struct::Applicant.new(
|
56
|
+
externalUserId: 'appt20',
|
57
|
+
email: 'grivia@mail.com'
|
58
|
+
)
|
59
|
+
|
60
|
+
response = request.create_applicant('basic-kyc-level', applicant)
|
61
|
+
|
62
|
+
applicant_id = response['id']
|
63
|
+
|
64
|
+
metadata = Sumsub::Struct::DocumentMetadata.new(
|
65
|
+
idDocType: 'ID_CARD',
|
66
|
+
country: 'BRA'
|
67
|
+
)
|
68
|
+
|
69
|
+
request.add_id_doc(
|
70
|
+
applicant_id,
|
71
|
+
metadata,
|
72
|
+
file_path: 'home/myself/Pictures/id_card.png'
|
73
|
+
)
|
74
|
+
|
75
|
+
request.get_applicant_status(applicant_id)
|
76
|
+
```
|
77
|
+
|
78
|
+
The return from `Sumsub::Request` method will always be a ruby hash (in case of success) or an instance of `Sumsub::Struct::ErrorResponse` (in case error).
|
79
|
+
|
80
|
+
## Development
|
81
|
+
|
82
|
+
Run `bin/setup` to install dependencies. For an interactive prompt that will allow you to experiment, run `bin/console`.
|
83
|
+
|
84
|
+
Run `bundle exec rspec`, if none error appears you're ready to go.
|
85
|
+
|
86
|
+
## License
|
87
|
+
|
88
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "sumsub"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/sumsub.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'http'
|
4
|
+
require 'types'
|
5
|
+
require 'mime/types'
|
6
|
+
|
7
|
+
module Sumsub
|
8
|
+
require 'sumsub/message_signer'
|
9
|
+
require 'sumsub/configuration'
|
10
|
+
require 'sumsub/parser'
|
11
|
+
require 'sumsub/request'
|
12
|
+
require 'sumsub/struct/base_struct'
|
13
|
+
require 'sumsub/struct/error_response'
|
14
|
+
require 'sumsub/struct/address'
|
15
|
+
require 'sumsub/struct/info'
|
16
|
+
require 'sumsub/struct/applicant'
|
17
|
+
require 'sumsub/struct/applicant_update'
|
18
|
+
require 'sumsub/struct/document_metadata'
|
19
|
+
require 'sumsub/version'
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :configuration
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.configuration
|
26
|
+
@configuration ||= Configuration.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.reset
|
30
|
+
@configuration = Configuration.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.configure
|
34
|
+
yield(configuration)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.error_response?(response)
|
38
|
+
response.class == Sumsub::Struct::ErrorResponse
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Sumsub
|
2
|
+
# https://developers.sumsub.com/api-reference/#signing-a-request
|
3
|
+
class MessageSigner
|
4
|
+
def self.sign(
|
5
|
+
time:,
|
6
|
+
resource:,
|
7
|
+
method:,
|
8
|
+
body: nil,
|
9
|
+
secret_key: Sumsub.configuration.secret_key
|
10
|
+
)
|
11
|
+
data = time.to_s + method + '/resources/' + resource + body.to_s
|
12
|
+
digest = OpenSSL::Digest.new('sha256')
|
13
|
+
|
14
|
+
OpenSSL::HMAC.hexdigest(digest, secret_key, data)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Sumsub
|
2
|
+
class Parser
|
3
|
+
def self.parse(json_payload)
|
4
|
+
payload = JSON.parse(json_payload)
|
5
|
+
|
6
|
+
# return unless is an error response
|
7
|
+
return payload unless (payload['code'] && payload['description'])
|
8
|
+
|
9
|
+
Sumsub::Struct::ErrorResponse.new(
|
10
|
+
description: payload['description'],
|
11
|
+
code: payload['code'],
|
12
|
+
correlation_id: payload['correlationId'],
|
13
|
+
error_code: payload['errorCode'],
|
14
|
+
error_name: payload['errorName']
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
module Sumsub
|
2
|
+
class Request
|
3
|
+
PRODUCTION_URL = "https://api.sumsub.com/resources"
|
4
|
+
TEST_URL = "https://test-api.sumsub.com/resources"
|
5
|
+
|
6
|
+
attr_reader :url, :secret_key, :token
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
token: Sumsub.configuration.token,
|
10
|
+
secret_key: Sumsub.configuration.secret_key,
|
11
|
+
production: Sumsub.configuration.production
|
12
|
+
)
|
13
|
+
@token = token
|
14
|
+
@secret_key = secret_key
|
15
|
+
@url = production ? PRODUCTION_URL : TEST_URL
|
16
|
+
end
|
17
|
+
|
18
|
+
# API docs: https://developers.sumsub.com/api-reference/#creating-an-applicant
|
19
|
+
# Sumsub::Struct::Applicant can be used as applicant.
|
20
|
+
def create_applicant(lvl_name, applicant)
|
21
|
+
resource = "applicants?levelName=#{lvl_name}"
|
22
|
+
headers = build_header(resource, body: applicant.to_json)
|
23
|
+
response = HTTP.headers(headers)
|
24
|
+
.post("#{@url}/#{resource}", json: applicant)
|
25
|
+
|
26
|
+
parse_response(response)
|
27
|
+
end
|
28
|
+
|
29
|
+
# API docs: https://developers.sumsub.com/api-reference/#adding-an-id-document
|
30
|
+
# To understand how the body was build manually bellow: https://roytuts.com/boundary-in-multipart-form-data/
|
31
|
+
# Sumsub::Struct::DocumentMetadata can be used as metadata.
|
32
|
+
def add_id_doc(applicant_id, metadata, file_path: nil)
|
33
|
+
resource = "applicants/#{applicant_id}/info/idDoc"
|
34
|
+
|
35
|
+
boundary = '----XYZ'
|
36
|
+
|
37
|
+
body = + '--' + boundary + "\r\n"
|
38
|
+
body += 'Content-Disposition: form-data; name="metadata"'
|
39
|
+
body += "\r\nContent-type: application/json; charset=utf-8\r\n\r\n"
|
40
|
+
body += metadata.to_json
|
41
|
+
body += "\r\n"
|
42
|
+
body += '--' + boundary
|
43
|
+
|
44
|
+
if file_path
|
45
|
+
content = File.read(file_path)
|
46
|
+
file_name = File.basename(file_path)
|
47
|
+
content_type = MIME::Types.type_for(file_name).first.content_type
|
48
|
+
|
49
|
+
body += "\r\n"
|
50
|
+
body += 'Content-Disposition: form-data; name="content"; filename="' + file_name + '"'
|
51
|
+
body += "\r\nContent-type: #{content_type}; charset=utf-8\r\n\r\n"
|
52
|
+
body += content + "\r\n"
|
53
|
+
body += '--' + boundary + '--'
|
54
|
+
else
|
55
|
+
body += '--'
|
56
|
+
end
|
57
|
+
|
58
|
+
headers = build_header(
|
59
|
+
resource,
|
60
|
+
body: body,
|
61
|
+
content_type: 'multipart/form-data; boundary=' + boundary
|
62
|
+
).merge({ "X-Return-Doc-Warnings": true })
|
63
|
+
response = HTTP.headers(headers)
|
64
|
+
.post("#{@url}/#{resource}", body: body)
|
65
|
+
|
66
|
+
parse_response(response)
|
67
|
+
end
|
68
|
+
|
69
|
+
# API docs: https://developers.sumsub.com/api-reference/#getting-applicant-status-api
|
70
|
+
def get_applicant_detailed_status(applicant_id)
|
71
|
+
resource = "applicants/#{applicant_id}/requiredIdDocsStatus"
|
72
|
+
headers = build_header(resource, method: 'GET')
|
73
|
+
response = HTTP.headers(headers)
|
74
|
+
.get("#{@url}/#{resource}")
|
75
|
+
|
76
|
+
parse_response(response)
|
77
|
+
end
|
78
|
+
|
79
|
+
# API docs: https://developers.sumsub.com/api-reference/#getting-applicant-data
|
80
|
+
def get_applicant_data(applicant_id, as_external_user_id: false)
|
81
|
+
resource = as_external_user_id ?
|
82
|
+
"applicants/-;externalUserId=#{applicant_id}/one" :
|
83
|
+
"applicants/#{applicant_id}/one"
|
84
|
+
headers = build_header(resource, method: 'GET')
|
85
|
+
response = HTTP.headers(headers)
|
86
|
+
.get("#{@url}/#{resource}")
|
87
|
+
|
88
|
+
parse_response(response)
|
89
|
+
end
|
90
|
+
|
91
|
+
# API docs: https://developers.sumsub.com/api-reference/#getting-applicant-status-sdk
|
92
|
+
def get_applicant_status(applicant_id)
|
93
|
+
resource = "applicants/#{applicant_id}/status"
|
94
|
+
headers = build_header(resource, method: 'GET')
|
95
|
+
response = HTTP.headers(headers)
|
96
|
+
.get("#{@url}/#{resource}")
|
97
|
+
|
98
|
+
parse_response(response)
|
99
|
+
end
|
100
|
+
|
101
|
+
# API docs: https://developers.sumsub.com/api-reference/#requesting-an-applicant-check
|
102
|
+
def request_applicant_check(applicant_id, reason: nil)
|
103
|
+
resource = "applicants/#{applicant_id}/status/pending?reason=#{reason}"
|
104
|
+
headers = build_header(resource)
|
105
|
+
response = HTTP.headers(headers)
|
106
|
+
.post("#{@url}/#{resource}")
|
107
|
+
|
108
|
+
parse_response(response)
|
109
|
+
end
|
110
|
+
|
111
|
+
# API docs: https://developers.sumsub.com/api-reference/#getting-document-images
|
112
|
+
def get_document_image(inspection_id, image_id)
|
113
|
+
resource = "inspections/#{inspection_id}/resources/#{image_id}"
|
114
|
+
headers = build_header(resource, method: 'GET')
|
115
|
+
response = HTTP.headers(headers)
|
116
|
+
.get("#{@url}/#{resource}")
|
117
|
+
|
118
|
+
parse_response(response)
|
119
|
+
end
|
120
|
+
|
121
|
+
# API docs: https://developers.sumsub.com/api-reference/#resetting-an-applicant
|
122
|
+
def reset_applicant(applicant_id)
|
123
|
+
resource = "applicants/#{applicant_id}/reset"
|
124
|
+
headers = build_header(resource)
|
125
|
+
response = HTTP.headers(headers)
|
126
|
+
.post("#{@url}/#{resource}")
|
127
|
+
|
128
|
+
parse_response(response)
|
129
|
+
end
|
130
|
+
|
131
|
+
# API docs: https://developers.sumsub.com/api-reference/#changing-top-level-info
|
132
|
+
# Sumsub::Struct::ApplicantUpdate can be used as applicant_new_values.
|
133
|
+
def change_applicant_top_level_info(applicant_new_values)
|
134
|
+
resource = "applicants/"
|
135
|
+
headers = build_header(resource, method: 'PATCH', body: applicant_new_values.to_json)
|
136
|
+
response = HTTP.headers(headers)
|
137
|
+
.patch("#{@url}/#{resource}", json: applicant_new_values)
|
138
|
+
|
139
|
+
parse_response(response)
|
140
|
+
end
|
141
|
+
|
142
|
+
# API docs: https://developers.sumsub.com/api-reference/#access-tokens-for-sdks
|
143
|
+
def get_access_token(user_id, ttl_in_seconds: nil, external_action_id: nil)
|
144
|
+
resource = "accessTokens?userId=#{user_id}&ttlInSecs=#{ttl_in_seconds}&external_action_id=#{external_action_id}"
|
145
|
+
headers = build_header(resource, method: 'POST')
|
146
|
+
response = HTTP.headers(headers)
|
147
|
+
.post("#{@url}/#{resource}")
|
148
|
+
|
149
|
+
parse_response(response)
|
150
|
+
end
|
151
|
+
|
152
|
+
# API docs: https://developers.sumsub.com/api-reference/#verifying-webhook-sender
|
153
|
+
# Your payload need to be informed as a string.
|
154
|
+
def verify_webhook_sender(webhook_secret_key, payload)
|
155
|
+
resource = "inspectionCallbacks/testDigest?secretKey=#{webhook_secret_key}"
|
156
|
+
headers = build_header(
|
157
|
+
resource,
|
158
|
+
method: 'POST',
|
159
|
+
content_type: 'text/plain',
|
160
|
+
accept: 'text/plain',
|
161
|
+
body: payload
|
162
|
+
)
|
163
|
+
|
164
|
+
response = HTTP.headers(headers)
|
165
|
+
.post("#{@url}/#{resource}", body: payload)
|
166
|
+
|
167
|
+
parse_response(response)
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
# More infos about the required header and the signing strategy:
|
173
|
+
# https://developers.sumsub.com/api-reference/#app-tokens
|
174
|
+
def build_header(
|
175
|
+
resource,
|
176
|
+
body: nil,
|
177
|
+
method: 'POST',
|
178
|
+
content_type: 'application/json',
|
179
|
+
accept: 'application/json'
|
180
|
+
)
|
181
|
+
epoch_time = Time.now.to_i
|
182
|
+
access_signature = Sumsub::MessageSigner.sign(
|
183
|
+
time: epoch_time,
|
184
|
+
resource: resource,
|
185
|
+
body: body,
|
186
|
+
method: method,
|
187
|
+
)
|
188
|
+
|
189
|
+
{
|
190
|
+
"X-App-Token": @token.encode("UTF-8"),
|
191
|
+
"X-App-Access-Sig": access_signature.encode("UTF-8"),
|
192
|
+
"X-App-Access-Ts": epoch_time.to_s.encode("UTF-8"),
|
193
|
+
"Accept": accept,
|
194
|
+
"Content-Type": content_type
|
195
|
+
}
|
196
|
+
end
|
197
|
+
|
198
|
+
def parse_response(response)
|
199
|
+
Sumsub::Parser.parse(response.to_s)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Sumsub
|
2
|
+
module Struct
|
3
|
+
# https://developers.sumsub.com/api-reference/#addresses-elements-fields
|
4
|
+
class Address < BaseStruct
|
5
|
+
include Types
|
6
|
+
|
7
|
+
attribute? :country, Types::String
|
8
|
+
attribute? :postCode, Types::String
|
9
|
+
attribute? :town, Types::String
|
10
|
+
attribute? :street, Types::String
|
11
|
+
attribute? :subStreet, Types::String
|
12
|
+
attribute? :state, Types::String
|
13
|
+
attribute? :buildingName, Types::String
|
14
|
+
attribute? :flatNumber, Types::String
|
15
|
+
attribute? :buildingNumber, Types::String
|
16
|
+
attribute? :startDate, Types::String
|
17
|
+
attribute? :endDate, Types::String
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sumsub
|
2
|
+
module Struct
|
3
|
+
# https://developers.sumsub.com/api-reference/#request-body
|
4
|
+
class Applicant < BaseStruct
|
5
|
+
include Types
|
6
|
+
|
7
|
+
attribute :externalUserId, Types::Coercible::String
|
8
|
+
attribute? :sourceKey, Types::String
|
9
|
+
attribute? :email, Types::String
|
10
|
+
attribute? :lang, Types::String
|
11
|
+
attribute? :metadata, Types::Array.of(Types::Hash)
|
12
|
+
attribute? :info, Types::Instance(Sumsub::Struct::Info)
|
13
|
+
attribute? :fixedInfo, Types::Instance(Sumsub::Struct::Info)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sumsub
|
2
|
+
module Struct
|
3
|
+
# https://developers.sumsub.com/api-reference/#request-body-2
|
4
|
+
class ApplicantUpdate < BaseStruct
|
5
|
+
include Types
|
6
|
+
|
7
|
+
attribute :id, Types::String
|
8
|
+
attribute? :externalUserId, Types::String
|
9
|
+
attribute? :sourceKey, Types::String
|
10
|
+
attribute? :email, Types::String
|
11
|
+
attribute? :lang, Types::String
|
12
|
+
attribute? :metadata, Types::Array.of(Types::Hash)
|
13
|
+
attribute? :type, Types::String
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Sumsub
|
2
|
+
module Struct
|
3
|
+
# https://developers.sumsub.com/api-reference/#request-metadata-body-part-fields
|
4
|
+
class DocumentMetadata < BaseStruct
|
5
|
+
include Types
|
6
|
+
|
7
|
+
attribute :idDocType, Types::IdDocTypes
|
8
|
+
attribute? :idDocSubType, Types::IdDocSubType
|
9
|
+
attribute :country, Types::String # https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3
|
10
|
+
attribute? :firstName, Types::String
|
11
|
+
attribute? :middleName, Types::String
|
12
|
+
attribute? :lastName, Types::String
|
13
|
+
attribute? :issuedDate, Types::String
|
14
|
+
attribute? :validUntil, Types::String
|
15
|
+
attribute? :number, Types::String
|
16
|
+
attribute? :dob, Types::String
|
17
|
+
attribute? :placeOfBirth, Types::String
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Sumsub
|
2
|
+
module Struct
|
3
|
+
# https://developers.sumsub.com/api-reference/#response-body
|
4
|
+
class ErrorResponse < BaseStruct
|
5
|
+
include Types
|
6
|
+
|
7
|
+
attribute :description, Types::String.optional
|
8
|
+
attribute :code, Types::Coercible::String.optional
|
9
|
+
attribute :correlation_id, Types::Coercible::String.optional
|
10
|
+
attribute? :error_code, Types::Coercible::String.optional
|
11
|
+
attribute? :error_name, Types::String.optional
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Sumsub
|
2
|
+
module Struct
|
3
|
+
# https://developers.sumsub.com/api-reference/#fixedinfo-and-info-attributes
|
4
|
+
class Info < BaseStruct
|
5
|
+
include Types
|
6
|
+
|
7
|
+
attribute? :firstName, Types::String
|
8
|
+
attribute? :lastName, Types::String
|
9
|
+
attribute? :middleName, Types::String
|
10
|
+
attribute? :firstNameEn, Types::String
|
11
|
+
attribute? :lastNameEn, Types::String
|
12
|
+
attribute? :middleNameEn, Types::String
|
13
|
+
attribute? :legalName, Types::String
|
14
|
+
attribute? :gender, Types::String
|
15
|
+
attribute? :dob, Types::String
|
16
|
+
attribute? :placeOfBirth, Types::String
|
17
|
+
attribute? :countryOfBirth, Types::String
|
18
|
+
attribute? :stateOfBirth, Types::String
|
19
|
+
attribute? :country, Types::String
|
20
|
+
attribute? :nationality, Types::String
|
21
|
+
attribute? :phone, Types::String
|
22
|
+
attribute? :addresses, Types::Array.of(Sumsub::Struct::Address)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/types.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'dry-struct'
|
2
|
+
|
3
|
+
module Types
|
4
|
+
include Dry.Types()
|
5
|
+
|
6
|
+
# https://developers.sumsub.com/api-reference/#supported-document-types
|
7
|
+
IdDocTypes = Types::Strict::Symbol
|
8
|
+
.constructor(&:to_sym)
|
9
|
+
.enum(
|
10
|
+
:ID_CARD,
|
11
|
+
:PASSPORT,
|
12
|
+
:DRIVERS, # Driving license
|
13
|
+
:BANK_CARD,
|
14
|
+
:UTILITY_BILL,
|
15
|
+
:BANK_STATEMENT,
|
16
|
+
:SELFIE,
|
17
|
+
:VIDEO_SELFIE,
|
18
|
+
:PROFILE_IMAGE,
|
19
|
+
:ID_DOC_PHOTO,
|
20
|
+
:AGREEMENT,
|
21
|
+
:CONTRACT,
|
22
|
+
:RESIDENCE_PERMIT,
|
23
|
+
:EMPLOYMENT_CERTIFICATE,
|
24
|
+
:DRIVERS_TRANSLATION,
|
25
|
+
:INVESTOR_DOC,
|
26
|
+
:VEHICLE_REGISTRATION_CERTIFICATE,
|
27
|
+
:INCOME_SOURCE, # Proof of income
|
28
|
+
:PAYMENT_METHOD,
|
29
|
+
:OTHER,
|
30
|
+
nil,
|
31
|
+
)
|
32
|
+
|
33
|
+
IdDocSubType = Types::Strict::Symbol
|
34
|
+
.constructor(&:to_sym)
|
35
|
+
.enum(
|
36
|
+
:FRONT_SIDE,
|
37
|
+
:BACK_SIDE,
|
38
|
+
)
|
39
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/sumsub/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "sumsub-ruby-sdk"
|
7
|
+
spec.version = Sumsub::VERSION
|
8
|
+
spec.authors = ["Rodrigo W. Ehresmann"]
|
9
|
+
spec.email = ["igoehresmann@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "SumSub Ruby SDK"
|
12
|
+
spec.description = "SDK written in Ruby to handle SumSub API."
|
13
|
+
spec.homepage = "https://github.com/rwehresmann/sumsub-ruby-sdk"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
|
16
|
+
|
17
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
18
|
+
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
+
spec.metadata["source_code_uri"] = "https://github.com/rwehresmann/sumsub-ruby-sdk"
|
21
|
+
spec.metadata["changelog_uri"] = "https://github.com/rwehresmann/sumsub-ruby-sdk"
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
27
|
+
end
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
# Uncomment to register a new dependency of your gem
|
33
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
34
|
+
|
35
|
+
# For more information and examples about making a new gem, checkout our
|
36
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
37
|
+
|
38
|
+
spec.add_dependency "http", "~> 5.0.0"
|
39
|
+
spec.add_dependency "dry-struct", "~> 1.4.0"
|
40
|
+
spec.add_dependency "rspec", "~> 3.10.0"
|
41
|
+
spec.add_dependency "pry", "~> 0.14.1"
|
42
|
+
spec.add_dependency "webmock", "~> 3.13.0"
|
43
|
+
spec.add_dependency "timecop", "~> 0.9.4"
|
44
|
+
spec.add_dependency "mime-types", "~> 3.3.1"
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sumsub-ruby-sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rodrigo W. Ehresmann
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: http
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-struct
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.4.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.10.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.10.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.14.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.14.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: webmock
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.13.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.13.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: timecop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.9.4
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.9.4
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mime-types
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.3.1
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.3.1
|
111
|
+
description: SDK written in Ruby to handle SumSub API.
|
112
|
+
email:
|
113
|
+
- igoehresmann@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".circleci/config.yml"
|
119
|
+
- ".editorconfig"
|
120
|
+
- ".gitignore"
|
121
|
+
- ".rspec"
|
122
|
+
- Gemfile
|
123
|
+
- Gemfile.lock
|
124
|
+
- LICENSE.txt
|
125
|
+
- README.md
|
126
|
+
- Rakefile
|
127
|
+
- bin/console
|
128
|
+
- bin/setup
|
129
|
+
- lib/sumsub.rb
|
130
|
+
- lib/sumsub/configuration.rb
|
131
|
+
- lib/sumsub/message_signer.rb
|
132
|
+
- lib/sumsub/parser.rb
|
133
|
+
- lib/sumsub/request.rb
|
134
|
+
- lib/sumsub/struct/address.rb
|
135
|
+
- lib/sumsub/struct/applicant.rb
|
136
|
+
- lib/sumsub/struct/applicant_update.rb
|
137
|
+
- lib/sumsub/struct/base_struct.rb
|
138
|
+
- lib/sumsub/struct/document_metadata.rb
|
139
|
+
- lib/sumsub/struct/error_response.rb
|
140
|
+
- lib/sumsub/struct/info.rb
|
141
|
+
- lib/sumsub/version.rb
|
142
|
+
- lib/types.rb
|
143
|
+
- sumsub-ruby-sdk.gemspec
|
144
|
+
homepage: https://github.com/rwehresmann/sumsub-ruby-sdk
|
145
|
+
licenses:
|
146
|
+
- MIT
|
147
|
+
metadata:
|
148
|
+
allowed_push_host: https://rubygems.org
|
149
|
+
homepage_uri: https://github.com/rwehresmann/sumsub-ruby-sdk
|
150
|
+
source_code_uri: https://github.com/rwehresmann/sumsub-ruby-sdk
|
151
|
+
changelog_uri: https://github.com/rwehresmann/sumsub-ruby-sdk
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 2.4.0
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubygems_version: 3.2.15
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: SumSub Ruby SDK
|
171
|
+
test_files: []
|