Skip to content

WebAPI Server retrieval

Instantiate WebAPITransfer

Instantiate a WebAPITransfer object and set the TransferReceiveCallback and TransferProgressListener.

Instantiation may throw SDKException if cannot create the object.

  • NotInitializedException if SDK is not initialized
  • UnsupportedFeatureException if license does not support this feature

Setting timeout

WebAPI class provides two methods to set the timeout for connection and reading. Both methods accept the timeout in milliseconds.

  • WebAPI#setReadTimeout(int)
  • WebAPI#setConnectionTimeout(int)

Example

MainActivity.java
package com.example.app;

import ...

public class MainActivity extends AppCompatActivity
        implements DeviceEngagementCallback, TransferReceiveCallback {

    ...
    private final Map<String, Map<String, Map<String, Boolean>>> docRequests
            = new HashMap<>();
    private WebAPITransfer webApiTransfer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Map<String, Boolean> itemsRequest = new HashMap<>();
        itemsRequest.put("age_over_21", true);
        itemsRequest.put("portrait", true);

        Map<String, Map<String, Boolean>> nameSpaces = new HashMap<>();
        nameSpaces.put("org.iso.18013.5.1", itemsRequest);

        docRequests.put("org.iso.18013.5.1.mDL", nameSpaces);

        try {
            webApiTransfer = new WebAPITransfer()
                    .setTransferReceiveCallback(this);
        } catch (SDKException e) {
            // handle failed BLETransfer initialization
        }   
        ...
    }

   ...

}

Send request

When device engagement is received, use the WebAPITransfer#forDeviceEngagement(DeviceEngagement) method to set the current device engagement to WebAPITransfer object.

Then create the request using RequestBuilder and use the WebAPITransfer#send(Request) to send it.

Example

MainActivity.java
package com.example.app;

import ...

public class MainActivity extends AppCompatActivity
        implements DeviceEngagementCallback, TransferReceiveCallback {

    ...
    private WebAPITransfer webApiTransfer;

    ...

    @Override
    public void onEngage(@NonNull Received<EngagementReceived> received) {
        try {
            received.runCatching(
                    failure -> {
                        // handle failed device engagement
                    },
                    success -> {
                        DeviceEngagement deviceEngagement = success.getDeviceEngagement();

                        Request request = new RequestBuilder()
                                .setDeviceEngagement(deviceEngagement)
                                .setDocRequests(docRequests)
                                .build();

                        webAPITransfer
                                .forDeviceEngagement(deviceEngagement)
                                .send(request);
                    }
            );
        } catch (Exception e) {
            // handle exception sending request
        }
    }

    ...

}

Receiving response

When response is received, use the Received#run(Consumer<Failure>, Consumer<TransferReceived>) or Received#runCatching(Functions.FailableConsumer<Failure>, Functions.FailableConsumer<TransferReceived>) to handle the response.

Example

MainActivity.java
package com.example.app;

import ...

public class MainActivity extends AppCompatActivity
        implements DeviceEngagementCallback, TransferReceiveCallback {

    ...

    @Override
    public void onReceive(@NonNull Received<TransferReceived> received) {
        try {
            received.runCatching(
                    failure -> {
                        // handle failed data received
                    },
                    success -> success.runCatchingForServer(bytesReceived -> {
                        // consume bytesReceived
                    })
            );
        } catch (Exception e) {
            // handle exception
        }
    }

}

Failure Types

  • WEBAPI_ERROR
  • WEBAPI_JWT_VERIFICATION_ERROR

Sample code

The following example demonstrates a typical implementation for retrieving data using QR device engagement and WebAPI.

Example

MainActivity.java
package com.example.app;

import android.Manifest.permission;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import com.scytales.mvalid.sdk.FailureType;
import com.scytales.mvalid.sdk.Received;
import com.scytales.mvalid.sdk.SDKException;
import com.scytales.mvalid.sdk.data.Request;
import com.scytales.mvalid.sdk.data.RequestBuilder;
import com.scytales.mvalid.sdk.data.ServerResponse;
import com.scytales.mvalid.sdk.engagement.DeviceEngagement;
import com.scytales.mvalid.sdk.engagement.DeviceEngagementCallback;
import com.scytales.mvalid.sdk.engagement.EngagementReceived;
import com.scytales.mvalid.sdk.engagement.qr.QRDeviceEngagement;
import com.scytales.mvalid.sdk.retrieval.TransferProgressEvent;
import com.scytales.mvalid.sdk.retrieval.TransferProgressListener;
import com.scytales.mvalid.sdk.retrieval.TransferReceiveCallback;
import com.scytales.mvalid.sdk.retrieval.TransferReceived;
import com.scytales.mvalid.sdk.retrieval.server.WebAPITransfer;
import com.scytales.mvalid.sdk.verify.ServerResponseVerifier;
import com.scytales.mvalid.sdk.verify.ServerVerifierResult;
import com.scytales.mvalid.sdk.verify.Verifier;
import com.scytales.mvalid.sdk.verify.VerifierResult;

import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;

public class MainActivity extends AppCompatActivity
        implements DeviceEngagementCallback, TransferProgressListener,
        TransferReceiveCallback {
    private static final String TAG = "MainActivity";

    private final QRDeviceEngagement qrDeviceEngagement = new QRDeviceEngagement();
    private WebAPITransfer webAPITransfer;
    private final ActivityResultLauncher<String> requestPermissionsLauncher =
            registerForActivityResult(new ActivityResultContracts.RequestPermission(), status -> {
                if (status) {
                    enableScanQrBtn();
                }
            });
    private Collection<X509Certificate> rootCertificates;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rootCertificates = Verifier.getRootCertificates(this);

        if (ContextCompat.checkSelfPermission(this, permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            requestPermissionsLauncher.launch(permission.CAMERA);
        } else {
            enableScanQrBtn();
        }

        try {
            qrDeviceEngagement.enableDeviceEngagement(this, this);

            webAPITransfer = new WebAPITransfer()
                    .setTransferProgressListener(this)
                    .setTransferReceiveCallback(this);

        } catch (SDKException e) {
            Log.e(TAG, "onCreate", e);
            // handle failed initialization
        }
    }

    private void enableScanQrBtn() {
        Button scanQrBtn = findViewById(R.id.scan_qr_btn);
        scanQrBtn.setOnClickListener(v -> qrDeviceEngagement.scanQR());
    }

    @Override
    public void onEngage(@NonNull Received<EngagementReceived> received) {
        Log.d(TAG, received.toString());
        try {
            received.runCatching(
                    failure -> {
                        Log.e(TAG, failure.toString());
                        FailureType type = failure.getType();
                        // handle failed device engagement
                    },
                    success -> {
                        DeviceEngagement deviceEngagement = success.getDeviceEngagement();

                        // request for age_over_21
                        Request request = new RequestBuilder()
                                .setDeviceEngagement(deviceEngagement)
                                .forIsoDocTypeAgeOver(21, true)
                                .build();

                        webAPITransfer
                                .forDeviceEngagement(deviceEngagement)
                                .send(request);
                    }
            );
        } catch (Exception e) {
            // handle exception sending request
        }
    }

    @Override
    public void onProgressEvent(@NonNull TransferProgressEvent transferProgressEvent) {
        Log.i(TAG, transferProgressEvent.toString());
        // update UI with progress information
    }

    @Override
    public void onReceive(@NonNull Received<TransferReceived> received) {
        try {
            received.runCatching(
                    failure -> {
                        Log.e(TAG, failure.toString());
                        FailureType type = failure.getType();
                        // handle failed data received
                    },
                    success -> success.runCatchingForServer(bytesReceived -> {
                        // create a ServerResponse to manipulate received data
                        ServerResponse serverResponse =
                                ServerResponse.fromBytes(bytesReceived);

                        // verify received data; a ServerVerifierResult for each
                        // requested document
                        List<ServerVerifierResult> verifierResults =
                                new ServerResponseVerifier(rootCertificates)
                                        .verify(bytesReceived);

                        // check verification for all verified documents
                        boolean isVerified = verifierResults.stream()
                                .allMatch(VerifierResult::isValid);
                    })
            );
        } catch (Exception e) {
            Log.e(TAG, "onReceive", e);
            // handle exception
        }
    }
}