-
Notifications
You must be signed in to change notification settings - Fork 6
How to create a notification by yourself
This repository uses VS Code Dev Container extension for its development process.
Also, you can access the technical documentation of the module to familiarize with the classes, methods and functions provided: Technical Documentation
Recommended readings:
-
Start by cloning this repository onto your local machine.
-
Before proceeding, ensure that Docker is installed on your system. If you don't have Docker installed, you can download it from here.
If you are using Windows, it is recommended to install WSL for Docker Desktop. Detailed instructions for installation can be found here.
-
The repository employs an FTP extension that automatically uploads files to WHMCS upon saving. You will find a file named
.vscode/sftp.example.json
within the repository. Rename this file tosftp.json
and put your FPT credentials there.For more information on using this extension, refer to the documentation available here.
-
Next, install the necessary Dev Container extensions in your VSCode. You can find these extensions in the Visual Studio Code Marketplace here.
And for WSL.
-
Open the command palette in VSCode by pressing CTRL + Shift + P. Type "Reopen in Container" and select it from the options that appear, then press Enter.
By following these steps, you will have successfully set up the development environment.
To familiarize yourself with the process of creating a notification, you can open one of the existing notification folders in the repository and explore its structure and components. Access notifications.
Furthermore, the repository includes the stubs.php
file, which not only provides information about the available classes and methods of the module but also enables VSCode to display method and class previews as you type.
Additionally, you can access the documentation of the available classes and methods here.
If you intend to contribute your own notification to this repository, you can make and push your commits to the dev
branch and then initiate a pull request from the dev
branch to the main
branch.
We will be using a notification that runs when a order is created in WHMCS:
<?php
/**
* Code: OrderCreated
*/
namespace Lkn\HookNotification\Notifications\WhatsApp\OrderCreated;
use Lkn\HookNotification\Config\Hooks;
use Lkn\HookNotification\Config\ReportCategory;
use Lkn\HookNotification\Domains\Platforms\WhatsApp\AbstractWhatsAppNotifcation;
use Lkn\HookNotification\Helpers\Logger;
final class OrderCreatedNotification extends AbstractWhatsAppNotifcation
{
public string $notificationCode = 'OrderCreated';
public Hooks|array|null $hook = Hooks::AFTER_SHOPPING_CART_CHECKOUT;
public function run(): bool
{
$orderId = $this->hookParams['OrderID'];
// Setup properties for reporting purposes (not required).
$this->setReportCategory(ReportCategory::ORDER);
$this->setReportCategoryId($orderId);
// Setup client ID for getting its WhatsApp number (required).
$clientId = $this->getClientIdByInvoiceId($this->hookParams['InvoiceID']);
$this->setClientId($clientId);
$fraudCheckResponse = localAPI('OrderFraudCheck', ['orderid' => $orderId]);
if (isset($fraudCheckResponse['status']) && $fraudCheckResponse['status'] === 'Fail') {
Logger::log(
$this->getNotificationLogName(),
[
'msg' => 'Abort for order was identified as fraud',
'instance' => $this
],
['fraud_check' => $fraudCheckResponse]
);
return false;
}
// Send the message and get the raw response (converted to array) from WhatsApp API.
$response = $this->sendMessage();
// Defines if response tells if the message was sent successfully.
$success = isset($response['messages'][0]['id']);
return $success;
}
public function defineParameters(): void
{
$this->parameters = [
'order_id' => [
'label' => $this->lang['order_id'],
'parser' => fn () => $this->hookParams['OrderID'],
],
'order_items_descrip' => [
'label' => $this->lang['order_items_descrip'],
'parser' => fn () => self::getOrderItemsDescripByOrderId($this->hookParams['OrderID'])
],
'client_first_name' => [
'label' => $this->lang['client_first_name'],
'parser' => fn () => $this->getClientFirstNameByClientId($this->clientId),
],
'client_full_name' => [
'label' => $this->lang['client_full_name'],
'parser' => fn () => $this->getClientFullNameByClientId($this->clientId),
]
];
}
}
- Note that the notification must have docblock on the top of the file in the format "Code: {NotificationName}":
<?php
/**
* Code: OrderCreated
*/
- Then, the notifications extends from
AbstractWhatsAppNotifcation
and must set these two properties$notificationCode
and$hook
as defined in step 1:
final class OrderCreatedNotification extends AbstractWhatsAppNotifcation
{
public string $notificationCode = 'OrderCreated';
public Hooks|array|null $hook = Hooks::AFTER_SHOPPING_CART_CHECKOUT;
-
AbstractWhatsAppNotification
provides specific methods and properties for a WhatsApp notification. Access AbstractWhatsAppNotification docs. -
$hooks
is one of WHMCS hooks by which the notification must be executed. A notification can be run on different hooks:
public Hooks|array|null $hook = [Hooks::CANCEL_ORDER, Hooks::CANCEL_AND_REFUND_ORDER];
-
$notificationCode
is the identifier of this notification, must be unique and must have the same name as the notification folder.
- Then, the notification implements the required
run
method.
public function run(): bool
{
$orderId = $this->hookParams['OrderID'];
// Setup properties for reporting purposes (not required).
$this->setReportCategory(ReportCategory::ORDER);
$this->setReportCategoryId($orderId);
// Setup client ID for getting its WhatsApp number (required).
$clientId = $this->getClientIdByInvoiceId($this->hookParams['InvoiceID']);
$this->setClientId($clientId);
$fraudCheckResponse = localAPI('OrderFraudCheck', ['orderid' => $orderId]);
// Only sends the notification for order that has passed the fraud check.
if (isset($fraudCheckResponse['status']) && $fraudCheckResponse['status'] === 'Fail') {
Logger::log(
$this->getNotificationLogName(),
[
'msg' => 'Abort for order was identified as fraud',
'instance' => $this
],
['fraud_check' => $fraudCheckResponse]
);
return false;
}
// Send the message and get the raw response (converted to array) from WhatsApp API.
$response = $this->sendMessage();
// Defines if response tells if the message was sent successfully.
$success = isset($response['messages'][0]['id']);
return $success;
}
The run
method:
- Should set report properties that will help keeping relatories of sent notifications.
- Should set the client ID that owns the order.
- Can perform specific conditions like if the order passed the fraud check in order to send or not the message.
- Can call the
$this->sendMessage()
that automatically fetches the client WhatsApp number and sends the notification. - Must determine if the notification was received by the WhatsApp API and return
true
orfalse
properly.
Note that the $this->hookParams
property holds the hook parameters passed by WHMCS to the notification. In this example, the hook parameters are the ones of the WHMCS hook AfterShoppingCartCheckout as defined in the $hook
property.
- After that, you should set the parameters that the notification will support using the
defineParameters
method.
For a WhatsApp notification, the term "parameter" refers to the specific values you want to substitute for the placeholder keys {{1}}
, {{2}}
that made when you created the message template, and so on. These parameters are dynamic pieces of information that personalize the notification content when it's sent to different recipients.
Ensure your notification follows the structure below of the parameters array.
public function defineParameters(): void
{
$this->parameters = [
'order_id' => [
'label' => $this->lang['order_id'],
'parser' => fn () => $this->hookParams['OrderID'],
],
'order_items_descrip' => [
'label' => $this->lang['order_items_descrip'],
'parser' => fn () => self::getOrderItemsDescripByOrderId($this->hookParams['OrderID'])
],
'client_first_name' => [
'label' => $this->lang['client_first_name'],
'parser' => fn () => $this->getClientFirstNameByClientId($this->clientId),
],
'client_full_name' => [
'label' => $this->lang['client_full_name'],
'parser' => fn () => $this->getClientFullNameByClientId($this->clientId),
]
];
}
AbstractWhatsAppNotifcation
uses the NotificationParamParseTrait
for getting the parameters values later.
Observe that the paramters follow a structure of the label
and the parser
that gets the values for the notification.
If this trait does not have the method you need, you can simply implement one in the notification itself:
// Add the new parameter to the defineParameters method:
public function defineParameters(): void
{
$this->parameters = [
// Other parameters...
'order_date' => [
'label' => $this->lang['order_date'],
'parser' => fn () => $this->getOrderDate($this->hookParams['OrderID']),
]
];
}
// Create the parser for order_date parameter.
/**
* @param int $orderId
*
* @return string
*/
private function getOrderDate(int $orderId): string {
// Use WHMCS Capsule to interact with the database: https://developers.whmcs.com/advanced/db-interaction/#the-query-manager
return Capsule::table('tblorders')->where('id', $orderId)->value('date');
}
The labels of the parameters will appear in the notification setup page as show below.
- Finally, inside each notification folder, there is a
hooks.php
with the code responsible for registering the notification in the module:
<?php
use Lkn\HookNotification\Domains\Notifications\Messenger;
use Lkn\HookNotification\Notifications\WhatsApp\OrderCreated\OrderCreatedNotification;
Messenger::run(OrderCreatedNotification::class);
You should use the Messenger class in order to the notification work properly when active.
- Now, to activate the notification, go to the module settings page and access the page below to setup the notification with a message template from WhatsApp.
Then, searh for "Order created" and click on activate:
And configure the notification:
If you wish to test this notification, access the client area and finish a checkout of a service.
Notification on this repository will support English, Portuguese (BR) and Portuguse (PT).
Inside each notification folder, there is a lang
folder that holds the translations for the notification title, description and parameters:
A language file structure:
<?php
$lang['notification_title'] = 'Order created';
$lang['notification_description'] = 'Runs when the client completes a checkout and the order is created.';
// Parameters labels
$lang['order_id'] = 'Order ID';
$lang['order_items_descrip'] = 'Order items';
$lang['client_first_name'] = 'Client first name';
$lang['client_full_name'] = 'Client full name';
return $lang;
The only translation required if for notification_title
. If it is not provided, the notification won't show proproperly on the list.
For notifications parameters, their labels are called in the defineParameters
method using the $this-lang
property that automatically loads the language file according to the Language setting.
public function defineParameters(): void
{
$this->parameters = [
'order_id' => [
'label' => $this->lang['order_id'],
'parser' => ...,
],
'order_items_descrip' => [
'label' => $this->lang['order_items_descrip'],
'parser' => ...
],
'client_first_name' => [
'label' => $this->lang['client_first_name'],
'parser' => ...,
],
'client_full_name' => [
'label' => $this->lang['client_full_name'],
'parser' => ...,
]
];
}
If you use the module only in english, you can simply create the english.php
and provide the necessary translation.
If you need more examples on use cases for notifications, please refer to the OrderPendingFor3DaysNotification.
This is a notification that runs on the DailyCronJob hook and send a message to clients that have an pending order for three days.
Manual notifications are triggered by an admin and have a visual output like the InvoiceReminderPdfNotification.
If you wish to make a notification like this, please expore the InvoiceReminderNotification folder and the files located in this folder that handles the display of the button: /modules/addons/lknhooknotification/src/resources/notifications/hooks/AdminInvoicesControlsOutput
.
By default, the module automatically save reports about the notifications that are sent and triggers some events like sending a private note to Chatwoot.
In the run()
method of you notification, you need to provide the client id and the report category as follow:
$this->setReportCategory(ReportCategory::INVOICE);
$this->setReportCategoryId($this->hookParams['invoiceid']);
Also, in the run()
method, you need to find out the client ID, considering your context:
$clientId = $this->getClientIdByInvoiceId($this->hookParams['invoiceid']);
$this->setClientId($clientId);
if (!$this->mustRun()) {
$this->events = [];
$this->enableAutoReport = false;
return false;
}
If you have any report to give, please open an issue or contact us at ticket@linknacional.com.