Creating Webhooks (HTTP Triggers)
Syncing once per day (or once per hour) is a start, but it is much better if jobs are triggered as soon as a record is updated in the source system. A common way to handle that is to have the source application trigger the job via a HTTP request (a webhook).
These are not included in the package, but here is how to write one...
In routes/api.php, define a route for each webhook:
Route::withoutMiddleware('throttle:api')->group(function () {
Route::post('sync-triggers/crm-accounts', [SyncTriggerController::class, 'crmAccounts']);
//...
});
Note: We disable throttling so that we don't miss any changes.
Then create a controller & action such as this:
class SyncTriggerController extends Controller
{
private function auth(string $username, string $password): void
{
$request = request();
if ($request->getUser() !== $username || !hash_equals($password, $request->getPassword())) {
throw new UnauthorizedHttpException('Basic', 'Invalid credentials.');
}
}
public function crmAccounts(Request $request): void
{
$this->auth('crm', config('custom.crm_api_token'));
$request->validate([
'trigger' => ['nullable', 'string'],
'record_id' => ['nullable', 'string', 'max:255'],
'record_name' => ['nullable', 'string'],
]);
$trigger = $request->trigger ?? 'API call from ' . $request->getClientIp();
SyncAccountsFromCrmToPasswordsDatabase::dispatch($trigger, $request->record_id, $request->record_name);
SyncAccountsFromCrmToSupportCases::dispatch($trigger, $request->record_id, $request->record_name);
SyncAccountsFromCrmToKbClientPages::dispatch($trigger, $request->record_id, $request->record_name);
SyncAccountsFromCrmToTimesheets::dispatch($trigger, $request->record_id, $request->record_name);
}
}
(TODO: Move the auth() method into a trait/helper/middleware in Laravel Utilities?)
In this example we are manually authenticating the request against a password set in .env / config/custom.php. Another option is to create users in the database and use Laravel's built-in token authentication driver (or the new Sanctum package).
To trigger a webhook from another Laravel application, do something like this:
// TODO: Untested
$url = config('custom.sync_api_uri');
try {
HTTP::acceptJson()
->timeout(2)
->withBasicAuthentication('crm', config('custom.sync_api_token'))
->post($url, [
'trigger' => "{$user->name} editing account '{$account->name}'",
'record_id' => $account->id,
'record_name' => $account->name,
]);
} catch (HttpClientException $e) {
Log::warn("Failed to notify $url: {$e->getMessage()}");
}
For a plain PHP example using cURL, see the Alberon CRM.
For webhooks from third-party applications, you may need to read their documentation on how to authenticate requests and what format the request will take.
Warning: You should not allow unauthenticated requests, as it could potentially be used in a denial-of-service attack (to overload the server).