Verify with GoPay

Verify with GoPay Request

The verify flow is initiated by calling FeatureManager.verify() with a FeatureRequest built via the Builder API.

let request = FeatureRequest.Builder()
    .requestId(UUID().uuidString)
    .userCorrelationId("corr-5678")
    .token("linking-token-xyz")
    .build()

Field nameDescription
requestIdUnique identifier for the request, generated by the client. Required — callback.onError(GPE-2206) is called if blank.
userCorrelationIdIdentifier linking the client user to GoPay. Required — callback.onError(GPE-2206) is called if blank.
tokenThe linking token for the user. Provide a short-term linking token when using .exchange, or a long-term token when using .none.

Note: FeatureRequest.Builder.build() does not validate fields. Validation happens inside verify() — missing required fields result in callback.onError being called with GPE-2206, not a thrown error.

Verify with GoPay Response

callback.onComplete is called with a VerifyResult upon successful completion.

public struct VerifyResult {
    public let submissionId: String
}

FieldDescription
submissionIdSubmission identifier for the KYC flow, returned by the backend.

FeatureRequest

FeatureRequest is constructed via its Builder. requestId and userCorrelationId are validated inside verify() — if either is blank, callback.onError is called with GPE-2206 rather than throwing.

public struct FeatureRequest {
    public let requestId: String
    public let featureId: String?
    public let userCorrelationId: String
    public let token: String?

    public final class Builder {
        public init()

        @discardableResult public func requestId(_ id: String) -> Builder
        @discardableResult public func featureId(_ id: String?) -> Builder
        @discardableResult public func userCorrelationId(_ id: String) -> Builder
        @discardableResult public func token(_ t: String?) -> Builder

        public func build() -> FeatureRequest
    }
}

Fields

Field nameTypeRequiredDescription
requestIdStringYesUnique identifier for the request, generated by the client (e.g. a UUID). Validated inside verify(); error returned if blank.
featureIdString?NoReserved for internal use. Do not set this field for the verify flow.
userCorrelationIdStringYesIdentifier linking the client user to GoPay. Validated inside verify(); error returned if blank.
tokenString?YesThe linking token for the user. Pass a short-term linking token when using .exchange, or a long-term token when using .none.

Usage Notes

  • build() performs no validation — a request with blank requestId or userCorrelationId will build successfully but trigger callback.onError(GPE-2206) when passed to verify().
  • requestId must be unique per flow and is used for state correlation during the handshake.
  • Generate a fresh requestId for every verify call — do not reuse across calls.

GoPayCredential

Represents the authentication credential issued by the SDK to the client during the auth-code exchange.

public enum GoPayCredential {
    case authCode(code: String)
}
CaseDescription
authCodeThe one-time authentication code to exchange server-side for a user correlation ID.

CredentialReceiver

Controls how the SDK delivers a GoPayCredential to the client during a flow requiring an auth-code handshake.

public enum CredentialReceiver {
    case exchange(handler: CredentialExchangeHandler)
    case none
}

public struct CredentialExchangeHandler {
    public let handle: (
        _ credential: GoPayCredential,
        _ requestId: String,
        _ completion: @escaping (ExchangeResult) -> Void
    ) -> Void

    public init(handle: @escaping (
        _ credential: GoPayCredential,
        _ requestId: String,
        _ completion: @escaping (ExchangeResult) -> Void
    ) -> Void)
}
CaseDescription
exchangeUse when the user has a short-term linking token. The SDK calls the handler with an auth code; the client exchanges it server-side and calls completion with the result.
noneUse when the user has a long-term token that is still valid. No auth-code exchange is required.

Usage Notes

  • Use .exchange when the user has a short-term linking token that requires a backend exchange.
  • Use .none when the user has a long-term token and no exchange is required.
  • The handle closure may be invoked on a background thread — do not perform UI operations directly inside it.
  • Always call the completion closure exactly once per handler invocation. Do not throw or return without calling it.

ExchangeResult

Returned via the completion closure of CredentialExchangeHandler to signal the outcome of the backend credential exchange.

public enum ExchangeResult {
    case success(userCorrelationId: String)
    case failure(reason: String)
}
CaseAssociated ValueDescription
successuserCorrelationIdThe unique user identifier returned from the client's backend after exchanging the auth code.
failurereasonA human-readable description of why the exchange failed. The SDK propagates this in GPE-2208.

Usage Notes

  • Call completion(.success(userCorrelationId:)) after a successful backend call that returns the userCorrelationId.
  • Call completion(.failure(reason:)) if your backend call fails. The SDK stops the flow and calls callback.onError with code GPE-2208.
  • Never throw from inside the handler — always call completion.

Example Usage

With credential exchange (short-term linking token)

Use this when the user has a short-term linking token. The SDK invokes the exchange handler with an auth code; your backend exchanges it for the user's correlation ID.

let request = FeatureRequest.Builder()
    .requestId(UUID().uuidString)
    .userCorrelationId("corr-5678")
    .token("short-term-linking-token")
    .build()

let credentialReceiver = CredentialReceiver.exchange(
    handler: CredentialExchangeHandler { credential, requestId, completion in
        switch credential {
        case .authCode(let code):
            myBackend.exchangeAuthCode(code, requestId: requestId) { result in
                switch result {
                case .success(let correlationId):
                    completion(.success(userCorrelationId: correlationId))
                case .failure(let error):
                    completion(.failure(reason: error.localizedDescription))
                }
            }
        }
    }
)

let callback = VerifyFeatureCallback { result in
    print("Submission ID: \(result.submissionId)")
} onError: { error in
    print("Error [\(error.code)]: \(error.title) — \(error.message)")
}
self.verifyCallback = callback  // retain strongly

do {
    try sdk.getFeatureManager().verify(
        viewController: self,
        request: request,
        credentialReceiver: credentialReceiver,
        callback: AnyFeatureCallback(wrapping: callback)
    )
} catch {
    print("verify threw: \(error)")
}

Without credential exchange (long-term token)

Use this when the user already has a long-term token. No auth-code exchange is required.

let request = FeatureRequest.Builder()
    .requestId(UUID().uuidString)
    .userCorrelationId("corr-5678")
    .token("long-term-token")
    .build()

let callback = VerifyFeatureCallback { result in
    print("Submission ID: \(result.submissionId)")
} onError: { error in
    print("Error [\(error.code)]: \(error.message)")
}
self.verifyCallback = callback

do {
    try sdk.getFeatureManager().verify(
        viewController: self,
        request: request,
        credentialReceiver: .none,
        callback: AnyFeatureCallback(wrapping: callback)
    )
} catch {
    print("verify threw: \(error)")
}

Usage Notes

  • Always call verify() on the main thread.
  • verify() is marked throws — wrap it in a do-catch block.
  • build() does not throw — validation is performed inside verify(). Ensure both requestId and userCorrelationId are non-blank before calling.
  • Pass .exchange when the user has a short-term linking token. The SDK invokes the handler with an auth code; your backend exchanges it and returns the userCorrelationId via completion.
  • Pass .none when the user has a long-term token that is still valid.
  • Call completion(.failure(reason:)) — never throw — from inside the handler if your backend call fails. The SDK invokes callback.onError with GPE-2208.
  • The data parameter in onComplete may carry additional SDK metadata and can safely be ignored if not needed.
  • Keep a strong reference to your FeatureCallback instance for the duration of the flow. AnyFeatureCallback holds it weakly.