We will be off from 27/1 (Monday) to 31/1 (Friday) (GMT +7) for our Tet Holiday (Lunar New Year) in our country

Commit 8da089ce authored by Attila Kiss's avatar Attila Kiss Committed by GitHub

[PW-3130] Use the generic component for stored payment methods (#919)

* Tokenize payment methods in payment response handler

Do not save recurring details "manually" for /payments/details response

* Standardise Oneclick Observer

* Use generic component for recurring payments

* sonarcloud suggestions

* Remove unused div
parent 3f7ebc9e
...@@ -55,20 +55,6 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface ...@@ -55,20 +55,6 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject); $paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment(); $payment = $paymentDataObject->getPayment();
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$requestBody['paymentMethod']['type'] = "scheme";
if ($variant = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::VARIANT)) {
$requestBody['paymentMethod']['type'] = $variant;
}
if ($securityCode = $payment->getAdditionalInformation(
AdyenOneclickDataAssignObserver::ENCRYPTED_SECURITY_CODE
)) {
$requestBody['paymentMethod']['encryptedSecurityCode'] = $securityCode;
}
$payment->unsAdditionalInformation(AdyenOneclickDataAssignObserver::ENCRYPTED_SECURITY_CODE);
if ($payment->getAdditionalInformation('customer_interaction')) { if ($payment->getAdditionalInformation('customer_interaction')) {
$shopperInteraction = "Ecommerce"; $shopperInteraction = "Ecommerce";
} else { } else {
...@@ -76,9 +62,7 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface ...@@ -76,9 +62,7 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface
} }
$requestBody['shopperInteraction'] = $shopperInteraction; $requestBody['shopperInteraction'] = $shopperInteraction;
$requestBody['paymentMethod']['recurringDetailReference'] = $payment->getAdditionalInformation(
AdyenOneclickDataAssignObserver::RECURRING_DETAIL_REFERENCE
);
// if it is a sepadirectdebit set selectedBrand to sepadirectdebit in the case of oneclick // if it is a sepadirectdebit set selectedBrand to sepadirectdebit in the case of oneclick
if ($payment->getCcType() == "sepadirectdebit") { if ($payment->getCcType() == "sepadirectdebit") {
......
...@@ -1713,7 +1713,7 @@ class Data extends AbstractHelper ...@@ -1713,7 +1713,7 @@ class Data extends AbstractHelper
$billingAgreement->getAgreementId(), $billingAgreement->getAgreementId(),
$order->getId() $order->getId()
)) { )) {
// save into sales_billing_agreement_order // save into billing_agreement_order
$billingAgreement->addOrderRelation($order); $billingAgreement->addOrderRelation($order);
} }
// add to order to save agreement // add to order to save agreement
...@@ -1733,6 +1733,7 @@ class Data extends AbstractHelper ...@@ -1733,6 +1733,7 @@ class Data extends AbstractHelper
$comment = $order->addStatusHistoryComment($message); $comment = $order->addStatusHistoryComment($message);
$order->addRelatedObject($comment); $order->addRelatedObject($comment);
$order->save();
} }
} }
......
...@@ -27,6 +27,7 @@ use Adyen\Payment\Logger\AdyenLogger; ...@@ -27,6 +27,7 @@ use Adyen\Payment\Logger\AdyenLogger;
use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Api\Data\OrderPaymentInterface;
use Magento\Sales\Model\Order; use Magento\Sales\Model\Order;
use Adyen\Payment\Helper\Vault;
class PaymentResponseHandler class PaymentResponseHandler
{ {
...@@ -41,12 +42,36 @@ class PaymentResponseHandler ...@@ -41,12 +42,36 @@ class PaymentResponseHandler
const ERROR = 'Error'; const ERROR = 'Error';
const CANCELLED = 'Cancelled'; const CANCELLED = 'Cancelled';
/**
* @var AdyenLogger
*/
private $adyenLogger; private $adyenLogger;
/**
* @var Data
*/
private $adyenHelper;
/**
* @var Vault
*/
private $vaultHelper;
/**
* PaymentResponseHandler constructor.
*
* @param AdyenLogger $adyenLogger
* @param Data $adyenHelper
* @param \Adyen\Payment\Helper\Vault $vaultHelper
*/
public function __construct( public function __construct(
AdyenLogger $adyenLogger AdyenLogger $adyenLogger,
Data $adyenHelper,
Vault $vaultHelper
) { ) {
$this->adyenLogger = $adyenLogger; $this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
$this->vaultHelper = $vaultHelper;
} }
public function formatPaymentResponse($resultCode, $action = null, $additionalData = null) public function formatPaymentResponse($resultCode, $action = null, $additionalData = null)
...@@ -144,6 +169,24 @@ class PaymentResponseHandler ...@@ -144,6 +169,24 @@ class PaymentResponseHandler
} }
break; break;
case self::AUTHORISED: case self::AUTHORISED:
if (!empty($paymentsResponse['pspReference'])) {
// set pspReference as transactionId
$payment->setCcTransId($paymentsResponse['pspReference']);
$payment->setLastTransId($paymentsResponse['pspReference']);
// set transaction
$payment->setTransactionId($paymentsResponse['pspReference']);
}
if (!empty($paymentsResponse['additionalData']['recurring.recurringDetailReference']) &&
$payment->getMethodInstance()->getCode() !== \Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider::CODE) {
if ($this->adyenHelper->isCreditCardVaultEnabled()) {
$this->vaultHelper->saveRecurringDetails($payment, $paymentsResponse['additionalData']);
} else {
$order = $payment->getOrder();
$this->adyenHelper->createAdyenBillingAgreement($order, $paymentsResponse['additionalData']);
}
}
case self::IDENTIFY_SHOPPER: case self::IDENTIFY_SHOPPER:
case self::CHALLENGE_SHOPPER: case self::CHALLENGE_SHOPPER:
break; break;
......
...@@ -27,7 +27,6 @@ use Adyen\AdyenException; ...@@ -27,7 +27,6 @@ use Adyen\AdyenException;
use Adyen\Payment\Api\AdyenPaymentDetailsInterface; use Adyen\Payment\Api\AdyenPaymentDetailsInterface;
use Adyen\Payment\Helper\Data; use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\PaymentResponseHandler; use Adyen\Payment\Helper\PaymentResponseHandler;
use Adyen\Payment\Helper\Vault;
use Adyen\Payment\Logger\AdyenLogger; use Adyen\Payment\Logger\AdyenLogger;
use Magento\Checkout\Model\Session; use Magento\Checkout\Model\Session;
use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\LocalizedException;
...@@ -50,11 +49,6 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface ...@@ -50,11 +49,6 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface
*/ */
private $adyenLogger; private $adyenLogger;
/**
* @var Vault
*/
private $vaultHelper;
/** /**
* @var OrderRepositoryInterface * @var OrderRepositoryInterface
*/ */
...@@ -71,7 +65,6 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface ...@@ -71,7 +65,6 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface
* @param Session $checkoutSession * @param Session $checkoutSession
* @param Data $adyenHelper * @param Data $adyenHelper
* @param AdyenLogger $adyenLogger * @param AdyenLogger $adyenLogger
* @param Vault $vaultHelper
* @param OrderRepositoryInterface $orderRepository * @param OrderRepositoryInterface $orderRepository
* @param PaymentResponseHandler $paymentResponseHandler * @param PaymentResponseHandler $paymentResponseHandler
*/ */
...@@ -79,14 +72,12 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface ...@@ -79,14 +72,12 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface
Session $checkoutSession, Session $checkoutSession,
Data $adyenHelper, Data $adyenHelper,
AdyenLogger $adyenLogger, AdyenLogger $adyenLogger,
Vault $vaultHelper,
OrderRepositoryInterface $orderRepository, OrderRepositoryInterface $orderRepository,
PaymentResponseHandler $paymentResponseHandler PaymentResponseHandler $paymentResponseHandler
) { ) {
$this->checkoutSession = $checkoutSession; $this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
$this->adyenLogger = $adyenLogger; $this->adyenLogger = $adyenLogger;
$this->vaultHelper = $vaultHelper;
$this->orderRepository = $orderRepository; $this->orderRepository = $orderRepository;
$this->paymentResponseHandler = $paymentResponseHandler; $this->paymentResponseHandler = $paymentResponseHandler;
} }
...@@ -139,14 +130,7 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface ...@@ -139,14 +130,7 @@ class AdyenPaymentDetails implements AdyenPaymentDetailsInterface
throw new LocalizedException(__('Payment details call failed')); throw new LocalizedException(__('Payment details call failed'));
} }
//TODO test this with payments that return additionalData // Handle response
//TODO check for Authorized result code and move to the handler
if (!empty($paymentDetails['additionalData'])) {
$this->vaultHelper->saveRecurringDetails($payment, $paymentDetails['additionalData']);
}
//TODO check if order save is necessary to save additionalData
if (!$this->paymentResponseHandler->handlePaymentResponse($paymentDetails, $payment, $order)) { if (!$this->paymentResponseHandler->handlePaymentResponse($paymentDetails, $payment, $order)) {
$this->checkoutSession->restoreQuote(); $this->checkoutSession->restoreQuote();
throw new LocalizedException(__('The payment is REFUSED.')); throw new LocalizedException(__('The payment is REFUSED.'));
......
...@@ -37,6 +37,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -37,6 +37,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
const GUEST_EMAIL = 'guestEmail'; const GUEST_EMAIL = 'guestEmail';
const COMBO_CARD_TYPE = 'combo_card_type'; const COMBO_CARD_TYPE = 'combo_card_type';
const STATE_DATA = 'stateData'; const STATE_DATA = 'stateData';
const STORE_PAYMENT_METHOD = 'storePaymentMethod';
/** /**
* Approved root level keys from additional data array * Approved root level keys from additional data array
...@@ -113,5 +114,10 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -113,5 +114,10 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
if (!empty($additionalData[self::CC_TYPE])) { if (!empty($additionalData[self::CC_TYPE])) {
$paymentInfo->setCcType($additionalData[self::CC_TYPE]); $paymentInfo->setCcType($additionalData[self::CC_TYPE]);
} }
// set storeCc
if (!empty($stateData[self::STORE_PAYMENT_METHOD])) {
$paymentInfo->setAdditionalInformation(self::STORE_CC, $stateData[self::STORE_PAYMENT_METHOD]);
}
} }
} }
...@@ -23,39 +23,34 @@ ...@@ -23,39 +23,34 @@
namespace Adyen\Payment\Observer; namespace Adyen\Payment\Observer;
use Adyen\Service\Validator\CheckoutStateDataValidator;
use Adyen\Service\Validator\DataArrayValidator;
use Magento\Framework\Event\Observer; use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface; use Magento\Quote\Api\Data\PaymentInterface;
class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
{ {
const RECURRING_DETAIL_REFERENCE = 'recurring_detail_reference'; const CC_TYPE = 'cc_type';
const ENCRYPTED_SECURITY_CODE = 'cvc'; const BRAND = 'brand';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments'; const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const VARIANT = 'variant'; const STATE_DATA = 'stateData';
const JAVA_ENABLED = 'java_enabled';
const SCREEN_COLOR_DEPTH = 'screen_color_depth';
const SCREEN_WIDTH = 'screen_width';
const SCREEN_HEIGHT = 'screen_height';
const TIMEZONE_OFFSET = 'timezone_offset';
const LANGUAGE = 'language';
/** /**
* Approved root level keys from additional data array
*
* @var array * @var array
*/ */
protected $additionalInformationList = [ private static $approvedAdditionalDataKeys = [
self::RECURRING_DETAIL_REFERENCE, self::STATE_DATA,
self::ENCRYPTED_SECURITY_CODE,
self::NUMBER_OF_INSTALLMENTS, self::NUMBER_OF_INSTALLMENTS,
self::VARIANT,
self::JAVA_ENABLED,
self::SCREEN_COLOR_DEPTH,
self::SCREEN_WIDTH,
self::SCREEN_HEIGHT,
self::TIMEZONE_OFFSET,
self::LANGUAGE
]; ];
/**
* @var CheckoutStateDataValidator
*/
private $checkoutStateDataValidator;
/** /**
* @var \Adyen\Payment\Helper\Data * @var \Adyen\Payment\Helper\Data
*/ */
...@@ -72,9 +67,11 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver ...@@ -72,9 +67,11 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
* @param \Adyen\Payment\Helper\Data $adyenHelper * @param \Adyen\Payment\Helper\Data $adyenHelper
*/ */
public function __construct( public function __construct(
CheckoutStateDataValidator $checkoutStateDataValidator,
\Adyen\Payment\Helper\Data $adyenHelper, \Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Framework\Model\Context $context \Magento\Framework\Model\Context $context
) { ) {
$this->checkoutStateDataValidator = $checkoutStateDataValidator;
$this->adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
$this->appState = $context->getAppState(); $this->appState = $context->getAppState();
} }
...@@ -85,27 +82,47 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver ...@@ -85,27 +82,47 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
*/ */
public function execute(Observer $observer) public function execute(Observer $observer)
{ {
// Get request fields
$data = $this->readDataArgument($observer); $data = $this->readDataArgument($observer);
// Get additional data array
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) { if (!is_array($additionalData)) {
return; return;
} }
$paymentInfo = $this->readPaymentModelArgument($observer); // Get a validated additional data array
$additionalData = DataArrayValidator::getArrayOnlyWithApprovedKeys(
$additionalData,
self::$approvedAdditionalDataKeys
);
// set ccType // json decode state data
$variant = $additionalData['variant']; $stateData = [];
$ccType = $this->adyenHelper->getMagentoCreditCartType($variant); if (!empty($additionalData[self::STATE_DATA])) {
$paymentInfo->setCcType($ccType); $stateData = json_decode($additionalData[self::STATE_DATA], true);
}
foreach ($this->additionalInformationList as $additionalInformationKey) { // Get validated state data array
if (isset($additionalData[$additionalInformationKey])) { if (!empty($stateData)) {
$paymentInfo->setAdditionalInformation( $stateData = $this->checkoutStateDataValidator->getValidatedAdditionalData(
$additionalInformationKey, $stateData
$additionalData[$additionalInformationKey]
); );
} }
// Replace state data with the decoded and validated state data
$additionalData[self::STATE_DATA] = $stateData;
// Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer);
foreach ($additionalData as $key => $data) {
$paymentInfo->setAdditionalInformation($key, $data);
}
// set ccType
if (!empty($stateData[self::BRAND])) {
$ccType = $this->adyenHelper->getMagentoCreditCartType($stateData[self::BRAND]);
$paymentInfo->setCcType($ccType);
} }
// set customerInteraction // set customerInteraction
...@@ -115,11 +132,6 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver ...@@ -115,11 +132,6 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
} else { } else {
$paymentInfo->setAdditionalInformation('customer_interaction', false); $paymentInfo->setAdditionalInformation('customer_interaction', false);
} }
// set ccType
$variant = $additionalData['variant'];
$ccType = $this->adyenHelper->getMagentoCreditCartType($variant);
$paymentInfo->setAdditionalInformation('cc_type', $ccType);
} }
/** /**
......
...@@ -71,6 +71,12 @@ ...@@ -71,6 +71,12 @@
<fieldset <fieldset
data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}"> data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}">
<div id="oneclick_actionModalWrapper">
<div id="oneclick_actionModal">
<div id="oneclick_actionContainer"></div>
</div>
</div>
<!-- ko if: agreement_data.card --> <!-- ko if: agreement_data.card -->
<div class="field number"> <div class="field number">
<label class="label"> <label class="label">
...@@ -135,10 +141,6 @@ ...@@ -135,10 +141,6 @@
</div> </div>
<!-- /ko --> <!-- /ko -->
<div id="threeDS2ModalOneClick">
<div id="threeDS2ContainerOneClick"></div>
</div>
</fieldset> </fieldset>
<div class="checkout-agreements-block"> <div class="checkout-agreements-block">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment