0

I need to learn how to work some data in my custom activity backend. - The issue is that I'm not sure how to grab the data in backend once activity has posted data to my execute endpoint.

My backend activity js is below. - If you scroll down to my execute function you will see what I am trying to do.

I simply want to take the data from my inArguments[0] and then post them to another endpoint.

So far I have been unsuccessful in figuring out how to grab the data once it's been posted to /execute endpoint. I can confirm the client side of my activity is working properly because I am able to post the payload from JB to postBin, however, when I send it to my own endpoint e.g. (https://someactivityurl.herokuapp.com/journeybuilder/execute) I have no idea how to grab the data from there.

Any advice here would be greatly appreciated!

"use strict";
  var util = require("util");

  // Deps
  const Path = require("path");
  const JWT = require(Path.join(__dirname, "..", "lib", "jwtDecoder.js"));
  var util = require("util");
  var http = require("https");
  var request = require("request");

  exports.logExecuteData = [];

  function logData(req) {
    exports.logExecuteData.push({
      body: req.body,
      headers: req.headers,
      trailers: req.trailers,
      method: req.method,
      url: req.url,
      params: req.params,
      query: req.query,
      route: req.route,
      cookies: req.cookies,
      ip: req.ip,
      path: req.path,
      host: req.host,
      fresh: req.fresh,
      stale: req.stale,
      protocol: req.protocol,
      secure: req.secure,
      originalUrl: req.originalUrl,
    });
    console.log("body: " + util.inspect(req.body));
    console.log("headers: " + req.headers);
    console.log("trailers: " + req.trailers);
    console.log("method: " + req.method);
    console.log("url: " + req.url);
    console.log("params: " + util.inspect(req.params));
    console.log("query: " + util.inspect(req.query));
    console.log("route: " + req.route);
    console.log("cookies: " + req.cookies);
    console.log("ip: " + req.ip);
    console.log("path: " + req.path);
    console.log("host: " + req.host);
    console.log("fresh: " + req.fresh);
    console.log("stale: " + req.stale);
    console.log("protocol: " + req.protocol);
    console.log("secure: " + req.secure);
    console.log("originalUrl: " + req.originalUrl);
  }

  /*
   * POST Handler for / route of Activity (this is the edit route).
   */
  exports.edit = function (req, res) {
    // Data from the req and put it in an array accessible to the main app.
    //console.log( req.body );
    logData(req);
    res.send(200, "Edit");
  };

  /*
   * POST Handler for /save/ route of Activity.
   */
  exports.save = function (req, res) {
    // Data from the req and put it in an array accessible to the main app.
    //console.log( req.body );
    logData(req);
    res.send(200, "Save");
  };

  /*
   * POST Handler for /execute/ route of Activity.
   */

     exports.execute = function (req, res) {
    // example on how to decode JWT
    JWT(req.body, process.env.jwtSecret, (err, decoded) => {
      // verification error -> unauthorized request
      if (err) {
        console.error(err);
        return res.status(401).end();
      }

      if (decoded && decoded.inArguments && decoded.inArguments.length > 0) {
        // decoded in arguments
        var decodedArgs = decoded.inArguments[0];

        var options = {
          method: "POST",
          url: "https://someapi",
          headers: {
            Authorization:
              "Bearer somekey",
            "Content-Type": "application/json",
          },
          body: JSON.stringify(decodedArgs),
        };
        request(options, function (error, response) {
          if (error) throw new Error(error);
          console.log(response.body);
        });

        logData(req);
        res.send(200, "Execute");
      } else {
        console.error("inArguments invalid.");
        return res.status(400).end();
      }
    });
  };

  /*
   * POST Handler for /publish/ route of Activity.
   */
  exports.publish = function (req, res) {
    // Data from the req and put it in an array accessible to the main app.
    //console.log( req.body );
    logData(req);
    res.send(200, "Publish");
  };

  /*
   * POST Handler for /validate/ route of Activity.
   */
  exports.validate = function (req, res) {
    // Data from the req and put it in an array accessible to the main app.
    //console.log( req.body );
    logData(req);
    res.send(200, "Validate");
  };

jwtDecoder.js file

'use strict';

  module.exports = (body, secret, cb) => {
    if (!body) {
      return cb(new Error('invalid jwtdata'));
    }

    require('jsonwebtoken').verify(body.toString('utf8'), secret, {
      algorithm: 'HS256'
    }, cb);
  };

1 Answer 1

1

Your execute logic doesn't make sense. You're attempting to make a request before you've decoded your JWT and retrieved the necessary value. At the beginning of your execute script, you should decode the JWT and access the arguments there. Then nest any of your calls within that portion and make your API call.

exports.execute = function (req, res) {
  JWT(req.body, process.env.jwtSecret, (err, decoded) => {
    if (err) {
      console.error(err);
      return res.status(401).end();
    }
    if (decoded && decoded.inArguments && decoded.inArguments.length > 0) {
      var decodedArgs = decoded.inArguments[0];
      logData(req);
      // do something
    }
  });
};
7
  • Jason, thank you for your response. - I have already tried exactly what you mentioned, however for some reason I am still unsuccessful in posting the required data. I've updated my above example to what I've done previously. - Also included the code for my current jwt file since I'm unsure if the issue resides somewhere else. - In addition, is there an easier way to log the payload being sent to my endpoint for testing? As it stands, I currently have to redeploy code to SFMC and test in the journey canvas and I will never see the payload unless the POST within my execute function is valid.
    – Aib Syed
    Commented Sep 3, 2020 at 20:45
  • Why don't you just set your execute script to decode the arguments and run your logData function so that you can confirm in the logs that your payload is being passed correctly? That data should be readily visible in the platform you are using to host this application. Commented Sep 3, 2020 at 20:46
  • As far as running the logData function goes. How/when will I run it to see the payload from my JB config? My current understanding is that I won't see the JB payload unless I actually run my activity and send data from my DE into my config.JSON which will then POST to my endpoint.
    – Aib Syed
    Commented Sep 3, 2020 at 20:53
  • 1
    To test your payload, just execute the activity in a sample journey. It will fire the execute method and, with the logData function added to your logic (edited my answer to include this), you will get all the information that you could need to dig into this issue. If you attempt to debug this without using an error log, then it's going to take you forever to find out where the issue lies. If you write your request to the console then you can start to identify where something has gone wrong (like having an empty payload). Commented Sep 3, 2020 at 21:18
  • Thank you for the comprehensive information. - I was not looking at logs in my server platform. My most recent run spit this out -- name: 'JsonWebTokenError', message: 'jwt malformed' } -- It looks like I have a jwt issue and need to familiarize myself with how to use it properly. Do you think it's worth deleting the current jwt code included in my question and just do it all in my activity.js? Come to think of it, I'm not even seeing a jwt.sign() anywhere in my current project meaning tokens aren't even being created right?
    – Aib Syed
    Commented Sep 3, 2020 at 21:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .