We will work on Apr 26th (Saturday) and will be off from Apr 30th (Wednesday) until May 2nd (Friday) for public holiday in our country

ResultPos.php 9.14 KB
Newer Older
rikterbeek's avatar
rikterbeek committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
<?php
/**
 *                       ######
 *                       ######
 * ############    ####( ######  #####. ######  ############   ############
 * #############  #####( ######  #####. ######  #############  #############
 *        ######  #####( ######  #####. ######  #####  ######  #####  ######
 * ###### ######  #####( ######  #####. ######  #####  #####   #####  ######
 * ###### ######  #####( ######  #####. ######  #####          #####  ######
 * #############  #############  #############  #############  #####  ######
 *  ############   ############  #############   ############  #####  ######
 *                                      ######
 *                               #############
 *                               ############
 *
 * Adyen Payment module (https://www.adyen.com/)
 *
 * Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
 * See LICENSE.txt for license details.
 *
 * Author: Adyen <magento@adyen.com>
 */

namespace Adyen\Payment\Controller\Process;

class ResultPos extends \Magento\Framework\App\Action\Action
{
    /**
     * @var \Adyen\Payment\Helper\Data
     */
    protected $_adyenHelper;

    /**
     * @var \Magento\Sales\Model\OrderFactory
     */
    protected $_orderFactory;

    /**
     * @var \Magento\Sales\Model\Order
     */
    protected $_order;

    /**
     * @var \Magento\Sales\Model\Order\Status\HistoryFactory
     */
    protected $_orderHistoryFactory;

    /**
     * @var \Magento\Checkout\Model\Session
     */
    protected $_session;

    /**
     * @var \Adyen\Payment\Logger\AdyenLogger
     */
    protected $_adyenLogger;

    /**
59 60
     * ResultPos constructor.
     *
rikterbeek's avatar
rikterbeek committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Adyen\Payment\Helper\Data $adyenHelper
     * @param \Magento\Sales\Model\OrderFactory $orderFactory
     * @param \Magento\Sales\Model\Order\Status\HistoryFactory $orderHistoryFactory
     * @param \Magento\Checkout\Model\Session $session
     * @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Adyen\Payment\Helper\Data $adyenHelper,
        \Magento\Sales\Model\OrderFactory $orderFactory,
        \Magento\Sales\Model\Order\Status\HistoryFactory $orderHistoryFactory,
        \Magento\Checkout\Model\Session $session,
        \Adyen\Payment\Logger\AdyenLogger $adyenLogger
    ) {
        $this->_adyenHelper = $adyenHelper;
        $this->_orderFactory = $orderFactory;
        $this->_orderHistoryFactory = $orderHistoryFactory;
        $this->_session = $session;
        $this->_adyenLogger = $adyenLogger;
        parent::__construct($context);
    }

84 85 86
    /**
     * Return result
     */
rikterbeek's avatar
rikterbeek committed
87 88 89 90 91 92 93 94 95 96
    public function execute()
    {
        $response = $this->getRequest()->getParams();
        $this->_adyenLogger->addAdyenResult(print_r($response, true));

        $result = $this->_validateResponse($response);

        if ($result) {
            $session = $this->_session;
            $session->getQuote()->setIsActive(false)->save();
97
            $this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
rikterbeek's avatar
rikterbeek committed
98 99
        } else {
            $this->_cancel($response);
100
            $this->_redirect($this->_adyenHelper->getAdyenAbstractConfigData('return_path'));
rikterbeek's avatar
rikterbeek committed
101 102 103
        }
    }

104 105 106 107
    /**
     * @param $response
     * @return bool
     */
rikterbeek's avatar
rikterbeek committed
108 109 110 111
    private function _validateResponse($response)
    {
        $result = false;

112
        if ($response != null && $response['result'] != "" && $this->_validateChecksum($response)) {
rikterbeek's avatar
rikterbeek committed
113 114 115
            $incrementId = $response['merchantReference'];
            $responseResult = $response['result'];

116
            if ($incrementId) {
rikterbeek's avatar
rikterbeek committed
117 118
                $order = $this->_getOrder($incrementId);
                if ($order->getId()) {
119 120 121 122 123 124
                    $comment = __(
                        '%1 <br /> Result: %2 <br /> paymentMethod: %3',
                        'Adyen App Result URL Notification:',
                        $responseResult,
                        'POS'
                    );
rikterbeek's avatar
rikterbeek committed
125

126
                    if ($responseResult == 'APPROVED') {
rikterbeek's avatar
rikterbeek committed
127 128 129 130 131 132
                        $this->_adyenLogger->addAdyenResult('Result is approved');

                        $history = $this->_orderHistoryFactory->create()
                            //->setStatus($status)
                            ->setComment($comment)
                            ->setEntityName('order')
133
                            ->setOrder($order);
rikterbeek's avatar
rikterbeek committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
                        $history->save();

                        // needed  becuase then we need to save $order objects
                        $order->setAdyenResulturlEventCode("POS_APPROVED");

                        // save order
                        $order->save();

                        return true;
                    } else {
                        $this->_adyenLogger->addAdyenResult('Result is:' . $responseResult);

                        $history = $this->_orderHistoryFactory->create()
                            //->setStatus($status)
                            ->setComment($comment)
                            ->setEntityName('order')
150
                            ->setOrder($order);
rikterbeek's avatar
rikterbeek committed
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
                        $history->save();

                        // cancel the order
                        if ($order->canCancel()) {
                            $order->cancel()->save();
                            $this->_adyenLogger->addAdyenResult('Order is cancelled');
                        } else {
                            $this->_adyenLogger->addAdyenResult('Order can not be cancelled');
                        }
                    }
                } else {
                    $this->_adyenLogger->addAdyenResult('Order does not exists with increment_id: ' . $incrementId);
                }
            } else {
                $this->_adyenLogger->addAdyenResult('Empty merchantReference');
            }
        } else {
            $this->_adyenLogger->addAdyenResult('actionName or checksum failed or response is empty');
        }
        return $result;
    }

173 174 175 176 177 178
    /**
     * Validate checksum from result parameters
     *
     * @param $response
     * @return bool
     */
rikterbeek's avatar
rikterbeek committed
179 180 181 182 183 184 185 186 187
    protected function _validateChecksum($response)
    {
        $checksum = $response['cs'];
        $result = $response['result'];
        $amount = $response['originalCustomAmount'];
        $currency = $response['originalCustomCurrency'];
        $sessionId = $response['sessionId'];

        // for android sessionis is with low i
188
        if ($sessionId == "") {
rikterbeek's avatar
rikterbeek committed
189 190 191 192
            $sessionId = $response['sessionid'];
        }

        // calculate amount checksum
193
        $amountChecksum = 0;
rikterbeek's avatar
rikterbeek committed
194 195

        $amountLength = strlen($amount);
196
        for ($i = 0; $i < $amountLength; $i++) {
rikterbeek's avatar
rikterbeek committed
197 198
            // ASCII value use ord
            $checksumCalc = ord($amount[$i]) - 48;
199
            $amountChecksum += $checksumCalc;
rikterbeek's avatar
rikterbeek committed
200 201
        }

202
        $currencyChecksum = 0;
rikterbeek's avatar
rikterbeek committed
203
        $currencyLength = strlen($currency);
204
        for ($i = 0; $i < $currencyLength; $i++) {
rikterbeek's avatar
rikterbeek committed
205
            $checksumCalc = ord($currency[$i]) - 64;
206
            $currencyChecksum += $checksumCalc;
rikterbeek's avatar
rikterbeek committed
207 208
        }

209
        $resultChecksum = 0;
rikterbeek's avatar
rikterbeek committed
210
        $resultLength = strlen($result);
211
        for ($i = 0; $i < $resultLength; $i++) {
rikterbeek's avatar
rikterbeek committed
212
            $checksumCalc = ord($result[$i]) - 64;
213
            $resultChecksum += $checksumCalc;
rikterbeek's avatar
rikterbeek committed
214 215
        }

216
        $sessionIdChecksum = 0;
rikterbeek's avatar
rikterbeek committed
217
        $sessionIdLength = strlen($sessionId);
218
        for ($i = 0; $i < $sessionIdLength; $i++) {
rikterbeek's avatar
rikterbeek committed
219
            $checksumCalc = $this->_getAscii2Int($sessionId[$i]);
220
            $sessionIdChecksum += $checksumCalc;
rikterbeek's avatar
rikterbeek committed
221 222
        }

223
        $totalResultChecksum = (($amountChecksum + $currencyChecksum + $resultChecksum) * $sessionIdChecksum) % 100;
rikterbeek's avatar
rikterbeek committed
224 225

        // check if request is valid
226
        if ($totalResultChecksum == $checksum) {
rikterbeek's avatar
rikterbeek committed
227 228 229 230 231 232 233
            $this->_adyenLogger->addAdyenResult('Checksum is valid');
            return true;
        }
        $this->_adyenLogger->addAdyenResult('Checksum is invalid!');
        return false;
    }

234 235 236 237
    /**
     * @param $ascii
     * @return int
     */
rikterbeek's avatar
rikterbeek committed
238 239
    protected function _getAscii2Int($ascii)
    {
240
        if (is_numeric($ascii)) {
rikterbeek's avatar
rikterbeek committed
241 242 243 244 245 246 247
            $int = ord($ascii) - 48;
        } else {
            $int = ord($ascii) - 64;
        }
        return $int;
    }

248 249 250 251
    /**
     * @param $incrementId
     * @return \Magento\Sales\Model\Order
     */
rikterbeek's avatar
rikterbeek committed
252 253 254 255 256 257 258 259
    protected function _getOrder($incrementId)
    {
        if (!$this->_order) {
            $this->_order = $this->_orderFactory->create()->loadByIncrementId($incrementId);
        }
        return $this->_order;
    }

260 261 262
    /**
     * @param $response
     */
rikterbeek's avatar
rikterbeek committed
263 264 265 266 267 268 269 270 271
    protected function _cancel($response)
    {
        $session = $this->_session;

        // restore the quote
        $session->restoreQuote();

        $order = $this->_order;

272
        if ($order) {
rikterbeek's avatar
rikterbeek committed
273 274
            $this->_adyenHelper->cancelOrder($order);

275 276
            if (isset($response['authResult']) &&
                $response['authResult'] == \Adyen\Payment\Model\Notification::CANCELLED) {
rikterbeek's avatar
rikterbeek committed
277 278 279 280 281 282
                $this->messageManager->addError(__('You have cancelled the order. Please try again'));
            } else {
                $this->messageManager->addError(__('Your payment failed, Please try again later'));
            }
        }
    }
283
}