Skip to content

Commit

Permalink
Merge pull request #158 from omise/tesco-email-code
Browse files Browse the repository at this point in the history
Send Tesco barcode to customer's email
  • Loading branch information
jacstn committed Nov 21, 2018
2 parents b28d7b0 + 536fc18 commit 6037c94
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 23 deletions.
17 changes: 6 additions & 11 deletions Block/Checkout/Onepage/Success/TescoAdditionalInformation.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,13 @@ protected function _toHtml()
if (!isset($paymentData['additional_information']['payment_type']) || $paymentData['additional_information']['payment_type'] !== 'bill_payment_tesco_lotus') {
return;
}
$tescoCodeImageUrl = $paymentData['additional_information']['barcode'];
$orderCurrency = $this->_checkoutSession->getLastRealOrder()->getOrderCurrency()->getCurrencyCode();

if ($tescoCodeImageUrl) {
$orderCurrency = $this->_checkoutSession->getLastRealOrder()->getOrderCurrency()->getCurrencyCode();

$this->addData(
[
'tesco_code_url' => $tescoCodeImageUrl,
'order_amount' => number_format($paymentData['amount_ordered'], 2) .' '.$orderCurrency
]
);
}
$this->addData([
'tesco_code_image' => $paymentData['additional_information']['barcode'],
'order_amount' => number_format($paymentData['amount_ordered'], 2) .' '.$orderCurrency
]);

return parent::_toHtml();
}
}
18 changes: 17 additions & 1 deletion Gateway/Response/PaymentDetailsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@

class PaymentDetailsHandler implements HandlerInterface
{
/**
* @param string $url URL to Tesco Barcode generated in Omise Backend
* @return string Barcode in SVG format
*/
private function downloadTescoBarcode($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

return curl_exec($ch);
}

/**
* @inheritdoc
*/
Expand All @@ -19,7 +33,9 @@ public function handle(array $handlingSubject, array $response)
$payment->setAdditionalInformation('payment_type', $response['charge']->source['type']);

if ($response['charge']->source['type'] === 'bill_payment_tesco_lotus') {
$payment->setAdditionalInformation('barcode', $response['charge']->source['references']['barcode']);
$barcode = $this->downloadTescoBarcode($response['charge']->source['references']['barcode']);
$payment->setAdditionalInformation('barcode', $barcode);
}
}
}

64 changes: 64 additions & 0 deletions Helper/OmiseHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Store\Model\ScopeInterface;
use SimpleXMLElement;
use DOMDocument;

class OmiseHelper extends AbstractHelper
{
Expand Down Expand Up @@ -39,4 +41,66 @@ public function omiseAmountFormat($currency, $amount)

return $amount;
}

/**
* Convert tesco code returned from Omise Backend in SVG format to HTML format
*
* @param string $svg
*
* @return string
*/
public function convertTescoSVGCodeToHTML($svg)
{
// remove from $svg unnecessary elements

// find first "<rect" node element
// delete everything until first "<rect"
$svg = substr($svg, strpos($svg, '<rect'));

//find last </g> closing tag and cut everything after it
$svg = substr($svg, 0, strpos($svg, '</g>') + strlen('</g>'));

//insert everything into master tag (requirement of SimpleXMLElement class)
$svg = '<svg>' . $svg . '</svg>';
$xml = new SimpleXMLElement($svg);
if (!$xml) {
return;
}

//get first children
$node = $xml->children();

//initialize return value
$xhtml = new DOMDocument();

//analyze svg nodes, and generate html
foreach ($node as $child) {
// all rect nodes are in group master node
if ($child->getName() === 'g') {
$prevX = 0;
$prevWidth = 0;

// get data from all rect nodes
foreach ($child->children() as $rect) {
$attrArr = $rect->attributes();
$divRect = $xhtml->createElement('div');
$width = $attrArr['width'];
$margin = ($attrArr['x'] - $prevX - $prevWidth) . 'px';

//set html attributes based on SVG attributes
$divRect->setAttribute('style', "float:left; position:relative; height:50px; width:$width; background-color:#000; margin-left:$margin");

$xhtml->appendChild($divRect);

$prevX = $attrArr['x'];
$prevWidth = $attrArr['width'];
}
// add empty div tag to clear 'float' css property
$div = $xhtml->createElement('div');
$div->setAttribute('style', "clear:both");
$xhtml->appendChild($div);
}
}
return $xhtml->saveXML(null, LIBXML_NOEMPTYTAG);
}
}
88 changes: 88 additions & 0 deletions Observer/TescoPaymentObserver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php
namespace Omise\Payment\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;

class TescoPaymentObserver implements ObserverInterface
{
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
private $_scopeConfig;

/**
* @var \Magento\Framework\Mail\Template\TransportBuilder
*/
private $_transportBuilder;

/**
* @var \Omise\Payment\Helper
*/
private $_helper;

public function __construct(
\Omise\Payment\Helper\OmiseHelper $helper,
\Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
) {
$this->_scopeConfig = $scopeConfig;
$this->_helper = $helper;
$this->_transportBuilder = $transportBuilder;
}

/**
* @param \Magento\Framework\Event\Observer $observer
* @return $this
*/
public function execute(Observer $observer)
{
$order = $observer->getEvent()->getOrder();
$payment = $order->getPayment();

if (!$payment) {
return $this;
}

$paymentData = $payment->getData();

if ($paymentData['additional_information']['payment_type'] !== 'bill_payment_tesco_lotus') {
return $this;
}

$amount = number_format($paymentData['amount_ordered'], 2) . ' ' . $order->getOrderCurrency()->getCurrencyCode();
$barcodeHtml = $this->_helper->convertTescoSVGCodeToHTML($paymentData['additional_information']['barcode']);
$storeName = $this->_scopeConfig->getValue('trans_email/ident_sales/name', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
$storeEmail = $this->_scopeConfig->getValue('trans_email/ident_sales/email', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
$customerEmail = $order->getCustomerEmail();
$orderId = $order->getIncrementId();

// make sure timezone is Thailand.
date_default_timezone_set("Asia/Bangkok");

// get DateTime deadline that is in next 24 hours.
$validUntil = date("d-m-Y H:i:s" , time() + 24 * 60 * 60) . ' ICT';

$emailData = new \Magento\Framework\DataObject();
$emailData->setData(['barcode' => $barcodeHtml, 'amount' => $amount, 'storename' => $storeName, 'orderId' => $orderId, 'valid' => $validUntil]);

// build and send email
$transport = $this->_transportBuilder
->setTemplateIdentifier('send_email_tesco_template')
->setTemplateOptions([
'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID,
])
->setTemplateVars(['data' => $emailData])
->setFrom([
'name' => $storeName,
'email' => $storeEmail,
])
->addTo(['email' => $customerEmail], \Magento\Store\Model\ScopeInterface::SCOPE_STORE)
->getTransport();

$transport->sendMessage();

return $this;
}
}
9 changes: 8 additions & 1 deletion etc/config.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<tesco>
<email>
<send_email>send_email_email_template</send_email>
</email>
</tesco>
<payment>

<omise>
<sandbox_status>0</sandbox_status>
<model>OmiseAdapter</model>
Expand Down
5 changes: 5 additions & 0 deletions etc/email_templates.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Email/etc/email_templates.xsd">
<template id="send_email_tesco_template" label="Email Form" file="tesco_template.html" type="html"
module="Omise_Payment" area="frontend"/>
</config>
4 changes: 4 additions & 0 deletions etc/events.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@
<event name="payment_method_assign_data_omise_offsite_internetbanking">
<observer name="omise_data_assign" instance="Omise\Payment\Observer\InternetbankingDataAssignObserver" />
</event>

<event name="sales_order_place_after">
<observer name="omise_end_order" instance="Omise\Payment\Observer\TescoPaymentObserver" />
</event>
</config>
19 changes: 19 additions & 0 deletions view/frontend/email/tesco_template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!--@subject {{trans "Tesco Lotus Payment"}} @-->
{{template config_path="design/email/header_template"}}
<div>
<p>
{{trans "%thankyou" thankyou="Thank you for your order."}}</p>
{{trans "%message" message="This is your Tesco Lotus payment code. Please print it and bring it to any Tesco
Lotus store within the next 24 hours to finalise payment. After that time your order will be automatically
cancelled."}}<br/>
{{trans "%orderid" orderid="Order ID:"}} <strong>{{var data.orderId|raw}}</strong><br/>
{{trans "%valid" valid="Valid until:"}} <strong>{{var data.valid|raw}}</strong><br/>
{{trans "%amounttopay" amounttopay="Amount to pay:"}} <strong>{{var data.amount|raw}}</strong><br/>
<i>{{trans "%extrafees" extrafees="Extra fees may apply for the payment."}}</i>
</p>
<p style="margin: 50px auto; min-width: 600px; display: block;">
<div>{{var data.barcode|raw}}</div>
</p>
<p style="margin-top: 50px"><i>{{var data.storename|raw}}</i></p>
</div>
{{template config_path="design/email/footer_template"}}
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@ define(
return window.checkoutConfig.quoteData.store_currency_code;
},

/**
* Handle payment error
*/
handlePaymentError: function(response) {
errorProcessor.process(response, self.messageContainer);
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
},

/**
* Hook the placeOrder function.
* Original source: placeOrder(data, event); @ module-checkout/view/frontend/web/js/view/payment/default.js
Expand All @@ -85,7 +76,9 @@ define(
self.getPlaceOrderDeferredObject()
.fail(
function(response) {
self.handlePaymentError(response);
errorProcessor.process(response, self.messageContainer);
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
}
).done(
function() {
Expand Down

0 comments on commit 6037c94

Please sign in to comment.