smile-identity-core 0.2.3 → 1.1.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: 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