Integrating Sugar with a CMS using REST APIs

SugarCRM strives to be the "No-Touch" CRMOne of the most important steps in making this vision a reality is to integrate Sugar with systems that customers uses to engage with organizations. For example, if a customer has been recently complaining about your product on your blog, wouldn't you want to know about that before talking with them?

Building a Wordpress integration

This post will explain how to import a comment from your blog (using Wordpress for this example) into Sugar as a note record related to the lead or contact who posted it. The goal of this exercise was to illustrate how to communicate from a common external content management system and Sugar. It turns out that getting the data into Sugar using REST APIs is pretty simple. It was everything else that took some thought and time.

The project started out as "send a Wordpress comment to Sugar as a note." It turned into much more than that (and has the potential to go so much further). So, here's a high level of our steps:

  • Created a Wordpress plugin
    • Plugin will record the Sugar login credentials and instance path
    • Plugin will call the Sugar OAuth REST endpoint to validate the user's credentials before allowing a save 
  • Upon submitting a comment to any Wordpress blog post, the comment data is sent to our instance of Sugar as a Note
    • Get the current logged-in Wordpress user
    • Authenticate to the Sugar API
    • Check if Wordpress user is in Sugar already (by e-mail address)
      • If so, add this comment as a Note linked to their [Account] record
      • If not, create a Lead record then create and link a Note to that record

Every CMS has its own special methods for connecting to external APIs. I chose to not use those functions in Wordpress for this exercise and simply used PHP's cURL functions. This should allow our example to be reused more easily with other applications.

The first step was to create the Wordpress plugin with a Settings page to allow a Wordpress admin to configure the integration. Our Settings page asks for Sugar user credentials, the URL to your instance of Sugar, and which version of the API your instance is using. All of this information gets stored in the Wordpress database for easy retrieval by our plugin.

The Wordpress settings page for our custom plugin

Now that we have our credentials, we will do something with them. We will create some functions that kick off when a Wordpress user adds a comment on any blog post. Wordpress has an action called "comment_post" that gets triggered after a comment is added by a user and subsequently stored in Wordpress database. We can assign a custom function to fire when that event is triggered by writing:

add_action( 'comment_post', 'send_comment_to_sugar_function', 10, 2 );

Basically, this line says any time a comment is saved to the Wordpress database, call the function called 'send_comment_to_sugar_function' with a priority of 10 and 2 possible parameters. For more information on Wordpress actions and hooks, check out the Wordpress Codex.

Now, let's write the guts for that custom function. The first thing we must do is authenticate to Sugar API. To do that, we will build the URL to the REST endpoint by concatenating the values that we stored in the plugin's settings page. This looks something like:

$api_path_auth = "/oauth2/token";
$auth_url = get_option('sugarcrm_input_url') . '/rest/v' . get_option("sugarcrm_input_api_version") . $api_path_auth;

On the settings page, I saved the values in the DB as "sugarcrm_input_url", "sugarcrm_input_api_version", "sugarcrm_input_username", and "sugarcrm_input_password". So, we can access those values with get_option(OPTION_NAME).

The oauth2/token endpoint needs parameters to return a successful authentication. Here is what we are sending:

$oauth2_token_arguments = array(
        'grant_type' => 'password',
        'client_id' => 'sugar',
        'client_secret' => '',
        'username' => get_option( 'sugarcrm_input_username' ),
        'password' => get_option( 'sugarcrm_input_password' ),
        'platform' => 'wordpress_api'
);

Note the "platform" parameter. This is the name you are giving to your Wordpress instance. You must go into Sugar's Admin settings to allow this platform to communicate with the Sugar REST API. The name could be anything that you like - as long as you add that same name to the Sugar API Platforms list.

Configure API Platforms page in the Sugar Admin

Now that we have our parameters to send, we need to set the cURL options. For a more detailed explanation of cURL in PHP, check out the PHP cURL manual

 

These are our options (pretty typical):

$auth_request = curl_init($auth_url);
curl_setopt($auth_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($auth_request, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($auth_request, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($auth_request, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($auth_request, CURLOPT_HTTPHEADER, array(
    "Content-Type: application/json"
));

//convert arguments to json
$json_arguments = json_encode($oauth2_token_arguments);
curl_setopt($auth_request, CURLOPT_POSTFIELDS, $json_arguments);

That last line is where we are ensuring that we are POSTing to the endpoint and that we are sending a JSON encoded array of parameters.

 

Finally, we can execute the request and parse out the data that we need from the response:

$oauth2_token_response = curl_exec($auth_request);
$oauth2_token_response_obj = json_decode($oauth2_token_response);
$sugar_oauth_token = $oauth2_token_response_obj->access_token;

I originally had the function return the auth_token but I decided to also store the auth_token and the refresh_token values in the Wordpress cache so that I can grab them whenever I need them. This will ensures we aren't needlessly logging into Sugar over and over again.

wp_cache_set('sugar_oauth_token_access', $sugar_oauth_token);
wp_cache_set('sugar_oauth_token_refresh', $oauth2_token_response_obj->refresh_token);

Now that we have authenticated, we can start sending data through the Sugar REST API. Let's see if the current wordpress user is in our instance of Sugar by utilizing the global search API (/search). Since we are making a GET request, we will format our URL to include our parameters in the URL query string. I used the http_build_query function to loop through an array of parameters and construct a query string to be appended to the end of our endpoint URL. This could have been done manually.

Either way works as long as the final result resembles:

http://localhost:8080/sugar/rest/v11_3/search?q=mshaheen@sugarcrm.com&module_list=Contacts,Leads

With the URL setup, we need to use cURL again. Since the settings are essentially the same for each of my requests, I wrote a single function to initialize and execute our REST calls.

function curl_it($sugar_oauth_token, $curl_url, $data = null, $ispost = false) {
     $the_response = null;
     $the_request = curl_init($curl_url);
     curl_setopt($the_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
     curl_setopt($the_request, CURLOPT_SSL_VERIFYPEER,1);
     curl_setopt($the_request, CURLOPT_RETURNTRANSFER, 1);
     curl_setopt($the_request, CURLOPT_FOLLOWLOCATION, 0);
     curl_setopt($the_request, CURLOPT_HTTPHEADER, array(
         "Content-Type: application/json",
         "oauth-token: {$sugar_oauth_token}"
     ));
     if ($ispost) {
          curl_setopt($the_request, CURLOPT_POSTFIELDS, $data);
     }
     $the_response = curl_exec($the_request) ;
     curl_close($the_request);
     return $the_response;
}

The notable part of this is where we set the OAuth-Token or a standard bearer token. This wasn't necessary in the initial auth call.

curl_setopt($the_request, CURLOPT_HTTPHEADER, array(
    "Content-Type: application/json",
    "OAuth-Token: {$sugar_oauth_token}"
));

Now we should have a response back from Sugar. This response, if successful, will contain a record that has an e-mail address matching the one we sent in. From the returned record, we can grab the IDs that we need to be able to associate this comment with the returned user. We will add the comment as a note linked to the account record. In order to appropriately associate the new note, we'll send the Sugar User ID as the parent_id for the note and ensure that we are using the appropriate parent_type.

What if the e-mail address of the current Wordpress commenter can't be found in Sugar? Well then let's add them as a Lead and THEN create the new note and attach it to the newly created lead record.

What if the e-mail address is found but it is a Lead and not a Contact? Then we need to set the parent_type to "Leads" and the parent_id to the id of the Lead record. For anything else, we use the account_id from sugar as the parent_id.

Now that the plugin is doing essentially what we want it to do, there’s many enhancements we could add. The first one I threw in there was a verify button on the admin form to check if the user settings are valid. I adjusted the auth function to take the form values as parameters. That way, when we expose the function for REST calls we can pass in the values from the form BEFORE they are saved to the Wordpress database.

This button is essentially making the same authentication REST call that we are making when sending data to Sugar. I could have written the javascript to call the Sugar endpoint directly but that opens up a few issues. Firstly we would likely (I did) run into a Same-Origin policy conflict where the Sugar client doesn’t recognize and/or trust the external Wordpress domain. The other issue I saw was that I’d have to rewrite exactly what I did in the PHP for the front-end. I prefer reusable code. There were also some security issues to consider but these were the glaring problems from a strictly front-end implementation. SO, I simply researched how to turn my Wordpress functions within the plugin into additional endpoints in the Wordpress API. All it took was registering the route for the endpoint and telling it which function to call.

add_action( 'rest_api_init', 'init_rest_api' );

function init_rest_api () {
     register_rest_route( 'sugarcrm-api/v1', '/auth', array(
          'methods' => \WP_REST_Server::EDITABLE,
          'callback' => 'sugarcrm_rest_auth_validate',
          'args' => ['username', 'password', 'url', 'version']
     ));
}

Other tips & tricks

Much of this exercise was new to me (or I needed some refreshers). What I found was that sending the data to Sugar was not particularly difficult. The work came from deciding what to do with the information and how to handle different scenarios - like the user already being in the system as a Lead not a Contact. I spent a lot of time using the browser console to look at objects returned in the Sugar instance. I think I used this command in the console more than any other:

SUGAR.App.controller.context.get("model")

I would navigate to a Lead or Note record in Sugar and then run that command in the developer console to see all of the properties and values for the current module. It really helped me decide on what data to send or grab.

But not everything could be traced out on the front-end. So, Stack Overflow came to my rescue with a simple logging function I implemented in the PHP. With this function, I could spit out whatever I wanted to a local log file for debugging. If I wanted to see the contents of a response object, for example, I would write the line:

log_it($my_response, 'The object my_response contains: ');

Try it out yourself!

If you would like to use the code that was written for this article for some hands-on practice, you will need an instance of Sugar and an instance of Wordpress. I did it all locally with a Vagrant box for Sugar and MAMP for the Wordpress instance.

You don't need to install any custom code into Sugar. It uses the standard REST API and a custom API platform which can be configured easily via Sugar Admin panel.

The Wordpress integration code has been added to the SugarCRM Building Blocks git repository in the api-examples directory. Simply download and unpack the plugin files and drop them into your Wordpress plugins directory (typically at /wp-content/plugins). Now you should be able to activate the plugin in Wordpress and add your customized settings via the "Sugar API Plugin" settings menu option on the left navigation (like that custom logo icon? hehe).

Remember to register the platform in Sugar's admin section using the name "wordpress_api" or whatever you change it to in the code. That's it!

To try it out, you should be able to add a comment to a Wordpress post and see it attached to a record in Sugar.

Now go play! Here are some ideas for changes you can make to my plug-in example.

  • Try to add more detail to the Note created in Sugar.
  • When a comment is deleted in Wordpress, find the note in Sugar and update it.
  • Include a link to the record in Sugar that points back to the comment in Wordpress.
  • And please... share with the community what you did - no matter how minor or major.

I hope you enjoyed this article. I’ve never really thought of myself as a writer. In fact, my first job was working in an orange juice factory. But I got canned. I couldn’t concentrate.