OneSpan Sign How To: Creating a Simple Node.js Web Application
Node.js is an open source runtime built on Chrome’s V8 JavaScript engine for developing server-side web applications. JavaScript is arguably the most popular programming language. Therefore, if you already know JavaScript, you can pick up Node.js fairly easily. The Node.js library is very fast on code execution (Chrome’s V8 JavaScript Engine) and allows for asynchronous, event-driven coding (i.e. non-blocking). This becomes very handy when it comes to building real-time web applications. In this blog, I will show you how to create a simple web application in Node.js.
Requirements
Before diving into the code, you will need to setup your environment to create your Node.js web application. For this blog, you will need Node.js and a text editor.
Node.js
You can download the installer from the link below. Node.js is available for Windows, Mac, and Linux. In order to run this example, you will need to install v5.12.
Sublime Text
You will also need a text editor. For this blog, I will be using Sublime Text. You can download a free copy from the link below.
The Code
Once you’ve installed Node.js, you can do a quick check to verify the integrity of the installation by entering the following in a command prompt window:
node console.log("hello world!");
Using the node command with no arguments opens an interactive shell where you can execute raw JavaScript code. Below is screenshot of what you can expect:
It also prints "undefined" because the node command also displays the return value of each command and console.log doesn’t return anything.
We are now ready to dive into the code. Create a new folder in a location of your choice (e.g. C:\Users\hhaidary\Desktop\nodejs). Make sure to save all your files in the same directory. The first step is to create your HTML form. Using Sublime Text, create a new HTML file called "form.html" and copy the following:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Form</title> </head> <body> <h3>Please fill-out the following form:</h3> <div style="border:1px solid #D0D0D0;width:400px;padding:10px;"> <form method="POST" enctype="multipart/form-data"> First Name: <input type="text" id="firstName" name="firstName" placeholder="Enter your first name"> <br> Last Name : <input type="text" id="lastName" name="lastName" placeholder="Enter your last name"> <br> Email Address : <input type="text" id="emailAddress" name="emailAddress" placeholder="Enter your email address"> <br> Company : <input type="text" id="company" name="company" placeholder="Enter your company"> <br> Address : <input type="text" id="address" name="address" placeholder="Enter your address"> <br> City : <input type="text" id="city" name="city" placeholder="Enter your city"> <br> State : <input type="text" id="state" name="state" placeholder="Enter your state"> <br> Zip : <input type="text" id="zip" name="zip" placeholder="Enter your zip"> <br> Country : <input type="text" id="country" name="country" placeholder="Enter your country"> <br> Phone Number : <input type="text" id="phoneNumber" name="phoneNumber" placeholder="Enter your phone number"> <br> Policy Number : <input type="text" id="policyNumber" name="policyNumber" placeholder="Enter your policy number"> <br> <hr> <input type="submit" value="Submit"> </form> </div> </body> </html>
Save the HTML file in the folder you just created (i.e. "nodejs"). Node.js by itself is not capable of handling the work required to process the data of the form. You will need to install a third-party module to parse the form data. In your command prompt window, change your directory (if you haven’t done so already) to the location where you saved your HTML file (i.e. "nodejs") and enter the following:
npm install formidable@latest –-save
While we are on the subject of modules, go ahead and also install the request module:
npm install request@latest –-save
The request module allows you to make http calls in Node.js. It is by far the simplest and easiest http client available. A module can be interpreted as a class file. Go ahead and create a new file named "server.js" and add the following code:
var http = require('http'); var fs = require('fs'); var esl = require('./ESLPackageCreation.js'); var server = http.createServer(function (req, res) { if (req.method.toLowerCase() == 'get') { displayForm(res); } else if (req.method.toLowerCase() == 'post') { var signerToken = esl.processAllFieldsOfTheForm(req, res); } }); function displayForm(res) { fs.readFile('form.html', function (err, data) { res.writeHead(200, { 'Content-Type': 'text/html', 'Content-Length': data.length }); res.write(data); res.end(); }); } server.listen(8888); console.log("Listening on port 8888...");
In the sample code above, an HTTP server is created with a callback which calls the function displayForm. The res object is passed as a parameter in order for the response to be sent back to the client. Then, the displayForm function reads the form.html file and returns the data back to the client. When a user clicks on the submit button in the form, a post request is submitted with the information to the same URL. The callback on the http server calls the processForm function in the eventuality of a post request. This function comes from the "ESLPackageCreation.js" module. Let’s create this module.
Create a new file in Sublime Text and copy the following:
var request = require('request'); var formidable = require('formidable'); var fs = require('fs'); var http = require('http'); var document = fs.readFileSync('sample_contract2.pdf'); var token; var packageid; var api_key = 'your_api_key'; var eslFunctions = module.exports = { processForm: function (req, res) { var form = new formidable.IncomingForm(); form.parse(req, function (err, fields) { var jsonPayload = '{ "roles": [ { "id": "Signer1", "type": "SIGNER", "signers": [ { "firstName": "' + fields.firstName + '", "lastName": "' + fields.lastName+ '", "email": "' + fields.emailAddress + '", "id": "Signer1" } ] }, { "id": "Sender1", "type": "SIGNER", "signers": [ { "firstName": "Haris", "lastName": "Haidary", "email": "[email protected]", "id": "Sender1" } ] } ], "documents": [ { "fields": [ { "value": "' + fields.firstName + '", "name": "first_name" }, { "value": "' + fields.lastName + '", "name": "last_name" }, { "value": "' + fields.address + '", "name": "address" }, { "value": "' + fields.city + '", "name": "city" }, { "value": "' + fields.zip + '", "name": "zip" }, { "value": "' + fields.state + '", "name": "state" }, { "value": "' + fields.country + '", "name": "country" }, { "value": "' + fields.phoneNumber + '", "name": "phone_number" }, { "value": "' + fields.emailAddress + '", "name": "email" }, { "value": "' + fields.company + '", "name": "company" }, { "value": "' + fields.policyNumber + '", "name": "policy_number" } ], "name": "Sample Contract", "id" : "contract", "extract": true } ], "name": "NodeJS Example", "type": "PACKAGE", "status": "SENT" }'; var options = { method: 'POST', url: 'https://sandbox.esignlive.com/api/packages', headers: { accept: 'application/json', authorization: 'Basic ' + api_key, 'content-type': 'multipart/form-data; boundary=---011000010111000001101001' }, formData: { file: { value: document, options: { filename: { '0': {} }, contentType: null } }, payload: jsonPayload } }; request(options, function (error, response, body) { if (error) throw new Error(error); var tmp = JSON.parse(body); packageid = tmp['id']; console.log("The package id is: " + packageid); eslFunctions.getSignerToken(res); }); }); }, getSignerToken: function (res) { var options = { method: 'POST', url: 'https://sandbox.esignlive.com/api/signerAuthenticationTokens', headers: { 'content-type': 'application/json', accept: 'application/json', authorization: 'Basic ' + api_key}, body: { packageId: packageid, signerId: 'Signer1' }, json: true }; request(options, function (error, response, body) { if (error) throw new Error(error); token = body['value']; console.log("The session token is: " + token); eslFunctions.complete(res); }); }, complete: function(res) { res.writeHead(200, { 'content-type': 'text/html' }); res.write('<html>'); res.write('<head>'); res.write('<title>Form Processing</title>'); res.write('</head>'); res.write('<body><h3>Thank you for completing the form! Please sign the document below:</h3>'); res.write('<iframe src="https://sandbox.esignlive.com/access?sessionToken=' + token + '" width="1000" height="800"></iframe>'); res.write('</body>'); res.write('</html>'); res.end(); } };
Now, let’s go over the code in detail. In the processForm function, an object is created for the incoming form. On that object, we pass the res (i.e. response) object and set a callback on it which will be called when the form is parsed and return the parsed fields. The parsed field values are then subsequently used to build the json payload needed to create and send your package using the request module. Once the package is created, the package id returned by OneSpan Sign is used to create a signer token that will used to embed the signing ceremony in an iframe. Once the signer token is created, the res object used to write a new HTTP header (status code 200). Finally, the res.end() line writes the body and closes the response.
Running Your Project
You are now ready to run your Node.js web application. In your command prompt window (assuming your current directory is where you have saved your files), enter the following line:
node server.js
Now, enter "localhost:8888" in your web browser. You should be able to see your form. Go ahead and fill-out some sample information and click on Submit.
Once you’ve hit Submit, you will be redirected to the OneSpan Sign signing ceremony. You will be presented with a sample contract with the fields populated with the data you entered in your form and the contract ready to be signed.
You can download the complete project from the Developer Community Code Share, here.
If you have questions regarding this blog or anything else concerning integrating OneSpan Sign into your application, visit the developer community forums:
https://developer.esignlive.com. That's it from me. Thank you for reading! If you found this post helpful, please share it on Facebook, Twitter, or LinkedIn.
Haris Haidary
Junior Technical Evangelist
LinkedIn | Twitter