smile-identity-core 0.2.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21c2a5a3b5e5f424a1c496debe16bab3a3950123b734c1a35e43035da2f7c622
4
- data.tar.gz: a8cebcd27f35a24ae3bdcd61c692dae4523d8cf80e2f7adaf2e021dfe150a30e
3
+ metadata.gz: 2c6c2b9d1846e6939c1a1f8407b24d08f40eb54492f302ff682f0070afbd837a
4
+ data.tar.gz: 46d3ef6830ee732870ea1657faeb3d1feb8f020b05dd715b615d313541e90bfe
5
5
  SHA512:
6
- metadata.gz: f30735bd2481bd6baecad7b0c37c4aa6ca239e3c00ef61e96aa4f4346b732a2641fc2bcf34898e68de766835ec94aa759d481e014350936a4a6d40b2086b46a5
7
- data.tar.gz: fd8bfef72649e53477633ed2bcd3d2235295b06b78ee418fecdfbe06466da244c1b0afd19ed5e79b9fb526bef191ce90b272e7fb658f48c22bdc214d53ddc015
6
+ metadata.gz: 6548acb1e3cb5efa6cd2d73b048449e99ef74c8e3dde60fa06373c6535353f97bc46eb950446ed825c5938b95559db85d58870ce8909f258bcd7066bedae0085
7
+ data.tar.gz: 4a0b84d72c3ce4b69c051c944d2cc95d4c02bb58244fd2b47bc532d7f6a67ab5e7bb5d7cccb89c8e4a7fc0f217c3548a457ae1a6783ed6bdd2e9b3b18ed80d7d
data/.travis.yml CHANGED
@@ -4,4 +4,7 @@ language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
6
  - 2.5.1
7
- before_install: gem install bundler -v 2.0.2
7
+ - 2.6
8
+ - 2.7
9
+ - 3.0
10
+ before_install: gem install bundler -v 2.2.6
data/CHANGELOG.md CHANGED
@@ -32,3 +32,18 @@ Add the language to the package information
32
32
  ## [0.2.3] - 2019-09-17
33
33
  ### Updated
34
34
  Lenient Decoding of the api key
35
+
36
+ ## [1.0.0] - 2019-10-11
37
+ ## Updated
38
+ Amend the success response when job status is false to be a JSON String containing {"success":true,"smile_job_id":"job_id"}
39
+ Add the ID API Class
40
+ Add the ability to query ID Api from the Web API class
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 (0.2.3)
4
+ smile-identity-core (1.1.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)
@@ -28,13 +28,13 @@ GEM
28
28
  diff-lcs (>= 1.2.0, < 2.0)
29
29
  rspec-support (~> 3.8.0)
30
30
  rspec-support (3.8.2)
31
- rubyzip (1.2.4)
31
+ rubyzip (1.3.0)
32
32
  simplecov (0.12.0)
33
33
  docile (~> 1.1.0)
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,11 +1,14 @@
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
8
 
9
+ 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
+ - submit_job
11
+
9
12
  The **Signature Class** allows you as the Partner to generate a sec key to interact with our servers. It has the following public methods:
10
13
  - generate_sec_key
11
14
  - confirm_sec_key
@@ -15,9 +18,9 @@ The **Utilities Class** allows you as the Partner to have access to our general
15
18
 
16
19
  ## Documentation
17
20
 
18
- This gem requires specific input parameters, for more detail on these parameters please refer to our [documentation for Web API](https://docs-smileid.herokuapp.com/docs#web-api-introduction).
21
+ This gem requires specific input parameters, for more detail on these parameters please refer to our [documentation for Web API](https://docs.smileidentity.com).
19
22
 
20
- 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).
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://portal.smileidentity.com/signup).
21
24
 
22
25
  ## Installation
23
26
 
@@ -52,51 +55,203 @@ $ response = connection.submit_job(partner_params, images, id_info, options)
52
55
  ```
53
56
 
54
57
  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
+ ```
60
+ $ response = connection.submit_job(partner_params, images, nil, nil);
61
+ ```
62
+
63
+ 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
+ ```
66
+ $ response = connection.submit_job(partner_params, nil, id_info, nil);
67
+ ```
68
+
69
+ **Response:**
70
+
71
+ Should you choose to *set return_job_status to false*, the response will be a JSON String containing:
55
72
  ```
56
- String response = connection.submit_job(partner_params, images, nil, nil);
73
+ {success: true, smile_job_id: smile_job_id}
57
74
  ```
58
75
 
59
- The response will be nil if you chose to set return_job_status to false, however if you have set return_job_status to true then you will receive a response like below:
76
+ 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
+ {
79
+ "job_success":true,
80
+ "result":{
81
+ "ConfidenceValue":"99",
82
+ "JSONVersion":"1.0.0",
83
+ "Actions":{
84
+ "Verify_ID_Number":"Verified",
85
+ "Return_Personal_Info":"Returned",
86
+ "Human_Review_Update_Selfie":"Not Applicable",
87
+ "Human_Review_Compare":"Not Applicable",
88
+ "Update_Registered_Selfie_On_File":"Not Applicable",
89
+ "Liveness_Check":"Not Applicable",
90
+ "Register_Selfie":"Approved",
91
+ "Human_Review_Liveness_Check":"Not Applicable",
92
+ "Selfie_To_ID_Authority_Compare":"Completed",
93
+ "Selfie_To_ID_Card_Compare":"Not Applicable",
94
+ "Selfie_To_Registered_Selfie_Compare":"Not Applicable"
95
+ },
96
+ "ResultText":"Enroll User",
97
+ "IsFinalResult":"true",
98
+ "IsMachineResult":"true",
99
+ "ResultType":"SAIA",
100
+ "PartnerParams":{
101
+ "job_type":"1",
102
+ "optional_info":"we are one",
103
+ "user_id":"HBBBBBBH57g",
104
+ "job_id":"HBBBBBBHg"
105
+ },
106
+ "Source":"WebAPI",
107
+ "ResultCode":"0810",
108
+ "SmileJobID":"0000001111"
109
+ },
110
+ "code":"2302",
111
+ "job_complete":true,
112
+ "signature":"HKBhxcv+1qaLy\C7PjVtk257dE=|1577b051a4313ed5e3e4d29893a66f966e31af0a2d2f6bec2a7f2e00f2701259",
113
+ "history":[
114
+ {
115
+ "ConfidenceValue":"99",
116
+ "JSONVersion":"1.0.0",
117
+ "Actions":{
118
+ "Verify_ID_Number":"Verified",
119
+ "Return_Personal_Info":"Returned",
120
+ "Human_Review_Update_Selfie":"Not Applicable",
121
+ "Human_Review_Compare":"Not Applicable",
122
+ "Update_Registered_Selfie_On_File":"Not Applicable",
123
+ "Liveness_Check":"Not Applicable",
124
+ "Register_Selfie":"Approved",
125
+ "Human_Review_Liveness_Check":"Not Applicable",
126
+ "Selfie_To_ID_Authority_Compare":"Completed",
127
+ "Selfie_To_ID_Card_Compare":"Not Applicable",
128
+ "Selfie_To_Registered_Selfie_Compare":"Not Applicable"
129
+ },
130
+ "ResultText":"Enroll User",
131
+ "IsFinalResult":"true",
132
+ "IsMachineResult":"true",
133
+ "ResultType":"SAIA",
134
+ "PartnerParams":{
135
+ "job_type":"1",
136
+ "optional_info":"we are one",
137
+ "user_id":"HBBBBBBH57g",
138
+ "job_id":"HBBBBBBHg"
139
+ },
140
+ "Source":"WebAPI",
141
+ "ResultCode":"0810",
142
+ "SmileJobID":"0000001111"
143
+ }
144
+ ],
145
+ "image_links":{
146
+ "selfie_image":"image_link"
147
+ },
148
+ "timestamp":"2019-10-10T12:32:04.622Z"
149
+ }
150
+ ```
60
151
 
152
+ You can also *view your response asynchronously at the callback* that you have set, it will look as follows:
61
153
  ```
62
154
  {
63
- "timestamp": "2018-03-13T21:04:11.193Z",
64
- "signature": "<your signature>",
65
- "job_complete": true,
66
- "job_success": true,
67
- "result": {
68
- "ResultText": "Enroll User",
69
- "ResultType": "SAIA",
70
- "SmileJobID": "0000001897",
71
- "JSONVersion": "1.0.0",
72
- "IsFinalResult": "true",
73
- "PartnerParams": {
74
- "job_id": "52d0de86-be3b-4219-9e96-8195b0018944",
75
- "user_id": "e54e0e98-8b8c-4215-89f5-7f9ea42bf650",
76
- "job_type": 4
77
- },
78
- "ConfidenceValue": "100",
79
- "IsMachineResult": "true",
80
- }
81
- "code": "2302"
155
+ "job_success":true,
156
+ "result":{
157
+ "ConfidenceValue":"99",
158
+ "JSONVersion":"1.0.0",
159
+ "Actions":{
160
+ "Verify_ID_Number":"Verified",
161
+ "Return_Personal_Info":"Returned",
162
+ "Human_Review_Update_Selfie":"Not Applicable",
163
+ "Human_Review_Compare":"Not Applicable",
164
+ "Update_Registered_Selfie_On_File":"Not Applicable",
165
+ "Liveness_Check":"Not Applicable",
166
+ "Register_Selfie":"Approved",
167
+ "Human_Review_Liveness_Check":"Not Applicable",
168
+ "Selfie_To_ID_Authority_Compare":"Completed",
169
+ "Selfie_To_ID_Card_Compare":"Not Applicable",
170
+ "Selfie_To_Registered_Selfie_Compare":"Not Applicable"
171
+ },
172
+ "ResultText":"Enroll User",
173
+ "IsFinalResult":"true",
174
+ "IsMachineResult":"true",
175
+ "ResultType":"SAIA",
176
+ "PartnerParams":{
177
+ "job_type":"1",
178
+ "optional_info":"we are one",
179
+ "user_id":"HBBBBBBH57g",
180
+ "job_id":"HBBBBBBHg"
181
+ },
182
+ "Source":"WebAPI",
183
+ "ResultCode":"0810",
184
+ "SmileJobID":"0000001111"
185
+ },
186
+ "code":"2302",
187
+ "job_complete":true,
188
+ "signature":"HKBhxcv+1qaLy\C7PjVtk257dE=|1577b051a4313ed5e3e4d29893a66f966e31af0a2d2f6bec2a7f2e00f2701259",
189
+ "history":[
190
+ {
191
+ "ConfidenceValue":"99",
192
+ "JSONVersion":"1.0.0",
193
+ "Actions":{
194
+ "Verify_ID_Number":"Verified",
195
+ "Return_Personal_Info":"Returned",
196
+ "Human_Review_Update_Selfie":"Not Applicable",
197
+ "Human_Review_Compare":"Not Applicable",
198
+ "Update_Registered_Selfie_On_File":"Not Applicable",
199
+ "Liveness_Check":"Not Applicable",
200
+ "Register_Selfie":"Approved",
201
+ "Human_Review_Liveness_Check":"Not Applicable",
202
+ "Selfie_To_ID_Authority_Compare":"Completed",
203
+ "Selfie_To_ID_Card_Compare":"Not Applicable",
204
+ "Selfie_To_Registered_Selfie_Compare":"Not Applicable"
205
+ },
206
+ "ResultText":"Enroll User",
207
+ "IsFinalResult":"true",
208
+ "IsMachineResult":"true",
209
+ "ResultType":"SAIA",
210
+ "PartnerParams":{
211
+ "job_type":"1",
212
+ "optional_info":"we are one",
213
+ "user_id":"HBBBBBBH57g",
214
+ "job_id":"HBBBBBBHg"
215
+ },
216
+ "Source":"WebAPI",
217
+ "ResultCode":"0810",
218
+ "SmileJobID":"0000001111"
219
+ }
220
+ ],
221
+ "image_links":{
222
+ "selfie_image":"image_link"
223
+ },
224
+ "timestamp":"2019-10-10T12:32:04.622Z"
82
225
  }
83
226
  ```
84
- You can also view your response asynchronously at the callback that you have set, it will look as follows:
227
+
228
+ If you have queried a job type 5, your response be a JSON String that will contain the following:
85
229
  ```
86
230
  {
87
- "ResultCode": "1220",
88
- "ResultText": "Authenticated",
89
- "ResultType": "DIVA",
90
- "SmileJobID": "0000000001",
91
- "JSONVersion": "1.0.0",
92
- "IsFinalResult": "true",
93
- "PartnerParams": {
94
- "job_id": "e7ca3e6c-e527-7165-b0b5-b90db1276378",
95
- "user_id": "07a0c120-98d7-4fdc-bc62-3c6bfd16c60e",
96
- "job_type": 2
97
- },
98
- "ConfidenceValue": "100.000000",
99
- "IsMachineResult": "true"
231
+ "JSONVersion":"1.0.0",
232
+ "SmileJobID":"0000001105",
233
+ "PartnerParams":{
234
+ "user_id":"T6yzdOezucdsPrY0QG9LYNDGOrC",
235
+ "job_id":"FS1kd1dd15JUpd87gTBDapvFxv0",
236
+ "job_type":5
237
+ },
238
+ "ResultType":"ID Verification",
239
+ "ResultText":"ID Number Validated",
240
+ "ResultCode":"1012",
241
+ "IsFinalResult":"true",
242
+ "Actions":{
243
+ "Verify_ID_Number":"Verified",
244
+ "Return_Personal_Info":"Returned"
245
+ },
246
+ "Country":"NG",
247
+ "IDType":"PASSPORT",
248
+ "IDNumber":"A04150107",
249
+ "ExpirationDate":"2017-10-28",
250
+ "FullName":"ADEYEMI KEHINDE ADUNOLA",
251
+ "DOB":"1989-09-20",
252
+ "Photo":"SomeBase64Image",
253
+ "sec_key":"pjxsxEY69zEHjSPFvPEQTqu17vpZbw+zTNqaFxRWpYDiO+7wzKc9zvPU2lRGiKg7rff6nGPBvQ6rA7/wYkcLrlD2SuR2Q8hOcDFgni3PJHutij7j6ThRdpTwJRO2GjLXN5HHDB52NjAvKPyclSDANHrG1qb/tloO7x4bFJ7tKYE=|8faebe00b317654548f8b739dc631431b67d2d4e6ab65c6d53539aaad1600ac7",
254
+ "timestamp":1570698930193
100
255
  }
101
256
  ```
102
257
 
@@ -120,6 +275,127 @@ Please note that if you do not need to pass through options if you will not be u
120
275
  response = connection.get_job_status(partner_params, nil);
121
276
  ```
122
277
 
278
+ **Response**
279
+
280
+ Your response will return a JSON Object below with image_links and history included:
281
+
282
+ ```
283
+ {
284
+ "job_success":true,
285
+ "result":{
286
+ "ConfidenceValue":"99",
287
+ "JSONVersion":"1.0.0",
288
+ "Actions":{
289
+ "Verify_ID_Number":"Verified",
290
+ "Return_Personal_Info":"Returned",
291
+ "Human_Review_Update_Selfie":"Not Applicable",
292
+ "Human_Review_Compare":"Not Applicable",
293
+ "Update_Registered_Selfie_On_File":"Not Applicable",
294
+ "Liveness_Check":"Not Applicable",
295
+ "Register_Selfie":"Approved",
296
+ "Human_Review_Liveness_Check":"Not Applicable",
297
+ "Selfie_To_ID_Authority_Compare":"Completed",
298
+ "Selfie_To_ID_Card_Compare":"Not Applicable",
299
+ "Selfie_To_Registered_Selfie_Compare":"Not Applicable"
300
+ },
301
+ "ResultText":"Enroll User",
302
+ "IsFinalResult":"true",
303
+ "IsMachineResult":"true",
304
+ "ResultType":"SAIA",
305
+ "PartnerParams":{
306
+ "job_type":"1",
307
+ "optional_info":"we are one",
308
+ "user_id":"HBBBBBBH57g",
309
+ "job_id":"HBBBBBBHg"
310
+ },
311
+ "Source":"WebAPI",
312
+ "ResultCode":"0810",
313
+ "SmileJobID":"0000001111"
314
+ },
315
+ "code":"2302",
316
+ "job_complete":true,
317
+ "signature":"HKBhxcv+1qaLy\C7PjVtk257dE=|1577b051a4313ed5e3e4d29893a66f966e31af0a2d2f6bec2a7f2e00f2701259",
318
+ "history":[
319
+ {
320
+ "ConfidenceValue":"99",
321
+ "JSONVersion":"1.0.0",
322
+ "Actions":{
323
+ "Verify_ID_Number":"Verified",
324
+ "Return_Personal_Info":"Returned",
325
+ "Human_Review_Update_Selfie":"Not Applicable",
326
+ "Human_Review_Compare":"Not Applicable",
327
+ "Update_Registered_Selfie_On_File":"Not Applicable",
328
+ "Liveness_Check":"Not Applicable",
329
+ "Register_Selfie":"Approved",
330
+ "Human_Review_Liveness_Check":"Not Applicable",
331
+ "Selfie_To_ID_Authority_Compare":"Completed",
332
+ "Selfie_To_ID_Card_Compare":"Not Applicable",
333
+ "Selfie_To_Registered_Selfie_Compare":"Not Applicable"
334
+ },
335
+ "ResultText":"Enroll User",
336
+ "IsFinalResult":"true",
337
+ "IsMachineResult":"true",
338
+ "ResultType":"SAIA",
339
+ "PartnerParams":{
340
+ "job_type":"1",
341
+ "optional_info":"we are one",
342
+ "user_id":"HBBBBBBH57g",
343
+ "job_id":"HBBBBBBHg"
344
+ },
345
+ "Source":"WebAPI",
346
+ "ResultCode":"0810",
347
+ "SmileJobID":"0000001111"
348
+ }
349
+ ],
350
+ "image_links":{
351
+ "selfie_image":"image_link"
352
+ },
353
+ "timestamp":"2019-10-10T12:32:04.622Z"
354
+ }
355
+ ```
356
+
357
+ #### ID Api Class
358
+
359
+
360
+ ##### submit_job method
361
+ ```
362
+ $ connection = SmileIdentityCore::IDApi.new(partner_id, api_key, sid_server)
363
+
364
+ $ response = connection.submit_job(partner_params, id_info)
365
+ ```
366
+
367
+ **Response**
368
+
369
+ Your response will return a JSON String containing the below:
370
+ ```
371
+ {
372
+ "JSONVersion":"1.0.0",
373
+ "SmileJobID":"0000001105",
374
+ "PartnerParams":{
375
+ "user_id":"T6yzdOezucdsPrY0QG9LYNDGOrC",
376
+ "job_id":"FS1kd1dd15JUpd87gTBDapvFxv0",
377
+ "job_type":5
378
+ },
379
+ "ResultType":"ID Verification",
380
+ "ResultText":"ID Number Validated",
381
+ "ResultCode":"1012",
382
+ "IsFinalResult":"true",
383
+ "Actions":{
384
+ "Verify_ID_Number":"Verified",
385
+ "Return_Personal_Info":"Returned"
386
+ },
387
+ "Country":"NG",
388
+ "IDType":"PASSPORT",
389
+ "IDNumber":"A04150107",
390
+ "ExpirationDate":"2017-10-28",
391
+ "FullName":"ADEYEMI KEHINDE ADUNOLA",
392
+ "DOB":"1989-09-20",
393
+ "Photo":"SomeBase64Image",
394
+ "sec_key":"pjxsxEY69zEHjSPFvPEQTqu17vpZbw+zTNqaFxRWpYDiO+7wzKc9zvPU2lRGiKg7rff6nGPBvQ6rA7/wYkcLrlD2SuR2Q8hOcDFgni3PJHutij7j6ThRdpTwJRO2GjLXN5HHDB52NjAvKPyclSDANHrG1qb/tloO7x4bFJ7tKYE=|8faebe00b317654548f8b739dc631431b67d2d4e6ab65c6d53539aaad1600ac7",
395
+ "timestamp":1570698930193
396
+ }
397
+ ```
398
+
123
399
  #### Signature Class
124
400
 
125
401
  ##### generate_sec_key method
@@ -154,9 +430,7 @@ $ sec_key = connection.confirm_sec_key(sec_key, timestamp)
154
430
 
155
431
  You may want to receive more information about a job. This is built into Web Api if you choose to set return_job_status as true in the options hash. However, you also have the option to build the functionality yourself by using the Utilities class. Please note that if you are querying a job immediately after submitting it, you will need to poll it for the duration of the job.
156
432
 
157
- ```java
158
-
159
-
433
+ ```ruby
160
434
  utilities_connection = SmileIdentityCore::Utilities.new('partner_id', 'api_key' , sid_server)
161
435
 
162
436
  utilities_connection.get_job_status('user_id', 'job_id', options)
@@ -169,13 +443,23 @@ After checking out the repo, run `bundle install` to install dependencies. Then,
169
443
 
170
444
  To install this gem onto your local machine, run `bundle exec rake install`.
171
445
 
446
+ You can use `bundle console` and then call the necessary classes with their parameters.
447
+
448
+ ## Testing
449
+
450
+ Run `bundle exec rspec` to run the tests.
451
+ After running your tests open the coverage/index.html to view the test coverage
452
+
453
+ ## Deployment
454
+
172
455
  To release a new version:
173
456
  - Update the version number in `version.rb`
174
457
  - Run `gem build smile-identity-core.gemspec`
175
- - Thereafter `gem push smile-identity-core-version.gem`.
458
+ - Thereafter `gem push smile-identity-core-<version>.gem`.
176
459
 
177
460
  Make sure to git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
178
461
 
462
+
179
463
  ## Contributing
180
464
 
181
465
  Bug reports and pull requests are welcome on GitHub at https://github.com/smileidentity/smile-identity-core
@@ -0,0 +1,124 @@
1
+ module SmileIdentityCore
2
+ class IDApi
3
+
4
+ def initialize(partner_id, api_key, sid_server)
5
+ @partner_id = partner_id.to_s
6
+ @api_key = api_key
7
+
8
+ @sid_server = sid_server
9
+ if !(sid_server =~ URI::regexp)
10
+ sid_server_mapping = {
11
+ 0 => 'https://testapi.smileidentity.com/v1',
12
+ 1 => 'https://api.smileidentity.com/v1',
13
+ }
14
+ @url = sid_server_mapping[sid_server.to_i]
15
+ else
16
+ @url = sid_server
17
+ end
18
+ end
19
+
20
+ def submit_job(partner_params, id_info, options = {})
21
+ self.partner_params = symbolize_keys partner_params
22
+ self.id_info = symbolize_keys id_info
23
+ @use_new_signature = symbolize_keys(options || {}).fetch(:signature, false)
24
+
25
+ if @partner_params[:job_type].to_i != 5
26
+ raise ArgumentError.new('Please ensure that you are setting your job_type to 5 to query ID Api')
27
+ end
28
+
29
+ return setup_requests
30
+ end
31
+
32
+ def partner_params=(partner_params)
33
+ if partner_params == nil
34
+ raise ArgumentError.new('Please ensure that you send through partner params')
35
+ end
36
+
37
+ if !partner_params.is_a?(Hash)
38
+ raise ArgumentError.new('Partner params needs to be a hash')
39
+ end
40
+
41
+ [:user_id, :job_id, :job_type].each do |key|
42
+ unless partner_params[key] && !partner_params[key].nil? && !(partner_params[key].empty? if partner_params[key].is_a?(String))
43
+ raise ArgumentError.new("Please make sure that #{key.to_s} is included in the partner params")
44
+ end
45
+ end
46
+
47
+ @partner_params = partner_params
48
+ end
49
+
50
+ def id_info=(id_info)
51
+
52
+ updated_id_info = id_info
53
+
54
+ if updated_id_info.nil? || updated_id_info.keys.length == 0
55
+ raise ArgumentError.new("Please make sure that id_info not empty or nil")
56
+ end
57
+
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.new("Please make sure that #{key.to_s} is included in the id_info")
61
+ end
62
+ end
63
+
64
+ @id_info = updated_id_info
65
+ end
66
+
67
+ private
68
+
69
+ def symbolize_keys params
70
+ (params.is_a?(Hash)) ? Hash[params.map{ |k, v| [k.to_sym, v] }] : params
71
+ end
72
+
73
+ def setup_requests
74
+ url = "#{@url}/id_verification"
75
+
76
+ request = Typhoeus::Request.new(
77
+ url,
78
+ method: 'POST',
79
+ headers: {'Content-Type'=> "application/json"},
80
+ body: configure_json
81
+ )
82
+
83
+ request.on_complete do |response|
84
+ if response.success?
85
+ return response.body
86
+ elsif response.timed_out?
87
+ raise "#{response.code.to_s}: #{response.body}"
88
+ elsif response.code == 0
89
+ # Could not get an http response, something's wrong.
90
+ raise "#{response.code.to_s}: #{response.body}"
91
+ else
92
+ # Received a non-successful http response.
93
+ raise "#{response.code.to_s}: #{response.body}"
94
+ end
95
+ end
96
+ request.run
97
+ end
98
+
99
+ def configure_json
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
106
+ end
107
+
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
122
+ end
123
+ end
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)
@@ -36,5 +36,21 @@ module SmileIdentityCore
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
+ return {
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 = "0.2.3"
2
+ VERSION = "1.1.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
@@ -28,10 +28,13 @@ module SmileIdentityCore
28
28
  end
29
29
 
30
30
  def submit_job(partner_params, images, id_info, options)
31
+
31
32
  self.partner_params = symbolize_keys partner_params
32
- self.images = images
33
- @timestamp = Time.now.to_i
33
+ if @partner_params[:job_type].to_i == 5
34
+ return SmileIdentityCore::IDApi.new(@partner_id, @api_key, @sid_server).submit_job(partner_params, id_info)
35
+ end
34
36
 
37
+ self.images = images
35
38
  self.id_info = symbolize_keys id_info
36
39
  self.options = symbolize_keys options
37
40
 
@@ -92,6 +95,7 @@ module SmileIdentityCore
92
95
  end
93
96
 
94
97
  @images = images.map { |image| symbolize_keys image }
98
+
95
99
  end
96
100
 
97
101
  def id_info=(id_info)
@@ -113,34 +117,24 @@ module SmileIdentityCore
113
117
  end
114
118
 
115
119
  if updated_id_info[:entered] && updated_id_info[:entered] == 'true'
116
- [:first_name, :last_name, :country, :id_type, :id_number].each do |key|
120
+ [:country, :id_type, :id_number].each do |key|
117
121
  unless id_info[key] && !id_info[key].nil? && !id_info[key].empty?
118
122
  raise ArgumentError.new("Please make sure that #{key.to_s} is included in the id_info")
119
123
  end
120
124
  end
121
125
  end
122
126
 
123
- 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?)
124
- raise ArgumentError.new("The ID type #{updated_id_info[:id_type]} for #{updated_id_info[:country]} requires a valid dob paramater.")
125
- end
126
-
127
127
  @id_info = updated_id_info
128
128
  end
129
129
 
130
130
  def options=(options)
131
- updated_options = options
131
+ updated_options = options || {}
132
132
 
133
- if updated_options.nil?
134
- updated_options = {}
135
- end
136
-
137
- [:optional_callback, :return_job_status, :return_image_links, :return_history].map do |key|
138
- if key != :optional_callback
139
- updated_options[key] = check_boolean(key, options)
140
- else
141
- updated_options[key] = check_string(key, options)
142
- end
143
- 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)
144
138
 
145
139
  @options = updated_options
146
140
  end
@@ -174,6 +168,7 @@ module SmileIdentityCore
174
168
 
175
169
  return obj[key]
176
170
  end
171
+ # zeKn:WFL7t2X/+4
177
172
 
178
173
  def check_string(key, obj)
179
174
  if (!obj || !obj[key])
@@ -183,23 +178,30 @@ module SmileIdentityCore
183
178
  end
184
179
  end
185
180
 
186
- def determine_sec_key
187
- @sec_key = SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)[:sec_key]
181
+ def request_security(use_new_signature: true)
182
+ if use_new_signature
183
+ @timestamp = Time.now.to_s
184
+ {
185
+ signature: SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_signature(@timestamp)[:signature],
186
+ timestamp: @timestamp,
187
+ }
188
+ else
189
+ @timestamp = Time.now.to_i
190
+ {
191
+ sec_key: SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)[:sec_key],
192
+ timestamp: @timestamp,
193
+ }
194
+ end
188
195
  end
189
196
 
190
197
  def configure_prep_upload_json
191
-
192
- body = {
198
+ request_security(use_new_signature: @use_new_signature).merge(
193
199
  file_name: 'selfie.zip',
194
- timestamp: @timestamp,
195
- sec_key: determine_sec_key,
196
200
  smile_client_id: @partner_id,
197
201
  partner_params: @partner_params,
198
202
  model_parameters: {}, # what is this for
199
203
  callback_url: @callback_url
200
- }
201
-
202
- JSON.generate(body)
204
+ ).to_json
203
205
  end
204
206
 
205
207
  def setup_requests
@@ -214,11 +216,17 @@ module SmileIdentityCore
214
216
 
215
217
  request.on_complete do |response|
216
218
  if response.success?
219
+ # TODO: if/when we sign these responses, verify the signature here and raise if it's off.
220
+ # if updated_options[:signature]
221
+ # SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_signature(@timestamp)
222
+ # else
223
+ # SmileIdentityCore::Signature.new(@partner_id, @api_key).generate_sec_key(@timestamp)
224
+ # end
217
225
 
218
226
  prep_upload_response = JSON.parse(response.body)
219
227
  info_json = configure_info_json(prep_upload_response)
220
228
 
221
- file_upload_response = upload_file(prep_upload_response['upload_url'], info_json)
229
+ file_upload_response = upload_file(prep_upload_response['upload_url'], info_json, prep_upload_response['smile_job_id'])
222
230
  return file_upload_response
223
231
 
224
232
  elsif response.timed_out?
@@ -237,18 +245,12 @@ module SmileIdentityCore
237
245
  def configure_info_json(server_information)
238
246
  info = {
239
247
  "package_information": {
240
- "apiVersion": {
241
- "buildNumber": 0,
242
- "majorVersion": 2,
243
- "minorVersion": 0
244
- },
248
+ "apiVersion": SmileIdentityCore.version_as_hash,
245
249
  "language": "ruby"
246
250
  },
247
- "misc_information": {
248
- "sec_key": @sec_key,
251
+ "misc_information": request_security(use_new_signature: @use_new_signature).merge(
249
252
  "retry": "false",
250
253
  "partner_params": @partner_params,
251
- "timestamp": @timestamp,
252
254
  "file_name": "selfie.zip", # figure out what to do here
253
255
  "smile_client_id": @partner_id,
254
256
  "callback_url": @callback_url,
@@ -264,7 +266,7 @@ module SmileIdentityCore
264
266
  "countryCode": "+",
265
267
  "countryName": ""
266
268
  }
267
- },
269
+ ),
268
270
  "id_info": @id_info,
269
271
  "images": configure_image_payload,
270
272
  "server_information": server_information
@@ -274,7 +276,7 @@ module SmileIdentityCore
274
276
 
275
277
  def configure_image_payload
276
278
  @images.map { |i|
277
- if isImageFile?i[:image_type_id]
279
+ if image_file?(i[:image_type_id])
278
280
  {
279
281
  image_type_id: i[:image_type_id],
280
282
  image: '',
@@ -290,7 +292,7 @@ module SmileIdentityCore
290
292
  }
291
293
  end
292
294
 
293
- def isImageFile?type
295
+ def image_file?(type)
294
296
  type.to_i == 0 || type.to_i == 1
295
297
  end
296
298
 
@@ -311,7 +313,7 @@ module SmileIdentityCore
311
313
  end
312
314
  end
313
315
 
314
- def upload_file(url, info_json)
316
+ def upload_file(url, info_json, smile_job_id)
315
317
 
316
318
  file = zip_up_file(info_json)
317
319
  file.rewind
@@ -327,9 +329,12 @@ module SmileIdentityCore
327
329
  if response.success?
328
330
  if @options[:return_job_status]
329
331
  @utilies_connection = SmileIdentityCore::Utilities.new(@partner_id, @api_key, @sid_server)
330
- return query_job_status
332
+ job_response = query_job_status
333
+ job_response["success"] = true
334
+ job_response["smile_job_id"] = smile_job_id
335
+ return job_response
331
336
  else
332
- return
337
+ return {success: true, smile_job_id: smile_job_id}.to_json
333
338
  end
334
339
  elsif response.timed_out?
335
340
  raise " #{response.code.to_s}: #{response.body}"
@@ -1,5 +1,6 @@
1
1
  require "smile-identity-core/version"
2
2
  require "smile-identity-core/web_api.rb"
3
+ require "smile-identity-core/id_api.rb"
3
4
  require "smile-identity-core/signature.rb"
4
5
  require "smile-identity-core/utilities.rb"
5
6
 
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = "https://github.com/smileidentity/smile-identity-core-ruby"
19
- spec.metadata["documentation_uri"] = "https://docs-smileid.herokuapp.com/docs#web-api-introduction"
19
+ spec.metadata["documentation_uri"] = "https://docs.smileidentity.com"
20
20
  spec.metadata["changelog_uri"] = "https://github.com/smileidentity/smile-identity-core/blob/master/CHANGELOG.md"
21
21
 
22
22
  # Specify which files should be added to the gem when it is released.
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: 0.2.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ridhwana
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-17 00:00:00.000000000 Z
11
+ date: 2021-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -124,21 +124,21 @@ files:
124
124
  - bin/console
125
125
  - bin/setup
126
126
  - lib/smile-identity-core.rb
127
+ - lib/smile-identity-core/id_api.rb
127
128
  - lib/smile-identity-core/signature.rb
128
129
  - lib/smile-identity-core/utilities.rb
129
130
  - lib/smile-identity-core/version.rb
130
131
  - lib/smile-identity-core/web_api.rb
131
132
  - smile-identity-core.gemspec
132
- - travis.yml
133
133
  homepage: https://www.smileidentity.com/
134
134
  licenses:
135
135
  - MIT
136
136
  metadata:
137
137
  homepage_uri: https://www.smileidentity.com/
138
138
  source_code_uri: https://github.com/smileidentity/smile-identity-core-ruby
139
- documentation_uri: https://docs-smileid.herokuapp.com/docs#web-api-introduction
139
+ documentation_uri: https://docs.smileidentity.com
140
140
  changelog_uri: https://github.com/smileidentity/smile-identity-core/blob/master/CHANGELOG.md
141
- post_install_message:
141
+ post_install_message:
142
142
  rdoc_options: []
143
143
  require_paths:
144
144
  - lib
@@ -153,9 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  - !ruby/object:Gem::Version
154
154
  version: '0'
155
155
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.7.6
158
- signing_key:
156
+ rubygems_version: 3.2.3
157
+ signing_key:
159
158
  specification_version: 4
160
159
  summary: The Smile Identity Web API allows the user to access most of the features
161
160
  of the Smile Identity system through direct server to server queries.
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