|
| 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>`. |
0 commit comments