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!

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 = "test@gmail.com";
            // 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
    Nov 30 '18 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 Oct 28 '20 at 14:34
  • It's typo. I updated answer. Oct 28 '20 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.

0

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

0
  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;?>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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