Document Processing on Web Service
- Overview
- Step 1: Preparation
- Step 2: Select Processing Mode
- Step 3: Start Processing
- Processing Configuration
- HTTP Request Interception
- Examples
Overview
To get the maximum performance and ease the workload on the Mobile device, you can delegate document processing to the Web Service—use the Online Processing feature. The size of the mobile application significantly decreases in this case.
However, to ensure secure Client-Server communication, we recommend using the Complete Server-Side Verification feature.
The key difference between the Complete Server-Side Verification and Online Processing features is the security layer organization. Online Processing mechanism utilizes the standard HTTP(S) Request-Response model, while establishes connection between the Client (Mobile Application with integrated Document Reader Mobile SDK) and Server (Web Service with integrated Document Reader Web API). In this case, the end application is fully responsible for protection against the potential fraudulent request or response modifications.
On the other hand, when using the Complete Server-Side Verification, the Document Reader SDK guarantees data encryption and protection.
Also note that unlike the Online Processing feature, during the Complete Server-Side Verification, the transaction data is saved to the Database and Storage, to allow the session reprocessing afterwards.
To set up the Online Processing feature, follow the steps below.
Step 1: Preparation
Android
Add the INTERNET
permission to your AndroidManifest file - it's needed to send requests to the Web API service.
<uses-permission android:name="android.permission.INTERNET" />
iOS
No permissions needed.
Step 2: Select Processing Mode
Before setting up, you need to specify the processing mode for the Mobile SDK. There two modes available: MANUAL
and AUTO
.
Manual Mode
In this mode, the document processing is performed fully on the Web API service, while the Mobile SDK is used only for capturing document images and passing them to the service.
- The processing is performed fully on the backend.
- No need to add the Core framework.
- No need to add the database.
- No need to perform the initialization process.
Auto Mode
In this mode, the document processing is performed both on the mobile side and on the Web API service.
- The processing is performed on both mobile and web sides.
- Need to add the Core framework.
- Need to add the database, if applicable.
- Need to perform the initialization process.
Step 3: Start Processing
Create a configuration object and then use it on the document processing:
let onlineConfig = DocReader.OnlineProcessingConfig(mode: .manual)
let config = DocReader.ScannerConfig()
config.scenario = RGL_SCENARIO_FULL_PROCESS
config.onlineProcessingConfig = onlineConfig
DocReader.shared.showScanner(presenter: self, config: config) { (action, result, error) in
if action == .complete || action == .processTimeout {
print(result)
}
}
RGLOnlineProcessingConfig *onlineConfig = [[RGLOnlineProcessingConfig alloc] initWithMode:RGLOnlineProcessingModeManual];
RGLScannerConfig *config = [[RGLScannerConfig alloc] init];
config.scenario = RGL_SCENARIO_FULL_PROCESS;
config.onlineProcessingConfig = onlineConfig;
[RGLDocReader.shared showScannerFromPresenter:self config:config completion:^(enum RGLDocReaderAction action, RGLDocumentReaderResults * _Nullable results, NSError * _Nullable error) {
if (action == RGLDocReaderActionComplete || action == RGLDocReaderActionProcessTimeout) {
NSLog(@"%@", results);
}
}];
val config = OnlineProcessingConfig.Builder(OnlineMode.MANUAL).build()
DocumentReader.Instance().showScanner(this@MainActivity, ScannerConfig.Builder(config).build(), completion)
OnlineProcessingConfig config = new OnlineProcessingConfig.Builder(OnlineMode.MANUAL).build();
DocumentReader.Instance().showScanner(MainActivity.this, new ScannerConfig.Builder(config).build(), completion);
var config = ScannerConfig.withOnlineProcessingConfig(OnlineProcessingConfig(OnlineMode.MANUAL));
DocumentReader.instance.scan(config, completion);
var onlineConfig = new OnlineProcessingConfig()
onlineConfig.mode = OnlineMode.MANUAL
var config = new ScannerConfig()
config.onlineProcessingConfig = onlineConfig
DocumentReader.scan(config, _ => { }, _ => { })
var onlineConfig = new OnlineProcessingConfig()
onlineConfig.mode = OnlineMode.MANUAL
var config = new ScannerConfig()
config.onlineProcessingConfig = onlineConfig
DocumentReader.scan(config)
var onlineConfig = new OnlineProcessingConfig()
onlineConfig.mode = OnlineMode.MANUAL
var config = new ScannerConfig()
config.onlineProcessingConfig = onlineConfig
DocumentReader.scan(config, _ => { }, _ => { })
// Android
OnlineProcessingConfig config = new OnlineProcessingConfig.Builder(OnlineMode.Manual).Build();
DocumentReader.Instance().ShowScanner(this, config, completion);
// iOS
RGLOnlineProcessingConfig onlineConfig = new(RGLOnlineProcessingMode.Manual);
RGLScannerConfig config = new()
{
Scenario = Constants.RGL_SCENARIO_FULL_PROCESS,
OnlineProcessingConfig = onlineConfig
};
RGLDocReader.Shared.ShowScannerFromPresenter(this, config, completion);
By default, the FullProcess
scenario is used to process the document on the Web API service. You can change the scenario and turn on other configuration settings by defining them in the processParams
property and passing it to the configuration object.
See options of the document processing on the Getting Started page.
Processing Configuration
The OnlineProcessingConfig
class may contain the following config parameters:
Parameter | Description |
---|---|
mode |
Determines the operation mode: MANUAL or AUTO. |
processParam |
Contains a set of processing parameters used during document recognition or data extraction. |
url |
Specifies the web service endpoint or URL to which the SDK will send requests. |
imageFormat |
Specifies the format of the input image or images, such as JPEG or PNG. |
imageCompressionQuality |
Controls the level of compression applied to images during document recognition. |
To learn more, follow the link with OnlineProcessingConfig
documentation.
HTTP Request Interception
Since the Document Reader SDK allows processing through Regula Web Service, you may need to adjust HTTP request properties from your app before requests are sent to the Web Service.
This example demonstrates request interception:
import DocumentReader
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let onlineConfig = DocReader.OnlineProcessingConfig(mode: .manual)
onlineConfig.requestInterceptingDelegate = self
let config = DocReader.ScannerConfig()
config.scenario = RGL_SCENARIO_FULL_PROCESS
config.onlineProcessingConfig = onlineConfig
DocReader.shared.showScanner(presenter: self, config: config) { (action, result, error) in
if action == .complete || action == .processTimeout {
print(result)
}
}
return true
}
}
extension AppDelegate: DocReader.URLRequestInterceptingDelegate {
func interceptorPrepare(_ request: URLRequest) -> URLRequest? {
var request = request
request.addValue("Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs", forHTTPHeaderField: "Authorization")
return request
}
}
#import "AppDelegate.h"
#import <DocumentReader/DocumentReader.h>
@interface AppDelegate ()<RGLURLRequestInterceptingDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RGLOnlineProcessingConfig *onlineConfig = [[RGLOnlineProcessingConfig alloc] initWithMode:RGLOnlineProcessingModeManual];
onlineConfig.requestInterceptingDelegate = self;
RGLScannerConfig *scannerConfig = [[RGLScannerConfig alloc] init];
scannerConfig.scenario = RGL_SCENARIO_FULL_PROCESS;
scannerConfig.onlineProcessingConfig = onlineConfig;
UIViewController *presenter = self.window.rootViewController;
[RGLDocReader.shared showScannerFromPresenter:presenter config:scannerConfig completion:^(RGLDocReaderAction action, RGLDocumentReaderResults * _Nullable results, NSError * _Nullable error) {
if (action == RGLDocReaderActionComplete || action == RGLDocReaderActionProcessTimeout) {
NSLog(@"%@", results);
}
}];
return YES;
}
- (NSURLRequest * _Nullable)interceptorPrepareRequest:(NSURLRequest * _Nonnull)request {
NSMutableURLRequest *newRequest = [request mutableCopy];
[newRequest addValue:@"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs"
forHTTPHeaderField:@"Authorization"];
return newRequest;
}
@end
class MainActivity : Activity(), NetworkInterceptorListener {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
val onlineProcessingConfig = OnlineProcessingConfig.Builder(OnlineMode.AUTO, Scenario.SCENARIO_FULL_PROCESS).setNetworkInterceptorListener(this).build()
val config = ScannerConfig.Builder(Scenario.SCENARIO_FULL_PROCESS, onlineProcessingConfig).build()
DocumentReader.Instance().showScanner(this, config, IDocumentReaderCompletion { action, documentReaderResults, error ->
if (action == DocReaderAction.COMPLETE || action == DocReaderAction.TIMEOUT) {
print(result)
}
})
}
override fun onPrepareRequest(connection: HttpURLConnection?) {
connection?.setRequestProperty("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs")
}
}
public class MainActivity extends Activity implements NetworkInterceptorListener {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OnlineProcessingConfig onlineProcessingConfig = new OnlineProcessingConfig.Builder(OnlineMode.AUTO, Scenario.SCENARIO_FULL_PROCESS).setNetworkInterceptorListener(this).build();
ScannerConfig config = new ScannerConfig.Builder(Scenario.SCENARIO_FULL_PROCESS, onlineProcessingConfig).build();
DocumentReader.Instance().showScanner(this, config, (action, documentReaderResults, e) -> {
if (action == DocReaderAction.COMPLETE || action == DocReaderAction.TIMEOUT) {
print(result)
}
});
}
@Override
public void onPrepareRequest(HttpURLConnection httpURLConnection) {
httpURLConnection.setRequestProperty("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs");
}
}
var config = OnlineProcessingConfig(OnlineMode.AUTO);
config.requestHeaders = { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs"};
var config = new OnlineProcessingConfig()
config.requestHeaders = { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs" }
var config = new OnlineProcessingConfig()
config.requestHeaders = { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs" }
var config = new OnlineProcessingConfig()
config.requestHeaders = { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs" }
// Android
public class DocReaderScanner : Java.Lang.Object, IDocumentReaderCompletion, INetworkInterceptorListener
{
public void scan()
{
OnlineProcessingConfig onlineProcessingConfig = new OnlineProcessingConfig.Builder(OnlineMode.Auto, Scenario.ScenarioFullAuth).SetNetworkInterceptorListener(this).Build();
ScannerConfig config = new ScannerConfig.Builder(Scenario.ScenarioFullProcess, onlineProcessingConfig).Build();
DocumentReader.Instance().ShowScanner(Platform.AppContext, config, this);
}
public void OnCompleted(int action, DocumentReaderResults results, DocumentReaderException error)
{
if (action == DocReaderAction.Complete || action == DocReaderAction.Timeout)
{
Console.WriteLine(results);
}
}
public void OnPrepareRequest(HttpURLConnection httpURLConnection)
{
httpURLConnection.SetRequestProperty("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs");
}
}
// iOS
public class DocReaderScanner : RGLURLRequestInterceptingDelegate
{
public void scan()
{
RGLOnlineProcessingConfig onlineConfig = new(RGLOnlineProcessingMode.Manual) { RequestInterceptingDelegate = this };
RGLScannerConfig scannerConfig = new(Constants.RGL_SCENARIO_FULL_PROCESS) { OnlineProcessingConfig = onlineConfig };
RGLDocReader.Shared.ShowScannerFromPresenter(UIApplication.SharedApplication.KeyWindow.RootViewController, scannerConfig, OnResultsObtained);
}
override public NSUrlRequest InterceptorPrepareRequest(NSUrlRequest request)
{
NSMutableUrlRequest mutableRequest = (NSMutableUrlRequest)request.MutableCopy();
var key = new NSString("Authorization");
var value = new NSString("Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYWNlLXNkayI6IkhhdmUgYSBncmVhdCBkYXkhIn0.IPoW0D0LnMv_pL4U22MuIhDNGIdK34TaHhqhKBAaBEs");
mutableRequest.Headers = new NSDictionary(key, value);
return mutableRequest;
}
private void OnResultsObtained(RGLDocReaderAction action, RGLDocumentReaderResults result, NSError error)
{
if (action == RGLDocReaderAction.Complete || action == RGLDocReaderAction.ProcessTimeout)
{
Console.WriteLine(result);
}
}
}
Examples
See the sample projects that demonstrate how to set up the document processing on the Web Service.