Skip to content

How to customize PDF of Invoice Notification

Bruno Ferreira edited this page Feb 21, 2025 · 2 revisions

For this implementation, you will need to learn how to create a custom notification for your use case.

Please, refer to this link: How to create a notification by yourself.

After that, you will have the expertise to customize the invoice PDF or any other PDF/Document sent in the notification.

Customizing PDF

  1. Create a method to generate and modify the PDF:
public static function getInvoicePdfUrlByInvocieId(int $id, bool $returnNullOtherwise = false): ?string
{
    require_once __DIR__ . '/../../../../../../../includes/invoicefunctions.php';

    // 1. Generate the invoice PDF using WHMCS built-in function.
    $whmcsInvoicePdf = pdfInvoice($id);


    $randonPrefix = (string) (random_int(0, 100000));
    $randomFileName = uniqid($randonPrefix, true) . '.pdf';

    $pdfPath = __DIR__ . "/../../../resources/temp/invoices_pdf/$randomFileName";

    // 2. Save the WHMCS-generated PDF to be able to edit it after.
    $wasInvoicePdfSaved = file_put_contents($pdfPath, $whmcsInvoicePdf);

    if (!$wasInvoicePdfSaved) {
        throw new Exception('Could not create invoice PDF: ' . $wasInvoicePdfSaved);
    }

    // 3. Use fpdi to edit the PDF.

    /**
    * @see https://manuals.setasign.com/fpdi-manual/v1/the-fpdi-class/examples/
    */
    $pdfEditorInstance = new Fpdi();

    $pageCount = $pdfEditorInstance->setSourceFile($pdfPath);

    for ($i = 1; $i <= $pageCount; $i++) {
        $tplId = $pdfEditorInstance->importPage($i);

        $pdfEditorInstance->AddPage();
        $pdfEditorInstance->useTemplate($tplId);
    }

    // 4. Insert a new page at the end of the PDF.

    $pdfEditorInstance->setSourceFile($pdfPath);
    $pdfEditorInstance->AddPage();
    $pdfEditorInstance->SetFont('Helvetica', '', 12);
    $pdfEditorInstance->SetXY(12, 12);

    // 4.1 Insert any text. At the pointm you can use Capsule::table() to retrieve data from the Database
    // and insert in the PDF.

    $textToAdd = 'Pix Copia e Cola!!!';

    $pdfEditorInstance->Cell(0, 10, $textToAdd);

    $pdfEditorInstance->Output('F', $pdfPath);

    $invoicePdfUrl = Link::moduleUrl() . "/src/resources/temp/invoices_pdf/$randomFileName";

    return $invoicePdfUrl;
}
  1. In the defineParameters method, add a new parameter that uses the method you just created:
public function defineParameters(): void
{
    $this->parameters = [
        'invoice_pdf_url' => [
            'label' => $this->lang['invoice_pdf_url'],
            'parser' => fn () => self::getInvoicePdfUrlByInvocieId($this->hookParams['invoiceId'])
        ],
    ];
}

Full Code Example

For example, to add a Boleto/Pix code at the PDF, you just need to overwrite the method getInvoicePdfUrlByInvocieId in the notification class. This method is used by the module to create the PDF of the invoice to be sent to the client.

// ...

use setasign\Fpdi\Fpdi;

final class InvoiceReminderPdfNotification extends AbstractWhatsAppNotifcation
{
    public string $notificationCode = 'InvoiceReminderPdf';

    public function run(): bool
    {
        // ...
    }

    public static function getInvoicePdfUrlByInvocieId(int $id, bool $returnNullOtherwise = false): ?string
    {
        require_once __DIR__ . '/../../../../../../../includes/invoicefunctions.php';

        // 1. Generate the invoice PDF using WHMCS built-in function.
        $whmcsInvoicePdf = pdfInvoice($id);


        $randonPrefix = (string) (random_int(0, 100000));
        $randomFileName = uniqid($randonPrefix, true) . '.pdf';

        $pdfPath = __DIR__ . "/../../../resources/temp/invoices_pdf/$randomFileName";

        // 2. Save the WHMCS-generated PDF to be able to edit it after.
        $wasInvoicePdfSaved = file_put_contents($pdfPath, $whmcsInvoicePdf);

        if (!$wasInvoicePdfSaved) {
            throw new Exception('Could not create invoice PDF: ' . $wasInvoicePdfSaved);
        }

        // 3. Use fpdi to edit the PDF.

        /**
         * @see https://manuals.setasign.com/fpdi-manual/v1/the-fpdi-class/examples/
         */
        $pdfEditorInstance = new Fpdi();

        $pageCount = $pdfEditorInstance->setSourceFile($pdfPath);

        for ($i = 1; $i <= $pageCount; $i++) {
            $tplId = $pdfEditorInstance->importPage($i);

            $pdfEditorInstance->AddPage();
            $pdfEditorInstance->useTemplate($tplId);
        }

        // 4. Insert a new page at the end of the PDF.

        $pdfEditorInstance->setSourceFile($pdfPath);
        $pdfEditorInstance->AddPage();
        $pdfEditorInstance->SetFont('Helvetica', '', 12);
        $pdfEditorInstance->SetXY(12, 12);

        // 4.1 Insert any text. At the pointm you can use Capsule::table() to retrieve data from the Database
        // and insert in the PDF.

        $textToAdd = 'Pix Copia e Cola!!!';

        $pdfEditorInstance->Cell(0, 10, $textToAdd);

        $pdfEditorInstance->Output('F', $pdfPath);

        $invoicePdfUrl = Link::moduleUrl() . "/src/resources/temp/invoices_pdf/$randomFileName";

        return $invoicePdfUrl;
    }

    public function defineParameters(): void
    {
        $this->parameters = [
            'invoice_pdf_url' => [
                'label' => $this->lang['invoice_pdf_url'],
                'parser' => fn () => self::getInvoicePdfUrlByInvocieId($this->hookParams['invoiceId'])
            ],
        ];
    }
}

Clone this wiki locally