Node Js Heroku Canvas Integration

Introduction

In this blog, I am going to explain Heroku and node js canvas integration. Canvas allows you to integrate web applications with Salesforce in the different places of salesforce like Chatter Tab, Visualforce Page, Lightning Component, Publisher, Chatter Feed, Console, Open CTI, Mobile Navigation, Layouts, and Mobile Cards. In this post, I am going to show the simple table that contains the product master data which is a simple HTML table.

Prerequisites

  1. Git installed on your local machine
  2. Heroku account
  3. Heroku toolbelt installed.
  4. Node.js installed on your local machine

Creating Connected App

In order to integrate the salesforce with Heroku application, you need to create the configure the salesforce connected app as shown.

  • Setup -> Create -> Apps -> Connected Apps-> New
  • Fill  Connected App NameAPI Name, and Contact Email as shown in the image 
  • Check the Enable OAuth Settings in the API (Enable OAuth Settings) section
    • Callback URL: add as https://localhost.com/_callback. Later after deploying node js app to Heroku, we need to change this.
    • Selected OAuth Scopes: select the scopes you want for the NodeJS app access token to grant.  Select as ” Full Access ” for this testing app.
  • In the section, Canvas App Settings type Check Force.com Canvas
  • Canvas App URL: https://localhost.com/canvas/callback.Later after deploying the apps Heroku, we are going to change this URL.
  • Access Method: Signed Request (POST)
  • Locations: choose Chatter Tab and publisher as of now. but you can select one or more based on the where you want to show this the canvas on salesforce.
    Now finally connected App is looking as shown below.

Now you need to enable the app for the profiles or users. To do this,

  • Click on the Manage on the connected App which you created in above .click edit policies
  • In the OAuth policies select Admin approved users are pre-authorized for the Permitted Users field and save it
  • In the Profiles related list add the profiles or permission set which you wanted to grant access

Building Your App on Node Js

Let’s set up the basic app structure. We will use Express to set up a basic Node application. Here is the below package.json file which we will use to build the node js application. The application folder structure is shown below.

package.json

{
    "name": "canvasquickaction",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "dependencies": {
        "body-parser": "^1.15.0",
        "crypto-js": "^3.1.6",
        "express": "^4.13.4"
    },
    "devDependencies": {},
    "scripts": {
        "start": "node index.js",
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "",
    "license": "ISC"
}
  • Once you have created your file structure, set up a Git repo in this directory by running from command. $ git init your command line within this directory.
  • Inside of the public > views > index.html file, add the following code
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <script src="https://code.jquery.com/jquery.js"></script>
        <style>
            * {
                margin: 0;
                padding: 0;
                font-family: Lato;
            }
            
            body {
                padding: 0px;
                background: #f6f3f7;
            }
            
            h1 {
                display: block;
                width: 100%;
                background: #64e0ef;
                height: 55px;
                padding-left: 10px;
                color: #fff;
                font-size: 20px;
                line-height: 55px;
                text-shadow: 1px 1px 1px rgba(0, 0, 0, .3);
                box-sizing: border-box;
                text-align: center;
            }
            
            table {
                width: 100%;
                min-width: 500px;
                border-collapse: collapse;
                font-weight: bold;
                color: #6b6b6b;
            }
            
            thead {
                background-color: rgba(29, 150, 178, 1);
                border: 1px solid rgba(29, 150, 178, 1);
                font-weight: normal;
                text-align: center;
                color: white;
            }
            
            tr {
                height: 50px;
                text-align: center;
            }
            
            td {
                box-sizing: border-box;
                text-align: center;
            }
        </style>
    </head>
    
    <body>
        <div>
            <h1>Product Manangement Node Js Heroku Integration </h1>
            <table>
                <thead>
                    <tr>
                        <th>Item Name </th>
                        <th>Master Price </th>
                        <th>Discount </th>
                        <th>Product Description </th>
                        <th>Discount Approval </th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                      
                        <td>Product ACT 100</td>
                        <td>$279.00</td>
                        <td>$29.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>Yes</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 200</td>
                        <td>$279.00</td>
                        <td>$29.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>No</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 300</td>
                        <td>$279.00</td>
                        <td>$10.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>No</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 400</td>
                        <td>$279.00</td>
                        <td>$39.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>Yes</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 500</td>
                        <td>$279.00</td>
                        <td>$21.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>Yes</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 600</td>
                        <td>$279.00</td>
                        <td>$19.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>No</td>
                    </tr>
                </tbody>
            </table>
        </div>
    
    </html>

     

  • From the command line in the main app directory initialize your Node app by running -.npm install which will load all the node modules from the package.json

In the index.js file add the following code:

var express  = require('express'),
  bodyParser = require('body-parser'),
  path       = require('path'),
  CryptoJS   = require("crypto-js");

app        = express(),
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'bower_components')));

app.use(bodyParser.json()); // create application/json parser
app.use(bodyParser.urlencoded({ entended: true })); //create application/x-www-urlencoded parser

var views = path.join(__dirname, 'public/views');
 var   consumerSecret = process.env.CONSUMER_SECRET;

app.get('/', function (req, res) {
  res.sendFile(path.join(views, 'index.html'));
});

app.post('/', function (req, res) {
  // Desk secret key	
  var shared = consumerSecret;
  // Grab signed request
  var signed_req = req.body.signed_request;
  // split request at '.'
  var hashedContext = signed_req.split('.')[0];
  var context = signed_req.split('.')[1];
  // Sign hash with secret
  var hash = CryptoJS.HmacSHA256(context, shared); 
  // encrypt signed hash to base64
  var b64Hash = CryptoJS.enc.Base64.stringify(hash);
  if (hashedContext === b64Hash) {
    res.sendFile(path.join(views, 'index.html'));
  } else {
    res.send("authentication failed");
  };  		
})

var port = process.env.PORT || 9000;
app.listen(port);
console.log('Listening on port ' + port);

Run the following from the command line within your main app directory to push your changes to Heroku.

  1. heroku create
  2. git add .
  3. git commit -m "pushing to heroku"
  4. git push heroku master
  5. heroku open
    Open the URL which looks like as a random string like https://limitless-retreat-55750.herokuapp.com/

Now go to the Connected app which you created in earlier, update the callback URL and Canvas App URL with the Heroku app URL  example https://limitless-retreat-55750.herokuapp.com/

Now We have to add the Environmental variable Consumer secret from the connected app to Heroku by runs the following command.

heroku config:set CONSUMER_SECRET=xxxx

Now you can see the Canvas app on the chatter tab as shown below.

Github URL for complete code: https://github.com/rajamohanvakati/Canvas-App-Quick-Action