Example file

send-event.php

PHP: signs and sends a sale from your CRM to an inbound custom integration's delivery URL.

send-event.php · PHP Download
<?php
// Sends one signed event to a Subcontext inbound custom integration, in PHP 8.1
// or later with the curl extension. Here it's a sale from your CRM, which
// Subcontext records as an outcome on the lead.
//
// Set these first (all three are on the integration's page in Subcontext):
//   SUBCONTEXT_DELIVERY_URL      the Delivery URL
//   SUBCONTEXT_SIGNING_SECRET    the value of the secret variable chosen as the Signing secret variable
//   SUBCONTEXT_SIGNATURE_HEADER  the Signature header (X-Integrations-Signature unless you changed it)
//
// Run it:  php send-event.php

declare(strict_types=1);

$deliveryUrl = getenv('SUBCONTEXT_DELIVERY_URL') ?: '';
$secret = getenv('SUBCONTEXT_SIGNING_SECRET') ?: '';
$headerName = getenv('SUBCONTEXT_SIGNATURE_HEADER') ?: 'X-Integrations-Signature';
if ($deliveryUrl === '' || $secret === '') {
    fwrite(STDERR, "Set SUBCONTEXT_DELIVERY_URL and SUBCONTEXT_SIGNING_SECRET.\n");
    exit(1);
}

function signatureHeader(string $rawBody, string $secret, ?int $timestamp = null): string
{
    $timestamp ??= time();
    return 't=' . $timestamp . ',v1=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
}

// The shape is up to you. The integration's settings say where to find each part.
// This one fits an Event type path of "type" and the outcome mapping on the
// Integrations guide.
$event = [
    'event_id' => bin2hex(random_bytes(16)), // send the same id again if you retry, so it's recorded once
    'type' => 'deal.won',
    'deal' => [
        'id' => 'DEAL-123',
        'contact_id' => 'YOUR_CRM_CONTACT_ID', // your id for the lead, or send ours (contact_id) instead
        'closed_at' => gmdate('c'),
        'commission' => '450.00',
    ],
];

// Sign the exact string you send.
$body = json_encode($event);
$curl = curl_init($deliveryUrl);
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 15,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        $headerName . ': ' . signatureHeader($body, $secret),
    ],
]);
curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);

// 200: accepted. 400: not JSON. 403: signature, secret or clock problem. 404: wrong URL.
echo $status, ' ', $status === 200 ? 'accepted' : 'not accepted', "\n";

Stuck, or something missing?

Get in touch and a person on the team will help.

Contact us