1. Go to this page and download the library: Download bootdesk/chat-sdk-laravel 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/ */
bootdesk / chat-sdk-laravel example snippets
return [
// The display name your bot uses when posting messages.
'user_name' => env('BOT_USERNAME', 'Bot'),
// Platform adapters to enable. Only adapters whose Composer package
// is installed (class_exists) will be loaded. For multi-tenant
// setups, omit the platform here and use an AdapterResolver instead.
'adapters' => [
// 'slack' => [
// 'bot_token' => env('SLACK_BOT_TOKEN'),
// 'signing_secret' => env('SLACK_SIGNING_SECRET'),
// ],
// 'telegram' => [
// 'bot_token' => env('TELEGRAM_BOT_TOKEN'),
// ],
// 'whatsapp' => [
// 'access_token' => env('WHATSAPP_ACCESS_TOKEN'),
// 'app_secret' => env('WHATSAPP_APP_SECRET'),
// 'phone_number_id' => env('WHATSAPP_PHONE_NUMBER_ID'),
// 'verify_token' => env('WHATSAPP_VERIFY_TOKEN'),
// ],
// 'discord' => [
// 'bot_token' => env('DISCORD_BOT_TOKEN'),
// 'application_id' => env('DISCORD_APPLICATION_ID'),
// 'public_key' => env('DISCORD_PUBLIC_KEY'),
// ],
// 'messenger' => [
// 'page_access_token' => env('MESSENGER_PAGE_ACCESS_TOKEN'),
// 'app_secret' => env('MESSENGER_APP_SECRET'),
// 'verify_token' => env('MESSENGER_VERIFY_TOKEN'),
// ],
// 'web' => [
// 'user_name' => env('BOT_USERNAME', 'Bot'),
// ],
// 'github' => [
// 'auth_token' => env('GITHUB_TOKEN'),
// 'webhook_secret' => env('GITHUB_WEBHOOK_SECRET'),
// ],
// 'linear' => [
// 'api_key' => env('LINEAR_API_KEY'),
// 'webhook_secret' => env('LINEAR_WEBHOOK_SECRET'),
// ],
],
// State persistence backed by the Laravel Cache facade. The cache
// store is resolved from the facade at runtime — configure it in
// config/cache.php as usual.
'state' => [
'prefix' => env('CHAT_STATE_PREFIX', 'chat:'),
],
// Global handler classes registered on every Chat instance regardless
// of adapter. Each class must implement a register($chat) method.
'handlers' => [
// \App\Chat\GlobalHandlers::class,
],
// Adapter-specific handler groups. Only the matching group is
// registered per webhook request, alongside global handlers above.
'handler_groups' => [
// 'slack' => [
// \App\Chat\SlackHandler::class,
// ],
// 'telegram' => [
// \App\Chat\TelegramHandler::class,
// ],
],
// How to handle concurrent messages for the same thread.
// Core strategies: drop (default), queue, debounce, concurrent.
// Laravel uses QueueConcurrencyHandler to dispatch jobs for async processing.
'concurrency' => env('CHAT_CONCURRENCY', 'drop'),
// Scope for distributed locks: 'thread' (default) or 'channel'.
// Use 'channel' for platforms like WhatsApp/Telegram where
// conversations are per-channel (one conversation per phone number).
'lock_scope' => env('CHAT_LOCK_SCOPE', 'thread'),
// Cross-platform per-user message persistence. Requires an
// IdentityResolver bound to the container (IdentityResolver::class).
'transcripts' => null,
];
// routes/web.php or routes/api.php
use BootDesk\ChatSDK\Laravel\Http\Controllers\WebhookController;
Route::match(['get', 'post'], '/api/webhooks/{adapter}', WebhookController::class);
// app/Chat/ChatHandlers.php
namespace App\Chat;
use BootDesk\ChatSDK\Core\Chat;
use BootDesk\ChatSDK\Core\MessageContext;
use BootDesk\ChatSDK\Laravel\Contracts\ChatHandler as ChatHandlerContract;
class ChatHandlers implements ChatHandlerContract
{
public function register(Chat $chat): void
{
$chat->onNewMessage('/^hello$/i', function (MessageContext $ctx) {
$ctx->thread->post('Hey!');
});
$chat->fallback(function (MessageContext $ctx) {
$ctx->thread->post("I don't understand that.");
});
}
}
// Global — fires for every adapter
'handlers' => [\App\Chat\ChatHandlers::class],
use Illuminate\Http\Request;
use Psr\Http\Message\ServerRequestInterface;
class ChannelAwareController extends WebhookController
{
protected function resolveGroups(string $adapter, Request $request, ServerRequestInterface $psrRequest): array
{
$channel = $request->input('channel_id');
return match ($channel) {
'C001' => ['slack', 'internal-support'],
'C002' => ['slack', 'customer-support'],
default => [$adapter],
};
}
}
use BootDesk\ChatSDK\Laravel\Contracts\ChatHandlerWithRequest;
class TenantAwareHandler implements ChatHandlerWithRequest
{
public function register(Chat $chat, ?ServerRequestInterface $request = null): void
{
$tenant = $request?->getHeaderLine('X-Tenant') ?? 'default';
$chat->onNewMessage('/bill/', function (MessageContext $ctx) use ($tenant) {
// tenant-specific billing flow
});
}
}
use BootDesk\ChatSDK\Core\Contracts\WebhookMiddleware;
use BootDesk\ChatSDK\Core\Contracts\ReceivingMiddleware;
use BootDesk\ChatSDK\Core\Contracts\SendingMiddleware;
class ChatHandlers
{
public function register(Chat $chat): void
{
// Intercept raw webhook before parsing
$chat->addWebhookMiddleware(new class implements WebhookMiddleware {
public function handle(ServerRequestInterface $request, callable $next): ResponseInterface {
logger()->info('Webhook received', ['path' => $request->getUri()->getPath()]);
return $next($request);
}
});
// Transform inbound messages before handlers
$chat->addReceivingMiddleware(new class implements ReceivingMiddleware {
public function handle(Message $message, Adapter $adapter, callable $next): ?Message {
// Return null to drop the message
if (str_contains($message->text, 'blocked')) {
return null;
}
return $next($message);
}
});
// Transform outbound messages before delivery
$chat->addSendingMiddleware(new class implements SendingMiddleware {
public function handle(string $threadId, PostableMessage $message, Adapter $adapter, string $operation, callable $next): ?SentMessage {
logger()->info('Sending message', ['thread' => $threadId, 'operation' => $operation]);
return $next($message);
}
});
}
}
// AppServiceProvider::register()
use BootDesk\ChatSDK\Core\Contracts\IdentityResolver;
use BootDesk\ChatSDK\Core\Author;
$this->app->bind(IdentityResolver::class, fn () => new class implements IdentityResolver {
public function resolve(Author $author): ?string {
return $author->id;
}
});
$this->app->bind(TranscriptsApi::class, function ($app) {
return new MyRedisTranscriptsApi(
state: $app->make(StateAdapter::class),
config: ['max_messages' => 200],
);
});
$transcripts = $chat->getTranscripts();
// List history for a user
$entries = $transcripts->list('user:U123');
// Each entry has: id, text, authorId, threadId, timestamp, direction
// Count
$count = $transcripts->count('user:U123');
// Delete
$transcripts->delete('user:U123');
// app/Chat/MultiTenantAdapterResolver.php
namespace App\Chat;
use BootDesk\ChatSDK\Core\Contracts\Adapter;
use BootDesk\ChatSDK\Core\Contracts\AdapterResolver;
use BootDesk\ChatSDK\Slack\SlackAdapter;
use BootDesk\ChatSDK\Telegram\TelegramAdapter;
use Illuminate\Support\Facades\DB;
use Psr\Http\Message\ServerRequestInterface;
class MultiTenantAdapterResolver implements AdapterResolver
{
public function resolve(string $name, ?ServerRequestInterface $request): ?Adapter
{
// Extract tenant from request (header, subdomain, route param, etc.)
// When called from a job, $request is null - use other context (job payload, auth, etc.)
$tenantId = $request?->getHeaderLine('X-Tenant-ID')
?? $this->getTenantFromContext();
if ($tenantId === null || $tenantId === '') {
return null;
}
// Load tenant-specific credentials from database
$config = DB::table('tenant_chat_configs')
->where('tenant_id', $tenantId)
->where('adapter', $name)
->first();
if (! $config) {
return null;
}
// Instantiate adapter with tenant credentials
return match ($name) {
'slack' => new SlackAdapter(
botToken: $config->credentials['bot_token'],
httpClient: app(\Psr\Http\Client\ClientInterface::class),
signingSecret: $config->credentials['signing_secret'] ?? null,
),
'telegram' => new TelegramAdapter(
botToken: $config->credentials['bot_token'],
httpClient: app(\Psr\Http\Client\ClientInterface::class),
secretToken: $config->credentials['secret_token'] ?? null,
),
default => null,
};
}
}
// app/Providers/AppServiceProvider.php
use BootDesk\ChatSDK\Core\Contracts\AdapterResolver;
public function register(): void
{
$this->app->bind(
AdapterResolver::class,
\App\Chat\MultiTenantAdapterResolver::class
);
}
use BootDesk\ChatSDK\Laravel\ChatFactory;
class MessageController
{
public function __construct(
private ChatFactory $chatFactory,
) {}
public function send()
{
$chat = $this->chatFactory->default(); // global handlers only
$chat->thread('slack:C123')->post('Hello!');
}
}
$chat = $this->chatFactory->forGroup('slack'); // global + slack handlers
$chat->handleWebhook('slack', $psrRequest);
$chat = $this->chatFactory->forGroups(['slack', 'internal-support']); // global + both groups