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

AdyenThreeDS2Process.php 4.94 KB
Newer Older
attilak's avatar
[WIP]  
attilak 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
<?php
/**
 *                       ######
 *                       ######
 * ############    ####( ######  #####. ######  ############   ############
 * #############  #####( ######  #####. ######  #############  #############
 *        ######  #####( ######  #####. ######  #####  ######  #####  ######
 * ###### ######  #####( ######  #####. ######  #####  #####   #####  ######
 * ###### ######  #####( ######  #####. ######  #####          #####  ######
 * #############  #############  #############  #############  #####  ######
 *  ############   ############  #############   ############  #####  ######
 *                                      ######
 *                               #############
 *                               ############
 *
 * Adyen Payment module (https://www.adyen.com/)
 *
 * Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
 * See LICENSE.txt for license details.
 *
 * Author: Adyen <magento@adyen.com>
 */

namespace Adyen\Payment\Model;

use \Adyen\Payment\Api\AdyenThreeDS2ProcessInterface;

class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
{
    /**
     * @var \Magento\Checkout\Model\Session
     */
    private $checkoutSession;

    /**
     * @var \Adyen\Payment\Helper\Data
     */
    private $adyenHelper;

    /**
     * AdyenThreeDS2Process constructor.
     *
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Adyen\Payment\Helper\Data $adyenHelper
     */
    public function __construct(
        \Magento\Checkout\Model\Session $checkoutSession,
        \Adyen\Payment\Helper\Data $adyenHelper
    )
    {
        $this->checkoutSession = $checkoutSession;
        $this->adyenHelper = $adyenHelper;
    }

    /**
     * @api
attilak's avatar
[WIP]  
attilak committed
57 58
     * @param string $payload
     * @return string
attilak's avatar
[WIP]  
attilak committed
59 60 61 62 63 64
     */
    public function initiate($payload)
    {
        // Decode payload from frontend
        $payload = json_decode($payload, true);

attilak's avatar
[WIP]  
attilak committed
65
        // Validate JSON that has just been parsed if it was in a valid format
attilak's avatar
[WIP]  
attilak committed
66 67 68 69 70 71 72 73 74
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed because the request was not a valid JSON'));
        }

        // Get payment and cart information from session
        $quote = $this->checkoutSession->getQuote();
        $payment = $quote->getPayment();

        // Init payments/details request
attilak's avatar
[WIP]  
attilak committed
75
        $result = [];
attilak's avatar
[WIP]  
attilak committed
76

attilak's avatar
[WIP]  
attilak committed
77 78 79 80 81 82 83 84 85 86 87
        if ($paymentData = $payment->getAdditionalInformation("threeDS2PaymentData")) {
            // Add payment data into the request object
            $request = [
                "paymentData" => $payment->getAdditionalInformation("threeDS2PaymentData")
            ];

            // unset payment data from additional information
            $payment->unsAdditionalInformation("threeDS2PaymentData");
        } else {
            throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed, payment data not found'));
        }
attilak's avatar
[WIP]  
attilak committed
88

attilak's avatar
[WIP]  
attilak committed
89 90 91
        // Depends on the component's response we send a fingerprint or the challenge result
        if (!empty($payload['details']['threeds2.fingerprint'])) {
            $request['details']['threeds2.fingerprint'] = $payload['details']['threeds2.fingerprint'];
attilak's avatar
[WIP]  
attilak committed
92
        } elseif (!empty($payload['details']['threeds2.challengeResult'])) {
attilak's avatar
[WIP]  
attilak committed
93 94 95 96 97 98 99
            $request['details']['threeds2.challengeResult'] = $payload['details']['threeds2.challengeResult'];
        }

        // Send the request
        try {
            $client = $this->adyenHelper->initializeAdyenClient($quote->getStoreId());
            $service = $this->adyenHelper->createAdyenCheckoutService($client);
100

attilak's avatar
[WIP]  
attilak committed
101 102 103 104 105 106 107 108
            $result = $service->paymentsDetails($request);
        } catch (\Adyen\AdyenException $e) {
            throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed'));
        }

        // Check if result is challenge shopper, if yes return the token
        if (!empty($result['resultCode']) &&
            $result['resultCode'] === 'ChallengeShopper' &&
attilak's avatar
[WIP]  
attilak committed
109
            !empty($result['authentication']['threeds2.challengeToken'])
attilak's avatar
[WIP]  
attilak committed
110
        ) {
attilak's avatar
[WIP]  
attilak committed
111
            return $this->adyenHelper->buildThreeDS2ProcessResponseJson($result['resultCode'], $result['authentication']['threeds2.challengeToken']);
attilak's avatar
[WIP]  
attilak committed
112 113 114
        }

        // Payment can get back to the original flow
attilak's avatar
[WIP]  
attilak committed
115 116

        // Save the payments response because we are going to need it during the place order flow
attilak's avatar
[WIP]  
attilak committed
117
        $payment->setAdditionalInformation("paymentsResponse", $result);
attilak's avatar
[WIP]  
attilak committed
118 119 120

        // Setting the placeOrder to true enables the process to skip the payments call because the paymentsResponse
        // is already in place - only set placeOrder to true when you have the paymentsResponse
attilak's avatar
[WIP]  
attilak committed
121
        $payment->setAdditionalInformation('placeOrder', true);
attilak's avatar
[WIP]  
attilak committed
122 123

        // To actually save the additional info changes into the quote
attilak's avatar
[WIP]  
attilak committed
124 125 126
        $quote->save();

        // 3DS2 flow is done, original place order flow can continue from frontend
attilak's avatar
[WIP]  
attilak committed
127
        return $this->adyenHelper->buildThreeDS2ProcessResponseJson();
attilak's avatar
[WIP]  
attilak committed
128 129
    }
}