PHP code example of aimeos / pagible-webhooks

1. Go to this page and download the library: Download aimeos/pagible-webhooks library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

aimeos / pagible-webhooks example snippets


use Aimeos\Cms\Permission;
use Aimeos\Cms\WebhookManager;

$result = app( WebhookManager::class )->add( 'https://example.com/hooks/cms', ['page.published'], true, $user, 'Shop sync' );

$result['webhook']->id; // subscription ID for save(), rotate(), ping() and purge()
$result['secret'];      // returned only once, store it now

// without user, e.g. when a new tenant is created
$result = Permission::system( fn() => app( WebhookManager::class )->add( 'https://example.com/hooks/cms', ['page.published'], true, null ) );

use Aimeos\Cms\Events\Change;
use Aimeos\Cms\WebhookConfig;

WebhookConfig::payload( function( array $changes, string $event ) {
    $ids = array_map( fn( Change $change ) => $change->id, $changes );

    // all changes of an event belong to the same tenant
    return Product::where( 'tenant_id', $changes[0]->tenant )->whereIn( 'page_id', $ids )->pluck( 'sku', 'page_id' )
        ->map( fn( string $sku ) => ['sku' => $sku] )
        ->all();
} );

use Aimeos\Cms\Events\Change;

Change::listen( ['published', 'dropped'], \App\Listeners\SyncShop::class );

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;

Route::post( '/hooks/cms', function( Request $request ) {

    $id = (string) $request->header( 'webhook-id' );
    $time = (string) $request->header( 'webhook-timestamp' );
    $signatures = explode( ' ', (string) $request->header( 'webhook-signature' ) );

    if( $id === '' || !ctype_digit( $time ) || abs( time() - (int) $time ) > 300 ) {
        abort( 401 );
    }

    // The key is the base64 part of the "whsec_..." secret and the body is the raw one,
    // not the decoded and re-encoded JSON
    $key = base64_decode( substr( (string) config( 'services.cms.webhook_secret' ), 6 ) );
    $hmac = hash_hmac( 'sha256', $id . '.' . $time . '.' . $request->getContent(), $key, true );
    $expected = 'v1,' . base64_encode( $hmac );

    if( !array_filter( $signatures, fn( $signature ) => hash_equals( $expected, $signature ) ) ) {
        abort( 401 );
    }

    // Delivered before: 24 hours delivery age plus 5 minutes clock skew
    if( !Cache::add( 'cms-delivery:' . $id, true, 86700 ) ) {
        return response()->noContent();
    }

    try {
        $event = json_decode( $request->getContent(), true, 512, JSON_THROW_ON_ERROR );
        // Process $event['event'] and $event['data'] ...
    } catch( \Throwable $e ) {
        Cache::forget( 'cms-delivery:' . $id ); // so the retry isn't skipped
        throw $e;
    }

    return response()->noContent();
} );

'endpoints' => [
    'indexer' => [
        'url' => env( 'CMS_WEBHOOK_INDEXER_URL' ),        // e.g. http://indexer:8080/cms
        'secret' => env( 'CMS_WEBHOOK_INDEXER_SECRET' ),  // "whsec_..." or a list
        'events' => ['page.published', 'page.deleted'],
    ],
],
bash
composer cms:install:webhooks
php artisan migrate
bash
php artisan queue:work redis --queue=cms-webhooks
bash
php artisan cms:webhooks:check