Bitrix24: Blogs
  • Fast Bitrix24 Integration: Webhook Street Magic

    Yana Prokopets 30 January 2017
    As you may know, Bitrix24 includes extensive REST API that can be used to extend Bitrix24 features and integrate third-party systems. The REST methods can create and edit CRM entities and tasks, post messages to Activity Stream – in fact, they can do almost anything.

    Until recently, however, a seemingly nonchalant REST developer's life was troubled by a looming shadow of OAuth 2.0 protocol which had been a requirement, and a tricky one to implement at that. Even though it has now been quite a while since it was introduced, and is currently in use by major software companies, many developers are still faint-hearted when the protocol needs to be implemented from scratch. Another disadvantage is you would have to update authentication tokens now and again should your requirement be an automated, unsupervised continuous data exchange with Bitrix24.

    Sometimes all a developer is asked of is connect a Bitrix24 instance to a known third party system, or just to a simple web form. Say the boss suffering from a terrible headache after a yesterday's backyard party suddenly wants to have warehouse reports posted to Activity Stream. What say you?

    At ease, gentlemen. We have just made your life easier: a new Bitrix24 integration system was devised, and it's just a perfect fit for in-house solutions. I'm talking about the notorious web hooks. Well, notorious may be a wrong word indeed: they are famous for making developer happy!

    With webhooks you can take advantage of the REST API methods while saving the trouble of having to implement OAuth 2.0.

    Inbound Webhooks


    Right, let's see how we do it. Assume we have a feedback form on our website that is still not employing Bitrix24 CRM Forms for some reason and, instead of going for it, we are stubborn enough to leave the form as it is while adding doodads and whatnots so that a new lead be created in Bitrix24 when the form is submitted.

    All we do is open Applications > Webhooks and click "Add webhook":

    a9c03838a9176cf77b399d78355e440d.png
    Select "Inbound webhook" as webhook type (our intention is connect to Bitrix24 externally, correct?) and behold – here cometh the webhook parameters form.

    Enter the webhook name and description, and select the module whose access is required. In this case we need access to the CRM module because we want to add leads.

    9ef1327ef18e8410ef5577f2cd7d28c5.png
    Click "Save". The form now shows some new information:

    da2b6f36b488ea53cc67ce95704dfb4c.png
    Now let's see what this URL includes.

    1.This is the user ID whose access permissions will apply to the webhook. Obviously, the URL specifies the ID of a user who has just created the webhook.
    2. The webhook code. Keep it secure. Don’t post a selfie with this code on Instagram.3A REST method to execute. The "profile" method is just an example; we are going to use crm.lead.add instead.
    3. All we have to do now is call the appropriate URL – the one the clever machine has created for us, just include a required method name. That's all there is to it.

    And here's how it can be done:

    <?
    /**
     * Write data to log file.
     *
     * @param mixed $data
     * @param string $title
     *
     * @return bool
     */
    function writeToLog($data, $title = '') {
     $log = "\n------------------------\n";
     $log .= date("Y.m.d G:i:s") . "\n";
     $log .= (strlen($title) > 0 ? $title : 'DEBUG') . "\n";
     $log .= print_r($data, 1);
     $log .= "\n------------------------\n";
     file_put_contents(getcwd() . '/hook.log', $log, FILE_APPEND);
     return true;
    }
    
    $defaults = array('first_name' => '', 'last_name' => '', 'phone' => '', 'email' => '');
    
    if (array_key_exists('saved', $_REQUEST)) {
     $defaults = $_REQUEST;
     writeToLog($_REQUEST, 'webform');
    
     $queryUrl = 'https://restapi.bitrix24.ru/rest/1/31uhq2q855fk1foj/crm.lead.add.json';
     $queryData = http_build_query(array(
     'fields' => array(
     "TITLE" => $_REQUEST['first_name'].' '.$_REQUEST['last_name'],
     "NAME" => $_REQUEST['first_name'],
     "LAST_NAME" => $_REQUEST['last_name'],
     "STATUS_ID" => "NEW",
     "OPENED" => "Y",
     "ASSIGNED_BY_ID" => 1,
     "PHONE" => array(array("VALUE" => $_REQUEST['phone'], "VALUE_TYPE" => "WORK" )),
     "EMAIL" => array(array("VALUE" => $_REQUEST['email'], "VALUE_TYPE" => "WORK" )),
     ),
     'params' => array("REGISTER_SONET_EVENT" => "Y")
     ));
    
     $curl = curl_init();
     curl_setopt_array($curl, array(
     CURLOPT_SSL_VERIFYPEER => 0,
     CURLOPT_POST => 1,
     CURLOPT_HEADER => 0,
     CURLOPT_RETURNTRANSFER => 1,
     CURLOPT_URL => $queryUrl,
     CURLOPT_POSTFIELDS => $queryData,
     ));
    
     $result = curl_exec($curl);
     curl_close($curl);
    
     $result = json_decode($result, 1);
     writeToLog($result, 'webform result');
    
     if (array_key_exists('error', $result)) echo "Error saving lead: ".$result['error_description']."<br/>";
    }
    
    ?>
    <fo rm method="post" action="">
        Name: <input type="text" name="first_name" size="15" value="<?=$defaults['first_name']?>"><br/>
        Last name: <input type="text" name="last_name" size="15" value="<?=$defaults['last_name']?>"><br/>
        Phone: <input type="phone" name="phone" value="<?=$defaults['phone']?>"><br/>
        E-mail: <input type="email" name="email" value="<?=$defaults['email']?>"><br/>
        <input type="hidden" name="saved" value="yes">
        <input type="submit" value="send">
    </form>  

    Now, some important notes. First and foremost: never make your web forms as ugly and insecure as the one in the example J. Next, nearly all Bitrix24 integration approaches boil down to these simple steps: create an URL; fill in the $queryData variable (read more here); initialize curl and invoke Bitrix24 using a call to curl_exec. Process the JSON response – and everyone's happy. Even your boss's hangover is over, pardon the pun.

    Let's summarize the three simple steps:

    1. Add a webhook and use the webhook parameters form to get a hot and sizzling new URL, right in your Bitrix24.
    2. Replace the default REST method name with the one you require. Create the query data array.
    3. Call Bitrix24 using the URL.

    Should you want to test your new little brainchild– open the form, fill in the fields and submit the form. Now browse your Bitrix24 to see the new lead added. That's all, you can take five and relax.

    Outbound Webhooks

    Now that you have had your R&R, you'll be delighted to know that's not all the fun you can get! Integration can come from both sides. Sometimes one desperately needs to send some information to a third party system whenever a change occurs in Bitrix24. For example, create an order in your custom ERP when a sales representative updates a Bitrix24 deal to a certain status.

    Again, open Applications > Webhooks but click on "Outbound webhook" this time. This will bring up a different form because we don't have to create an inbound key. However, we have to select an event which, when activated, will call our handler.

    8a4a97693136086fd35d9f33d92ff62a.png
    Specify the handler URL, give the new webhook a nice and clear name and, most importantly, select the ONCRMDEALUPDATE event. Submit the form to create an authentication key that we will use in our handler to check if it is called from Bitrix24 and the call is authentic. This may be not the bulletproof security measure, but it will suffice in most cases.

    2f80fd003232fb5bf14a8dc2dad292d5.png
    The handler in this example does the simplest job possible: it logs everything passed on to it.

    <?
    
    print_r($_REQUEST);
    writeToLog($_REQUEST, 'incoming');
    
    /**
     * Write data to log file.
     *
     * @param mixed $data
     * @param string $title
     *
     * @return bool
     */
    function writeToLog($data, $title = '') {
     $log = "\n------------------------\n";
     $log .= date("Y.m.d G:i:s") . "\n";
     $log .= (strlen($title) > 0 ? $title : 'DEBUG') . "\n";
     $log .= print_r($data, 1);
     $log .= "\n------------------------\n";
     file_put_contents(getcwd() . '/hook.log', $log, FILE_APPEND);
     return true;
    }  

    Now, if we open a deal for editing and save changes, we will see an entry in the log:

    2017.01.17 12:58:29
    incoming
    Array
    (
        [event] => ONCRMDEALUPDATE
        [data] => Array
         (
          [FIELDS] => Array
              (
               [ID] => 662
              )
    
         )
    
        [ts] => ххх
        [auth] => Array
         (
          [domain] => ххх.bitrix24.com
          [client_endpoint] => https://ххх.bitrix24.com/rest/
          [server_endpoint] => https://oauth.bitrix.info/rest/
          [member_id] => ххх
          [application_token] => ххх
         )
    
    )
      
    Did you see how simple getting deal change information was? Now we can use the inbound webhook discussed earlier to get deal details by calling the crm.deal.get method.

    Here Be the Cyborgs!

    We found webhooks so much simple and useful that we took one step even further to make it support CRM automation!

    Open the CRM preferences form, select Automation in the menu and click Deals.

    8380cccc74fcb21237e393fbccb3e65b.png
    To keep things simple, we will use the same outbound webhook handler we have previously created. However, we will call it explicitly.

    Click "Configure automation rules" and add a rule to any deal stage while selecting "Webhook" as the rule type. Once the rule type is selected, a new form will follow in which we will specify the handler URL and parameters to pass on to it.

    15df8cb4b6c4754b996df44299f09f9a.png
    As an example, let's feed the handler with the deal stage:

    cfd983a51f956609312a55f2dd80916a.png
    Save everything (not the whole world at the moment, just click "Save" in the forms). Open any deal and change its stage to the one for which we have created a rule. This will trigger the outbound webhook, and the handler will add deal data to the log:

    2017.01.17 12:58:27
    incoming
    Array
    (
        [status] => New
        [document_id] => Array
         (
          [0] => crm
          [1] => CCrmDocumentDeal
          [2] => DEAL_662
         )
    
        [auth] => Array
         (
          [domain] => xxx.bitrix24.com
          [client_endpoint] => https://xxx.bitrix24.com/rest/
          [server_endpoint] => https://oauth.bitrix.info/rest/
          [member_id] => xxx
         )
    
    ) 

    Isn't it beautiful?
2,000,000+
organizations
are already using Bitrix24