CRM and CX Blogs by SAP
Stay up-to-date on the latest developments and product news about intelligent customer experience and CRM technologies through blog posts from SAP experts.
cancel
Showing results for 
Search instead for 
Did you mean: 
sanju_joseph
Product and Topic Expert
Product and Topic Expert
1,054

Here we get into the details of creating an extension endpoint in CDC (a.k.a Gigya) and its deployment in cloud foundry.


The challenge faced by CDC developer is to understand the behavior of CDC extension that is hosted elsewhere, the blog is an attempt to explain the intricacies of creating such an extension using Node.js , this will help in testing an extension events.


Review a step-by-step guide below to create extension using Node.js and test this using postman followed by steps to deploy this on a cloud foundry.




  • Getting the right plugins:
    VS Code

  • Create a project:  From your visual studio editor, choose Terminal->New Terminal
    and create folder ‘Register’(parent folder) and ‘myapp’ (subfolder).
    $ mkdir register
    $ cd register
    $ mkdir myapp
    $ cd myapp

  • Initialize the App: Navigate to the subfolder myapp
    $ npm init
    Press enter for every question that is being asked in your CLI, this will create a package.json file

  • Install downloads a package and it's dependencies.
    $ npm install express --save
    $ npm install memory-cache --save
    $ npm install jws
    $ npm install jws-jwk
    $ npm install gigya

  • Create server.js and app.js in sub folder (myapp)
    server.js :  Define the file to call, when running npm start and to start the server at a given port.
    // require http modules first
    const http = require('http');

    //import app.js file
    const app = require('./app');

    app.get('/', (req, res, next) => {
    res.status(200).send('You have called the root directory');
    });

    //define port to be used
    const port = process.env.PORT || 3100;
    const server = http.createServer(app);


    server.listen(port, () => {
    // let's print a message when the server run successfully
    console.log("Server restarted successfully")
    });​

    app.js :  Define the routes which should handle request( GET, POST)

    Initialize code below with your API Key, data center, user key and Secret key
    // **********************
    // AUXILIAR FUNCTIONS
    // **********************
    const express = require('express');
    const cache = require('memory-cache');
    const jws = require('jws');
    const jws_jwk = require('jws-jwk');
    const Gigya = require('gigya').Gigya

    // Initialize SDK with your API Key , data center, user key and Secret.
    const gigya = new Gigya('<API_Key>', '<data_center>', '<user_key>' , '<Secret_key>');
    const app = express();
    const router = express.Router();

    // import body-parser
    app.use(express.json()); // to support JSON-encoded bodies
    app.use(express.urlencoded({ // to support URL-encoded bodies
    extended: true
    }));

    // Routes which should handle request
    app.get('/register', (req, res, next) => {
    res.json(["Array1","Array2","Array3"]);
    });

    app.post('/register', async (req, res) => {
    var token = req.body.jws;
    var decoded = jws.decode(token);
    var jwk = cache.get('jwk');
    //verify token
    var body = JSON.parse(decoded.payload);
    var ret = { status: 'OK' };
    if (body.extensionPoint === 'OnBeforeAccountsRegister' && !body.data.params.email.endsWith('@xyz.com'))
    {
    ret.status = 'FAIL';
    var customMessage = 'Email should belong to domain "xyz.com" ';
    ret.data = {
    validationErrors: [
    { fieldName: 'profile.email', message: customMessage },
    ]
    }
    }
    res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify(ret));
    });

    // Global error handler - route handlers/middlewares which throw end up here
    app.use((err, req, res, next) => {
    res.status(err.status || 500);
    res.end();
    });
    //export app
    module.exports = app;


     

  • Start the Server: within myapp folder

  • Convert to JWS format

    The validation here is for the event OnBeforeAccountsRegister when email id ends with domain other than ‘xyz.com’, it throws an error ‘Email should belong to domain \"xyz.com\’


    Sample payload for OnBeforeAccountsRegister is available at the link below


    https://help.sap.com/viewer/8b8d6fffe113457094a17701f63e3d6a/GIGYA/en-US/4153ec2f70b21014bbc5a10ce40...

    This is in "json" format which needs to be converted into "jws" format, online tool like jwt.io can help with conversion( here you can edit the decoded information one at a time as per our requirement and this in turn encoded the format in jws ), finally we need this( jws) to test in postman.


    the payload include the email id: test1@abc.com which doesn't end with "xyz" and the extension event is OnBeforeAccountsRegister, the expectation here is status 'FAIL' with validation error '

    Email should belong to domain \"xyz.com\" '


"apiKey": "3_ve...tyu",
"callID": "809.....169f",
"extensionPoint": "OnBeforeAccountsRegister",
"data": {
"params": {
"email": "test1@abc.com",
"password": "what ever password the user entered",
"profile": {
"firstName": "test"
},
"data": {
"terms": true
}
},
"context": {
"clientIP": "1.0.0.0"
}
}
}



{
"jws": "eyJhbGciOiJIUzI1NiIsImtpZCI6IlJEQXpSRVl5TmpCRk5USTVSak5ETURrd1JEUkJNMEZDUkRRM1FqQkNSRUpDUmpZNE9ESkZRUSJ9.eyJhcGlLZXkiOiIzX3ZlLi4udHl1IiwiY2FsbElEIjoiODA5Li4uLi4xNjlmIiwiZXh0ZW5zaW9uUG9pbnQiOiJPbkJlZm9yZUFjY291bnRzUmVnaXN0ZXIiLCJkYXRhIjp7InBhcmFtcyI6eyJlbWFpbCI6InRlc3QxQGFiYy5jb20iLCJwYXNzd29yZCI6IndoYXQgZXZlciBwYXNzd29yZCB0aGUgdXNlciBlbnRlcmVkIiwicHJvZmlsZSI6eyJmaXJzdE5hbWUiOiJ0ZXN0In0sImRhdGEiOnsidGVybXMiOnRydWV9fSwiY29udGV4dCI6eyJjbGllbnRJUCI6IjEuMC4wLjAifX19.3tzVu5n3NvXPDIDQaVpJ5UYEA8zs8KpsxAnacovkMac"

}


  • Test Using Postman( try the desktop agent, not on the browser)


          The final step is to test using postman and check for the response in case the email ends with             domain other than xyz.com.


          URL: http://localhost:3100/register
          Body: the JWS format encoded in step above
          Type:  JSON



Response




{

    "status": "FAIL",

    "data": {

        "validationErrors": [

            {

                "fieldName": "profile.email",

                "message": "Email should belong to domain \"xyz.com\" "

            }

        ]

    }

}



  • Deploy in cloud foundry.1. As a next step we will deploy Node.js App to SCP Cloud Foundry for this we need to  create  yml in the folder register.



                                                                  Manifest Folder



Manifest.yml


      2. Upload the Manifest file in cloud foundry.



            Run the Powershell/msdos in administrator mode and navigate to folder that contain                 manifest.yml file


       cf api api-end-point( example https://api.cf.eu10.hana.ondemand.com )

       A. cf api https://api.cf.us10.hana.ondemand.com/  for example


           


      B. cf login and if you have multiple org, choose the org where you shall upload this.


     C. cf push


           


      D . Make Note of the URL as this will be used in extension in CDC. You can find this URL within                the service that is created in cloud foundry.


     




  • Configure CDC extension with new endpoint and activate it.
    Mention the folder name at the end of the Cloud foundry endpoint URL ,here in this example its register.https://myapp-unexpected-camel-ze.cfapps.us10.hana.ondemand.com/register ( you can also test the URL in postman)Its is better to Increase the default timeout to 6000ms as it may take some time to receive  response from the Server.





  • Test the extension by registering an account with email ending with domain other than 'xyz.com' .


    With the response received from the server, fail the registration and registration response returned to the client.