OneSpan Sign Developer: Callback Event Notification – Part 3

Duo Liang, April 24, 2019
OneSpan Sign Developer: Callback Event Notification – Part 3

In the first two parts of this blog series, we reviewed the benefits of using event notifications as well as the recommended workflow for polling transaction and signer related information in Part 1. From there, we walked through the technical details related to callback listener in Part 2.

For the third part of this blog series, we will use a simple spring boot project to showcase how to setup a callback listener in action. Combined with Part 2, you’ll see how we follow these flows to facilitate your event listening integration.

Callback Event Notification in Action

Before beginning the spring boot project, be sure you complete the following:

Register for Event Notifications

Before the OneSpan Sign system can notify you of an event, you must turn on notifications. Follow this feature guide to learn how to register.

In our example, we will simply register from the web portal.

Download OneSpan Sign’s Java SDK

You will also need OneSpan Sign’s Java SDK. Download and unzip the SDK to the location of your choice.

Or alternatively, you can import OneSpan Sign Java SDK from Maven Repository by:


Install JDK & IDE

Download Ngrok

Basic Spring Boot & Maven knowledge

In this guide, we’ll build a spring boot project using spring asynchronous methods. The complete source code can be found here.

Feel free to directly import the source code as an existing maven project or copy and paste all necessary files/codes to your existing project.

Be sure to also refer to the official tutorials on Building a RESTful Web Service with Spring Boot and Creating Asynchronous Methods.

The Code

We will need a controller to handle callback requests sent from OneSpan Sign. Below is the code for the CallbackController to process the event notification.

public class CallbackController {

	private OssCallbackService ossCallbackService;

	public void callback(@RequestBody OssCallbackVo ossCallbackVo, @RequestHeader("Authorization") String callbackKey) {
		System.out.println("receive a callback notification!");

		// 1. check callback key
		if (callbackKey != null) {
			System.out.println("callback key: " + callbackKey);
			if (!ossCallbackService.validateCallbackKey(callbackKey)) {
				throw new RuntimeException("Callback key is not valid: " + callbackKey);
		System.out.println("callback body: " + ossCallbackVo);

		// 2. handle callback asynchronously
		try {
		} catch (Exception e) {

In the code above, any POST request hitting “/callback” route will be handled by our application.

Once all documents in a package have been signed and the package completed, OneSpan Sign will make a POST request to the registered URL with the following example JSON payload: 

  "@class": "com.silanis.esl.packages.event.ESLProcessEvent",
  "sessionUser": "0787be84-f095-44c7-ba00-787093df86fc",
  "packageId": "KHiRfOXgKK0gpVWwwpFOSNy6o34=",
  "message": null,
  "documentId": null


The “sessionUser” above refers to signer Id, so it’s recommended to set custom Id (in SDK) or signer Id(in REST) when signer creation and store it at your local database.

Then, we will distribute to different service functions depending on the callback event. A service class with asynchronous method was used to handle this business logic.

public class OssCallbackService {

	private OssConfiguration ossConfiguration;

	public boolean validateCallbackKey(String callbackKey) {
		if (callbackKey != null) {
			String base64Credentials = callbackKey.substring("Basic".length()).trim();
			return ossConfiguration.CALLBACK_KEY.equals(base64Credentials);
		} else {
			return false;

	public void handleCallback(OssCallbackVo ossCallbackVo) {
		switch (OssCallbackEvents.valueOf(ossCallbackVo.getName())) {





	private void process_PACKAGE_COMPLETE(OssCallbackVo ossCallbackVo) {
		EslClient eslClient = new EslClient(ossConfiguration.API_KEY, ossConfiguration.API_URL);
		String packageId = ossCallbackVo.getPackageId();
		byte[] documents = eslClient.downloadZippedDocuments(new PackageId(packageId));

		String filePath = ossConfiguration.FILE_SAVE_PATH + "\\documents_" + packageId + "_"
				+ new SimpleDateFormat("yyyy_MM_dd").format(new Date()) + ".zip";

		Files.saveTo(documents, filePath);
	private void process_DOCUMENT_SIGNED(OssCallbackVo ossCallbackVo) {
	private void process_SIGNER_COMPLETE(OssCallbackVo ossCallbackVo) {

We have declared all possible stub functions handling callback events in our code. In this example, “PACKAGE_COMPLETE” event was monitored and triggered the corresponding service function. Then eslClient was utilized to download the signed documents.

Finally, all your OneSpan Sign related configurations are stored in file. Simply adjust to your own information before running the code:


Perform a Test

Run the main function in your class. Then, open a command prompt and change the directory to the location where you saved your ngrok executable. Enter the following command:

ngrok http [port] -host-header="localhost:[port]"

Then, login to your OneSpan Sign account, browse to the Admin page and modify the domain of your callback URL. 

Finally, create, send, and complete a test package. You should be able to view the signed documents as a zipped file in the file. The moment OneSpan Sign sends a callback notification to your listener, you’ll see the message below at your IDE console. If you can see them both, it means your callback listener is working properly.4-24-1

If you have any questions regarding this blog or anything else concerning integrating OneSpan Sign into your application, visit the Developer Community Forums. Your feedback matters to us!

OneSpan Developer Community

OneSpan Developer Community

Join the OneSpan Developer Community! Forums, blogs, documentation, SDK downloads, and more.

Join Today