composer require wasenderapi/wasenderapi-symfony
config/bundles.php:
WasenderApi\SymfonyBundle\WasenderApiBundle::class => ['all' => true],
config/packages/wasenderapi.yaml with your API credentials:
wasenderapi:
api_key: '%env(WASENDERAPI_API_KEY)%'
personal_access_token: '%env(WASENDERAPI_PERSONAL_ACCESS_TOKEN)%'
base_url: 'https://www.wasenderapi.com/api'
webhook:
secret: '%env(WASENDERAPI_WEBHOOK_SECRET)%'
path: '/wasender/webhook'
.env:
WASENDERAPI_API_KEY=your_api_key_here
WASENDERAPI_PERSONAL_ACCESS_TOKEN=your_token_here
WASENDERAPI_WEBHOOK_SECRET=your_webhook_secret_here
config/routes.yaml:
wasenderapi_webhook:
resource: '@WasenderApiBundle/Resources/config/routing.xml'
Inject the WasenderApiClient into a controller or service and send a message:
use WasenderApi\SymfonyBundle\Client\WasenderApiClient;
class WhatsAppController
{
public function __construct(private WasenderApiClient $wasender) {}
public function sendWelcomeMessage()
{
$this->wasender->sendText('1234567890', 'Welcome to our service!');
return new Response('Message sent!');
}
}
public function __construct(WasenderApiClient $wasender) {}
$client = new WasenderApiClient('api_key_for_session_1');
$client->sendImage(
new SendImageMessageData('123', 'https://example.com/image.png', 'Caption')
);
CommandBus or Messenger for async processing.class WasenderEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [MessageReceived::class => 'handleIncomingMessage'];
}
}
# config/routes.yaml
wasenderapi_webhook:
path: /wasender/webhook
methods: [POST]
defaults: { _controller: 'WasenderApiBundle:Webhook:handle' }
$client->uploadMediaFile('data:image/png;base64,...'); // Dynamic
$client->uploadMediaFile('/path/to/file.png'); // Static
RetryConfig for transient failures:
$retryConfig = new RetryConfig(true, 3); // Retry 3 times
$client->sendText('123', 'Hello', [], $retryConfig);
WASENDERAPI_WEBHOOK_SECRET matches the secret in WasenderAPI dashboard.// In your webhook handler, log the signature comparison:
$isValid = $this->wasender->verifyWebhookSignature(
$request->getContent(),
$request->headers->get('x-webhook-signature')
);
RetryConfig to avoid dropped messages.Retry-After to adjust delays.$client->regenerateApiKey($sessionId);
group@g.us). Fetch via getGroups() first.Enable Guzzle Debugging:
Add to config/packages/wasenderapi.yaml:
wasenderapi:
debug: '%kernel.debug%'
This logs HTTP requests/responses to var/log/dev.log.
Event Dispatcher:
Use Symfony’s EventDispatcher to log all webhook events:
public function onMessageReceived(MessageReceived $event): void
{
$this->logger->info('Message received', ['payload' => $event->getPayload()]);
}
Custom Events: Extend the event system by creating your own event classes and dispatching them in subscribers:
$dispatcher->dispatch(new CustomWasenderEvent($payload));
Middleware: Add Guzzle middleware for logging, caching, or modifying requests:
$client->getGuzzleClient()->getEmitter()->attach(
new \GuzzleHttp\Middleware::tap(function ($request) {
$this->logger->debug('WasenderAPI request', ['url' => $request->getUri()]);
})
);
DTO Validation: Extend DTOs to add custom validation (e.g., phone number format):
use Symfony\Component\Validator\Constraints as Assert;
class SendTextMessageData
{
#[Assert\NotBlank]
#[Assert\Regex('/^\+?[0-9]{10,15}$/')]
public string $recipient;
// ...
}
base_url in config if using a custom WasenderAPI endpoint (e.g., staging):
wasenderapi:
base_url: 'https://staging.wasenderapi.com/api'
%env() with placeholders for multi-environment setups:
wasenderapi:
api_key: '%env(WASENDERAPI_API_KEY_%kernel.environment%)%'
Messenger to process webhooks asynchronously:
$bus->dispatch(new WasenderWebhookMessage($payload));
$cache->get('group_metadata_' . $groupJid, function () use ($client, $groupJid) {
return $client->getGroupMetadata($groupJid);
});
How can I help you explore Laravel packages today?