We will be off on April 7th (Monday) for public holiday in our country

Cc.php 13.1 KB
Newer Older
rikterbeek's avatar
rikterbeek committed
1 2
<?php
/**
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *                       ######
 *                       ######
 * ############    ####( ######  #####. ######  ############   ############
 * #############  #####( ######  #####. ######  #############  #############
 *        ######  #####( ######  #####. ######  #####  ######  #####  ######
 * ###### ######  #####( ######  #####. ######  #####  #####   #####  ######
 * ###### ######  #####( ######  #####. ######  #####          #####  ######
 * #############  #############  #############  #############  #####  ######
 *  ############   ############  #############   ############  #####  ######
 *                                      ######
 *                               #############
 *                               ############
 *
 * 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>
rikterbeek's avatar
rikterbeek committed
22
 */
23

rikterbeek's avatar
rikterbeek committed
24 25
namespace Adyen\Payment\Model\Method;

26 27 28 29 30 31
/**
 * Adyen CreditCard payment method
 * @SuppressWarnings(PHPMD.ExcessivePublicCount)
 * @SuppressWarnings(PHPMD.TooManyFields)
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
rikterbeek's avatar
rikterbeek committed
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
class Cc extends \Magento\Payment\Model\Method\Cc
{

    const METHOD_CODE               = 'adyen_cc';

    /**
     * Payment Method feature
     *
     * @var bool
     */
    protected $_canAuthorize = true;
    protected $_canCapture = true;
    protected $_canCapturePartial = true;
    protected $_canCaptureOnce = true;
    protected $_canRefund = true;
    protected $_canRefundInvoicePartial = true;

    /**
     * @var string
     */
    protected $_code = self::METHOD_CODE;

    /**
     * @var string
     */
    protected $_formBlockType = 'Adyen\Payment\Block\Form\Cc';
58
    protected $_infoBlockType = 'Adyen\Payment\Block\Info\Cc';
rikterbeek's avatar
rikterbeek committed
59

60 61 62
    /**
     * @var \Adyen\Payment\Model\Api\PaymentRequest
     */
rikterbeek's avatar
rikterbeek committed
63 64
    protected $_paymentRequest;

65 66 67
    /**
     * @var \Adyen\Payment\Logger\AdyenLogger
     */
68 69
    protected $_adyenLogger;

70 71 72 73 74
    /**
     * @var \Magento\Checkout\Model\Session
     */
    protected $_checkoutSession;

75 76 77
    /**
     * @var \Magento\Framework\UrlInterface
     */
78 79
    protected $_urlBuilder;

80 81 82
    /**
     * @var \Adyen\Payment\Helper\Data
     */
83 84
    protected $_adyenHelper;

rikterbeek's avatar
rikterbeek committed
85
    /**
86 87 88 89 90
     * @param \Adyen\Payment\Model\Api\PaymentRequest $paymentRequest
     * @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Magento\Framework\UrlInterface $urlBuilder
     * @param \Adyen\Payment\Helper\Data $adyenHelper
rikterbeek's avatar
rikterbeek committed
91 92 93 94 95 96
     * @param \Magento\Framework\Model\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
     * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory
     * @param \Magento\Payment\Helper\Data $paymentData
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
97
     * @param \Magento\Payment\Model\Method\Logger $logger
rikterbeek's avatar
rikterbeek committed
98 99
     * @param \Magento\Framework\Module\ModuleListInterface $moduleList
     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
100
     * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
101
     * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
rikterbeek's avatar
rikterbeek committed
102 103 104 105 106
     * @param array $data
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        \Adyen\Payment\Model\Api\PaymentRequest $paymentRequest,
107
        \Adyen\Payment\Logger\AdyenLogger $adyenLogger,
108 109
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Framework\UrlInterface $urlBuilder,
110
        \Adyen\Payment\Helper\Data $adyenHelper,
rikterbeek's avatar
rikterbeek committed
111 112 113 114 115 116 117 118 119
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
        \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
        \Magento\Payment\Helper\Data $paymentData,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Payment\Model\Method\Logger $logger,
        \Magento\Framework\Module\ModuleListInterface $moduleList,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
120
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
rikterbeek's avatar
rikterbeek committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        parent::__construct(
            $context,
            $registry,
            $extensionFactory,
            $customAttributeFactory,
            $paymentData,
            $scopeConfig,
            $logger,
            $moduleList,
            $localeDate,
            $resource,
            $resourceCollection,
            $data
        );
        $this->_paymentRequest = $paymentRequest;
139
        $this->_adyenLogger = $adyenLogger;
140 141
        $this->_checkoutSession = $checkoutSession;
        $this->_urlBuilder = $urlBuilder;
142
        $this->_adyenHelper = $adyenHelper;
rikterbeek's avatar
rikterbeek committed
143 144
    }

rikterbeek's avatar
rikterbeek committed
145 146 147 148 149
    protected $_paymentMethodType = 'api';
    public function getPaymentMethodType() {
        return $this->_paymentMethodType;
    }

rikterbeek's avatar
rikterbeek committed
150 151 152
    /**
     * Assign data to info model instance
     *
153
     * @param \Magento\Framework\DataObject|mixed $data
rikterbeek's avatar
rikterbeek committed
154
     * @return $this
155
     * @throws \Magento\Framework\Exception\LocalizedException
rikterbeek's avatar
rikterbeek committed
156
     */
157
    public function assignData(\Magento\Framework\DataObject $data)
rikterbeek's avatar
rikterbeek committed
158
    {
159 160
        parent::assignData($data);
        $infoInstance = $this->getInfoInstance();
rikterbeek's avatar
rikterbeek committed
161

162 163
        $infoInstance->setCcType($data['cc_type']);

164
        if($this->_adyenHelper->getAdyenCcConfigDataFlag('cse_enabled')) {
165 166 167 168 169
            if(isset($data['encrypted_data'])) {
                $infoInstance->setAdditionalInformation('encrypted_data', $data['encrypted_data']);
            } else {
                throw new \Magento\Framework\Exception\LocalizedException(__('Card encryption failed'));
            }
rikterbeek's avatar
rikterbeek committed
170
        }
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

        // save value remember details checkbox
        $infoInstance->setAdditionalInformation('store_cc', $data['store_cc']);

        return $this;
    }

    /**
     * Validate payment method information object
     *
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    public function validate()
    {
        // validation only possible on front-end for CSE script
189
        return $this;
rikterbeek's avatar
rikterbeek committed
190 191 192 193 194 195 196 197
    }

    public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount)
    {
        if (!$this->canAuthorize()) {
            throw new \Magento\Framework\Exception\LocalizedException(__('The authorize action is not available.'));
        }

198 199 200 201 202 203 204
        /*
         * do not send order confirmation mail after order creation wait for
         * Adyen AUTHORIISATION notification
         */
        $order = $payment->getOrder();
        $order->setCanSendNewEmailFlag(false);

205 206 207
        // do not let magento set status to processing
        $payment->setLastTransId($this->getTransactionId())->setIsTransactionPending(true);

rikterbeek's avatar
rikterbeek committed
208 209 210 211 212 213
        // DO authorisation
        $this->_processRequest($payment, $amount, "authorise");

        return $this;
    }

214
    protected function _processRequest(\Magento\Sales\Model\Order\Payment $payment, $amount, $request)
215
    {
rikterbeek's avatar
rikterbeek committed
216 217
        switch ($request) {
            case "authorise":
218
                $response = $this->_paymentRequest->fullApiRequest($payment, $this->_code);
rikterbeek's avatar
rikterbeek committed
219 220 221 222
                break;
        }

        if (!empty($response)) {
223
            $this->_processResponse($payment, $response);
rikterbeek's avatar
rikterbeek committed
224 225 226 227 228
        } else {
            throw new \Magento\Framework\Exception\LocalizedException(__('Empty result.'));
        }
    }

229 230
    protected function _processResponse(\Magento\Payment\Model\InfoInterface $payment, $response)
    {
231
        $payment->setAdditionalInformation('3dActive', false);
232

233
        switch ($response['resultCode']) {
234 235
            case "Authorised":
                //$this->_addStatusHistory($payment, $responseCode, $pspReference, $this->_getConfigData('order_status'));
236 237
                $this->_addStatusHistory($payment, $response['resultCode'], $response['pspReference']);
                $payment->setAdditionalInformation('pspReference', $response['pspReference']);
238 239
                break;
            case "RedirectShopper":
240
                // 3d is active so set the param to true checked in Controller/Validate3d
241
                $payment->setAdditionalInformation('3dActive', true);
242 243 244
                $issuerUrl = $response['issuerUrl'];
                $PaReq = $response['paRequest'];
                $md = $response['md'];
245 246

                if(!empty($PaReq) && !empty($md) && !empty($issuerUrl)) {
247 248 249
                    $payment->setAdditionalInformation('issuerUrl', $response['issuerUrl']);
                    $payment->setAdditionalInformation('paRequest', $response['paRequest']);
                    $payment->setAdditionalInformation('md', $response['md']);
250 251 252
                } else {
                    throw new \Magento\Framework\Exception\LocalizedException(__('3D secure is not valid'));
                }
253 254
                break;
            case "Refused":
255 256
                // refusalReason
                if($response['refusalReason']) {
257

258
                    $refusalReason = $response['refusalReason'];
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
                    switch($refusalReason) {
                        case "Transaction Not Permitted":
                            $errorMsg = __('The transaction is not permitted.');
                            break;
                        case "CVC Declined":
                            $errorMsg = __('Declined due to the Card Security Code(CVC) being incorrect. Please check your CVC code!');
                            break;
                        case "Restricted Card":
                            $errorMsg = __('The card is restricted.');
                            break;
                        case "803 PaymentDetail not found":
                            $errorMsg = __('The payment is REFUSED because the saved card is removed. Please try an other payment method.');
                            break;
                        case "Expiry month not set":
                            $errorMsg = __('The expiry month is not set. Please check your expiry month!');
                            break;
                        default:
                            $errorMsg = __('The payment is REFUSED by Adyen.');
                            break;
                    }
                } else {
rikterbeek's avatar
rikterbeek committed
280
                    $errorMsg = __('The payment is REFUSED by Adyen.');
281 282 283 284
                }

                if ($errorMsg) {
                    $this->_logger->critical($errorMsg);
285
                    throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
286 287 288
                }
                break;
        }
289
    }
290

291 292
    protected function _addStatusHistory($payment, $responseCode, $pspReference)
    {
293

294 295 296 297 298 299
        $type = 'Adyen Result URL response:';
        $comment = __('%1 <br /> authResult: %2 <br /> pspReference: %3 <br /> paymentMethod: %4', $type, $responseCode, $pspReference, "");
        $payment->getOrder()->setAdyenResulturlEventCode($responseCode);
        $payment->getOrder()->addStatusHistoryComment($comment);
        return $this;
    }
300

301 302 303 304 305
    /*
     * Called by validate3d controller when cc payment has 3D secure
     */
    public function authorise3d($payment)
    {
306

307
        $response = $this->_paymentRequest->authorise3d($payment);
308
        $responseCode = $response['resultCode'];
309
        return $responseCode;
310 311
    }

312 313 314 315 316 317 318 319 320 321
    /**
     * Checkout redirect URL getter for onepage checkout (hardcode)
     *
     * @see \Magento\Checkout\Controller\Onepage::savePaymentAction()
     * @see \Magento\Quote\Model\Quote\Payment::getCheckoutRedirectUrl()
     * @return string
     */
    public function getCheckoutRedirectUrl()
    {
        return $this->_urlBuilder->getUrl('adyen/process/validate3d/');
rikterbeek's avatar
rikterbeek committed
322 323
    }

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
    /**
     * Capture on Adyen
     *
     * @param \Magento\Payment\Model\InfoInterface $payment
     * @param float $amount
     */
    public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount)
    {
        parent::capture($payment, $amount);
        $this->_paymentRequest->capture($payment, $amount);
        return $this;
    }

    /**
     * Refund specified amount for payment
     *
     * @param \Magento\Framework\DataObject|InfoInterface $payment
     * @param float $amount
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     * @api
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)
    {
        parent::refund($payment, $amount);

        $order = $payment->getOrder();
        // if amount is a full refund send a refund/cancelled request so if it is not captured yet it will cancel the order
        $grandTotal = $order->getGrandTotal();

        if($grandTotal == $amount) {
            $this->_paymentRequest->cancelOrRefund($payment);
        } else {
            $this->_paymentRequest->refund($payment, $amount);
        }

        return $this;
    }

rikterbeek's avatar
rikterbeek committed
364
}