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!
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;
}
}
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
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.
<?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>
<?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;
}
}
}
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();
)
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;?>