Recovering a Pay account

In case you forgot the passcode of your Pay user, you can also use the SDK to recover your account. There are three steps:

1. Starting the flow

It's a simple call to start the flow in the background. The backend receives the phone number it should send the OTP verification to and will reply with the flow identifier you will need to use in follow-up calls.

vipasoPay.startRecoveryFlow(request: request) { result in
    switch result {
    case .success(let response):
        // Success: make sure to save the returned flow ID
    case .failure(let error):
        if case .recovery(.tooManyTries) = error {
            // Error: too many retries
        } else {
            // Error: any other error, server or network errors
        }
    }
}
val request = StartRecoveryRequest(phoneNumber = phoneNumber)
return vipasoWrapper.vipasoPay.startRecoveryFlow(request)

If you debug your networking calls, you should see the following traffic:

HTTP request and response for sending the OTP code and receiving the flow identifier.

POST /identity/recovery HTTP/1.1
Content-Type: application/json
{
  "identifier": "+439999999999"
}
HTTP/1.1 201 Created
Content-Type: application/json;charset=UTF-8
{
  "flowId": "be204c4a-e10e-4124-9b2e-c4b81c867cce",
  "expiresAt": "2024-11-27T09:05:03.517896776Z"
}

Example screenshots from our development application:

2. Verifying your phone number

This is where it gets a bit messy, but luckily the SDK can hide the bad parts from your eyes. In the second step, the client side sends the OTP code with the flow id and will receive a CSRF token with the settings flow ID it will need to use in the last call.

vipasoPay.sendRecoveryOTP(request: request) { result in
    switch result {
    case .success(let response):
        // Success: make sure to save the settings flow id and csrf token for later
    case .failure(let error):
        // Error: any server or network error
    }
}
return vipasoWrapper.vipasoPay.sendRecoveryOtp(flowId = flowId, code = code)

If you debug your networking calls, you should see the following traffic. Don't be surprised if you see a 422 error, it's used like this on purpose to get the CSRF token. Again, all the overhead is luckily hidden by the SDK APIs.

POST /a/self-service/recovery?flow=be204c4a-e10e-4124-9b2e-c4b81c867cce HTTP/1.1
Content-Type: application/json
{
  "method": "code",
  "code": "999999"
}
HTTP/1.1 422 Unprocessable Entity
Content-Length: 420
Content-Type: application/json
{
  "error": {
    "code": 422,
    ...
  },
  "redirect_browser_to": "..."
}

Example screenshots from our development application:

3. Setting the new passcode

The last step is update your passcode. You will need to send the received CSRF token and the new passcode to the received settings flow id. It's important to note that the SDK does not automatically authenticate you again. This is to let you implement your user experience the way you prefer. Once you got a success response, you can navigate your users to the login screen for example.

vipasoPay.finishRecoveryFlow(request: request) { result in
    switch result {
    case .success(let response):
        // Success: navigate to log in screen
    case .failure(let error):
        // Error: any server or network error
    }
}
val request = FinishRecoveryRequest(settingsFlowId, csrfValue, password)
return vipasoWrapper.vipasoPay.finishRecoveryFlow(request)

If you debug your networking calls, you should see the following traffic:

POST /a/self-service/settings?flow=6726b579-706a-4ebe-8742-6cd3cb73472d HTTP/1.1
Content-Type: application/json
{
  "csrf_token": "80PqKCzku/7g46kof5REfxeC8PdWuYwZfOxY8xESZXg=",
  "method": "password",
  "password": "111111"
}
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
  ...
}

Example screenshots from our development application:


What’s Next