smile-identity-core 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3b6be5ffaad64aa13c654eca628db1437da28d46a1e3d4b3564b373e4132508
4
- data.tar.gz: 1042167bb8981ac85cf0a1dbf466f2b099ca5468b013e62119a322582a879c9c
3
+ metadata.gz: 9614cb861ac00a8133527a647e8d6c6dcc91b00aca6c7fe643e32ddc986b3f7d
4
+ data.tar.gz: f1ac7dcb3413c1f08ac16c909e0f466091519dae0412519a1161cd0179143040
5
5
  SHA512:
6
- metadata.gz: f301a2f41634473bb47393dc5992f30f381a8088250aa2ebfc7739003384c52a37031182fc6e048b78227e990c465659f18fcc0d39bd4efc65ecc48d285325ce
7
- data.tar.gz: ba2e07c8c8f68117f7343bf0949277999a3e48ec770a50bfdd51ab0f98690d4219d2f989bbe436a558a9ca9adc3092607ae427911f2fc68e1233e94c33267f47
6
+ metadata.gz: db1d5e0344e58bb11728af749ef1b37f051add89fdda7797347d0771d091b3221482d90beed6f566d082d4120c9c2d45d63e0dea828202ff9c087d58c498094e
7
+ data.tar.gz: f524bd93102a7ac6621314a950b5fba0b06a62437f1ad4328e26c092192ffa74ccc9ce5919d1806e126a5d2d9305b9ad204e913da13cf02f1c31079d5775dc70
data/.travis.yml CHANGED
@@ -1,7 +1,11 @@
1
1
  ---
2
+ dist: bionic
2
3
  sudo: false
3
4
  language: ruby
4
5
  cache: bundler
5
6
  rvm:
6
7
  - 2.5.1
7
- before_install: gem install bundler -v 2.0.2
8
+ - 2.6
9
+ - 2.7
10
+ - 3.0
11
+ before_install: gem install bundler -v 2.2.6
data/CHANGELOG.md CHANGED
@@ -39,3 +39,11 @@ Amend the success response when job status is false to be a JSON String containi
39
39
  Add the ID API Class
40
40
  Add the ability to query ID Api from the Web API class
41
41
  Update the documentation
42
+
43
+ ## [1.0.1] - 2019-10-24
44
+ ## Updated
45
+ Remove first_name and last_name validations from id information in Web Api
46
+ Add country, id_number and id_type validations for id information in ID Api
47
+
48
+ ## [1.0.2] - 2020-01-16
49
+ Add {"success":true,"smile_job_id":"job_id"} to the response when we poll job status too
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smile-identity-core (1.0.0)
4
+ smile-identity-core (1.2.0)
5
5
  rubyzip (~> 1.2, >= 1.2.3)
6
6
  typhoeus (~> 1.0, >= 1.0.1)
7
7
 
@@ -12,8 +12,8 @@ GEM
12
12
  docile (1.1.5)
13
13
  ethon (0.12.0)
14
14
  ffi (>= 1.3.0)
15
- ffi (1.11.1)
16
- json (2.2.0)
15
+ ffi (1.13.1)
16
+ json (2.5.1)
17
17
  rake (10.5.0)
18
18
  rspec (3.8.0)
19
19
  rspec-core (~> 3.8.0)
@@ -34,7 +34,7 @@ GEM
34
34
  json (>= 1.8, < 3)
35
35
  simplecov-html (~> 0.10.0)
36
36
  simplecov-html (0.10.2)
37
- typhoeus (1.3.1)
37
+ typhoeus (1.4.0)
38
38
  ethon (>= 0.9.0)
39
39
 
40
40
  PLATFORMS
@@ -48,4 +48,4 @@ DEPENDENCIES
48
48
  smile-identity-core!
49
49
 
50
50
  BUNDLED WITH
51
- 2.0.2
51
+ 2.2.6
data/README.md CHANGED
@@ -1,12 +1,13 @@
1
- # SmileIdentityCore
1
+ # SmileIdentityCore [![Build Status](https://travis-ci.com/smileidentity/smile-identity-core-ruby.svg?branch=master)](https://travis-ci.com/smileidentity/smile-identity-core-ruby)
2
2
 
3
- The official Smile Identity gem exposes three classes namely, the Web API and Signature class.
3
+ The official Smile Identity gem exposes four classes namely; the Web Api class, the ID Api class, the Signature class and the Utilities class.
4
4
 
5
- The **Web API Class** allows you as the Partner to validate a user’s identity against the relevant Identity Authorities/Third Party databases that Smile Identity has access to using ID information provided by your customer/user (including photo for compare). It has the following public methods:
5
+ The **Web Api Class** allows you as the Partner to validate a user’s identity against the relevant Identity Authorities/Third Party databases that Smile Identity has access to using ID information provided by your customer/user (including photo for compare). It has the following public methods:
6
6
  - submit_job
7
7
  - get_job_status
8
+ - get_web_token
8
9
 
9
- The **ID Class** lets you performs basic KYC Services including verifying an ID number as well as retrieve a user's Personal Information. It has the following public methods:
10
+ The **ID Api Class** lets you performs basic KYC Services including verifying an ID number as well as retrieve a user's Personal Information. It has the following public methods:
10
11
  - submit_job
11
12
 
12
13
  The **Signature Class** allows you as the Partner to generate a sec key to interact with our servers. It has the following public methods:
@@ -20,7 +21,7 @@ The **Utilities Class** allows you as the Partner to have access to our general
20
21
 
21
22
  This gem requires specific input parameters, for more detail on these parameters please refer to our [documentation for Web API](https://docs.smileidentity.com).
22
23
 
23
- Please note that you will have to be a Smile Identity Partner to be able to query our services. You can sign up on the [Portal](https://test-smileid.herokuapp.com/signup?products[]=1-IDVALIDATION&products[]=2-AUTHENTICATION).
24
+ Please note that you will have to be a Smile Identity Partner to be able to query our services. You can sign up on the [Portal](https://portal.smileidentity.com/signup).
24
25
 
25
26
  ## Installation
26
27
 
@@ -39,7 +40,7 @@ require 'smile-identity-core'
39
40
 
40
41
  Or install it to your system as:
41
42
 
42
- ```
43
+ ```sh
43
44
  $ gem install smile-identity-core
44
45
  ```
45
46
 
@@ -48,33 +49,33 @@ You now may use the classes as follows:
48
49
  #### Web Api Class
49
50
 
50
51
  ##### submit_job method
51
- ```
52
- $ connection = SmileIdentityCore::WebApi.new(partner_id, default_callback, api_key, sid_server)
52
+ ```ruby
53
+ connection = SmileIdentityCore::WebApi.new(partner_id, default_callback, api_key, sid_server)
53
54
 
54
- $ response = connection.submit_job(partner_params, images, id_info, options)
55
+ response = connection.submit_job(partner_params, images, id_info, options)
55
56
  ```
56
57
 
57
58
  Please note that if you do not need to pass through id_info or options, you may omit calling those class and send through nil in submit_job, as follows:
58
59
 
59
- ```
60
- $ response = connection.submit_job(partner_params, images, nil, nil);
60
+ ```ruby
61
+ response = connection.submit_job(partner_params, images, nil, nil);
61
62
  ```
62
63
 
63
64
  In the case of a Job Type 5 you can simply omit the the images and options keys. Remember that the response is immediate, so there is no need to query the job_status. There is also no enrollment so no images are required. The response for a job type 5 can be found in the response section below.
64
65
 
65
- ```
66
- $ response = connection.submit_job(partner_params, nil, id_info, nil);
66
+ ```ruby
67
+ response = connection.submit_job(partner_params, nil, id_info, nil);
67
68
  ```
68
69
 
69
70
  **Response:**
70
71
 
71
72
  Should you choose to *set return_job_status to false*, the response will be a JSON String containing:
72
- ```
73
+ ```ruby
73
74
  {success: true, smile_job_id: smile_job_id}
74
75
  ```
75
76
 
76
77
  However, if you have *set return_job_status to true (with image_links and history)* then you will receive JSON Object response like below:
77
- ```
78
+ ```json
78
79
  {
79
80
  "job_success":true,
80
81
  "result":{
@@ -150,7 +151,7 @@ However, if you have *set return_job_status to true (with image_links and histor
150
151
  ```
151
152
 
152
153
  You can also *view your response asynchronously at the callback* that you have set, it will look as follows:
153
- ```
154
+ ```json
154
155
  {
155
156
  "job_success":true,
156
157
  "result":{
@@ -226,7 +227,7 @@ You can also *view your response asynchronously at the callback* that you have s
226
227
  ```
227
228
 
228
229
  If you have queried a job type 5, your response be a JSON String that will contain the following:
229
- ```
230
+ ```json
230
231
  {
231
232
  "JSONVersion":"1.0.0",
232
233
  "SmileJobID":"0000001105",
@@ -279,7 +280,7 @@ response = connection.get_job_status(partner_params, nil);
279
280
 
280
281
  Your response will return a JSON Object below with image_links and history included:
281
282
 
282
- ```
283
+ ```json
283
284
  {
284
285
  "job_success":true,
285
286
  "result":{
@@ -354,20 +355,54 @@ Your response will return a JSON Object below with image_links and history inclu
354
355
  }
355
356
  ```
356
357
 
358
+ ##### get_web_token method
359
+ You may want to use our hosted web integration, and create a session. The `get_web_token` method enables this.
360
+ You have your Web Api class initialised as follows:
361
+ ```ruby
362
+ connection = SmileIdentityCore::WebApi.new(partner_id, default_callback, api_key, sid_server)
363
+
364
+ ```
365
+
366
+ Next, you'll need to create your request params. This should take the following
367
+ structure:
368
+
369
+ ```ruby
370
+ {
371
+ user_id: 'user-1', # String: required
372
+ job_id: 'job-1', # String: required
373
+ product: 'authentication', # String: required one of 'authentication', 'identity_verification', 'smartselfie', 'ekyc_smartselfie', 'enhanced_kyc', 'document_verification'
374
+ callback_url: "https://smileidentity.com/callback" # String: required, optional if callback url was set during instantiation of the class
375
+ }
376
+ ```
377
+
378
+ Thereafter, call `get_web_token` with the correct parameters:
379
+ ```ruby
380
+ response = connection.get_web_token(request_params)
381
+ ```
382
+
383
+ **Response**
384
+
385
+ Your response will return a hash that contains
386
+ ```ruby
387
+ {
388
+ token: <token_string>
389
+ }
390
+ ```
391
+
357
392
  #### ID Api Class
358
393
 
359
394
 
360
395
  ##### submit_job method
361
- ```
362
- $ connection = SmileIdentityCore::IDApi.new(partner_id, api_key, sid_server)
396
+ ```ruby
397
+ connection = SmileIdentityCore::IDApi.new(partner_id, api_key, sid_server)
363
398
 
364
- $ response = connection.submit_job(partner_params, id_info)
399
+ response = connection.submit_job(partner_params, id_info)
365
400
  ```
366
401
 
367
402
  **Response**
368
403
 
369
404
  Your response will return a JSON String containing the below:
370
- ```
405
+ ```json
371
406
  {
372
407
  "JSONVersion":"1.0.0",
373
408
  "SmileJobID":"0000001105",
@@ -400,17 +435,17 @@ Your response will return a JSON String containing the below:
400
435
 
401
436
  ##### generate_sec_key method
402
437
 
403
- ```
404
- $ connection = SmileIdentityCore::Signature.new(partner_id, api_key)
438
+ ```ruby
439
+ connection = SmileIdentityCore::Signature.new(partner_id, api_key)
405
440
 
406
- $ sec_key = connection.generate_sec_key(timestamp)
441
+ sec_key = connection.generate_sec_key(timestamp)
407
442
  where timestamp is optional
408
443
 
409
444
  ```
410
445
 
411
446
  The response will be a hash:
412
447
 
413
- ```
448
+ ```ruby
414
449
  {
415
450
  :sec_key=> "<the generated sec key>",
416
451
  :timestamp=> 1563283420
@@ -422,8 +457,8 @@ The response will be a hash:
422
457
  You can also confirm the signature that you receive when you interacting with our servers, simply use the confirm_sec_key method which returns a boolean:
423
458
 
424
459
  ```ruby
425
- $ connection = SmileIdentityCore::Signature.new(partner_id, api_key)
426
- $ sec_key = connection.confirm_sec_key(sec_key, timestamp)
460
+ connection = SmileIdentityCore::Signature.new(partner_id, api_key)
461
+ sec_key = connection.confirm_sec_key(sec_key, timestamp)
427
462
  ```
428
463
 
429
464
  #### Utilities Class
@@ -443,13 +478,23 @@ After checking out the repo, run `bundle install` to install dependencies. Then,
443
478
 
444
479
  To install this gem onto your local machine, run `bundle exec rake install`.
445
480
 
481
+ You can use `bundle console` and then call the necessary classes with their parameters.
482
+
483
+ ## Testing
484
+
485
+ Run `bundle exec rspec` to run the tests.
486
+ After running your tests open the coverage/index.html to view the test coverage
487
+
488
+ ## Deployment
489
+
446
490
  To release a new version:
447
491
  - Update the version number in `version.rb`
448
492
  - Run `gem build smile-identity-core.gemspec`
449
- - Thereafter `gem push smile-identity-core-version.gem`.
493
+ - Thereafter `gem push smile-identity-core-<version>.gem`.
450
494
 
451
495
  Make sure to git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
452
496
 
497
+
453
498
  ## Contributing
454
499
 
455
500
  Bug reports and pull requests are welcome on GitHub at https://github.com/smileidentity/smile-identity-core
@@ -8,8 +8,8 @@ module SmileIdentityCore
8
8
  @sid_server = sid_server
9
9
  if !(sid_server =~ URI::regexp)
10
10
  sid_server_mapping = {
11
- 0 => 'https://3eydmgh10d.execute-api.us-west-2.amazonaws.com/test',
12
- 1 => 'https://la7am6gdm8.execute-api.us-west-2.amazonaws.com/prod'
11
+ 0 => 'https://testapi.smileidentity.com/v1',
12
+ 1 => 'https://api.smileidentity.com/v1',
13
13
  }
14
14
  @url = sid_server_mapping[sid_server.to_i]
15
15
  else
@@ -17,32 +17,30 @@ module SmileIdentityCore
17
17
  end
18
18
  end
19
19
 
20
- def submit_job(partner_params, id_info)
20
+ def submit_job(partner_params, id_info, options = {})
21
21
  self.partner_params = symbolize_keys partner_params
22
-
23
- @timestamp = Time.now.to_i
24
-
25
22
  self.id_info = symbolize_keys id_info
23
+ @use_new_signature = symbolize_keys(options || {}).fetch(:signature, false)
26
24
 
27
25
  if @partner_params[:job_type].to_i != 5
28
- raise ArgumentError.new('Please ensure that you are setting your job_type to 5 to query ID Api')
26
+ raise ArgumentError, 'Please ensure that you are setting your job_type to 5 to query ID Api'
29
27
  end
30
28
 
31
- return setup_requests
29
+ setup_requests
32
30
  end
33
31
 
34
32
  def partner_params=(partner_params)
35
33
  if partner_params == nil
36
- raise ArgumentError.new('Please ensure that you send through partner params')
34
+ raise ArgumentError, 'Please ensure that you send through partner params'
37
35
  end
38
36
 
39
37
  if !partner_params.is_a?(Hash)
40
- raise ArgumentError.new('Partner params needs to be a hash')
38
+ raise ArgumentError, 'Partner params needs to be a hash'
41
39
  end
42
40
 
43
41
  [:user_id, :job_id, :job_type].each do |key|
44
42
  unless partner_params[key] && !partner_params[key].nil? && !(partner_params[key].empty? if partner_params[key].is_a?(String))
45
- raise ArgumentError.new("Please make sure that #{key.to_s} is included in the partner params")
43
+ raise ArgumentError, "Please make sure that #{key} is included in the partner params"
46
44
  end
47
45
  end
48
46
 
@@ -54,10 +52,14 @@ module SmileIdentityCore
54
52
  updated_id_info = id_info
55
53
 
56
54
  if updated_id_info.nil? || updated_id_info.keys.length == 0
57
- raise ArgumentError.new("Please make sure that id_info not empty or nil")
55
+ raise ArgumentError, 'Please make sure that id_info not empty or nil'
58
56
  end
59
57
 
60
- # maybe do some validation on consistent required fields like id_type and id_number
58
+ [:country, :id_type, :id_number].each do |key|
59
+ unless updated_id_info[key] && !updated_id_info[key].nil? && !updated_id_info[key].empty?
60
+ raise ArgumentError, "Please make sure that #{key} is included in the id_info"
61
+ end
62
+ end
61
63
 
62
64
  @id_info = updated_id_info
63
65
  end
@@ -95,20 +97,28 @@ module SmileIdentityCore
95
97
  end
96
98
 
97
99
  def configure_json
98
- body = {
99
- timestamp: @timestamp,
100
- sec_key: determine_sec_key,
101
- partner_id: @partner_id,
102
- partner_params: @partner_params
103
- }
104
-
105
- body.merge!(@id_info)
106
- JSON.generate(body)
100
+ request_security(use_new_signature: @use_new_signature)
101
+ .merge(@id_info)
102
+ .merge(
103
+ partner_id: @partner_id,
104
+ partner_params: @partner_params)
105
+ .to_json
107
106
  end
108
107
 
109
- def determine_sec_key
110
- @sec_key = SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)[:sec_key]
108
+ def request_security(use_new_signature: true)
109
+ if use_new_signature
110
+ @timestamp = Time.now.to_s
111
+ {
112
+ signature: SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_signature(@timestamp)[:signature],
113
+ timestamp: @timestamp,
114
+ }
115
+ else
116
+ @timestamp = Time.now.to_i
117
+ {
118
+ sec_key: SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)[:sec_key],
119
+ timestamp: @timestamp,
120
+ }
121
+ end
111
122
  end
112
-
113
123
  end
114
124
  end
@@ -3,7 +3,7 @@ module SmileIdentityCore
3
3
 
4
4
  def initialize(partner_id, api_key)
5
5
  @api_key = api_key
6
- @partner_id = partner_id.to_i
6
+ @partner_id = partner_id
7
7
  end
8
8
 
9
9
  def generate_sec_key(timestamp=Time.now.to_i)
@@ -14,7 +14,7 @@ module SmileIdentityCore
14
14
  public_key = OpenSSL::PKey::RSA.new(Base64.decode64(@api_key))
15
15
  @sec_key = [Base64.encode64(public_key.public_encrypt(hash_signature)), hash_signature].join('|')
16
16
 
17
- return {
17
+ {
18
18
  sec_key: @sec_key,
19
19
  timestamp: @timestamp
20
20
  }
@@ -31,10 +31,26 @@ module SmileIdentityCore
31
31
  public_key = OpenSSL::PKey::RSA.new(Base64.decode64(@api_key))
32
32
  decrypted = public_key.public_decrypt(Base64.decode64(encrypted))
33
33
 
34
- return decrypted == hash_signature
34
+ decrypted == hash_signature
35
35
  rescue => e
36
36
  raise e
37
37
  end
38
38
  end
39
+
40
+ def generate_signature(timestamp=Time.now.to_s)
41
+ hmac = OpenSSL::HMAC.new(@api_key, 'sha256')
42
+ hmac.update(timestamp.to_s)
43
+ hmac.update(@partner_id)
44
+ hmac.update("sid_request")
45
+ signature = Base64.strict_encode64(hmac.digest())
46
+ {
47
+ signature: signature,
48
+ timestamp: timestamp.to_s
49
+ }
50
+ end
51
+
52
+ def confirm_signature(timestamp, msg_signature)
53
+ generate_signature(timestamp)[:signature] == msg_signature
54
+ end
39
55
  end
40
56
  end
@@ -7,8 +7,8 @@ module SmileIdentityCore
7
7
 
8
8
  if !(sid_server =~ URI::regexp)
9
9
  sid_server_mapping = {
10
- 0 => 'https://3eydmgh10d.execute-api.us-west-2.amazonaws.com/test',
11
- 1 => 'https://la7am6gdm8.execute-api.us-west-2.amazonaws.com/prod'
10
+ 0 => 'https://testapi.smileidentity.com/v1',
11
+ 1 => 'https://api.smileidentity.com/v1',
12
12
  }
13
13
  @url = sid_server_mapping[sid_server.to_i]
14
14
  else
@@ -20,16 +20,12 @@ module SmileIdentityCore
20
20
  end
21
21
 
22
22
  def get_job_status(user_id, job_id, options = {})
23
+ options = symbolize_keys(options || {})
24
+ options[:return_history] ||= false
25
+ options[:return_image_links] ||= false
23
26
 
24
- if(options.nil? || options.empty?)
25
- options = {
26
- return_history: false,
27
- return_job_status: false
28
- }
29
- end
30
-
31
- @timestamp = Time.now.to_i
32
- return query_job_status(user_id, job_id, symbolize_keys(options))
27
+ security = request_security(use_new_signature: options.fetch(:signature, false))
28
+ query_job_status(configure_job_query(user_id, job_id, options).merge(security))
33
29
  end
34
30
 
35
31
  private
@@ -38,21 +34,30 @@ module SmileIdentityCore
38
34
  (params.is_a?(Hash)) ? Hash[params.map{ |k, v| [k.to_sym, v] }] : params
39
35
  end
40
36
 
41
- def query_job_status(user_id, job_id, options)
37
+ def query_job_status(request_json_data)
42
38
  url = "#{@url}/job_status"
43
39
 
44
40
  request = Typhoeus::Request.new(
45
41
  url,
46
42
  headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
47
43
  method: :post,
48
- body: configure_job_query(user_id, job_id, options)
44
+ body: request_json_data.to_json
49
45
  )
50
46
 
51
47
  request.on_complete do |response|
52
48
  begin
53
49
  body = JSON.parse(response.body)
54
50
 
55
- valid = @signature_connection.confirm_sec_key(body['timestamp'], body['signature'])
51
+ # NB: we have to trust that the server will return the right kind of
52
+ # timestamp (integer or string) for the signature, and the right kind
53
+ # of signature in the "signature" field. The best way to know what
54
+ # kind of validation to perform is by remembering which kind of
55
+ # security we started with.
56
+ if request_json_data.has_key?(:sec_key)
57
+ valid = @signature_connection.confirm_sec_key(body['timestamp'], body['signature'])
58
+ else
59
+ valid = @signature_connection.confirm_signature(body['timestamp'], body['signature'])
60
+ end
56
61
 
57
62
  if(!valid)
58
63
  raise "Unable to confirm validity of the job_status response"
@@ -67,17 +72,30 @@ module SmileIdentityCore
67
72
  request.run
68
73
  end
69
74
 
75
+ def request_security(use_new_signature: false)
76
+ if use_new_signature
77
+ @timestamp = Time.now.to_s
78
+ {
79
+ signature: @signature_connection.generate_signature(@timestamp)[:signature],
80
+ timestamp: @timestamp,
81
+ }
82
+ else
83
+ @timestamp = Time.now.to_i
84
+ {
85
+ sec_key: @signature_connection.generate_sec_key(@timestamp)[:sec_key],
86
+ timestamp: @timestamp,
87
+ }
88
+ end
89
+ end
90
+
70
91
  def configure_job_query(user_id, job_id, options)
71
- return {
72
- sec_key: @signature_connection.generate_sec_key(@timestamp)[:sec_key],
73
- timestamp: @timestamp,
92
+ {
74
93
  user_id: user_id,
75
94
  job_id: job_id,
76
95
  partner_id: @partner_id,
77
- image_links: options[:return_image_links] || false,
78
- history: options[:return_history] || false
79
- }.to_json
96
+ image_links: options[:return_image_links],
97
+ history: options[:return_history]
98
+ }
80
99
  end
81
-
82
100
  end
83
101
  end
@@ -1,3 +1,8 @@
1
1
  module SmileIdentityCore
2
- VERSION = "1.0.0"
2
+ VERSION = "1.2.0"
3
+
4
+ def self.version_as_hash
5
+ major, minor, patch = *VERSION.split('.')
6
+ { majorVersion: major, minorVersion: minor, buildNumber: patch }
7
+ end
3
8
  end
@@ -18,8 +18,8 @@ module SmileIdentityCore
18
18
  @sid_server = sid_server
19
19
  if !(sid_server =~ URI::regexp)
20
20
  sid_server_mapping = {
21
- 0 => 'https://3eydmgh10d.execute-api.us-west-2.amazonaws.com/test',
22
- 1 => 'https://la7am6gdm8.execute-api.us-west-2.amazonaws.com/prod'
21
+ 0 => 'https://testapi.smileidentity.com/v1',
22
+ 1 => 'https://api.smileidentity.com/v1',
23
23
  }
24
24
  @url = sid_server_mapping[sid_server.to_i]
25
25
  else
@@ -35,8 +35,6 @@ module SmileIdentityCore
35
35
  end
36
36
 
37
37
  self.images = images
38
- @timestamp = Time.now.to_i
39
-
40
38
  self.id_info = symbolize_keys id_info
41
39
  self.options = symbolize_keys options
42
40
 
@@ -50,7 +48,7 @@ module SmileIdentityCore
50
48
 
51
49
  validate_return_data
52
50
 
53
- return setup_requests
51
+ setup_requests
54
52
  end
55
53
 
56
54
  def get_job_status(partner_params, options)
@@ -61,21 +59,21 @@ module SmileIdentityCore
61
59
  job_id = partner_params[:job_id]
62
60
 
63
61
  utilities = SmileIdentityCore::Utilities.new(@partner_id, @api_key, @sid_server)
64
- return utilities.get_job_status(user_id, job_id, options);
62
+ utilities.get_job_status(user_id, job_id, options);
65
63
  end
66
64
 
67
65
  def partner_params=(partner_params)
68
66
  if partner_params == nil
69
- raise ArgumentError.new('Please ensure that you send through partner params')
67
+ raise ArgumentError, 'Please ensure that you send through partner params'
70
68
  end
71
69
 
72
70
  if !partner_params.is_a?(Hash)
73
- raise ArgumentError.new('Partner params needs to be a hash')
71
+ raise ArgumentError, 'Partner params needs to be a hash'
74
72
  end
75
73
 
76
74
  [:user_id, :job_id, :job_type].each do |key|
77
75
  unless partner_params[key] && !partner_params[key].nil? && !(partner_params[key].empty? if partner_params[key].is_a?(String))
78
- raise ArgumentError.new("Please make sure that #{key.to_s} is included in the partner params")
76
+ raise ArgumentError, "Please make sure that #{key} is included in the partner params"
79
77
  end
80
78
  end
81
79
 
@@ -84,19 +82,20 @@ module SmileIdentityCore
84
82
 
85
83
  def images=(images)
86
84
  if images == nil
87
- raise ArgumentError.new('Please ensure that you send through image details')
85
+ raise ArgumentError, 'Please ensure that you send through image details'
88
86
  end
89
87
 
90
88
  if !images.is_a?(Array)
91
- raise ArgumentError.new('Image details needs to be an array')
89
+ raise ArgumentError, 'Image details needs to be an array'
92
90
  end
93
91
 
94
92
  # all job types require atleast a selfie
95
93
  if images.length == 0 || images.none? {|h| h[:image_type_id] == 0 || h[:image_type_id] == 2 }
96
- raise ArgumentError.new('You need to send through at least one selfie image')
94
+ raise ArgumentError, 'You need to send through at least one selfie image'
97
95
  end
98
96
 
99
97
  @images = images.map { |image| symbolize_keys image }
98
+
100
99
  end
101
100
 
102
101
  def id_info=(id_info)
@@ -118,53 +117,73 @@ module SmileIdentityCore
118
117
  end
119
118
 
120
119
  if updated_id_info[:entered] && updated_id_info[:entered] == 'true'
121
- [:first_name, :last_name, :country, :id_type, :id_number].each do |key|
120
+ [:country, :id_type, :id_number].each do |key|
122
121
  unless id_info[key] && !id_info[key].nil? && !id_info[key].empty?
123
- raise ArgumentError.new("Please make sure that #{key.to_s} is included in the id_info")
122
+ raise ArgumentError, "Please make sure that #{key.to_s} is included in the id_info"
124
123
  end
125
124
  end
126
125
  end
127
126
 
128
- if updated_id_info[:country] && updated_id_info[:country].upcase == 'NG' && ['PASSPORT', 'VOTER_ID', 'DRIVERS_LICENSE', 'NATIONAL_ID', 'TIN', 'CAC'].include?(updated_id_info[:id_type].upcase) && (!updated_id_info[:dob] || updated_id_info[:dob].empty? || updated_id_info[:dob].nil?)
129
- raise ArgumentError.new("The ID type #{updated_id_info[:id_type]} for #{updated_id_info[:country]} requires a valid dob paramater.")
130
- end
131
-
132
127
  @id_info = updated_id_info
133
128
  end
134
129
 
135
130
  def options=(options)
136
- updated_options = options
131
+ updated_options = options || {}
137
132
 
138
- if updated_options.nil?
139
- updated_options = {}
140
- end
141
-
142
- [:optional_callback, :return_job_status, :return_image_links, :return_history].map do |key|
143
- if key != :optional_callback
144
- updated_options[key] = check_boolean(key, options)
145
- else
146
- updated_options[key] = check_string(key, options)
147
- end
148
- end
133
+ updated_options[:optional_callback] = check_string(:optional_callback, options)
134
+ updated_options[:return_job_status] = check_boolean(:return_job_status, options)
135
+ updated_options[:return_image_links] = check_boolean(:return_image_links, options)
136
+ updated_options[:return_history] = check_boolean(:return_history, options)
137
+ @use_new_signature = updated_options.fetch(:signature, false)
149
138
 
150
139
  @options = updated_options
151
140
  end
152
141
 
142
+ def get_web_token(request_params)
143
+ raise ArgumentError, 'Please ensure that you send through request params' if request_params.nil?
144
+ raise ArgumentError, 'Request params needs to be an object' unless request_params.is_a?(Hash)
145
+
146
+ callback_url = request_params[:callback_url] || @callback_url
147
+ request_params[:callback_url] = callback_url
148
+
149
+ keys = %i[user_id job_id product callback_url]
150
+ blank_keys = get_blank_keys(keys, request_params)
151
+ error_message = "#{blank_keys.join(', ')} #{blank_keys.length > 1 ? 'are' : 'is'} required to get a web token"
152
+ raise ArgumentError, error_message unless blank_keys.empty?
153
+
154
+ request_web_token(request_params)
155
+ end
156
+
153
157
  private
154
158
 
159
+ def request_web_token(request_params)
160
+ request_params.merge!({ partner_id: @partner_id }).merge!(request_security)
161
+ url = "#{@url}/token"
162
+
163
+ response = Typhoeus.post(
164
+ url,
165
+ headers: { 'Content-Type' => 'application/json' },
166
+ body: request_params.to_json
167
+ )
168
+
169
+ return response.body if response.code == 200
170
+
171
+ raise "#{response.code}: #{response.body}"
172
+ end
173
+
155
174
  def symbolize_keys params
156
175
  (params.is_a?(Hash)) ? Hash[params.map{ |k, v| [k.to_sym, v] }] : params
157
176
  end
158
177
 
159
178
  def validate_return_data
160
179
  if (!@callback_url || @callback_url.empty?) && !@options[:return_job_status]
161
- raise ArgumentError.new("Please choose to either get your response via the callback or job status query")
180
+ raise ArgumentError, 'Please choose to either get your response via the callback or job status query'
162
181
  end
163
182
  end
164
183
 
165
184
  def validate_enroll_with_id
166
185
  if(((@images.none? {|h| h[:image_type_id] == 1 || h[:image_type_id] == 3 }) && @id_info[:entered] != 'true'))
167
- raise ArgumentError.new("You are attempting to complete a job type 1 without providing an id card image or id info")
186
+ raise ArgumentError, 'You are attempting to complete a job type 1 without providing an id card image or id info'
168
187
  end
169
188
  end
170
189
 
@@ -174,37 +193,54 @@ module SmileIdentityCore
174
193
  end
175
194
 
176
195
  if !!obj[key] != obj[key]
177
- raise ArgumentError.new("#{key} needs to be a boolean")
196
+ raise ArgumentError, "#{key} needs to be a boolean"
178
197
  end
179
198
 
180
- return obj[key]
199
+ obj[key]
181
200
  end
182
201
 
183
202
  def check_string(key, obj)
184
203
  if (!obj || !obj[key])
185
- return ''
204
+ ''
186
205
  else
187
- return obj[key]
206
+ obj[key]
188
207
  end
189
208
  end
190
209
 
191
- def determine_sec_key
192
- @sec_key = SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)[:sec_key]
210
+ def blank?(obj, key)
211
+ return obj[key].empty? if obj[key].respond_to?(:empty?)
212
+
213
+ obj[key].nil?
193
214
  end
194
215
 
195
- def configure_prep_upload_json
216
+ def get_blank_keys(keys, obj)
217
+ keys.select { |key| blank?(obj, key) }
218
+ end
196
219
 
197
- body = {
220
+ def request_security(use_new_signature: true)
221
+ if use_new_signature
222
+ @timestamp = Time.now.to_s
223
+ {
224
+ signature: SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_signature(@timestamp)[:signature],
225
+ timestamp: @timestamp,
226
+ }
227
+ else
228
+ @timestamp = Time.now.to_i
229
+ {
230
+ sec_key: SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)[:sec_key],
231
+ timestamp: @timestamp,
232
+ }
233
+ end
234
+ end
235
+
236
+ def configure_prep_upload_json
237
+ request_security(use_new_signature: @use_new_signature).merge(
198
238
  file_name: 'selfie.zip',
199
- timestamp: @timestamp,
200
- sec_key: determine_sec_key,
201
239
  smile_client_id: @partner_id,
202
240
  partner_params: @partner_params,
203
241
  model_parameters: {}, # what is this for
204
242
  callback_url: @callback_url
205
- }
206
-
207
- JSON.generate(body)
243
+ ).to_json
208
244
  end
209
245
 
210
246
  def setup_requests
@@ -219,6 +255,12 @@ module SmileIdentityCore
219
255
 
220
256
  request.on_complete do |response|
221
257
  if response.success?
258
+ # TODO: if/when we sign these responses, verify the signature here and raise if it's off.
259
+ # if updated_options[:signature]
260
+ # SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_signature(@timestamp)
261
+ # else
262
+ # SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)
263
+ # end
222
264
 
223
265
  prep_upload_response = JSON.parse(response.body)
224
266
  info_json = configure_info_json(prep_upload_response)
@@ -227,13 +269,13 @@ module SmileIdentityCore
227
269
  return file_upload_response
228
270
 
229
271
  elsif response.timed_out?
230
- raise "#{response.code.to_s}: #{response.body}"
272
+ raise "#{response.code}: #{response.body}"
231
273
  elsif response.code == 0
232
274
  # Could not get an http response, something's wrong.
233
- raise "#{response.code.to_s}: #{response.body}"
275
+ raise "#{response.code}: #{response.body}"
234
276
  else
235
277
  # Received a non-successful http response.
236
- raise "#{response.code.to_s}: #{response.body}"
278
+ raise "#{response.code}: #{response.body}"
237
279
  end
238
280
  end
239
281
  request.run
@@ -242,18 +284,12 @@ module SmileIdentityCore
242
284
  def configure_info_json(server_information)
243
285
  info = {
244
286
  "package_information": {
245
- "apiVersion": {
246
- "buildNumber": 0,
247
- "majorVersion": 2,
248
- "minorVersion": 0
249
- },
287
+ "apiVersion": SmileIdentityCore.version_as_hash,
250
288
  "language": "ruby"
251
289
  },
252
- "misc_information": {
253
- "sec_key": @sec_key,
290
+ "misc_information": request_security(use_new_signature: @use_new_signature).merge(
254
291
  "retry": "false",
255
292
  "partner_params": @partner_params,
256
- "timestamp": @timestamp,
257
293
  "file_name": "selfie.zip", # figure out what to do here
258
294
  "smile_client_id": @partner_id,
259
295
  "callback_url": @callback_url,
@@ -269,17 +305,17 @@ module SmileIdentityCore
269
305
  "countryCode": "+",
270
306
  "countryName": ""
271
307
  }
272
- },
308
+ ),
273
309
  "id_info": @id_info,
274
310
  "images": configure_image_payload,
275
311
  "server_information": server_information
276
312
  }
277
- return info
313
+ info
278
314
  end
279
315
 
280
316
  def configure_image_payload
281
317
  @images.map { |i|
282
- if isImageFile?i[:image_type_id]
318
+ if image_file?(i[:image_type_id])
283
319
  {
284
320
  image_type_id: i[:image_type_id],
285
321
  image: '',
@@ -295,7 +331,7 @@ module SmileIdentityCore
295
331
  }
296
332
  end
297
333
 
298
- def isImageFile?type
334
+ def image_file?(type)
299
335
  type.to_i == 0 || type.to_i == 1
300
336
  end
301
337
 
@@ -332,7 +368,10 @@ module SmileIdentityCore
332
368
  if response.success?
333
369
  if @options[:return_job_status]
334
370
  @utilies_connection = SmileIdentityCore::Utilities.new(@partner_id, @api_key, @sid_server)
335
- return query_job_status
371
+ job_response = query_job_status
372
+ job_response["success"] = true
373
+ job_response["smile_job_id"] = smile_job_id
374
+ return job_response
336
375
  else
337
376
  return {success: true, smile_job_id: smile_job_id}.to_json
338
377
  end
@@ -357,9 +396,9 @@ module SmileIdentityCore
357
396
  response = @utilies_connection.get_job_status(@partner_params[:user_id], @partner_params[:job_id], @options)
358
397
 
359
398
  if response && (response['job_complete'] == true || counter == 20)
360
- return response
399
+ response
361
400
  else
362
- return query_job_status(counter)
401
+ query_job_status(counter)
363
402
  end
364
403
 
365
404
  end
@@ -5,8 +5,8 @@ require "smile-identity-core/version"
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "smile-identity-core"
7
7
  spec.version = SmileIdentityCore::VERSION
8
- spec.authors = ["Ridhwana"]
9
- spec.email = ["ridhwana.khan16@gmail.com"]
8
+ spec.authors = ["Smile Identity"]
9
+ spec.email = ["support@smileidentity.com"]
10
10
 
11
11
  spec.summary = "The Smile Identity Web API allows the user to access most of the features of the Smile Identity system through direct server to server queries."
12
12
  spec.description = "The Official Smile Identity gem"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smile-identity-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Ridhwana
7
+ - Smile Identity
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-11 00:00:00.000000000 Z
11
+ date: 2021-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,7 +108,7 @@ dependencies:
108
108
  version: 1.2.3
109
109
  description: The Official Smile Identity gem
110
110
  email:
111
- - ridhwana.khan16@gmail.com
111
+ - support@smileidentity.com
112
112
  executables: []
113
113
  extensions: []
114
114
  extra_rdoc_files: []
@@ -130,7 +130,6 @@ files:
130
130
  - lib/smile-identity-core/version.rb
131
131
  - lib/smile-identity-core/web_api.rb
132
132
  - smile-identity-core.gemspec
133
- - travis.yml
134
133
  homepage: https://www.smileidentity.com/
135
134
  licenses:
136
135
  - MIT
@@ -154,8 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
153
  - !ruby/object:Gem::Version
155
154
  version: '0'
156
155
  requirements: []
157
- rubyforge_project:
158
- rubygems_version: 2.7.6
156
+ rubygems_version: 3.0.3
159
157
  signing_key:
160
158
  specification_version: 4
161
159
  summary: The Smile Identity Web API allows the user to access most of the features
data/travis.yml DELETED
@@ -1,9 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.5.1
4
-
5
- script:
6
- - bundle exec rake spec
7
-
8
- before_install:
9
- - gem install bundle