Skip to content

Commit 9ec28b8

Browse files
committed
release v2.0.0
1 parent 51d1cc9 commit 9ec28b8

File tree

9 files changed

+99
-75
lines changed

9 files changed

+99
-75
lines changed

README.md

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,3 @@
1-
> **Warning**
2-
>
3-
> **Starting June 2022, this repository is no longer being maintained.** The iProov iOS API Client is now made available directly as part of the [iProov iOS Biometrics SDK](https://github.com/iProov/ios).
4-
>
5-
> You should upgrade your Podfile from:
6-
>
7-
> ```
8-
> pod 'iProovAPIClient', :git => 'https://github.com/iProov/ios-api-client.git'
9-
> ```
10-
>
11-
> to:
12-
>
13-
> ```
14-
> pod 'iProovAPIClient', :podspec => 'https://raw.githubusercontent.com/iProov/ios/master/iProovAPIClient/iProovAPIClient.podspec'
15-
> ```
16-
>
17-
> For further details, see the [Upgrade Guide for SDK v9.4](https://github.com/iProov/ios/wiki/Upgrade-Guide#api-client).
18-
19-
---
20-
211
# iProov iOS API Client
222

233
## Introduction
@@ -49,8 +29,6 @@ And then run `pod install`.
4929
- `validate()` - Validates an existing token.
5030
- `enrolPhotoAndGetVerifyToken()` - A helper function which chains together `getToken()` for the enrolment token, `enrolPhoto()` to enrol the photo, and then `getToken()` for the verify token, which you can then use to launch the SDK.
5131

52-
You can find the API-calling code [here](https://github.com/iProov/swift-api-client/blob/master/iProovAPIClient/Classes/APIClient.swift).
53-
5432
## Example
5533

5634
Example of using iProov API Client together with iProov to get a verify token for an existing user and then launch the iProov SDK to perform the verification using Genuine Presence Assurance:

_Pods.xcodeproj

Lines changed: 0 additions & 1 deletion
This file was deleted.

iProovAPIClient.podspec

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
Pod::Spec.new do |s|
22
s.name = 'iProovAPIClient'
3-
s.version = '1.1.0'
3+
s.version = '2.0.0'
44
s.summary = 'iOS API Client for iProov REST API v2'
5-
s.homepage = 'https://github.com/iproov/ios-api-client'
6-
s.license = { :type => 'BSD-3', :file => 'LICENSE' }
5+
s.homepage = 'https://github.com/iProov/ios-api-client'
6+
s.license = { :type => 'BSD-3', :file => 'LICENSE.md' }
77
s.author = { 'iProov' => '[email protected]' }
88
s.source = { :git => 'https://github.com/iProov/ios-api-client.git', :tag => s.version.to_s }
9-
s.ios.deployment_target = '10.0'
9+
s.swift_version = '5.5'
10+
s.ios.deployment_target = '13.0'
1011
s.source_files = 'iProovAPIClient/Classes/**/*'
1112

1213
s.dependency 'Alamofire', '~> 5.0'

iProovAPIClient/Assets/.gitkeep

Whitespace-only changes.

iProovAPIClient/Classes/APIClient.swift

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
// Copyright (c) 2021 iProov Ltd. All rights reserved.
1+
// Copyright (c) 2024 iProov Ltd. All rights reserved.
22

33
// ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
44
// THIS CODE IS PROVIDED FOR DEMO PURPOSES ONLY AND SHOULD NOT BE USED IN
55
// PRODUCTION! YOU SHOULD NEVER EMBED YOUR CREDENTIALS IN A PUBLIC APP RELEASE!
66
// THESE API CALLS SHOULD ONLY EVER BE MADE FROM YOUR BACK-END SERVER
77
// ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
88

9-
import Foundation
109
import Alamofire
10+
import Foundation
1111

1212
typealias JSON = [String: Any]
1313

@@ -38,13 +38,13 @@ public class APIClient {
3838
public var errorDescription: String? {
3939
switch self {
4040
case .invalidImage:
41-
return "Invalid image"
41+
"Invalid image"
4242
case .noToken:
43-
return "No token"
43+
"No token"
4444
case .invalidJSON:
45-
return "Invalid JSON"
45+
"Invalid JSON"
4646
case let .serverError(errorDescription):
47-
return errorDescription
47+
errorDescription
4848
}
4949
}
5050
}
@@ -70,16 +70,17 @@ public class APIClient {
7070
public func getToken(assuranceType: AssuranceType,
7171
type: ClaimType,
7272
userID: String,
73+
resource: String? = nil,
7374
additionalOptions: [String: Any] = [:],
74-
completion: @escaping (Result<String, Swift.Error>) -> Void) {
75-
75+
completion: @escaping (Result<String, Swift.Error>) -> Void)
76+
{
7677
let url = String(format: "%@/claim/%@/token", baseURL, type.rawValue)
7778

7879
var params: [String: Any] = [
7980
"assurance_type": assuranceType.rawValue,
8081
"api_key": apiKey,
8182
"secret": secret,
82-
"resource": appID,
83+
"resource": resource ?? appID,
8384
"client": "ios",
8485
"user_id": userID,
8586
]
@@ -89,15 +90,15 @@ public class APIClient {
8990
}
9091

9192
AF.request(url, method: .post, parameters: params, encoding: JSONEncoding(), headers: nil)
92-
.validate(statusCode: 200..<500)
93+
.validate(statusCode: 200 ..< 500)
9394
.responseToken(completionHandler: completion)
9495
}
9596

9697
public func enrolPhoto(token: String,
9798
image: UIImage,
9899
source: PhotoSource,
99-
completion: @escaping (Result<String, Swift.Error>) -> Void) {
100-
100+
completion: @escaping (Result<String, Swift.Error>) -> Void)
101+
{
101102
let url = String(format: "%@/claim/enrol/image", baseURL)
102103

103104
guard let jpegData = image.safeJPEGData(compressionQuality: 1.0) else {
@@ -115,14 +116,14 @@ public class APIClient {
115116
multipartFormData.append(source.rawValue, withName: "source")
116117

117118
}, to: url)
118-
.validate(statusCode: 200..<500)
119-
.responseToken(completionHandler: completion)
119+
.validate(statusCode: 200 ..< 500)
120+
.responseToken(completionHandler: completion)
120121
}
121122

122123
public func validate(token: String,
123124
userID: String,
124-
completion: @escaping (Result<ValidationResult, Swift.Error>) -> Void) {
125-
125+
completion: @escaping (Result<ValidationResult, Swift.Error>) -> Void)
126+
{
126127
let url = String(format: "%@/claim/verify/validate", baseURL)
127128

128129
let params = [
@@ -132,16 +133,17 @@ public class APIClient {
132133
"token": token,
133134
"ip": "127.0.0.1",
134135
"client": appID,
136+
"risk_profile": "",
135137
]
136138

137139
AF.request(url, method: .post, parameters: params, encoding: JSONEncoding(), headers: nil)
138-
.validate(statusCode: 200..<500)
139-
.responseJSON { response in
140+
.validate(statusCode: 200 ..< 500)
141+
.responseData { response in
140142

141143
switch response.result {
142-
case let .success(json):
144+
case let .success(data):
143145

144-
guard let json = json as? JSON else {
146+
guard let json = try? JSONSerialization.jsonObject(with: data) as? JSON else {
145147
completion(.failure(Error.invalidJSON))
146148
return
147149
}
@@ -162,12 +164,11 @@ public class APIClient {
162164
}
163165

164166
public extension APIClient {
165-
166167
private struct ErrorSink<T> {
167168
let failure: (Swift.Error) -> Void
168169

169170
func onSuccess(_ next: @escaping (T) -> Void) -> (Result<T, Swift.Error>) -> Void {
170-
return { result in
171+
{ result in
171172
switch result {
172173
case let .success(value):
173174
next(value)
@@ -182,29 +183,26 @@ public extension APIClient {
182183
func enrolPhotoAndGetVerifyToken(userID: String,
183184
image: UIImage,
184185
source: PhotoSource,
185-
completion: @escaping (Result<String, Swift.Error>) -> Void) {
186-
186+
completion: @escaping (Result<String, Swift.Error>) -> Void)
187+
{
187188
let errorSink = ErrorSink<String> { completion(.failure($0)) }
188189

189190
getToken(assuranceType: .genuinePresence, type: .enrol, userID: userID, completion: errorSink.onSuccess { token in
190-
self.enrolPhoto(token: token, image: image, source: source, completion: errorSink.onSuccess { token in
191+
self.enrolPhoto(token: token, image: image, source: source, completion: errorSink.onSuccess { _ in
191192
self.getToken(assuranceType: .genuinePresence, type: .verify, userID: userID, completion: completion)
192193
})
193194
})
194-
195195
}
196196
}
197197

198-
extension DataRequest {
199-
198+
public extension DataRequest {
200199
@discardableResult
201-
public func responseToken(completionHandler: @escaping (Result<String, Swift.Error>) -> Void) -> Self {
202-
203-
responseJSON { response in
200+
func responseToken(completionHandler: @escaping (Result<String, Swift.Error>) -> Void) -> Self {
201+
responseData { response in
204202
switch response.result {
205-
case let .success(json):
203+
case let .success(data):
206204

207-
guard let json = json as? JSON else {
205+
guard let json = try? JSONSerialization.jsonObject(with: data) as? JSON else {
208206
completionHandler(.failure(APIClient.Error.invalidJSON))
209207
return
210208
}
@@ -225,6 +223,5 @@ extension DataRequest {
225223
completionHandler(.failure(error))
226224
}
227225
}
228-
229226
}
230227
}

iProovAPIClient/Classes/MultipartFormData+Append.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2021 iProov Ltd. All rights reserved.
1+
// Copyright (c) 2024 iProov Ltd. All rights reserved.
22

33
import Alamofire
44
import Foundation

iProovAPIClient/Classes/UIImage+Base64.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2021 iProov Ltd. All rights reserved.
1+
// Copyright (c) 2024 iProov Ltd. All rights reserved.
22

33
import UIKit
44

iProovAPIClient/Classes/UIImage+JPEG.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2021 iProov Ltd. All rights reserved.
1+
// Copyright (c) 2024 iProov Ltd. All rights reserved.
22

33
import UIKit
44

@@ -11,8 +11,8 @@ extension UIImage {
1111
return jpegData(compressionQuality: compressionQuality)
1212
}
1313

14-
guard let ciImage = ciImage,
15-
let cgImage = CIContext(options: nil).createCGImage(ciImage, from: ciImage.extent)
14+
guard let ciImage,
15+
let cgImage = CIContext(options: nil).createCGImage(ciImage, from: ciImage.extent)
1616
else { return nil }
1717

1818
return UIImage(cgImage: cgImage).jpegData(compressionQuality: compressionQuality)
Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,76 @@
1-
// Copyright (c) 2021 iProov Ltd. All rights reserved.
1+
// Copyright (c) 2024 iProov Ltd. All rights reserved.
22

33
import Foundation
44

5-
public struct ValidationResult {
5+
public struct ValidationResult: CustomStringConvertible {
66
public let isPassed: Bool
77
public let token: String
8+
public let type: String
9+
public let isFrameAvailable: Bool?
810
public let frame: UIImage?
911
public let failureReason: String?
12+
public let riskProfile: String?
13+
public let assuranceType: String?
14+
public let signals: [String: Any]?
15+
16+
enum Keys {
17+
static let isPassed = "passed"
18+
static let token = "token"
19+
static let type = "type"
20+
static let isFrameAvailable = "frame_available"
21+
static let frame = "frame"
22+
static let failureReason = "reason"
23+
static let riskProfile = "risk_profile"
24+
static let assuranceType = "assurance_type"
25+
static let signals = "signals"
26+
}
1027

1128
init(json: JSON) {
12-
isPassed = json["passed"] as! Bool
13-
token = json["token"] as! String
14-
if let frameBase64 = json["frame"] as? String {
29+
isPassed = json[Keys.isPassed] as! Bool
30+
token = json[Keys.token] as! String
31+
type = json[Keys.type] as! String
32+
isFrameAvailable = json[Keys.isFrameAvailable] as? Bool
33+
34+
if let frameBase64 = json[Keys.frame] as? String {
1535
frame = UIImage(base64String: frameBase64)
1636
} else {
1737
frame = nil
1838
}
1939

20-
if let resultJSON = json["result"] as? JSON {
21-
failureReason = resultJSON["reason"] as? String
22-
} else {
23-
failureReason = nil
40+
failureReason = json[Keys.failureReason] as? String
41+
riskProfile = json[Keys.riskProfile] as? String
42+
assuranceType = json[Keys.assuranceType] as? String
43+
signals = json[Keys.signals] as? JSON
44+
}
45+
46+
public var description: String {
47+
var baseDescription =
48+
"""
49+
Validation: \(isPassed)
50+
\(Keys.token): \(token)
51+
\(Keys.type): \(type)
52+
"""
53+
54+
if let isFrameAvailable {
55+
baseDescription += "\n\(Keys.isFrameAvailable): \(isFrameAvailable)"
56+
}
57+
58+
if let riskProfile {
59+
baseDescription += "\n\(Keys.riskProfile): \(riskProfile)"
60+
}
61+
62+
if let failureReason {
63+
baseDescription += "\n\(Keys.failureReason): \(failureReason)"
64+
}
65+
66+
if let assuranceType {
67+
baseDescription += "\n\(Keys.assuranceType): \(assuranceType)"
68+
}
69+
70+
if let signals {
71+
baseDescription += "\n\(Keys.signals): \(signals)"
2472
}
2573

74+
return baseDescription
2675
}
2776
}

0 commit comments

Comments
 (0)