Complete Server-Side Verification
While it's true that all authenticity checks can be successfully completed on smartphones and edge devices, they alone might not suffice. There's a potential risk of verification results being intercepted and modified by fraudsters directly on the same device. In the "zero trust to mobile" approach, Regula introduces an additional layer of protection against such fraud through Complete Server-Side Verification.
Info
Current page describes the process of Complete Server-Side Verification for the physical ID document (either containing an RFID chip or not). For details about the Mobile Driver's License, see the dedicated mDL Data Server-Side Reprocessing page.
See the sequence diagram of the entire document processing (click to enlarge).
Let's have a look at it step by step.
- Preparation
- Step 1: Optical Processing
- Step 2: RFID Chip Reading (Optional)
- Step 3: Finalize Package
- Step 4: Reprocessing on Web Service
- Step 5: Retrieve Processed Data
- Partial Results Finalizing
Preparation
Enable the backend processing feature on the Mobile side.
let backendProcessingConfig = RGLBackendProcessingConfig()
backendProcessingConfig.url = "https://api.regulaforensics.com"
DocReader.shared.processParams.backendProcessingConfig = backendProcessingConfig
RGLBackendProcessingConfig *backendProcessingConfig = [[RGLBackendProcessingConfig alloc] init];
backendProcessingConfig.serviceURL = @"https://api.regulaforensics.com";
RGLDocReader.shared.processParams.backendProcessingConfig = backendProcessingConfig;
DocumentReader.Instance().processParams().backendProcessingConfig = BackendProcessingConfig("https://api.regulaforensics.com")
DocumentReader.Instance().processParams().backendProcessingConfig = new BackendProcessingConfig("https://api.regulaforensics.com");
DocumentReader.instance.processParams.backendProcessingConfig = BackendProcessingConfig("https://api.regulaforensics.com");
DocumentReader.instance.processParams.backendProcessingConfig = new BackendProcessingConfig("https://api.regulaforensics.com")
// Android
DocumentReader.Instance().ProcessParams().BackendProcessingConfig = new BackendProcessingConfig("https://api.regulaforensics.com");
// iOS
RGLBackendProcessingConfig backendProcessingConfig = new()
{
Url = "https://api.regulaforensics.com"
};
RGLDocReader.Shared.ProcessParams.BackendProcessingConfig = backendProcessingConfig;
DocumentReader.setProcessParams({
backendProcessingConfig: {
url: "https://api.regulaforensics.com"
}
}, _ => { }, _ => { })
DocumentReader.setProcessParams({
backendProcessingConfig: {
url: "https://api.regulaforensics.com"
}
})
DocumentReader.setProcessParams({
backendProcessingConfig: {
url: "https://api.regulaforensics.com"
}
}, function (m) { }, function (e) { })
For Complete Server-Side Verification, you need to run the Regula Web Service in your environment. Refer to the Web Service section for instructions on how to do that.
HTTP Headers
Since Regula Web Service is engaged when working with Regula Mobile SDK, you may need to adjust HTTP requests’ headers in your application to pass additional information to the Web Service. That can be achieved in the following way:
let backendProcessingConfig = RGLBackendProcessingConfig()
backendProcessingConfig.url = "https://api.regulaforensics.com"
backendProcessingConfig.httpHeaders = ["HttpHeader1": "value1", "HttpHeader2": "value2"]
DocReader.shared.processParams.backendProcessingConfig = backendProcessingConfig
RGLBackendProcessingConfig *backendProcessingConfig = [[RGLBackendProcessingConfig alloc] init];
backendProcessingConfig.serviceURL = @"https://api.regulaforensics.com";
backendProcessingConfig.httpHeaders = @{@"HttpHeader1": @"value1", @"HttpHeader2": @"value2"};
RGLDocReader.shared.processParams.backendProcessingConfig = backendProcessingConfig;
val httpHeaders: MutableMap<String, String> = HashMap()
httpHeaders["header1"] = "key1"
httpHeaders["header2"] = "key2"
val backendProcessingConfig = BackendProcessingConfig("https://api.regulaforensics.com")
backendProcessingConfig.httpHeaders = httpHeaders
DocumentReader.Instance().processParams().backendProcessingConfig = backendProcessingConfig
Map<String, String> httpHeaders = new HashMap<>();
httpHeaders.put("header1", "key1");
httpHeaders.put("header2", "key2");
BackendProcessingConfig backendProcessingConfig = new BackendProcessingConfig("https://api.regulaforensics.com");
backendProcessingConfig.setHttpHeaders(httpHeaders);
DocumentReader.Instance().processParams().backendProcessingConfig = backendProcessingConfig;
Map<String, String> httpHeaders = {};
httpHeaders["header1"] = "key1";
httpHeaders["header2"] = "key2";
BackendProcessingConfig backendProcessingConfig = BackendProcessingConfig(
"https://api.regulaforensics.com",
httpHeaders: httpHeaders
);
DocumentReader.instance.processParams.backendProcessingConfig = backendProcessingConfig;
const httpHeaders = { header1: "key1", header2: "key2" }
var backendProcessingConfig = new BackendProcessingConfig("https://api.regulaforensics.com", { httpHeaders: httpHeaders })
DocumentReader.instance.processParams.backendProcessingConfig = backendProcessingConfig
/// Android
var httpHeaders = new Dictionary<string, string>
{
["header1"] = "key1",
["header2"] = "key2"
};
var backendProcessingConfig = new BackendProcessingConfig("https://api.regulaforensics.com")
{
HttpHeaders = httpHeaders
};
DocumentReader.Instance().ProcessParams().BackendProcessingConfig = backendProcessingConfig;
// iOS
var httpHeaders = new NSMutableDictionary
{
["header1"] = new NSString("key1"),
["header2"] = new NSString("key1")
};
RGLBackendProcessingConfig backendProcessingConfig = new()
{
Url = "https://api.regulaforensics.com",
HttpHeaders = httpHeaders
};
RGLDocReader.Shared.ProcessParams.BackendProcessingConfig = backendProcessingConfig;
const httpHeaders = {
header1: 'key1',
header2: 'key2',
};
DocumentReader.setProcessParams({
backendProcessingConfig: {
url: "https://api.regulaforensics.com",
httpHeaders: httpHeaders
}
}, _ => { }, _ => { })
const httpHeaders: Record<string, string> = {
header1: 'key1',
header2: 'key2',
};
DocumentReader.setProcessParams({
backendProcessingConfig: {
url: "https://api.regulaforensics.com",
httpHeaders: httpHeaders
}
})
const httpHeaders = {
header1: 'key1',
header2: 'key2',
};
DocumentReader.setProcessParams({
backendProcessingConfig: {
url: "https://api.regulaforensics.com",
httpHeaders: httpHeaders
}
}, function (m) { }, function (e) { })
Step 1: Optical Processing
The first step is optical processing that is performed on the mobile side (click image to enlarge).
To initiate optical processing, follow the Start Processing guide.
The Customer Mobile App sends the request to Regula Mobile SDK for launching the document scanning, that makes Regula Web Service start a secure transaction. The Data Store (comprising the Database and Storage) saves the transaction data and sends the notification back to Regula Mobile SDK. After the secure transaction is started, Regula Mobile SDK performs all the document's optical processing and returns the obtained results back to your Customer Mobile App.
Step 2: RFID Chip Reading (Optional)
Once the optical processing is completed, encrypted results are generated. The next step is to perform RFID chip reading (click image to enlarge).
To start the processing, follow the RFID Chip Processing guide.
While reading is performed on the Regula Mobile SDK side via NFC, Regula Web Service becomes engaged in generating session keys and challenges, which are subsequently saved to the Data Store.
As soon as NFC chip processing is completed on the mobile side, the results will contain not only the optical outcomes but also the results of RFID chip processing.
To enable RFID reprocessing on the Regula Web Service, refer to the RFID Processing page.
Step 3: Finalize Package
The next step is to finalize results. It means that they are encrypted on the mobile side and then are transmitted to Regula Web Service via the secure communication channel (click image to enlarge).
During transmission, the Data Store becomes engaged in saving transaction info, metadata, results and so on.
Once the package is sent to Regula Web Service, you need to handle the transactionID that is returned in the callback and prepare it for sending to your service. See the code samples below.
DocReader.shared.finalizePackage { action, transactionInfo, error in
if error != nil {
guard let error = error else {
return
}
print("Finalize failed. Error: \(error)")
} else {
if action == .complete, let transactionId = transactionInfo?.transactionId {
print("Finalize done. Transaction ID: \(transactionId)")
}
}
}
[[RGLDocReader shared] finalizePackageWithCompletion:^(RGLDocReaderAction action, RGLTransactionInfo * _Nullable info, NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Finalize failed. Error: %@", error);
} else {
if (action == RGLDocReaderActionComplete) {
NSLog(@"Finalize done. Transaction ID: %@", info.transactionId);
}
}
}];
DocumentReader.Instance().finalizePackage(IDocumentReaderFinalizePackage { action, transactionInfo, error ->
error?.let {
Log.d("Activity", "Finalize failed. Error: " + error.message)
return@IDocumentReaderFinalizePackage
}
transactionInfo?.let {
if (action == DocReaderAction.COMPLETE) {
Log.d("Activity", "Finalize done. Transaction ID: " + transactionInfo.transactionId)
}
}
})
DocumentReader.Instance().finalizePackage(new IDocumentReaderFinalizePackage() {
@Override
public void onFinalizePackage(int action, @Nullable TransactionInfo transactionInfo, @Nullable DocumentReaderException error) {
if (error != null) {
Log.d("Activity","Finalize failed. Error: " + error.getMessage());
return;
}
if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
Log.d("Activity", "Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
}
});
var (action, info, error) = await DocumentReader.instance.finalizePackage();
if (error != null) {
print("Finalize failed. Error: " + error.message);
} else if (action == DocReaderAction.COMPLETE && info != null) {
print("Finalize done. Transaction ID: " + info.transactionId!);
}
var [action, info, error] = await DocumentReader.instance.finalizePackage()
if (error) {
console.log("Finalize failed. Error: " + error.message)
} else if (action == DocReaderAction.COMPLETE && info) {
console.log("Finalize done. Transaction ID: " + info.transactionId)
}
// Android
DocumentReader.Instance().FinalizePackage(this);
public void OnFinalizePackage(int action, TransactionInfo info, DocumentReaderException error)
{
if (error != null)
{
Console.WriteLine("Finalize failed. Error: " + error.Message);
return;
}
if (action == DocReaderAction.Complete && info != null)
{
Console.WriteLine("Finalize done. Transaction ID: " + info.TransactionId);
}
}
// iOS
RGLDocReader.Shared.FinalizePackageWithCompletion((action, info, error) => {
if (error != null)
Console.WriteLine("Finalize failed. Error: " + error.Description);
else if (action == RGLDocReaderAction.Complete)
Console.WriteLine("Finalize done. Transaction ID: " + info.TransactionId);
});
DocumentReader.finalizePackage(response => {
response = JSON.parse(response)
if (response["error"] != null) {
console.log("Finalize failed. Error: " + response["error"])
} else if (response["action"] == DocReaderAction.COMPLETE && response["info"] != null) {
console.log(("Finalize done. Transaction ID: " + response["info"]))
}
}, _ => { })
DocumentReader.finalizePackage().then(response => {
response = JSON.parse(response)
if (response["error"] != null) {
console.log("Finalize failed. Error: " + response["error"])
} else if (response["action"] == DocReaderAction.COMPLETE && response["info"] != null) {
console.log(("Finalize done. Transaction ID: " + response["info"]))
}
})
DocumentReader.finalizePackage(function (response) {
response = JSON.parse(response)
if (response["error"] != null) {
console.log("Finalize failed. Error: " + response["error"])
} else if (response["action"] == DocReaderAction.COMPLETE && response["info"] != null) {
console.log(("Finalize done. Transaction ID: " + response["info"]))
}
}, function (e) { })
The last step of finalizing the data package is to send the obtained transactionID to your backend (Customer Service) for retaining it for the future request that will be sent to Regula Web Service for reprocessing later.
Step 4: Reprocessing on Web Service
Now that you have the encrypted results, you can start making up the request to do reprocessing on Regula Web Service (click image to enlarge).
The request body should include at least the processing scenario and other settings depending on your needs:
{
"processParam": {
"scenario": "FullAuth"
}
}
Send the request to Regula Web Service to the following endpoint:
POST /api/v2/transaction/{transaction_id}/process
where {transaction_id} is what to get in the Step 3.
Request example using cURL
curl --request POST \
--url "http://localhost:8088/api/v2/transaction/76fa69d1-5ba6-4aa0-8dd5-477c8f81df91/process" \
--header "Content-Type: application/json" \
--data '{ "processParam": { "scenario": "FullAuth" } }'
Info
Note that the request demonstrated above doesn't contain any data, so you won't receive any results from the Regula Web Service if you run it.
The request demonstrates only the structure that should be followed.
Regula Web Service fetches raw data from the Data Store, processes it and then saves the reprocessed results back to the Data Store. This step may be time-consuming, so the results of the document's reprocessing are not returned in the same HTTP response. For getting the processed data, follow the next Step 5.
Step 5: Retrieve Processed Data
After the data has been processed on the Regula Web Service side and saved to the Data Store, you can retrieve the results (click image to enlarge).
Send the request to Regula Web Service to the following endpoint:
GET /api/v2/transaction/{transactionId}/results
where {transaction_id} is what to get in the Step 3 and what has been used in the reprocessing request, see the Step 4.
curl --request GET \
--url "http://localhost:8088/api/v2/transaction/76fa69d1-5ba6-4aa0-8dd5-477c8f81df91/results" \
--header "Content-Type: application/json"
This marks the final step of the Complete Server-Side Verification. Once the server-side reprocessing is completed, you can then handle the results appropriately and determine whether you should trust the mobile outcome or not.
Partial Results Finalizing
Instead of finalizing a single complete package that contains both optical and RFID data (see the Step 3), you can process and finalize these data sets separately.
Perform the optical processing (see the Step 1) and then finalize the package:
let finalizeConfig = DocReader.FinalizeConfig.defaultParams()
finalizeConfig.video = true
finalizeConfig.rawImages = true
DocReader.shared.finalizePackage(with: finalizeConfig) { action, transactionInfo, error in
if error != nil {
guard let error = error else {
return
}
print("Finalize failed. Error: \(error)")
} else {
if action == .complete, let transactionId = transactionInfo?.transactionId {
print("Finalize done. Transaction ID: \(transactionId)")
}
}
}
RGLFinalizeConfig *finalizeConfig = [RGLFinalizeConfig defaultParams];
finalizeConfig.video = true;
finalizeConfig.rawImages = true;
[RGLDocReader.shared finalizePackageWithFinalizeConfig:finalizeConfig completion:^(RGLDocReaderAction action, RGLTransactionInfo * _Nullable info, NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Finalize failed. Error: %@", error);
} else {
if (action == RGLDocReaderActionComplete) {
NSLog(@"Finalize done. Transaction ID: %@", info.transactionId);
}
}
}];
val finalizeConfig = FinalizeConfig.Builder()
.setVideo(true)
.setRawImages(true)
.build()
DocumentReader.Instance().finalizePackage(finalizeConfig, IDocumentReaderFinalizePackage {
action,
transactionInfo,
error ->
{
error?.let {
Log.d("Activity", "Finalize failed. Error: " + error.message)
return@IDocumentReaderFinalizePackage
}
transactionInfo?.let {
if (action == DocReaderAction.COMPLETE) {
Log.d("Activity", "Finalize done. Transaction ID: " + transactionInfo.transactionId)
}
}
}
})
FinalizeConfig finalizeConfig = new FinalizeConfig.Builder()
.setVideo(true)
.setRawImages(true)
.build();
DocumentReader.Instance().finalizePackage(finalizeConfig, new IDocumentReaderFinalizePackage() {
@Override
public void onFinalizePackage(int action, @Nullable TransactionInfo transactionInfo, @Nullable DocumentReaderException error) {
if (error != null) {
Log.d("Activity","Finalize failed. Error: " + error.getMessage());
return;
}
if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
Log.d("Activity", "Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
}
});
var (action, transactionInfo, error) = await DocumentReader.instance.finalizePackage(
config: new FinalizeConfig(
video: true,
rawImages: true,
),
);
if (error != null) {
print("Finalize failed. Error: $error");
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
print("Finalize done. Transaction ID: ${transactionInfo.transactionId}");
}
var [action, transactionInfo, error] = await DocumentReader.instance.finalizePackage({
video: true,
rawImages: true,
});
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
// Android
FinalizeConfig finalizeConfig = new FinalizeConfig.Builder()
.SetVideo(true)
.SetRawImages(true)
.Build();
DocumentReader.Instance().FinalizePackage(finalizeConfig, this);
public void OnFinalizePackage(int action, TransactionInfo transactionInfo, DocumentReaderException error) {
if (error != null) {
Console.WriteLine("Activity","Finalize failed. Error: " + error.Message);
return;
}
if (action == DocReaderAction.Complete && transactionInfo != null) {
Console.WriteLine("Activity", "Finalize done. Transaction ID: " + transactionInfo.TransactionId);
}
}
// iOS
var finalizeConfig = RGLFinalizeConfig.DefaultParams();
finalizeConfig.Video = true;
finalizeConfig.RawImages = true;
RGLDocReader.Shared.FinalizePackageWithFinalizeConfig(finalizeConfig, (RGLDocReaderAction action, RGLTransactionInfo info, NSError error) => {
if (error != null) {
Console.WriteLine("Finalize failed. Error: " + error);
} else {
if (action == RGLDocReaderAction.Complete) {
Console.WriteLine("Finalize done. Transaction ID: " + info.TransactionId);
}
}
});
var config = new FinalizeConfig()
config.video = true
config.rawImages = true
DocumentReader.finalizePackageWithFinalizeConfig(config, rawResult => {
var json = JSON.stringify(rawResult)
var action = json["action"]
var transactionInfo = TransactionInfo.fromJson(json["info"])
var error = RegulaException.fromJson(json["error"])
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
}, _ => {})
var config = new FinalizeConfig()
config.video = true
config.rawImages = true
DocumentReader.finalizePackageWithFinalizeConfig(config).then(rawResult => {
var json = JSON.stringify(rawResult)
var action = json["action"]
var transactionInfo = TransactionInfo.fromJson(json["info"])
var error = RegulaException.fromJson(json["error"])
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
})
var config = new FinalizeConfig()
config.video = true
config.rawImages = true
DocumentReader.finalizePackageWithFinalizeConfig(config, function (rawResult) {
var json = JSON.stringify(rawResult)
var action = json["action"]
var transactionInfo = TransactionInfo.fromJson(json["info"])
var error = RegulaException.fromJson(json["error"])
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
}, function (e) { })
After that you continue with RFID chip reading (see the Step 2) and finalize this data package separately (in this case the previously submitted data won't be sent again in this step):
let finalizeConfig = DocReader.FinalizeConfig.defaultParams()
finalizeConfig.rfidSession = true
DocReader.shared.finalizePackage(with: finalizeConfig) { action, transactionInfo, error in
if error != nil {
guard let error = error else {
return
}
print("Finalize failed. Error: \(error)")
} else {
if action == .complete, let transactionId = transactionInfo?.transactionId {
print("Finalize done. Transaction ID: \(transactionId)")
}
}
}
RGLFinalizeConfig *finalizeConfig = [RGLFinalizeConfig defaultParams];
finalizeConfig.rfidSession = true;
[RGLDocReader.shared finalizePackageWithFinalizeConfig:finalizeConfig completion:^(RGLDocReaderAction action, RGLTransactionInfo * _Nullable info, NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Finalize failed. Error: %@", error);
} else {
if (action == RGLDocReaderActionComplete) {
NSLog(@"Finalize done. Transaction ID: %@", info.transactionId);
}
}
}];
val finalizeConfig = FinalizeConfig.Builder()
.setRfidSession(true)
.build()
DocumentReader.Instance().finalizePackage(finalizeConfig, IDocumentReaderFinalizePackage {
action,
transactionInfo,
error ->
{
error?.let {
Log.d("Activity", "Finalize failed. Error: " + error.message)
return@IDocumentReaderFinalizePackage
}
transactionInfo?.let {
if (action == DocReaderAction.COMPLETE) {
Log.d("Activity", "Finalize done. Transaction ID: " + transactionInfo.transactionId)
}
}
}
})
FinalizeConfig finalizeConfig = new FinalizeConfig.Builder()
.setRfidSession(true)
.build();
DocumentReader.Instance().finalizePackage(finalizeConfig, new IDocumentReaderFinalizePackage() {
@Override
public void onFinalizePackage(int action, @Nullable TransactionInfo transactionInfo, @Nullable DocumentReaderException error) {
if (error != null) {
Log.d("Activity","Finalize failed. Error: " + error.getMessage());
return;
}
if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
Log.d("Activity", "Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
}
});
var (action, transactionInfo, error) = await DocumentReader.instance.finalizePackage(
config: new FinalizeConfig(
rfidSession: true,
),
);
if (error != null) {
print("Finalize failed. Error: $error");
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
print("Finalize done. Transaction ID: ${transactionInfo.transactionId}");
}
var [action, transactionInfo, error] = await DocumentReader.instance.finalizePackage({
rfidSession: true,
});
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
// Android
FinalizeConfig finalizeConfig = new FinalizeConfig.Builder()
.SetRfidSession(true)
.Build();
DocumentReader.Instance().FinalizePackage(finalizeConfig, this);
public void OnFinalizePackage(int action, TransactionInfo transactionInfo, DocumentReaderException error) {
if (error != null) {
Console.WriteLine("Activity","Finalize failed. Error: " + error.Message);
return;
}
if (action == DocReaderAction.Complete && transactionInfo != null) {
Console.WriteLine("Activity", "Finalize done. Transaction ID: " + transactionInfo.TransactionId);
}
}
// iOS
var finalizeConfig = RGLFinalizeConfig.DefaultParams();
finalizeConfig.RfidSession = true;
RGLDocReader.Shared.FinalizePackageWithFinalizeConfig(finalizeConfig, (RGLDocReaderAction action, RGLTransactionInfo info, NSError error) => {
if (error != null) {
Console.WriteLine("Finalize failed. Error: " + error);
} else {
if (action == RGLDocReaderAction.Complete) {
Console.WriteLine("Finalize done. Transaction ID: " + info.TransactionId);
}
}
});
var config = new FinalizeConfig()
config.rfidSession = true
DocumentReader.finalizePackageWithFinalizeConfig(config, rawResult => {
var json = JSON.stringify(rawResult)
var action = json["action"]
var transactionInfo = TransactionInfo.fromJson(json["info"])
var error = RegulaException.fromJson(json["error"])
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
}, _ => {})
var config = new FinalizeConfig()
config.rfidSession = true
DocumentReader.finalizePackageWithFinalizeConfig(config).then(rawResult => {
var json = JSON.stringify(rawResult)
var action = json["action"]
var transactionInfo = TransactionInfo.fromJson(json["info"])
var error = RegulaException.fromJson(json["error"])
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
})
var config = new FinalizeConfig()
config.rfidSession = true
DocumentReader.finalizePackageWithFinalizeConfig(config, function (rawResult) {
var json = JSON.stringify(rawResult)
var action = json["action"]
var transactionInfo = TransactionInfo.fromJson(json["info"])
var error = RegulaException.fromJson(json["error"])
if (error != null) {
console.log("Finalize failed. Error: " + error);
} else if (action == DocReaderAction.COMPLETE && transactionInfo != null) {
console.log("Finalize done. Transaction ID: " + transactionInfo.transactionId);
}
}, function (e) { })
Examples
See the sample projects, demonstrating how to set up the Complete Server-Side Verification on the Mobile side: