4

I'm currently creating a module which should send the invoice pdf via eMail to a customer.

How can I get the invoice pdf programatically?

Thanks for any help!

4 Answers 4

3

Create Sendmail.php file at app/code/CompanyName/ModuleName/Controller/Index and write the following code in it.

namespace CompanyName\ModuleName\Controller\Index;
 
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\Translate\Inline\StateInterface;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\Action\Action;
use Magento\Store\Model\Store;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\App\Filesystem\DirectoryList;
 
class Sendmail extends Action
{
    const XML_PATH_EMAIL_ADMIN_QUOTE_SENDER = 'emailcustom/general/sender';
    const XML_PATH_EMAIL_ADMIN_QUOTE_NOTIFICATION = 'emailcustom/general/template';
    const XML_PATH_EMAIL_ADMIN_EMAIL = 'emailcustom/general/reciver';
    

    protected $  scopeConfig;
    protected $_modelStoreManagerInterface;
    protected $  inlineTranslation;
    protected $_logLoggerInterface;
    protected $_transportBuilder;
    protected $_mediaDirectory;
    
    public function __construct(
        Context $context,
        StoreManagerInterface $modelStoreManagerInterface,
        ScopeConfigInterface $configScopeConfigInterface,
        StateInterface $inlineTranslation,
        LoggerInterface $logLoggerInterface,
        \Magento\Framework\Mail\Template\TransportBuilder $quoteTransportBuilder,
        \Magento\Framework\Filesystem $filesystem
    )
    {
        $this->scopeConfig = $configScopeConfigInterface;
        $this->_modelStoreManagerInterface = $modelStoreManagerInterface;
        $this->inlineTranslation = $inlineTranslation;
        $this->_logLoggerInterface = $logLoggerInterface;
        $this->_transportBuilder = $quoteTransportBuilder;
        $this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
        parent::__construct($context);
    }
    public function execute()
    {
        try
        {
            $customerName = " Customer Name  : Test";
            $email = "[email protected]";
            // Send Mail To Admin For This
            $pdfContent = $this->createPdf($customerName,$email);
                        
            $this->inlineTranslation->suspend();
            $storeScope = ScopeInterface::SCOPE_STORE;
            $transport = $this->_transportBuilder
                     ->setTemplateIdentifier($this->scopeConfig->getValue(self::XML_PATH_EMAIL_ADMIN_QUOTE_NOTIFICATION, $storeScope))
                     ->setTemplateOptions(['area' => 'frontend','store' => Store::DEFAULT_STORE_ID,])
                     ->setTemplateVars(['customerName'  => $customerName,'customerEmail'  => $email,])
                     ->setFrom($this->scopeConfig->getValue(self::XML_PATH_EMAIL_ADMIN_QUOTE_SENDER, $storeScope))
                     ->addTo($this->scopeConfig->getValue(self::XML_PATH_EMAIL_ADMIN_EMAIL, $storeScope))
                     ->addAttachment($pdfContent)
                     ->getTransport();

            $transport->sendMessage();
            $this->inlineTranslation->resume();
 
            $response = "success";            
            $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
            $resultJson->setData($response);
            return $resultJson;
        }
        catch(\Exception $e)
        {
            $this->_logLoggerInterface->debug($e->getMessage());
                                                
            $response = "error";  
            $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON);
            $resultJson->setData($response);
            return $resultJson; 
        }
    }
    public function getLogo($page)
    {
        $image = $this->scopeConfig->getValue('sales/identity/logo',\Magento\Store\Model\ScopeInterface::SCOPE_STORE,$this->_modelStoreManagerInterface->getStore()->getId());
                
        $imagePath = '/sales/store/logo/' . $image;
         
        if($this->_mediaDirectory->isFile($imagePath))
        {
            $image = \Zend_Pdf_Image::imageWithPath($this->_mediaDirectory->getAbsolutePath($imagePath));
            $top = 830;
            $width = $image->getPixelWidth();
            $height = $image->getPixelHeight();
            $y1 = $top - $height;
            $y2 = $top;
            $x1 = 25;
            $x2 = $x1 + $width;
            $page->drawImage($image, $x1, $y1, $x2, $y2);
        }
        return $page;
    }
    public function createPdf( $customername,$customeremail)
    {
        $pdf = new \Zend_Pdf(); //Create new PDF file
        $page = $pdf->newPage(\Zend_Pdf_Page::SIZE_A4);
        $pdf->pages[] = $page;
        $top = 810;
        $left = 50;
        $page->setFont(\Zend_Pdf_Font::fontWithName(\Zend_Pdf_Font::FONT_HELVETICA), 20);  //Set Font
        $page->drawText("Heading", $left+200, $top-110,'UTF-8');

        $page->setFont(\Zend_Pdf_Font::fontWithName(\Zend_Pdf_Font::FONT_HELVETICA), 14);  //Set Font
        $page->drawText("Customer Name : ".$customername, $left, $top-140,'UTF-8');
        $page->drawText("Customer Email : ".$customeremail, $left, $top-165,'UTF-8');
        
        $topstart = 500;
        $leftStart = 70;
        $addHeight = 25;
        $this->getLogo($page);
        $page->drawLine(25, $topstart+70, 550, $topstart+70);       
                                                                                                                                                                    
        $page->drawLine(25, $topstart-100, 550, $topstart-100);
        $page->drawText("Thank you" , 250, $topstart-120,'UTF-8');            
        $page->drawLine(25, $topstart-130, 550, $topstart-130);
        $page->setFillColor(new \Zend_Pdf_Color_RGB(0.1, 0.1, 0.1));
        $page->setFont(\Zend_Pdf_Font::fontWithName(\Zend_Pdf_Font::FONT_HELVETICA), 9);
        
        $footer = 10;
        $page->drawText("Company Name", 70, $footer, 'UTF-8');
        $page->drawText("Tel: +91 123456", 230, $footer, 'UTF-8');

        $pdfData = $pdf->render(); // Get PDF document as a string
        
        header("Content-Disposition: inline; filename=pdfresult.pdf");
        
        header("Content-type: application/x-pdf");
        return $pdfData;
    }
}

Then, You need to create another file at app/code/CompanyName/ModuleName/Model/Mail and add below code inside the file.

namespace CompanyName\ModuleName\Model\Mail;
 
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
    /**
    * @param Api\AttachmentInterface $attachment
    */
    public function addAttachment($pdfString)
    {
        $this->message->createAttachment($pdfString,'application/pdf',\Zend_Mime::DISPOSITION_ATTACHMENT,\Zend_Mime::ENCODING_BASE64,'attachment.pdf');
        return $this;
    }
    
    public function clearHeader($headerName)
    {
        if (isset($this->_headers[$headerName])) {
            unset($this->_headers[$headerName]);
        }
        return $this;
    }
}
3
  • Hi, @Rohan How can I test it.. i used this but no output..
    – Ajwad Syed
    Commented Nov 30, 2018 at 10:45
  • Hi, @Rohan Hapani. In your Sendmail.php you are using `Magecomp\Emailquotepro\Model\Mail\TransportBuilder $quoteTransportBuilder`. This seems to be 3rd party code, do I really need this here? Thx
    – Th. Schott
    Commented Oct 28, 2020 at 14:34
  • It's typo. I updated answer. Commented Oct 28, 2020 at 14:43
3

Easy Way

There are already extensions for this.

FREE - Fooman Email Attachments https://store.fooman.co.nz/magento-extension-email-attachments-m2.html

PAID - Magento 2 PDF Invoice by Mageplaza https://www.mageplaza.com/magento-2-pdf-invoice-extension/?utm_source=mageplaza&utm_medium=banner&utm_campaign=print-pdf-invoice

Hard Way

If you want to to do it programmatically then i recommend checking the below links

https://webkul.com/blog/generate-pdf-programmatically-magento2/

Magento2: How to create a PDF in a custom module

Hope i helped. Good luck.

1
  1. Create your module Vendor_Module
  2. Create route app/code/Vendor/Module/etc/frontend/routes.xml
    <?xml version="1.0" ?>
    
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
        <router id="standard">
            <route id="myroute" frontName="myroute">
                <module name="Vendor_Module"/>
            </route>
        </router>
    </config>
  1. Create front controller app/code/Vendor/Module/Controller/Getpdf/Invoice.php
<?php
declare(strict_types=1);

namespace Vendor\Module\Controller\Getpdf;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\Response\RedirectInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Controller\ResultFactory;
use Magento\Sales\Model\Order\Pdf\Invoice as PdfInvoice;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\App\Response\Http\FileFactory;
use Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory;
use Magento\Framework\Message\ManagerInterface;


class Invoice implements HttpGetActionInterface
{
    const SELECTED_PARAM = 'id';

    protected FileFactory $fileFactory;
    protected DateTime $dateTime;
    protected PdfInvoice $pdfInvoice;
    protected RequestInterface $request;
    protected RedirectInterface $redirect;
    protected ManagerInterface $messageManager;
    protected ResultFactory $resultFactory;
    protected CollectionFactory $collectionFactory;

    /**
     * @param DateTime $dateTime
     * @param FileFactory $fileFactory
     * @param PdfInvoice $pdfInvoice
     * @param CollectionFactory $collectionFactory
     * @param RequestInterface $request
     * @param RedirectInterface $redirect
     * @param ManagerInterface $messageManager
     * @param ResultFactory $resultFactory
     */
    public function __construct(
        DateTime          $dateTime,
        FileFactory       $fileFactory,
        PdfInvoice        $pdfInvoice,
        CollectionFactory $collectionFactory,
        RequestInterface  $request,
        RedirectInterface $redirect,
        ManagerInterface $messageManager,
        ResultFactory $resultFactory
    )
    {
        $this->fileFactory = $fileFactory;
        $this->dateTime = $dateTime;
        $this->pdfInvoice = $pdfInvoice;
        $this->request = $request;
        $this->redirect = $redirect;
        $this->messageManager = $messageManager;
        $this->resultFactory = $resultFactory;
        $this->collectionFactory = $collectionFactory;
    }

    /**
     * @return ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        try {
            $collection = $this->collectionFactory->create();

            $invoiceId = $this->request->getParam(self::SELECTED_PARAM);
            $filterIds = $invoiceId ? [$invoiceId] : [];
            $collection->addFieldToFilter(
                $collection->getResource()->getIdFieldName(),
                ['in' => $filterIds]
            );

            $pdf = $this->pdfInvoice->getPdf($collection);
            $fileContent = ['type' => 'string', 'value' => $pdf->render(), 'rm' => true];

            return $this->fileFactory->create(
                sprintf('invoice%s.pdf', $this->dateTime->date('Y-m-d_H-i-s')),
                $fileContent,
                DirectoryList::VAR_DIR,
                'application/pdf'
            );
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage($e->getMessage());            
            $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
            $resultRedirect->setUrl($this->redirect->getRefererUrl());
            return $resultRedirect;
        }
    }
}
  1. Now you are ready to use this controller. Just create a link and put there href with a path to our controller (In some cases it is a good idea to use Magento\Sales\Block\Order\Info as a class to your block for getting order like $order = $block->getOrder();)

  2. Having an order information you can get invoices in your .phtml file

<?php foreach ($order->getInvoiceCollection() as $invoice):?>
    <a href="<?= $block->getUrl('myroute/getpdf/invoice', ['id' => $invoice->getId()]);?>"><?php echo $this->escapeHtml(__('Invoice (PDF)')); ?></a>
<?php endforeach;?>
0

Just found this link, it works great Free Extension to download Invoice PDF

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.