Skip to content

Commit c81f753

Browse files
authored
v4.0.0 (#27)
1 parent 1bda6f1 commit c81f753

487 files changed

Lines changed: 79733 additions & 402914 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,19 @@ DerivedData
2222
# osx
2323
.DS_Store
2424
/APNS_Certs
25-
**/*.xcconfig
25+
**/*.xcconfig
26+
27+
# Claude Code
28+
.claude/
29+
30+
# dSYMs
31+
**/dSYMs/
32+
33+
# Swift documentation metadata (not needed for compilation or distribution)
34+
**/*.swiftdoc
35+
36+
# Simulator ABI JSON (only device slices are needed)
37+
**/*simulator*.abi.json
38+
39+
# Override global gitignore — CodeResources must be tracked for xcframework code signing
40+
!**/_CodeSignature/CodeResources

CHANGELOG.md

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
# Changelog
22

3-
## v3.2.5 - July 2nd, 2026
43

5-
### Fixed
6-
7-
- Fixed proper dismissal of navigation controller
4+
## v4.0.0 - June 27th, 2026
85

6+
Major release with a redesigned public API and open-source VerifyUI. Contains breaking changes.
97

10-
## v3.2.4 - June 24th, 2026
11-
12-
### Fixed
8+
- For integration guides and quick starts, see [`README.md`](./README.md).
9+
- For a full list of API changes and upgrade steps, see [`MIGRATION.md`](./MIGRATION.md).
10+
- For a complete public API reference, see [`Class Reference.md`](./Class%20Reference.md).
1311

14-
- SDK not submitting barcode for IDs
15-
- Removed the GlassUI effect from the back button
16-
- Fix for overriding localization from app
12+
## v3.3.0 - April 28th, 2026
1713

18-
## v3.2.3 - June 5th, 2026
19-
20-
### Fixed
14+
### Added
2115

22-
- SDK not submitting barcode for DLs
16+
- Enforced a hard stop in the collection flow when users deny required location permissions.
2317

2418
## v3.2.2 - April 17th, 2026
2519

Class Reference.md

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
# VerifyTransactionCoordinator / VerifyTransactionCoordinatorDelegate — iOS Public API Reference
2+
3+
Two-way contract between the verification UI and the SDK core.
4+
5+
- **`VerifyTransactionCoordinator`** — UI calls these on core to submit data and drive the flow.
6+
- **`VerifyTransactionCoordinatorDelegate`** — core calls these on the UI to instruct what to show next.
7+
8+
---
9+
10+
## `VerifyTransactionCoordinator`
11+
12+
### Document submission
13+
14+
| Method | Signature | Description |
15+
|--------|-----------|-------------|
16+
| Submit email | `submitEmail(_ email: String)` | Submits an email address for OTP verification. |
17+
| Submit phone | `submitPhone(_ phone: String)` | Submits a phone number for OTP verification
18+
| Submit selfie | `submitSelfie(_ result: SelfieCaptureResult)` | Submits a captured selfie to PingOne Verify. |
19+
| Submit government ID | `submitGovernmentId(_ result: IdCaptureResult)` | Submits a captured government ID to PingOne Verify. |
20+
| Submit geolocation | `submitGeolocation(latitude: Double, longitude: Double)` | Submits captured geolocation coordinates. |
21+
22+
### OTP
23+
24+
| Method | Signature | Description |
25+
|--------|-----------|-------------|
26+
| Submit OTP | `submitOtp(passcode: String, otpType: DocumentClass)` | Submits the one-time passcode entered by the user. `otpType` must be `.EMAIL` or `.PHONE`. |
27+
| Resend OTP | `resendOtp(for documentType: DocumentClass)` | Requests a new OTP delivery for the given document type. |
28+
29+
### Capture launch
30+
31+
| Method | Signature | Description |
32+
|--------|-----------|-------------|
33+
| Launch selfie capture | `captureSelfie(from navigationController: UINavigationController)` | Launches the selfie capture flow. Requires the selfie provider module. |
34+
| Launch ID capture | `captureGovernmentId(from navigationController: UINavigationController)` | Launches the ID capture flow. Requires the ID capture provider module. |
35+
| Capture geolocation | `captureGeolocation()` | Asks the geolocation provider to request the device's current location. |
36+
37+
### Flow control
38+
39+
| Method | Signature | Description |
40+
|--------|-----------|-------------|
41+
| Skip step | `skipDocument(type: DocumentClass)` | Skips the current optional step. The server must mark the step optional or the call fails. |
42+
| End flow | `endVerification()` | Ends the verification flow and releases observers. |
43+
44+
---
45+
46+
## `VerifyTransactionCoordinatorDelegate`
47+
48+
### Theme and language pack (triggerred before the first `shouldCaptureDocument`)
49+
50+
| Method | Signature | Description |
51+
|--------|-----------|-------------|
52+
| App theme ready | `coordinator(_:didReceiveAppTheme appTheme: AppThemeResponse?, error: Error?)` | Server theme fetched. `appTheme` is non-nil on success; `error` is non-nil on failure. |
53+
| Language pack ready | `coordinator(_:didReceiveLanguagePack languagePackProvider: LanguagePackProviderContract?, error: Error?)` | Language pack fetched. Use `error` (non-nil on failure) to fall back to bundled strings. Fires at `build` completion, before `start()`. |
54+
55+
### Capture lifecycle
56+
57+
| Method | Signature | Description |
58+
|--------|-----------|-------------|
59+
| Should capture | `coordinator(_:shouldCaptureDocument settings: DocumentCaptureSettings)` | Core needs the user to capture a document or provide OTP/geolocation. Read `settings.documentType` to determine the screen to show. |
60+
| Should retry | `coordinator(_:shouldRetryCapture feedback: RetryFeedback, settings: DocumentCaptureSettings)` | The previous submission failed due to the quality issues and the user may retry. |
61+
| Did submit document | `coordinator(_:didSubmitDocument response: DocumentSubmissionResponse)` | Document submitted successfully. |
62+
| Did capture selfie | `coordinator(_:didCaptureSelfie result: SelfieCaptureResult)` | Selfie camera finished. Show preview if desired, then call `submitSelfie(result)` or `captureSelfie(...)` to retake. |
63+
| Did capture ID | `coordinator(_:didCaptureGovernmentId result: IdCaptureResult)` | ID scan finished. Show preview if desired, then call `submitGovernmentId(result)` or `captureGovernmentId(...)` to retake. |
64+
| Did capture geolocation | `coordinator(_:didCaptureGeolocation latitude: Double, longitude: Double)` | Geolocation captured. Optionally show a confirmation, then call `submitGeolocation(...)`. |
65+
66+
### OTP
67+
68+
| Method | Signature | Description |
69+
|--------|-----------|-------------|
70+
| Did submit OTP | `coordinator(_:didSubmitOtp success: Bool)` | OTP verification result. `true` if the passcode was accepted. |
71+
| OTP session updated | `coordinator(_:didUpdateOtpSession settings: OtpCaptureSettings)` | OTP session state changed (e.g. after a resend acknowledgement). Refresh the OTP entry screen with the new state. |
72+
73+
### Completion / failure
74+
75+
| Method | Signature | Description |
76+
|--------|-----------|-------------|
77+
| Did complete | `coordinator(didCompleteSubmission coordinator: VerifyTransactionCoordinator)` | All required documents submitted. Navigate to your completion screen and release your reference to the coordinator. |
78+
| Did fail | `coordinator(_:didFailWith error: DocumentSubmissionError)` | Unrecoverable error. Use `error.getErrorCode()` / `error.getErrorMessage()` for details. |
79+
80+
---
81+
82+
## Data Model
83+
84+
### `DocumentStatus` — Server-reported per-document status
85+
86+
Used as values inside `DocumentSubmissionResponse.documentStatus`.
87+
88+
| Case | Raw value | Description |
89+
|------|-----------|-------------|
90+
| `REQUIRED` | `"REQUIRED"` | Must be collected before the transaction can complete. |
91+
| `OPTIONAL` | `"OPTIONAL"` | May be collected but can be skipped. |
92+
| `COLLECTED` | `"COLLECTED"` | Received by the server. |
93+
| `PROCESSED` | `"PROCESSED"` | Processed by the server. |
94+
| `SKIPPED` | `"SKIPPED"` | Skipped by the user or the SDK. |
95+
96+
### `DocumentSubmissionStatus` — Overall collection status
97+
98+
Returned in `DocumentSubmissionResponse.documentSubmissionStatus`.
99+
100+
| Case | Raw value | Description |
101+
|------|-----------|-------------|
102+
| `NOT_STARTED` | `"NOT_STARTED"` | Document collection has not yet begun. |
103+
| `STARTED` | `"STARTED"` | Document collection is in progress. |
104+
| `COMPLETED` | `"COMPLETED"` | All required documents have been collected. |
105+
| `PROCESS` | `"PROCESS"` | Documents are being processed by the server. |
106+
107+
### `OtpStatus` — OTP delivery / verification status (inside `OtpSession`)
108+
109+
| Case | Raw value | Description |
110+
|------|-----------|-------------|
111+
| `REQUESTED` | `"REQUESTED"` | OTP requested; delivery has not yet started. |
112+
| `IN_PROGRESS` | `"IN_PROGRESS"` | OTP delivery in progress. |
113+
| `OTP_SENT` | `"OTP_SENT"` | OTP delivered to the user. |
114+
| `SUCCESS` | `"SUCCESS"` | Delivery and verification successful. |
115+
| `FAIL` | `"FAIL"` | Delivery or verification failed; not retryable. |
116+
| `OTP_RETRYABLE` | `"OTP_RETRYABLE"` | Delivery failed; the user may request a new code. |
117+
| `OTP_VERIFIED` | `"OTP_VERIFIED"` | User successfully verified the OTP. |
118+
119+
### `SelfieCaptureResult`
120+
121+
Returned by `didCaptureSelfie` and consumed by `submitSelfie`.
122+
123+
| Field | Type | Description |
124+
|-------|------|-------------|
125+
| `selfie` | `let selfie: String` | Base64-encoded JPEG selfie image. |
126+
| `iadPayload` | `let iadPayload: String?` | Base64-encoded liveness payload from the Selfie Capture SDK, or `nil` if unavailable. |
127+
128+
### `IdCaptureResult`
129+
130+
Returned by `didCaptureGovernmentId` and consumed by `submitGovernmentId`.
131+
132+
| Field | Type | Description |
133+
|-------|------|-------------|
134+
| `documentData` | `let documentData: [String: String]` | Key-value map of OCR fields and base64-encoded images extracted from the document. |
135+
| `idType` | `let idType: String` | The scanned document type string (e.g. `"DRIVER_LICENSE"`, `"PASSPORT"`). |
136+
137+
### `DocumentSubmissionResponse`
138+
139+
Server response delivered to `didSubmitDocument`.
140+
141+
| Field | Type | Description |
142+
|-------|------|-------------|
143+
| `document` | `public var document: [String: String]?` | The submitted document data as a key-value dictionary (e.g. `["email": "user@example.com"]`). Used internally to derive the OTP destination for `EMAIL` / `PHONE` flows. |
144+
| `documentStatus` | `public var documentStatus: [String: DocumentStatus]?` | Per-document verification status, keyed by document type string. Values are typed `DocumentStatus` enum cases. |
145+
| `documentSubmissionStatus` | `public var documentSubmissionStatus: DocumentSubmissionStatus?` | Overall status of the document collection session. |
146+
| `createdAt` | `public var createdAt: String?` | ISO 8601 timestamp when the session was created on the server. |
147+
| `updatedAt` | `public var updatedAt: String?` | ISO 8601 timestamp of the most recent server-side update. |
148+
| `expiresAt` | `public var expiresAt: String?` | ISO 8601 timestamp after which the session is no longer valid. |
149+
150+
### `RetryFeedback`
151+
152+
Server feedback for a failed capture, delivered to `shouldRetryCapture`.
153+
154+
| Field | Type | Description |
155+
|-------|------|-------------|
156+
| `code` | `let code: String` | Server error code (e.g. `"QUALITY_CHECK_FAILED"`). |
157+
| `message` | `let message: String` | Human-readable fallback message from the server. |
158+
| `languagePackKey` | `let languagePackKey: String?` | Language-pack key for the localised error string. `nil` when no language-pack key was provided by the server. |
159+
160+
### `DocumentCaptureSettings`
161+
162+
Common base protocol for every capture step. Concrete subtypes — `IdCaptureSettings`, `SelfieCaptureSettings`, `EmailCaptureSettings`, `PhoneCaptureSettings`, `OtpCaptureSettings`, `LocationCaptureSettings` — carry additional fields specific to their step.
163+
164+
| Field | Type | Description |
165+
|-------|------|-------------|
166+
| `documentType` | `DocumentClass` | The data type this step collects. |
167+
| `optional` | `Bool` | When `true`, the user may skip this step. |
168+
| `isRetry` | `Bool` | `true` when this step is a retry of a previously failed attempt. |
169+
| `payloadSize` | `PayloadSize` | Compression level applied to the upload payload. |
170+
171+
### `OtpCaptureSettings` (conforms to `DocumentCaptureSettings`)
172+
173+
Subtype delivered to `shouldCaptureDocument` and `didUpdateOtpSession` for OTP steps.
174+
175+
| Field | Type | Description |
176+
|-------|------|-------------|
177+
| `destination` | `var destination: String` | Email address or phone number to which the OTP was sent. |
178+
| `otpSession` | `var otpSession: OtpSession?` | Typed OTP session state — contains expiry, resend availability, and ticker instances. |
179+
| `otpExpiryTicker` | `var otpExpiryTicker: OtpTicker { get }` | Countdown to OTP expiry. Subscribe to `onTick` / `onExpire`. |
180+
| `resendCooldownTicker` | `var resendCooldownTicker: OtpTicker { get }` | Countdown to when a new OTP delivery may be requested. |
181+
| `requirements` | `var requirements: RequirementsProtocol?` | Server-defined constraints on the destination field. |
182+
183+
### `OtpSession` (embedded in `OtpCaptureSettings.otpSession`)
184+
185+
| Field | Type | Description |
186+
|-------|------|-------------|
187+
| `otpStatus` | `OtpStatus` | Current delivery/verification status (see [OtpStatus](#otpstatus--otp-delivery--verification-status-inside-otpsession)). |
188+
| `expiresAt` | `String?` | ISO 8601 OTP expiry timestamp. |
189+
| `canResend` | `Bool?` | Whether the server permits another OTP delivery. |
190+
| `resendCooldown` | `String?` | Seconds the caller must wait before another resend. |
191+
| `remainingDeliveries` | `Int?` | Number of remaining OTP delivery attempts. |
192+
| `otpLength` | `Int?` | Expected length of the OTP code. |
193+
194+
### `OtpTicker`
195+
196+
Countdown ticker owned by the SDK core; instances are exposed on `OtpCaptureSettings`.
197+
198+
| Member | Type | Description |
199+
|--------|------|-------------|
200+
| `onTick` | `((TimeInterval) -> Void)?` | Fires every second on main with the remaining seconds (clamped at zero). |
201+
| `onExpire` | `(() -> Void)?` | Fires once on main when remaining time reaches zero. |
202+
| `remaining` | `TimeInterval` | Read-only current remaining seconds. |
203+
| `start(expiresAt:)` | `func start(expiresAt: String)` | Starts (or restarts) the ticker, counting down to the given UTC timestamp. Normally driven automatically by the SDK. |
204+
| `stop()` | `func stop()` | Stops the ticker. |
205+
206+
### `AppThemeResponse`
207+
208+
Delivered to `didReceiveAppTheme`.
209+
210+
| Field | Type | Description |
211+
|-------|------|-------------|
212+
| `companyName` | `var companyName: String?` | Configured company name, if any. |
213+
| `template` | `var template: String` | Template identifier (e.g. `"default"`). |
214+
| `defaultTheme` | `var defaultTheme: Bool` | `true` when the server returned the default PingOne theme. |
215+
| `configuration` | `var configuration: ThemeConfig` | Full set of colour, button, and logo configuration values. |
216+
217+
### `VerifyTransaction` (exposed via `currentTransaction`)
218+
219+
Live transaction state read from `coordinator.currentTransaction`.
220+
221+
| Field | Type | Description |
222+
|-------|------|-------------|
223+
| `transactionId` | `String` | Server-assigned transaction identifier. |
224+
| `verificationCode` | `String` | Short code the end user enters/scans to begin the transaction. |
225+
| `environmentId` | `String?` | PingOne environment ID owning the transaction, if provided. |
226+
| `keyVersion` | `String` | API contract version. Currently `"v1"`. |
227+
| `requiredDocuments` | `[String: DocumentStatus]` | Map of document type strings to their current status. |
228+
| `url` | `VerifyApiLinks` | API endpoint links for submit, poll, etc. |
229+
230+
### `DocumentSubmissionError`
231+
232+
Delivered to `didFailWith` on unrecoverable failures.
233+
234+
| Member | Type | Description |
235+
|--------|------|-------------|
236+
| `code` | `public var code: String!` | Machine-readable error code (e.g. `"tx_failed"`, `"doc_timeout"`). |
237+
| `localizedDescription` | `public var localizedDescription: String!` | Human-readable description, suitable for logging. |
238+
| `getErrorCode()` | `func getErrorCode() -> String` | Accessor for `code`. |
239+
| `getErrorMessage()` | `func getErrorMessage() -> String` | Accessor for `localizedDescription`. |
240+
241+
**`SubmissionError` enum cases**: `initiateDocumentTransactionError`, `submissionError`, `noDocumentToSubmitError`, `missingDocumentType`, `invalidKeyMap`, `documentCaptureError`, `documentSubmissionTimoutError`, `missingOtpDestination`, `missingOtp`, `failedOtp`, `transactionError`, `userCanceledError`, `encryptionError`.
242+
243+
## Canonical Flow
244+
245+
```
246+
shouldCapture<X> Core → UI (UI shows the capture screen)
247+
capture<X> UI → Core (UI launches the capture provider)
248+
didCapture<X> Core → UI (UI shows preview / confirm)
249+
submit<X> UI → Core (UI shows progress screen)
250+
didSubmitDocument Core → UI (UI hides progress, advances)
251+
```
252+
253+
Where `<X>` is one of `GovernmentId`, `Selfie`, `Geolocation`. For email/phone/OTP steps the UI shows a text-entry screen instead of a capture provider and skips the `capture<X>` / `didCapture<X>` legs.
254+
255+
**Progress screen lifecycle**:
256+
- Show after `submit<X>`.
257+
- Hide on `didSubmitDocument`, `didCompleteSubmission`, or the next `shouldCapture<X>`.

DISCLAIMER.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/***************************************************************************
2-
* Copyright (C) 2024 Ping Identity Corporation
2+
* Copyright (C) 2026 Ping Identity Corporation
33
* All rights reserved.
44
*
55
* Ping Identity Corporation

0 commit comments

Comments
 (0)