getbizapps / bizwachat-laravel-notification
Laravel notification channel and API client for Bizwachat public API.
Package info
github.com/getbizapps/bizwachat-laravel-notification
pkg:composer/getbizapps/bizwachat-laravel-notification
Requires
- php: ^8.2
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/notifications: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
This package is not auto-updated.
Last update: 2026-05-24 16:25:51 UTC
README
Laravel notification channel and API client for the Bizwachat public API.
What this package gives you
- Native Laravel notification channel for Bizwachat delivery
- Fluent builders for text, template, and media messages
- Full access to the public API resources from
openapi-3.yaml - Centralized exception handling with log entries in every catch block
- Config-first defaults so developers can send messages with minimal code
Installation
composer require getbizapps/bizwachat-laravel-notification php artisan vendor:publish --tag=bizwachat-notification-config
Environment
BIZWACHAT_BASE_URL=https://bizwachat.com BIZWACHAT_SUBDOMAIN=your-subdomain BIZWACHAT_API_TOKEN=your-public-api-token BIZWACHAT_TIMEOUT=30 BIZWACHAT_CONNECT_TIMEOUT=10 BIZWACHAT_THROW_EXCEPTIONS=true BIZWACHAT_LOG_CHANNEL=stack
Notification usage
<?php namespace App\Notifications; use BizwaChat\LaravelNotification\Channels\BizwaChatChannel; use BizwaChat\LaravelNotification\Messages\TemplateMessage; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; class WelcomeOnWhatsApp extends Notification { use Queueable; public function via(object $notifiable): array { return [BizwaChatChannel::class]; } public function toBizwaChat(object $notifiable): TemplateMessage { return TemplateMessage::make('welcome_message', 'en') ->headerTextParameter($notifiable->name) ->fields([ $notifiable->name, 'Bizwachat', ]); } }
If your model already has a phone number field, the channel will automatically try phone, phone_number, and mobile.
If you need explicit routing, define:
public function routeNotificationForBizwaChat(): array { return [ 'phone_number' => $this->phone, 'subdomain' => $this->tenant_subdomain, 'from_phone_number_id' => $this->bizwachat_phone_number_id, ]; }
Direct API usage
use BizwaChat\LaravelNotification\Facades\BizwaChat; use BizwaChat\LaravelNotification\Messages\ContactData; BizwaChat::sendText('+15550001111', 'Hello from Bizwachat', [ 'contact' => ContactData::make() ->firstname('John') ->lastname('Doe') ->email('john@example.com') ->groups(['VIP Customers', 'Newsletter']), ]); $templates = BizwaChat::templates()->list(); $contact = BizwaChat::contacts()->find(15);
Full API surface
The manager exposes the following resource clients:
contacts()statuses()sources()groups()templates()templateBots()messageBots()messages()request()/raw()for custom endpoints
Message builders
Simple message
use BizwaChat\LaravelNotification\Facades\BizwaChat; BizwaChat::send( BizwaChat::simple('Order confirmed')->to('+15550001111') );
Template message
use BizwaChat\LaravelNotification\Facades\BizwaChat; BizwaChat::send( BizwaChat::template('order_confirmation', 'en') ->to('+15550001111') ->headerTextParameter('John') ->fields(['#1001', 'Confirmed']) ->button(0, 'https://example.com/orders/1001') );
Template message from a saved whatsapp_templates record
If your saved template record looks like this:
template_name:bizcrmapp_marketinglanguage:enheader_data_format:IMAGEheader_params_count:0body_params_count:0footer_data:bizcrmapp.combuttons_data: two static URL buttonsheader_file_url: the WhatsApp-hosted image URL
then the package usage should stay minimal because this template has no dynamic body fields and no dynamic button variables:
use BizwaChat\LaravelNotification\Facades\BizwaChat; BizwaChat::send( BizwaChat::template('bizcrmapp_marketing', 'en') ->to('+15550001111') ->headerImageUrl('https://scontent.whatsapp.net/v/t61.29466-34/555348183_1147308740158118_3156578834425398790_n.png?ccb=1-7&_nc_sid=8b1bef&_nc_ohc=bEQ-iApmfAAQ7kNvwHNG2gs&_nc_oc=AdqyBrCfIsIRnQQEAdNFeTZnZX5ro84xEDQF8wK3Ao6nzqrWOrNRDhke9V96cCXRmF4&_nc_zt=3&_nc_ht=scontent.whatsapp.net&edm=AH51TzQEAAAA&_nc_gid=KYRZ6mVxGzG2iXeRPvCb9Q&_nc_tpa=Q5bMBQHuEc1BU6sBiuF3ezRGuATYAzfFNK2ZpjjSvrsp5Qju4iwUeAIr3Z0e3wXC2tJFIP9qJ6U7yfyCRA&oh=01_Q5Aa4gFzD2Izp0vef3Jdk2jnLMeeClkMqOGGLcSq-oQ9STochQ&oe=6A2B8042') );
The request payload generated by the package is:
{
"phone_number": "+15550001111",
"template_name": "bizcrmapp_marketing",
"template_language": "en",
"header_image_url": "https://scontent.whatsapp.net/v/t61.29466-34/555348183_1147308740158118_3156578834425398790_n.png?ccb=1-7&_nc_sid=8b1bef&_nc_ohc=bEQ-iApmfAAQ7kNvwHNG2gs&_nc_oc=AdqyBrCfIsIRnQQEAdNFeTZnZX5ro84xEDQF8wK3Ao6nzqrWOrNRDhke9V96cCXRmF4&_nc_zt=3&_nc_ht=scontent.whatsapp.net&edm=AH51TzQEAAAA&_nc_gid=KYRZ6mVxGzG2iXeRPvCb9Q&_nc_tpa=Q5bMBQHuEc1BU6sBiuF3ezRGuATYAzfFNK2ZpjjSvrsp5Qju4iwUeAIr3Z0e3wXC2tJFIP9qJ6U7yfyCRA&oh=01_Q5Aa4gFzD2Izp0vef3Jdk2jnLMeeClkMqOGGLcSq-oQ9STochQ&oe=6A2B8042"
}
Important mapping rules for templates like this:
header_data_format = IMAGEmeans you sendheader_image_urlorheader_image_file.body_params_count = 0means you do not send anyfield_1,field_2, or other body parameters.- Static URL buttons from
buttons_datastay inside the approved WhatsApp template, so you do not sendbutton_0orbutton_1unless the button itself contains a dynamic variable. footer_datais already part of the approved template, so it is not sent again in the API payload.
Template message with image header and one body variable
If the saved template record looks like this:
template_name:campaign_launch_bizcrmwalanguage:enheader_data_format:IMAGEheader_params_count:0body_params_count:1buttons_data: one static URL buttonbody_variable_value:[["Bhavik"]]
then the package call is:
use BizwaChat\LaravelNotification\Facades\BizwaChat; BizwaChat::send( BizwaChat::template('campaign_launch_bizcrmwa', 'en') ->to('+15550001111') ->headerImageUrl('https://scontent.whatsapp.net/v/t61.29466-34/417302034_550415017882935_4035659379883741642_n.png?ccb=1-7&_nc_sid=8b1bef&_nc_ohc=voABktHdO20Q7kNvwHRduyz&_nc_oc=Adqx5gokS4hjKiw1soHtgMPfagoTkOvkAsmbljMbYwtMyORJgCuCmzzPpHcln_k8ATY&_nc_zt=3&_nc_ht=scontent.whatsapp.net&edm=AH51TzQEAAAA&_nc_gid=KYRZ6mVxGzG2iXeRPvCb9Q&_nc_tpa=Q5bMBQFi_9cKw0mNZ6x77kSqgK6TNPDBqQDriF1Wyihl_h9G_tCqKj8IGv1tZHPtSB2GrJsplXkKk4zGiQ&oh=01_Q5Aa4gGEwCYaYevvzzX05ccPzbT4ytR8O4_JaJUArnWXIX1rYQ&oe=6A2B6D7C') ->field(1, 'Bhavik') );
The payload generated by the package is:
{
"phone_number": "+15550001111",
"template_name": "campaign_launch_bizcrmwa",
"template_language": "en",
"header_image_url": "https://scontent.whatsapp.net/v/t61.29466-34/417302034_550415017882935_4035659379883741642_n.png?ccb=1-7&_nc_sid=8b1bef&_nc_ohc=voABktHdO20Q7kNvwHRduyz&_nc_oc=Adqx5gokS4hjKiw1soHtgMPfagoTkOvkAsmbljMbYwtMyORJgCuCmzzPpHcln_k8ATY&_nc_zt=3&_nc_ht=scontent.whatsapp.net&edm=AH51TzQEAAAA&_nc_gid=KYRZ6mVxGzG2iXeRPvCb9Q&_nc_tpa=Q5bMBQFi_9cKw0mNZ6x77kSqgK6TNPDBqQDriF1Wyihl_h9G_tCqKj8IGv1tZHPtSB2GrJsplXkKk4zGiQ&oh=01_Q5Aa4gGEwCYaYevvzzX05ccPzbT4ytR8O4_JaJUArnWXIX1rYQ&oe=6A2B6D7C",
"field_1": "Bhavik"
}
Mapping rules for this case:
body_params_count = 1means send exactly one body placeholder asfield_1.- The static website button from
buttons_datais already part of the approved template, so there is still nobutton_0in the request payload. - The footer text is part of the template approval record and is not sent again.
Utility template with static text header and five body variables
If the saved template record looks like this:
template_name:bizcrm_subscription_orderlanguage:en_UScategory:UTILITYheader_data_format:TEXTheader_data_text:Assistance with Your BizCRM WhatsApp Setupheader_params_count:0body_params_count:5buttons_data: one staticPHONE_NUMBERbuttonbody_variable_value:[["Bhavik","successfully","Starter","Monthly","Dec 10, 2024"]]
then the package call is:
use BizwaChat\LaravelNotification\Facades\BizwaChat; BizwaChat::send( BizwaChat::template('bizcrm_subscription_order', 'en_US') ->to('+15550001111') ->fields([ 'Bhavik', 'successfully', 'Starter', 'Monthly', 'Dec 10, 2024', ]) );
The payload generated by the package is:
{
"phone_number": "+15550001111",
"template_name": "bizcrm_subscription_order",
"template_language": "en_US",
"field_1": "Bhavik",
"field_2": "successfully",
"field_3": "Starter",
"field_4": "Monthly",
"field_5": "Dec 10, 2024"
}
Mapping rules for this case:
header_data_format = TEXTwithheader_params_count = 0means the header text is already fixed in the approved template, so you do not sendheader_field_1.body_params_count = 5means send exactlyfield_1throughfield_5.- The
PHONE_NUMBERbutton is static, so you do not send anybutton_0value. - The footer text is part of the approved template and is not sent again.
Document header template with a dynamic URL button variable
For a document-header template with these characteristics:
template_name:invoice_share_with_portallanguage:enheader_data_format:DOCUMENTheader_params_count:0body_params_count:2buttons_data: one dynamicURLbutton likehttps://portal.example.com/invoices/{{1}}
the package call is:
use BizwaChat\LaravelNotification\Facades\BizwaChat; BizwaChat::send( BizwaChat::template('invoice_share_with_portal', 'en') ->to('+15550001111') ->headerDocumentUrl('https://cdn.example.com/invoices/INV-1001.pdf', 'Invoice_INV-1001.pdf') ->fields([ 'Bhavik', 'INV-1001', ]) ->button(0, 'INV-1001') );
The payload generated by the package is:
{
"phone_number": "+15550001111",
"template_name": "invoice_share_with_portal",
"template_language": "en",
"header_document_url": "https://cdn.example.com/invoices/INV-1001.pdf",
"header_document_name": "Invoice_INV-1001.pdf",
"field_1": "Bhavik",
"field_2": "INV-1001",
"button_0": "INV-1001"
}
Mapping rules for this case:
header_data_format = DOCUMENTmeans sendheader_document_urlorheader_document_file.header_document_nameis optional but useful for display when the header is a document.body_params_count = 2means sendfield_1andfield_2.- A dynamic URL button variable becomes
button_0,button_1, and so on, based on the button index in the approved template.
Media message
use BizwaChat\LaravelNotification\Messages\MediaMessage; BizwaChat::send( MediaMessage::image('https://cdn.example.com/product.jpg') ->to('+15550001111') ->caption('Latest catalog') );
Logging and exceptions
- Every transport, route-resolution, dispatch, and notification catch block writes a structured log entry.
- Set
BIZWACHAT_LOG_CHANNELto a dedicated channel if you want package-specific log routing. - Leave
BIZWACHAT_THROW_EXCEPTIONS=truefor fail-fast behavior. - Set
BIZWACHAT_THROW_EXCEPTIONS=falseto receive failedApiResponseobjects instead of thrown exceptions.