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 3c5450eb authored by cyattilakiss's avatar cyattilakiss Committed by GitHub

Merge pull request #562 from Adyen/develop

Release 5.0.0
parents 187e3f09 13076721
* @msilvagarcia @cyattilakiss @Aleffio @AlexandrosMor @rikterbeek
......@@ -2,6 +2,6 @@
**Plugin version**: x.y.z
**Description**
<!--
- please provide description of the issue. In case of bug report, please provide the necessary steps to reproduce.
- Please provide a description of the issue. In case of bug report, please provide the necessary steps to reproduce.
- For merchant specific requests, please use https://support.adyen.com
-->
\ No newline at end of file
......@@ -25,10 +25,10 @@ namespace Adyen\Payment\Api\Data;
interface NotificationInterface
{
/**#@+
/**
* Constants for keys of data array. Identical to the name of the getter in snake case.
*/
/*
* Entity ID.
*/
......@@ -66,7 +66,7 @@ interface NotificationInterface
*/
const AMOUNT_CURRENCY = 'amount_currency';
/*
* reason
* Reason
*/
const REASON = 'reason';
/*
......@@ -74,7 +74,7 @@ interface NotificationInterface
*/
const LIVE = 'live';
/*
* Live
* Done
*/
const DONE = 'done';
/*
......@@ -109,7 +109,7 @@ interface NotificationInterface
/**
* Gets the Pspreference for the notification.
*
* @return int|null Pspreference.
* @return string|null Pspreference.
*/
public function getPspreference();
......@@ -133,14 +133,14 @@ interface NotificationInterface
/**
* Gets the OriginalReference for the notification.
*
* @return int|null OriginalReference.
* @return string|null OriginalReference.
*/
public function getOriginalReference();
/**
* Gets the Merchantreference for the notification.
*
* @return int|null MerchantReference.
* @return string|null MerchantReference.
*/
public function getMerchantReference();
......@@ -155,7 +155,7 @@ interface NotificationInterface
/**
* Gets the Eventcode for the notification.
*
* @return int|null Eventcode.
* @return string|null Eventcode.
*/
public function getEventCode();
......@@ -172,7 +172,7 @@ interface NotificationInterface
*
* @return int|null Success.
*/
public function getSucess();
public function getSuccess();
/**
* Sets Success.
......@@ -185,7 +185,7 @@ interface NotificationInterface
/**
* Gets the Paymentmethod for the notification.
*
* @return int|null PaymentMethod.
* @return string|null PaymentMethod.
*/
public function getPaymentMethod();
......@@ -213,11 +213,11 @@ interface NotificationInterface
public function setAmountValue($amountValue);
/**
* Gets the AmountValue for the notification.
* Gets the AmountCurrency for the notification.
*
* @return int|null AmountValue.
* @return string|null AmountCurrency.
*/
public function getAmountCurency();
public function getAmountCurrency();
/**
* Sets AmountCurrency.
......
......@@ -25,10 +25,10 @@ namespace Adyen\Payment\Api\Data;
interface OrderPaymentInterface
{
/**#@+
/**
* Constants for keys of data array. Identical to the name of the getter in snake case.
*/
/*
* Entity ID.
*/
......
......@@ -112,11 +112,11 @@ class Installments extends \Magento\Config\Block\System\Config\Form\Field\FieldA
*/
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
$installlments = $row->getInstallments();
$installments = $row->getInstallments();
$options = [];
if ($installlments) {
$options['option_' . $this->getNumberOfInstallmentsRenderer()->calcOptionHash($installlments)]
if ($installments) {
$options['option_' . $this->getNumberOfInstallmentsRenderer()->calcOptionHash($installments)]
= 'selected="selected"';
$ccTypes = $row->getCcTypes();
......
......@@ -82,11 +82,11 @@ class InstallmentsPosCloud extends \Magento\Config\Block\System\Config\Form\Fiel
*/
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
$installlments = $row->getInstallments();
$installments = $row->getInstallments();
$options = [];
if ($installlments) {
$options['option_' . $this->getNumberOfInstallmentsRenderer()->calcOptionHash($installlments)]
if ($installments) {
$options['option_' . $this->getNumberOfInstallmentsRenderer()->calcOptionHash($installments)]
= 'selected="selected"';
}
$row->setData('option_extra_attrs', $options);
......
......@@ -99,15 +99,10 @@ class Cc extends \Magento\Payment\Block\Form\Cc
*/
public function hasVerification()
{
// if backend order and moto payments is turned on don't show cvc
// On Backend always use MOTO
if ($this->appState->getAreaCode() === \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) {
$this->getCheckoutSession();
$store = $this->checkoutSession->getQuote()->getStore();
$enableMoto = $this->adyenHelper->getAdyenCcConfigDataFlag('enable_moto', $store->getId());
if ($enableMoto) {
return false;
}
}
return true;
}
......@@ -120,7 +115,7 @@ class Cc extends \Magento\Payment\Block\Form\Cc
}
/**
* Retrieve availables credit card type codes by alt code
* Retrieve available credit card type codes by alt code
*
* @return array
*/
......@@ -141,4 +136,26 @@ class Cc extends \Magento\Payment\Block\Form\Cc
return $types;
}
/**
* Allow checkbox for MOTO payments to be saved as RECURRING
*
* @return bool
*/
public function allowRecurring()
{
if ($this->adyenHelper->getAdyenAbstractConfigData('enable_recurring', null)) {
return true;
}
return false;
}
/**
* @return mixed
*/
public function isVaultEnabled()
{
return $this->adyenHelper->isCreditCardVaultEnabled();
}
}
......@@ -36,7 +36,7 @@ class Oneclick extends \Adyen\Payment\Block\Form\Cc
protected $_sessionQuote;
/**
* Cc constructor.
* Oneclick constructor.
*
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Magento\Payment\Model\Config $paymentConfig
......
......@@ -32,9 +32,10 @@ class Cc extends AbstractInfo
protected $_template = 'Adyen_Payment::info/adyen_cc.phtml';
/**
* Return credit cart type
* Return credit card type
*
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function getCcTypeName()
{
......
......@@ -49,7 +49,7 @@ class Hpp extends AbstractInfo
}
/**
* Get all multibanco related data
* Get all Multibanco related data
*
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
......
......@@ -301,7 +301,7 @@ class Result extends \Magento\Framework\App\Action\Action
}
/**
* Authenticate using sha1 Merchant signature
* Authenticate using sha256 Merchant signature
*
* @param $response
* @return bool
......
......@@ -69,8 +69,13 @@ class TransactionAuthorization implements ClientInterface
public function placeRequest(\Magento\Payment\Gateway\Http\TransferInterface $transferObject)
{
$request = $transferObject->getBody();
$headers = $transferObject->getHeaders();
$requestOptions['idempotencyKey'] = $request['reference'];
$requestOptions = [];
if (!empty($headers['idempotencyKey'])) {
$requestOptions['idempotencyKey'] = $headers['idempotencyKey'];
}
// call lib
$service = new \Adyen\Service\Payment($this->_client);
......
......@@ -55,6 +55,7 @@ class TransactionPayment implements ClientInterface
public function placeRequest(\Magento\Payment\Gateway\Http\TransferInterface $transferObject)
{
$request = $transferObject->getBody();
$headers = $transferObject->getHeaders();
// If the payments call is already done return the request
if (!empty($request['resultCode'])) {
......@@ -65,7 +66,12 @@ class TransactionPayment implements ClientInterface
$client = $this->adyenHelper->initializeAdyenClient();
$service = new \Adyen\Service\Checkout($client);
$requestOptions['idempotencyKey'] = $request['reference'];
$requestOptions = [];
if (!empty($headers['idempotencyKey'])) {
$requestOptions['idempotencyKey'] = $headers['idempotencyKey'];
}
try {
$response = $service->payments($request, $requestOptions);
......
......@@ -52,8 +52,14 @@ class TransferFactory implements TransferFactoryInterface
*/
public function create(array $request)
{
return $this->transferBuilder
->setBody($request)
if (!empty($request['headers'])) {
$this->transferBuilder->setHeaders($request['headers']);
}
$transfer = $this->transferBuilder
->setBody($request['body'])
->build();
return $transfer;
}
}
......@@ -61,6 +61,8 @@ class AddressDataBuilder implements BuilderInterface
$billingAddress = $order->getBillingAddress();
$shippingAddress = $order->getShippingAddress();
return $this->adyenRequestsHelper->buildAddressData([], $billingAddress, $shippingAddress);
$request['body'] = $this->adyenRequestsHelper->buildAddressData([], $billingAddress, $shippingAddress);
return $request;
}
}
......@@ -55,12 +55,12 @@ class ApplePayAuthorizationDataBuilder implements BuilderInterface
public function build(array $buildSubject)
{
$request = [];
$requestBody = [];
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$token = $payment->getAdditionalInformation('token');
$request['paymentMethod']['type'] = 'applepay';
$requestBody['paymentMethod']['type'] = 'applepay';
// get payment data
if ($token) {
......@@ -68,7 +68,7 @@ class ApplePayAuthorizationDataBuilder implements BuilderInterface
$paymentData = $parsedToken->token->paymentData;
try {
$paymentData = base64_encode(json_encode($paymentData));
$request['paymentMethod']['applepay.token'] = $paymentData;
$requestBody['paymentMethod']['applepay.token'] = $paymentData;
} catch (\Exception $exception) {
$this->_adyenLogger->addAdyenDebug("exception: " . $exception->getMessage());
}
......@@ -76,6 +76,8 @@ class ApplePayAuthorizationDataBuilder implements BuilderInterface
$this->_adyenLogger->addAdyenDebug("PaymentToken is empty");
}
$request['body'] = $requestBody;
return $request;
}
}
......@@ -52,6 +52,7 @@ class BrowserInfoDataBuilder implements BuilderInterface
*/
public function build(array $buildSubject)
{
return $this->adyenRequestsHelper->buildBrowserData();
$request['body'] = $this->adyenRequestsHelper->buildBrowserData();
return $request;
}
}
......@@ -60,9 +60,11 @@ class CancelDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
$pspReference = $payment->getCcTransId();
return [
$request['body'] = [
"reference" => $order->getOrderIncrementId(),
"originalReference" => $pspReference
];
return $request;
}
}
......@@ -67,7 +67,7 @@ class CaptureDataBuilder implements BuilderInterface
$amount = $this->adyenHelper->formatAmount($amount, $currency);
$modificationAmount = ['currency' => $currency, 'value' => $amount];
$request = [
$requestBody = [
"modificationAmount" => $modificationAmount,
"reference" => $payment->getOrder()->getIncrementId(),
"originalReference" => $pspReference
......@@ -79,9 +79,11 @@ class CaptureDataBuilder implements BuilderInterface
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($brandCode)) {
$openInvoiceFields = $this->getOpenInvoiceData($payment);
$request["additionalData"] = $openInvoiceFields;
$requestBody["additionalData"] = $openInvoiceFields;
}
$request['body'] = $requestBody;
return $request;
}
......
......@@ -15,7 +15,7 @@
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
......@@ -24,32 +24,52 @@
namespace Adyen\Payment\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
class CcAuthorizationDataBuilder implements BuilderInterface
{
/**
* @param array $buildSubject
* @return array|mixed
* @throws \Magento\Framework\Exception\LocalizedException
* @return mixed
*/
public function build(array $buildSubject)
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
// retrieve payments response which we already got and saved in the payment controller
if ($response = $payment->getAdditionalInformation("paymentsResponse")) {
// the payments response needs to be passed to the next process because after this point we don't have
// access to the payment object therefore to the additionalInformation array
$request = $response;
// Remove from additional data
$payment->unsAdditionalInformation("paymentsResponse");
} else {
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
$requestBody = [];
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$requestBody['paymentMethod']['type'] = "scheme";
if ($cardNumber = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER)) {
$requestBody['paymentMethod']['encryptedCardNumber'] = $cardNumber;
}
if ($expiryMonth = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH)) {
$requestBody['paymentMethod']['encryptedExpiryMonth'] = $expiryMonth;
}
if ($expiryYear = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR)) {
$requestBody['paymentMethod']['encryptedExpiryYear'] = $expiryYear;
}
if ($holderName = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME)) {
$requestBody['paymentMethod']['holderName'] = $holderName;
}
if ($securityCode = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE)) {
$requestBody['paymentMethod']['encryptedSecurityCode'] = $securityCode;
}
// Remove from additional data
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME);
// if installments is set add it into the request
if ($payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) &&
$payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) > 0
) {
$requestBody['installments']['value'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS);
}
$request['body'] = $requestBody;
return $request;
}
}
\ No newline at end of file
......@@ -63,23 +63,23 @@ class CcBackendAuthorizationDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
$order = $paymentDataObject->getOrder();
$storeId = $order->getStoreId();
$request = [];
$requestBody = [];
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$request['paymentMethod']['type'] = 'scheme';
$requestBody['paymentMethod']['type'] = 'scheme';
if ($cardNumber = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER)) {
$request['paymentMethod']['encryptedCardNumber'] = $cardNumber;
$requestBody['paymentMethod']['encryptedCardNumber'] = $cardNumber;
}
if ($expiryMonth = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_MONTH)) {
$request['paymentMethod']['encryptedExpiryMonth'] = $expiryMonth;
$requestBody['paymentMethod']['encryptedExpiryMonth'] = $expiryMonth;
}
if ($expiryYear = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_EXPIRY_YEAR)) {
$request['paymentMethod']['encryptedExpiryYear'] = $expiryYear;
$requestBody['paymentMethod']['encryptedExpiryYear'] = $expiryYear;
}
if ($holderName = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME)) {
$request['paymentMethod']['holderName'] = $holderName;
$requestBody['paymentMethod']['holderName'] = $holderName;
}
if ($securityCode = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE)) {
$request['paymentMethod']['encryptedSecurityCode'] = $securityCode;
$requestBody['paymentMethod']['encryptedSecurityCode'] = $securityCode;
}
// Remove from additional data
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_CREDIT_CARD_NUMBER);
......@@ -88,20 +88,27 @@ class CcBackendAuthorizationDataBuilder implements BuilderInterface
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_SECURITY_CODE);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME);
/**
* if MOTO for backend is enabled use MOTO as shopper interaction type
* On Backend always use MOTO
*/
$enableMoto = $this->adyenHelper->getAdyenCcConfigDataFlag('enable_moto', $storeId);
if ($this->appState->getAreaCode() === \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE &&
$enableMoto
) {
$request['shopperInteraction'] = "Moto";
}
$requestBody['shopperInteraction'] = "Moto";
// if installments is set add it into the request
if ($payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) &&
$payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) > 0
) {
$request['installments']['value'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS);
$requestBody['installments']['value'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS);
}
// Flow for Billing agreements, for Vault check VaultDataBuilder
if (!$this->adyenHelper->isCreditCardVaultEnabled()) {
if ($payment->getAdditionalInformation(AdyenCcDataAssignObserver::STORE_CC)) {
$requestBody['enableRecurring'] = true;
} else {
$requestBody['enableRecurring'] = false;
}
}
$request['body'] = $requestBody;
return $request;
}
}
......@@ -69,31 +69,31 @@ class CheckoutDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
$order = $payment->getOrder();
$storeId = $order->getStoreId();
$request = [];
$requestBody = [];
// do not send email
$order->setCanSendNewEmailFlag(false);
$request['paymentMethod']['type'] = $payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE);
$requestBody['paymentMethod']['type'] = $payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE);
// Additional data for payment methods with issuer list
if ($payment->getAdditionalInformation(AdyenHppDataAssignObserver::ISSUER_ID)) {
$request['paymentMethod']['issuer'] = $payment->getAdditionalInformation(AdyenHppDataAssignObserver::ISSUER_ID);
$requestBody['paymentMethod']['issuer'] = $payment->getAdditionalInformation(AdyenHppDataAssignObserver::ISSUER_ID);
}
$request['returnUrl'] = $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK) . 'adyen/process/result';
$requestBody['returnUrl'] = $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK) . 'adyen/process/result';
// Additional data for ACH
if ($payment->getAdditionalInformation("bankAccountNumber")) {
$request['bankAccount']['bankAccountNumber'] = $payment->getAdditionalInformation("bankAccountNumber");
$requestBody['bankAccount']['bankAccountNumber'] = $payment->getAdditionalInformation("bankAccountNumber");
}
if ($payment->getAdditionalInformation("bankLocationId")) {
$request['bankAccount']['bankLocationId'] = $payment->getAdditionalInformation("bankLocationId");
$requestBody['bankAccount']['bankLocationId'] = $payment->getAdditionalInformation("bankLocationId");
}
if ($payment->getAdditionalInformation("bankAccountOwnerName")) {
$request['bankAccount']['ownerName'] = $payment->getAdditionalInformation("bankAccountOwnerName");
$requestBody['bankAccount']['ownerName'] = $payment->getAdditionalInformation("bankAccountOwnerName");
}
// Additional data for open invoice payment
......@@ -101,31 +101,31 @@ class CheckoutDataBuilder implements BuilderInterface
$order->setCustomerGender(\Adyen\Payment\Model\Gender::getMagentoGenderFromAdyenGender(
$payment->getAdditionalInformation("gender"))
);
$request['paymentMethod']['personalDetails']['gender'] = $payment->getAdditionalInformation("gender");
$requestBody['paymentMethod']['personalDetails']['gender'] = $payment->getAdditionalInformation("gender");
}
if ($payment->getAdditionalInformation("dob")) {
$order->setCustomerDob($payment->getAdditionalInformation("dob"));
$request['paymentMethod']['personalDetails']['dateOfBirth']= $this->adyenHelper->formatDate($payment->getAdditionalInformation("dob"), 'Y-m-d') ;
$requestBody['paymentMethod']['personalDetails']['dateOfBirth']= $this->adyenHelper->formatDate($payment->getAdditionalInformation("dob"), 'Y-m-d') ;
}
if ($payment->getAdditionalInformation("telephone")) {
$order->getBillingAddress()->setTelephone($payment->getAdditionalInformation("telephone"));
$request['paymentMethod']['personalDetails']['telephoneNumber']= $payment->getAdditionalInformation("telephone");
$requestBody['paymentMethod']['personalDetails']['telephoneNumber']= $payment->getAdditionalInformation("telephone");
}
if ($payment->getAdditionalInformation("ssn")) {
$request['paymentMethod']['personalDetails']['socialSecurityNumber']= $payment->getAdditionalInformation("ssn");
$requestBody['paymentMethod']['personalDetails']['socialSecurityNumber']= $payment->getAdditionalInformation("ssn");
}
// Additional data for sepa direct debit
if ($payment->getAdditionalInformation("ownerName")) {
$request['paymentMethod']['sepa.ownerName'] = $payment->getAdditionalInformation("ownerName");
$requestBody['paymentMethod']['sepa.ownerName'] = $payment->getAdditionalInformation("ownerName");
}
if ($payment->getAdditionalInformation("ibanNumber")) {
$request['paymentMethod']['sepa.ibanNumber'] = $payment->getAdditionalInformation("ibanNumber");
$requestBody['paymentMethod']['sepa.ibanNumber'] = $payment->getAdditionalInformation("ibanNumber");
}
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod(
......@@ -137,27 +137,27 @@ class CheckoutDataBuilder implements BuilderInterface
)
) {
$openInvoiceFields = $this->getOpenInvoiceData($order);
$request = array_merge($request, $openInvoiceFields);
$requestBody = array_merge($requestBody, $openInvoiceFields);
}
// Ratepay specific Fingerprint
if ($payment->getAdditionalInformation("df_value") && $this->adyenHelper->isPaymentMethodRatepayMethod(
$payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE)
)) {
$request['deviceFingerprint'] = $payment->getAdditionalInformation("df_value");
$requestBody['deviceFingerprint'] = $payment->getAdditionalInformation("df_value");
}
//Boleto data
if ($payment->getAdditionalInformation("social_security_number")) {
$request['socialSecurityNumber'] = $payment->getAdditionalInformation("social_security_number");
$requestBody['socialSecurityNumber'] = $payment->getAdditionalInformation("social_security_number");
}
if ($payment->getAdditionalInformation("firstname")) {
$request['shopperName']['firstName'] = $payment->getAdditionalInformation("firstname");
$requestBody['shopperName']['firstName'] = $payment->getAdditionalInformation("firstname");
}
if ($payment->getAdditionalInformation("lastName")) {
$request['shopperName']['lastName'] = $payment->getAdditionalInformation("lastName");
$requestBody['shopperName']['lastName'] = $payment->getAdditionalInformation("lastName");
}
if ($payment->getMethod() == \Adyen\Payment\Model\Ui\AdyenBoletoConfigProvider::CODE) {
......@@ -165,11 +165,11 @@ class CheckoutDataBuilder implements BuilderInterface
$boletoTypes = explode(',', $boletoTypes);
if (count($boletoTypes) == 1) {
$request['selectedBrand'] = $boletoTypes[0];
$request['paymentMethod']['type'] = $boletoTypes[0];
$requestBody['selectedBrand'] = $boletoTypes[0];
$requestBody['paymentMethod']['type'] = $boletoTypes[0];
} else {
$request['selectedBrand'] = $payment->getAdditionalInformation("boleto_type");
$request['paymentMethod']['type'] = $payment->getAdditionalInformation("boleto_type");
$requestBody['selectedBrand'] = $payment->getAdditionalInformation("boleto_type");
$requestBody['paymentMethod']['type'] = $payment->getAdditionalInformation("boleto_type");
}
$deliveryDays = (int)$this->adyenHelper->getAdyenBoletoConfigData("delivery_days", $storeId);
......@@ -186,10 +186,13 @@ class CheckoutDataBuilder implements BuilderInterface
)
);
$request['deliveryDate'] = $deliveryDate;
$requestBody['deliveryDate'] = $deliveryDate;
$order->setCanSendNewEmailFlag(true);
}
$request['body'] = $requestBody;
return $request;
}
......
......@@ -61,7 +61,8 @@ class CustomerDataBuilder implements BuilderInterface
$customerId = $order->getCustomerId();
$billingAddress = $order->getBillingAddress();
$storeId = $order->getStoreId();
return $this->adyenRequestsHelper->buildCustomerData([], $customerId, $billingAddress, $storeId, $payment);
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildCustomerData([], $customerId, $billingAddress, $storeId, $payment, $additionalInformation);
return $request;
}
}
......@@ -39,7 +39,8 @@ class CustomerIpDataBuilder implements BuilderInterface
*
* @param \Adyen\Payment\Helper\Requests $adyenRequestsHelper
*/
public function __construct(\Adyen\Payment\Helper\Requests $adyenRequestsHelper)
public function __construct(
\Adyen\Payment\Helper\Requests $adyenRequestsHelper)
{
$this->adyenRequestsHelper = $adyenRequestsHelper;
}
......@@ -52,8 +53,15 @@ class CustomerIpDataBuilder implements BuilderInterface
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$shopperIp = $paymentDataObject->getPayment()->getOrder()->getXForwardedFor();
$order = $paymentDataObject->getPayment()->getOrder();
$shopperIp = $order-> getRemoteIp();
return $this->adyenRequestsHelper->buildCustomerIpData([], $shopperIp);
if (empty($shopperIp)) {
$shopperIp = $order-> getXForwardedFor();
}
$request['body'] = $this->adyenRequestsHelper->buildCustomerIpData([], $shopperIp);
return $request;
}
}
......@@ -55,17 +55,17 @@ class GooglePayAuthorizationDataBuilder implements BuilderInterface
public function build(array $buildSubject)
{
$request = [];
$requestBody = [];
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$token = $payment->getAdditionalInformation('token');
$request['paymentMethod']['type'] = 'paywithgoogle';
$requestBody['paymentMethod']['type'] = 'paywithgoogle';
// get payment data
if ($token) {
$parsedToken = json_decode($token);
try {
$request['paymentMethod']['paywithgoogle.token'] = $parsedToken;
$requestBody['paymentMethod']['paywithgoogle.token'] = $parsedToken;
} catch (\Exception $exception) {
$this->adyenLogger->addAdyenDebug("exception: " . $exception->getMessage());
}
......@@ -73,6 +73,8 @@ class GooglePayAuthorizationDataBuilder implements BuilderInterface
$this->adyenLogger->addAdyenDebug("PaymentToken is empty");
}
$request['body'] = $requestBody;
return $request;
}
}
......@@ -56,6 +56,8 @@ class MerchantAccountDataBuilder implements BuilderInterface
$storeId = $order->getStoreId();
$method = $payment->getMethod();
return $this->adyenRequestsHelper->buildMerchantAccountData([], $method, $storeId);
$request['body'] = $this->adyenRequestsHelper->buildMerchantAccountData([], $method, $storeId);
return $request;
}
}
......@@ -34,7 +34,7 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface
private $adyenHelper;
/**
* CaptureDataBuilder constructor.
* OneclickAuthorizationDataBuilder constructor.
*
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/
......@@ -49,20 +49,20 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface
*/
public function build(array $buildSubject)
{
$request = [];
$requestBody = [];
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$request['paymentMethod']['type'] = "scheme";
$requestBody['paymentMethod']['type'] = "scheme";
if ($variant = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::VARIANT)) {
$request['paymentMethod']['type'] = $variant;
$requestBody['paymentMethod']['type'] = $variant;
}
if ($securityCode = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::ENCRYPTED_SECURITY_CODE)) {
$request['paymentMethod']['encryptedSecurityCode'] = $securityCode;
$requestBody['paymentMethod']['encryptedSecurityCode'] = $securityCode;
}
$payment->unsAdditionalInformation(AdyenOneclickDataAssignObserver::ENCRYPTED_SECURITY_CODE);
......@@ -73,12 +73,12 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface
$shopperInteraction = "ContAuth";
}
$request['shopperInteraction'] = $shopperInteraction;
$request['paymentMethod']['recurringDetailReference'] = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::RECURRING_DETAIL_REFERENCE);
$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 ($payment->getCcType() == "sepadirectdebit") {
$request['selectedBrand'] = "sepadirectdebit";
$requestBody['selectedBrand'] = "sepadirectdebit";
}
/*
......@@ -87,15 +87,16 @@ class OneclickAuthorizationDataBuilder implements BuilderInterface
*/
if (!$payment->getAdditionalInformation('customer_interaction')) {
if ($payment->getCcType() == "directEbanking" || $payment->getCcType() == "ideal") {
$request['selectedBrand'] = "sepadirectdebit";
$requestBody['selectedBrand'] = "sepadirectdebit";
}
}
// if installments is set add it into the request
if ($payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::NUMBER_OF_INSTALLMENTS) > 0) {
$request['installments']['value'] = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::NUMBER_OF_INSTALLMENTS);
$requestBody['installments']['value'] = $payment->getAdditionalInformation(AdyenOneclickDataAssignObserver::NUMBER_OF_INSTALLMENTS);
}
$request['body'] = $requestBody;
return $request;
}
}
......@@ -60,7 +60,12 @@ class PaymentDataBuilder implements BuilderInterface
$currencyCode = $fullOrder->getOrderCurrencyCode();
$amount = $fullOrder->getGrandTotal();
$reference = $order->getOrderIncrementId();
$paymentMethod = $payment->getMethod();
return $this->adyenRequestsHelper->buildPaymentData([], $amount, $currencyCode, $reference);
$request['body'] = $this->adyenRequestsHelper->buildPaymentData([], $amount, $currencyCode, $reference, $paymentMethod);
$request['headers'] = $this->adyenRequestsHelper->addIdempotencyKey([], $paymentMethod, $reference);
return $request;
}
}
......@@ -38,11 +38,13 @@ class PosCloudBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
return [
$request['body'] = [
"response" => $payment->getAdditionalInformation("terminalResponse"),
"serviceID" => $payment->getAdditionalInformation("serviceID"),
"initiateDate" => $payment->getAdditionalInformation("initiateDate"),
"terminalID" => $payment->getAdditionalInformation("terminal_id")
];
return $request;
}
}
......@@ -64,7 +64,8 @@ class RecurringDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
$storeId = $payment->getOrder()->getStoreId();
$areaCode = $this->appState->getAreaCode();
return $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId, $payment);
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId, $additionalInformation);
return $request;
}
}
......@@ -33,17 +33,20 @@ class RecurringVaultDataBuilder implements BuilderInterface
*/
public function build(array $buildSubject)
{
$result = [];
$requestBody = [];
$recurring = ['contract' => \Adyen\Payment\Model\RecurringType::RECURRING];
$result['recurring'] = $recurring;
$requestBody['recurring'] = $recurring;
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$extensionAttributes = $payment->getExtensionAttributes();
$paymentToken = $extensionAttributes->getVaultPaymentToken();
$result['selectedRecurringDetailReference'] = $paymentToken->getGatewayToken();
$result['shopperInteraction'] = 'ContAuth';
return $result;
$requestBody['selectedRecurringDetailReference'] = $paymentToken->getGatewayToken();
$requestBody['shopperInteraction'] = 'ContAuth';
$request['body'] = $requestBody;
return $request;
}
}
......@@ -107,7 +107,7 @@ class RefundDataBuilder implements BuilderInterface
}
// loop over payment methods and refund them all
$result = [];
$requestBody = [];
foreach ($orderPaymentCollection as $splitPayment) {
// could be that not all the split payments need a refund
if ($amount > 0) {
......@@ -140,7 +140,7 @@ class RefundDataBuilder implements BuilderInterface
'value' => $this->adyenHelper->formatAmount($modificationAmount, $currency)
];
$result[] = [
$requestBody[] = [
"modificationAmount" => $modificationAmountObject,
"reference" => $payment->getOrder()->getIncrementId(),
"originalReference" => $splitPayment->getPspreference(),
......@@ -153,7 +153,7 @@ class RefundDataBuilder implements BuilderInterface
$amount = $this->adyenHelper->formatAmount($amount, $currency);
$modificationAmount = ['currency' => $currency, 'value' => $amount];
$result = [
$requestBody = [
[
"modificationAmount" => $modificationAmount,
"reference" => $payment->getOrder()->getIncrementId(),
......@@ -170,11 +170,13 @@ class RefundDataBuilder implements BuilderInterface
$openInvoiceFields = $this->getOpenInvoiceData($payment);
//There is only one payment, so we add the fields to the first(and only) result
$result[0]["additionalData"] = $openInvoiceFields;
$requestBody[0]["additionalData"] = $openInvoiceFields;
}
}
return $result;
$request['body'] = $requestBody;
return $request;
}
/**
......
......@@ -13,22 +13,57 @@
* #############
* ############
*
* Adyen Payment Module
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
* Copyright (c) 2019 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Api;
namespace Adyen\Payment\Gateway\Request;
interface AdyenPaymentProcessInterface
use Magento\Payment\Gateway\Request\BuilderInterface;
class ThreeDS2DataBuilder implements BuilderInterface
{
/**
* @param string $payload
* @return string
* @var \Magento\Framework\App\State
*/
private $appState;
/**
* @var \Adyen\Payment\Helper\Requests
*/
private $adyenRequestsHelper;
/**
* ThreeDS2DataBuilder constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Adyen\Payment\Helper\Requests $adyenRequestsHelper
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Adyen\Payment\Helper\Requests $adyenRequestsHelper
) {
$this->appState = $context->getAppState();
$this->adyenRequestsHelper = $adyenRequestsHelper;
}
/**
* @param array $buildSubject
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function initiate($payload);
public function build(array $buildSubject)
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildThreeDS2Data([], $additionalInformation);
return $request;
}
}
<?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\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
class RecurringDataBuilder implements BuilderInterface
{
/**
* @var \Magento\Framework\App\State
*/
private $appState;
/**
* @var \Adyen\Payment\Helper\Requests
*/
private $adyenRequestsHelper;
/**
* RecurringDataBuilder constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Adyen\Payment\Helper\Requests $adyenRequestsHelper
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Adyen\Payment\Helper\Requests $adyenRequestsHelper
) {
$this->appState = $context->getAppState();
$this->adyenRequestsHelper = $adyenRequestsHelper;
}
/**
* @param array $buildSubject
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function build(array $buildSubject)
{
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$storeId = $payment->getOrder()->getStoreId();
$areaCode = $this->appState->getAreaCode();
return $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId, $payment);
}
}
......@@ -54,6 +54,8 @@ class VaultDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
$additionalInformation = $payment->getAdditionalInformation();
return $this->adyenRequestsHelper->buildVaultData([], $additionalInformation);
$request['body'] = $this->adyenRequestsHelper->buildVaultData([], $additionalInformation);
return $request;
}
}
......@@ -66,10 +66,19 @@ class CheckoutResponseValidator extends AbstractValidator
$payment->setAdditionalInformation('3dActive', false);
$isValid = true;
$errorMessages = [];
// validate result
if (isset($response['resultCode'])) {
switch ($response['resultCode']) {
case "IdentifyShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.fingerprintToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
break;
case "ChallengeShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.challengeToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
break;
case "Authorised":
case "Received":
// For banktransfers store all bankTransfer details
......@@ -93,10 +102,6 @@ class CheckoutResponseValidator extends AbstractValidator
$payment->setAdditionalInformation('cc_type', $ccType);
$payment->setCcType($ccType);
}
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
break;
case "Received":
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
break;
case "PresentToShopper":
......@@ -129,6 +134,8 @@ class CheckoutResponseValidator extends AbstractValidator
break;
case "RedirectShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$redirectUrl = null;
$paymentData = null;
......
......@@ -61,13 +61,13 @@ class ThreeDS2ResponseValidator extends AbstractValidator
if ($response['resultCode'] == "IdentifyShopper" &&
!empty($response['authentication']['threeds2.fingerprintToken'])
) {
$payment->setAdditionalInformation('threeDS2Type', $response['resultCode']);
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.fingerprintToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
} elseif ($response['resultCode'] == "ChallengeShopper" &&
!empty($response['authentication']['threeds2.challengeToken'])
) {
$payment->setAdditionalInformation('threeDS2Type', $response['resultCode']);
$payment->setAdditionalInformation('threeDSType', $response['resultCode']);
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.challengeToken']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
} else {
......
......@@ -33,8 +33,8 @@ class Data extends AbstractHelper
const MODULE_NAME = 'adyen-magento2';
const TEST = 'test';
const LIVE = 'live';
const CHECKOUT_COMPONENT_JS_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.0.0/adyen.js';
const CHECKOUT_COMPONENT_JS_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/3.0.0/adyen.js';
const CHECKOUT_COMPONENT_JS_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.2.0/adyen.js';
const CHECKOUT_COMPONENT_JS_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/3.2.0/adyen.js';
/**
* @var \Magento\Framework\Encryption\EncryptorInterface
......@@ -1834,12 +1834,13 @@ class Data extends AbstractHelper
{
$response = ['threeDS2' => false];
if(!empty($type)) {
$response['type'] = $type;
}
if ($type && $token) {
$response = [
"threeDS2" => true,
"type" => $type,
"token" => $token
];
$response['threeDS2'] = true;
$response['token'] = $token;
}
return json_encode($response);
......
......@@ -72,10 +72,10 @@ class Requests extends AbstractHelper
* @param $billingAddress
* @param $storeId
* @param null $payment
* @param null $payload
* @param null $additionalData
* @return array
*/
public function buildCustomerData($request = [], $customerId = 0, $billingAddress, $storeId, $payment = null, $payload = null)
public function buildCustomerData($request = [], $customerId = 0, $billingAddress, $storeId, $payment = null, $additionalData = null)
{
if ($customerId > 0) {
$request['shopperReference'] = $customerId;
......@@ -87,13 +87,13 @@ class Requests extends AbstractHelper
}
// In case of virtual product and guest checkout there is a workaround to get the guest's email address
if (!empty($payload['additional_data']['guestEmail'])) {
if (!empty($additionalData['guestEmail'])) {
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethod) &&
!$this->adyenHelper->isPaymentMethodAfterpayTouchMethod($paymentMethod)
) {
$request['paymentMethod']['personalDetails']['shopperEmail'] = $payload['additional_data']['guestEmail'];
$request['paymentMethod']['personalDetails']['shopperEmail'] = $additionalData['guestEmail'];
} else {
$request['shopperEmail'] = $payload['additional_data']['guestEmail'];
$request['shopperEmail'] = $additionalData['guestEmail'];
}
}
......@@ -262,20 +262,20 @@ class Requests extends AbstractHelper
}
/**
* @param $request
* @param array $request
* @param $amount
* @param $currencyCode
* @param $reference
* @return mixed
* @param $paymentMethod
* @return array
*/
public function buildPaymentData($request = [], $amount, $currencyCode, $reference)
public function buildPaymentData($request = [], $amount, $currencyCode, $reference, $paymentMethod)
{
$request['amount'] = [
'currency' => $currencyCode,
'value' => $this->adyenHelper->formatAmount($amount, $currencyCode)
];
$request["reference"] = $reference;
$request["fraudOffset"] = "0";
......@@ -302,23 +302,22 @@ class Requests extends AbstractHelper
* @param $store
* @return array
*/
public function buildThreeDS2Data($request = [], $payload, $store)
public function buildThreeDS2Data($request = [], $additionalData)
{
$request['additionalData']['allow3DS2'] = true;
$request['origin'] = $this->adyenHelper->getOrigin();
$request['channel'] = 'web';
$request['browserInfo']['screenWidth'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_WIDTH];
$request['browserInfo']['screenHeight'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_HEIGHT];
$request['browserInfo']['colorDepth'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH];
$request['browserInfo']['timeZoneOffset'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::TIMEZONE_OFFSET];
$request['browserInfo']['language'] = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::LANGUAGE];
$request['browserInfo']['screenWidth'] = $additionalData[AdyenCcDataAssignObserver::SCREEN_WIDTH];
$request['browserInfo']['screenHeight'] = $additionalData[AdyenCcDataAssignObserver::SCREEN_HEIGHT];
$request['browserInfo']['colorDepth'] = $additionalData[AdyenCcDataAssignObserver::SCREEN_COLOR_DEPTH];
$request['browserInfo']['timeZoneOffset'] = $additionalData[AdyenCcDataAssignObserver::TIMEZONE_OFFSET];
$request['browserInfo']['language'] = $additionalData[AdyenCcDataAssignObserver::LANGUAGE];
if ($javaEnabled = $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::JAVA_ENABLED]) {
if ($javaEnabled = $additionalData[AdyenCcDataAssignObserver::JAVA_ENABLED]) {
$request['browserInfo']['javaEnabled'] = $javaEnabled;
} else {
$request['browserInfo']['javaEnabled'] = false;
}
return $request;
}
......@@ -328,7 +327,7 @@ class Requests extends AbstractHelper
* @param $storeId
* @param $payment
*/
public function buildRecurringData($request = [], $areaCode, int $storeId, $payload)
public function buildRecurringData($request = [], $areaCode, int $storeId, $additionalData)
{
// If the vault feature is on this logic is handled in the VaultDataBuilder
if (!$this->adyenHelper->isCreditCardVaultEnabled()) {
......@@ -352,7 +351,8 @@ class Requests extends AbstractHelper
$request['enableRecurring'] = false;
}
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::STORE_CC]) && $payload[PaymentInterface::KEY_ADDITIONAL_DATA][AdyenCcDataAssignObserver::STORE_CC] === true) {
// value can be 0,1 or true
if (!empty($additionalData[AdyenCcDataAssignObserver::STORE_CC])) {
$request['paymentMethod']['storeDetails'] = true;
}
}
......@@ -363,7 +363,7 @@ class Requests extends AbstractHelper
/**
* @param $request
* @param $payment
* @param $storeId
* @param $storeIdbuildCCData
* @return mixed
*/
public function buildCCData($request = [], $payload, $storeId, $areaCode)
......@@ -409,6 +409,15 @@ class Requests extends AbstractHelper
$request['paymentMethod']['recurringDetailReference'] = $recurringDetailReference;
}
// set customerInteraction
$recurringContractType = $this->adyenHelper->getAdyenOneclickConfigData('recurring_payment_type');
if (!empty($payload['method']) && $payload['method'] == 'adyen_oneclick'
&& $recurringContractType == \Adyen\Payment\Model\RecurringType::RECURRING) {
$request['shopperInteraction'] = "ContAuth";
} else {
$request['shopperInteraction'] = "Ecommerce";
}
/**
* if MOTO for backend is enabled use MOTO as shopper interaction type
*/
......@@ -439,7 +448,9 @@ class Requests extends AbstractHelper
{
if ($this->adyenHelper->isCreditCardVaultEnabled()) {
if (!empty($payload[PaymentInterface::KEY_ADDITIONAL_DATA][VaultConfigProvider::IS_ACTIVE_CODE]) &&
$payload[PaymentInterface::KEY_ADDITIONAL_DATA][VaultConfigProvider::IS_ACTIVE_CODE] === true
$payload[PaymentInterface::KEY_ADDITIONAL_DATA][VaultConfigProvider::IS_ACTIVE_CODE] === true ||
!empty($payload[VaultConfigProvider::IS_ACTIVE_CODE]) &&
$payload[VaultConfigProvider::IS_ACTIVE_CODE] === true
) {
// store it only as oneclick otherwise we store oneclick tokens (maestro+bcmc) that will fail
$request['enableRecurring'] = true;
......@@ -471,4 +482,21 @@ class Requests extends AbstractHelper
return $address;
}
/**
* Only adds idempotency key if payment method is adyen_hpp for now
*
* @param array $request
* @param $paymentMethod
* @param $idempotencyKey
* @return array
*/
public function addIdempotencyKey($request = [], $paymentMethod, $idempotencyKey)
{
if (!empty($paymentMethod) && $paymentMethod == 'adyen_hpp') {
$request['idempotencyKey'] = $idempotencyKey;
}
return $request;
}
}
<?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\AdyenPaymentProcessInterface;
class AdyenPaymentProcess implements AdyenPaymentProcessInterface
{
/**
* @var \Magento\Checkout\Model\Session
*/
private $checkoutSession;
/**
* @var \Adyen\Payment\Helper\Data
*/
private $adyenHelper;
/**
* @var \Adyen\Payment\Helper\Requests
*/
private $adyenRequestHelper;
/**
* @var \Magento\Framework\Model\Context
*/
private $context;
/**
* @var \Adyen\Payment\Gateway\Http\TransferFactory
*/
private $transferFactory;
/**
* @var \Adyen\Payment\Gateway\Http\Client\TransactionPayment
*/
private $transactionPayment;
/**
* @var \Adyen\Payment\Gateway\Validator\CheckoutResponseValidator
*/
private $checkoutResponseValidator;
/**
* @var \Adyen\Payment\Gateway\Validator\ThreeDS2ResponseValidator
*/
private $threeDS2ResponseValidator;
/**
* AdyenPaymentProcess constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Checkout\Model\Session $checkoutSession
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Adyen\Payment\Helper\Requests $adyenRequestHelper
* @param \Adyen\Payment\Gateway\Http\TransferFactory $transferFactory
* @param \Adyen\Payment\Gateway\Http\Client\TransactionPayment $transactionPayment
* @param \Adyen\Payment\Gateway\Validator\CheckoutResponseValidator $checkoutResponseValidator
* @param \Adyen\Payment\Gateway\Validator\ThreeDS2ResponseValidator $threeDS2ResponseValidator
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Checkout\Model\Session $checkoutSession,
\Adyen\Payment\Helper\Data $adyenHelper,
\Adyen\Payment\Helper\Requests $adyenRequestHelper,
\Adyen\Payment\Gateway\Http\TransferFactory $transferFactory,
\Adyen\Payment\Gateway\Http\Client\TransactionPayment $transactionPayment,
\Adyen\Payment\Gateway\Validator\CheckoutResponseValidator $checkoutResponseValidator,
\Adyen\Payment\Gateway\Validator\ThreeDS2ResponseValidator $threeDS2ResponseValidator
)
{
$this->context = $context;
$this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper;
$this->adyenRequestHelper = $adyenRequestHelper;
$this->transferFactory = $transferFactory;
$this->transactionPayment = $transactionPayment;
$this->checkoutResponseValidator = $checkoutResponseValidator;
$this->threeDS2ResponseValidator = $threeDS2ResponseValidator;
}
/**
* @api
* @param string $payload
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function initiate($payload)
{
// Decode payload from frontend
$payload = json_decode($payload, true);
// Validate JSON that has just been parsed if it was in a valid format
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \Magento\Framework\Exception\LocalizedException(__('Error with payment method please select different payment method.'));
}
// Get payment and cart information from session
$quote = $this->checkoutSession->getQuote();
$payment = $quote->getPayment();
// Init request array
$request = [];
// Merchant account data builder
$paymentMethod = $payment->getMethod();
$storeId = $quote->getStoreId();
$request = $this->adyenRequestHelper->buildMerchantAccountData($request, $paymentMethod, $storeId);
// Customer data builder
$customerId = $quote->getCustomerId();
$billingAddress = $quote->getBillingAddress();
$request = $this->adyenRequestHelper->buildCustomerData($request, $customerId, $billingAddress, $storeId, null, $payload);
// Customer Ip data builder
$shopperIp = $quote->getXForwardedFor();
$request = $this->adyenRequestHelper->buildCustomerIpData($request, $shopperIp);
// AddressDataBuilder
$shippingAddress = $quote->getShippingAddress();
$request = $this->adyenRequestHelper->buildAddressData($request, $billingAddress, $shippingAddress);
// PaymentDataBuilder
$currencyCode = $quote->getQuoteCurrencyCode();
$amount = $quote->getGrandTotal();
// Setting the orderid to null, so that we generate a new one for each /payments call
$quote->setReservedOrderId(null);
$reference = $quote->reserveOrderId()->getReservedOrderId();
$request = $this->adyenRequestHelper->buildPaymentData($request, $amount, $currencyCode, $reference);
// Browser data builder
$request = $this->adyenRequestHelper->buildBrowserData($request);
// 3DS2.0 data builder
$isThreeDS2Enabled = $this->adyenHelper->isCreditCardThreeDS2Enabled($storeId);
if ($isThreeDS2Enabled) {
$request = $this->adyenRequestHelper->buildThreeDS2Data($request, $payload, $quote->getStore());
}
// RecurringDataBuilder
$areaCode = $this->context->getAppState()->getAreaCode();
$request = $this->adyenRequestHelper->buildRecurringData($request, $areaCode, $storeId, $payload);
// CcAuthorizationDataBuilder
$request = $this->adyenRequestHelper->buildCCData($request, $payload, $storeId, $areaCode);
// Vault data builder
$request = $this->adyenRequestHelper->buildVaultData($request, $payload);
// Create and send request
$transferObject = $this->transferFactory->create($request);
$paymentsResponse = $this->transactionPayment->placeRequest($transferObject);
// Check if 3DS2.0 validation is needed or not
// In case 3DS2.0 validation is necessary send the type and token back to the frontend
if (!empty($paymentsResponse['resultCode'])) {
if ($paymentsResponse['resultCode'] == 'IdentifyShopper' ||
$paymentsResponse['resultCode'] == 'ChallengeShopper') {
if ($this->threeDS2ResponseValidator->validate(array(
"response" => $paymentsResponse,
"payment" => $payment
))->isValid()) {
$quote->save();
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($payment->getAdditionalInformation('threeDS2Type'),
$payment->getAdditionalInformation('threeDS2Token'));
}
}
} else {
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
}
// Save the payments response because we are going to need it during the place order flow
$payment->setAdditionalInformation("paymentsResponse", $paymentsResponse);
// To actually save the additional info changes into the quote
$quote->save();
// Original flow can continue, return to frontend and place the order
return $this->adyenHelper->buildThreeDS2ProcessResponseJson();
}
}
......@@ -81,7 +81,7 @@ class AdyenRequestMerchantSession implements AdyenRequestMerchantSessionInterfac
"displayName":"' . $displayName . '"
}';
$this->_adyenLogger->addAdyenDebug("JSON Requesst is: " . print_r($data, true));
$this->_adyenLogger->addAdyenDebug("JSON Request is: " . print_r($data, true));
curl_setopt($ch, CURLOPT_URL, $validationUrl);
......
......@@ -37,6 +37,22 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
*/
private $adyenHelper;
/**
* @var \Magento\Sales\Model\OrderFactory
*/
private $orderFactory;
/**
* @var
*/
private $order;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
private $adyenLogger;
/**
* AdyenThreeDS2Process constructor.
*
......@@ -45,11 +61,15 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
*/
public function __construct(
\Magento\Checkout\Model\Session $checkoutSession,
\Adyen\Payment\Helper\Data $adyenHelper
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Sales\Model\OrderFactory $orderFactory,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger
)
{
$this->checkoutSession = $checkoutSession;
$this->adyenHelper = $adyenHelper;
$this->orderFactory = $orderFactory;
$this->adyenLogger = $adyenLogger;
}
/**
......@@ -68,8 +88,8 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
}
// Get payment and cart information from session
$quote = $this->checkoutSession->getQuote();
$payment = $quote->getPayment();
$order = $this->getOrder();
$payment = $order->getPayment();
// Init payments/details request
$result = [];
......@@ -83,6 +103,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// unset payment data from additional information
$payment->unsAdditionalInformation("threeDS2PaymentData");
} else {
$this->adyenLogger->error("3D secure 2.0 failed, payment data not found");
throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed, payment data not found'));
}
......@@ -95,11 +116,12 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// Send the request
try {
$client = $this->adyenHelper->initializeAdyenClient($quote->getStoreId());
$client = $this->adyenHelper->initializeAdyenClient($order->getStoreId());
$service = $this->adyenHelper->createAdyenCheckoutService($client);
$result = $service->paymentsDetails($request);
} catch (\Adyen\AdyenException $e) {
$this->adyenLogger->error("3D secure 2.0 failed" . $e->getMessage());
throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed'));
}
......@@ -111,19 +133,43 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($result['resultCode'], $result['authentication']['threeds2.challengeToken']);
}
// Payment can get back to the original flow
// Save the payments response because we are going to need it during the place order flow
$payment->setAdditionalInformation("paymentsResponse", $result);
// 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
$payment->setAdditionalInformation('placeOrder', true);
// To actually save the additional info changes into the quote
$quote->save();
$order->save();
$response = [];
// 3DS2 flow is done, original place order flow can continue from frontend
return $this->adyenHelper->buildThreeDS2ProcessResponseJson();
if($result['resultCode'] != 'Authorised') {
$this->checkoutSession->restoreQuote();
// Always cancel the order if the paymenth has failed
if (!$order->canCancel()) {
$order->setState(\Magento\Sales\Model\Order::STATE_NEW);
}
$order->cancel()->save();
throw new \Magento\Framework\Exception\LocalizedException(__('The payment is REFUSED.'));
}
$response['result'] = $result['resultCode'];
return json_encode($response);
}
/**
* Get order object
*
* @return \Magento\Sales\Model\Order
*/
protected function getOrder()
{
if (!$this->order) {
$incrementId = $this->checkoutSession->getLastRealOrderId();
$this->order = $this->orderFactory->create()->loadByIncrementId($incrementId);
}
return $this->order;
}
}
......@@ -197,7 +197,7 @@ class Notification extends \Magento\Framework\Model\AbstractModel implements Not
*
* @return int|null Success.
*/
public function getSucess()
public function getSuccess()
{
return $this->getData(self::SUCCESS);
}
......@@ -259,9 +259,9 @@ class Notification extends \Magento\Framework\Model\AbstractModel implements Not
/**
* Gets the AmountValue for the notification.
*
* @return int|null AmountValue.
* @return string|null AmountValue.
*/
public function getAmountCurency()
public function getAmountCurrency()
{
return $this->getData(self::AMOUNT_CURRENCY);
}
......@@ -280,7 +280,7 @@ class Notification extends \Magento\Framework\Model\AbstractModel implements Not
/**
* Gets the Reason for the notification.
*
* @return int|null Reason.
* @return string|null Reason.
*/
public function getReason()
{
......
......@@ -46,6 +46,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
const SCREEN_HEIGHT = 'screen_height';
const TIMEZONE_OFFSET = 'timezone_offset';
const LANGUAGE = 'language';
const GUEST_EMAIL = 'guestEmail';
/**
* @var array
......@@ -65,7 +66,8 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
self::SCREEN_WIDTH,
self::SCREEN_HEIGHT,
self::TIMEZONE_OFFSET,
self::LANGUAGE
self::LANGUAGE,
self::GUEST_EMAIL
];
/**
......@@ -89,7 +91,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
}
foreach ($this->additionalInformationList as $additionalInformationKey) {
if (!empty($additionalData[$additionalInformationKey])) {
if (isset($additionalData[$additionalInformationKey])) {
$paymentInfo->setAdditionalInformation(
$additionalInformationKey,
$additionalData[$additionalInformationKey]
......
<?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\Plugin;
use Adyen\Payment\Model\Ui\AdyenCcConfigProvider;
use Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider;
class PaymentInformationManagement
{
/**
* @var \Magento\Sales\Api\OrderRepositoryInterface
*/
protected $orderRepository;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
protected $adyenLogger;
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $adyenHelper;
/**
* PaymentInformationManagement constructor.
* @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/
public function __construct(
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Adyen\Payment\Helper\Data $adyenHelper
) {
$this->orderRepository = $orderRepository;
$this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
}
/**
* @param \Magento\Checkout\Api\PaymentInformationManagementInterface $subject
* @param $result
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function afterSavePaymentInformationAndPlaceOrder(
\Magento\Checkout\Api\PaymentInformationManagementInterface $subject,
$result
) {
try {
$order = $this->orderRepository->get($result);
$payment = $order->getPayment();
if ($payment->getMethod() === AdyenCcConfigProvider::CODE ||
$payment->getMethod() === AdyenOneclickConfigProvider::CODE
) {
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($payment->getAdditionalInformation('threeDSType'),
$payment->getAdditionalInformation('threeDS2Token'));
} else {
return $result;
}
} catch (NoSuchEntityException $e) {
$this->adyenLogger->error("Exception: " . $e->getMessage());
throw new \Magento\Framework\Exception\LocalizedException(__('This order no longer exists.'));
}
return $result;
}
}
......@@ -2,7 +2,7 @@
"name": "adyen/module-payment",
"description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.",
"type": "magento2-module",
"version": "4.5.4",
"version": "5.0.0",
"license": [
"OSL-3.0",
"AFL-3.0"
......
......@@ -10,7 +10,6 @@
<item name="address" xsi:type="string">Adyen\Payment\Gateway\Request\AddressDataBuilder</item>
<item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item>
<item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringDataBuilder</item>
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcBackendAuthorizationDataBuilder</item>
<item name="vault" xsi:type="string">Adyen\Payment\Gateway\Request\VaultDataBuilder</item>
</argument>
......
......@@ -70,14 +70,6 @@
sortOrder="150">
<label>Advanced Settings</label>
<frontend_model>Magento\Config\Block\System\Config\Form\Fieldset</frontend_model>
<field id="enable_moto" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1"
showInStore="1">
<label>Enable MOTO</label>
<tooltip>
<![CDATA[Important you have to activate MOTO for your account contact magento@adyen.com.]]></tooltip>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<config_path>payment/adyen_cc/enable_moto</config_path>
</field>
<field id="enable_installments" translate="label" type="select" sortOrder="219" showInDefault="1"
showInWebsite="1" showInStore="1">
<label>Enable Installments</label>
......
......@@ -47,7 +47,6 @@
<sort_order>2</sort_order>
<cctypes>AE,VI,MC,DI</cctypes>
<useccv>1</useccv>
<enable_moto>0</enable_moto>
<payment_action>authorize</payment_action>
<is_gateway>1</is_gateway>
<can_use_checkout>1</can_use_checkout>
......@@ -91,7 +90,6 @@
<recurring_payment_type>ONECLICK</recurring_payment_type>
<payment_action>authorize</payment_action>
<useccv>1</useccv>
<enable_moto>0</enable_moto>
<is_gateway>1</is_gateway>
<can_use_checkout>1</can_use_checkout>
<can_authorize>1</can_authorize>
......
......@@ -550,12 +550,21 @@
<virtualType name="AdyenPaymentCcAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
<argument name="builders" xsi:type="array">
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder
</item>
<item name="merchantaccount" xsi:type="string">Adyen\Payment\Gateway\Request\MerchantAccountDataBuilder</item>
<item name="customer" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerDataBuilder</item>
<item name="customerip" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerIpDataBuilder</item>
<item name="address" xsi:type="string">Adyen\Payment\Gateway\Request\AddressDataBuilder</item>
<item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item>
<item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringDataBuilder</item>
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder</item>
<item name="vault" xsi:type="string">Adyen\Payment\Gateway\Request\VaultDataBuilder</item>
<item name="threeds2" xsi:type="string">Adyen\Payment\Gateway\Request\ThreeDS2DataBuilder</item>
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentCcVaultAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
<argument name="builders" xsi:type="array">
......@@ -589,7 +598,15 @@
<virtualType name="AdyenPaymentOneclickAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
<argument name="builders" xsi:type="array">
<item name="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CcAuthorizationDataBuilder</item>
<item name="merchantaccount" xsi:type="string">Adyen\Payment\Gateway\Request\MerchantAccountDataBuilder</item>
<item name="customer" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerDataBuilder</item>
<item name="customerip" xsi:type="string">Adyen\Payment\Gateway\Request\CustomerIpDataBuilder</item>
<item name="address" xsi:type="string">Adyen\Payment\Gateway\Request\AddressDataBuilder</item>
<item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item>
<item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringDataBuilder</item>
<item name="oneclick" xsi:type="string">Adyen\Payment\Gateway\Request\OneclickAuthorizationDataBuilder</item>
<item name="threeds2" xsi:type="string">Adyen\Payment\Gateway\Request\ThreeDS2DataBuilder</item>
</argument>
</arguments>
</virtualType>
......@@ -1005,8 +1022,6 @@
type="Adyen\Payment\Model\AdyenRequestMerchantSession"/>
<preference for="Adyen\Payment\Api\AdyenInitiateTerminalApiInterface"
type="Adyen\Payment\Model\AdyenInitiateTerminalApi"/>
<preference for="Adyen\Payment\Api\AdyenPaymentProcessInterface"
type="Adyen\Payment\Model\AdyenPaymentProcess"/>
<preference for="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface"
type="Adyen\Payment\Model\AdyenThreeDS2Process"/>
<preference for="Adyen\Payment\Api\AdyenOriginKeyInterface"
......@@ -1014,4 +1029,7 @@
<type name="Magento\Vault\Api\PaymentTokenRepositoryInterface">
<plugin name="AdyenPaymentVaultDeleteToken" type="Adyen\Payment\Plugin\PaymentVaultDeleteToken" sortOrder="10"/>
</type>
<type name="Magento\Checkout\Api\PaymentInformationManagementInterface">
<plugin name="AdyenPaymentInformationManagementAddPaymentInfo" type="Adyen\Payment\Plugin\PaymentInformationManagement"/>
</type>
</config>
......@@ -58,13 +58,6 @@
</resources>
</route>
<route url="/V1/adyen/payment" method="POST">
<service class="Adyen\Payment\Api\AdyenPaymentProcessInterface" method="initiate"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route url="/V1/adyen/threeDS2Process" method="POST">
<service class="Adyen\Payment\Api\AdyenThreeDS2ProcessInterface" method="initiate"/>
<resources>
......
......@@ -61,6 +61,23 @@ echo $code; ?>" style="display:none">
echo $code; ?>-expiryYear" type="hidden" name="payment[expiryYear]">
<input id="<?php /* @noEscape */
echo $code; ?>-cc_type" type="hidden" name="payment[cc_type]">
<input id="<?php /* @noEscape */
echo $code; ?>-store_cc" type="hidden" name="payment[store_cc]">
<?php if ($block->isVaultEnabled()): ?>
<div class="field choice">
<input type="checkbox"
id="<?php /* @noEscape */
echo $code; ?>_vault"
name="payment[is_active_payment_token_enabler]"
class="checkbox"/>
<label class="label" for="<?php /* @noEscape */
echo $code; ?>_vault">
<span><?php echo $block->escapeHtml('Save for later use.'); ?></span>
</label>
</div>
<?php endif; ?>
<script>
require(
......@@ -93,7 +110,7 @@ echo $code; ?>" style="display:none">
/*
* Initialize secure fields and set up the onChange callback to
* - fill the input fields with the encrypted data
* - show the heklper text when necessary
* - show the helper text when necessary
*/
var secureFieldsInitialize = function () {
......@@ -117,6 +134,7 @@ echo $code; ?>" style="display:none">
type: 'card',
groupTypes: ccTypes,
hideCVC: hideCVC,
enableStoreDetails: "<?php echo $block->allowRecurring() && !$block->isVaultEnabled();?>",
onChange: function (state) {
// When the state is valid update the input fields
......@@ -126,6 +144,7 @@ echo $code; ?>" style="display:none">
jQuery("#<?php /* @noEscape */ echo $code; ?>-expiryMonth").val(state.data.paymentMethod.encryptedExpiryMonth);
jQuery("#<?php /* @noEscape */ echo $code; ?>-expiryYear").val(state.data.paymentMethod.encryptedExpiryYear);
jQuery("#<?php /* @noEscape */ echo $code; ?>-cvc").val(state.data.paymentMethod.encryptedSecurityCode);
jQuery("#<?php /* @noEscape */ echo $code; ?>-store_cc").val(state.data.storePaymentMethod);
}
},
onBrand: function (state) {
......
This diff is collapsed.
......@@ -10,23 +10,6 @@ define(
function (urlBuilder, storage) {
'use strict';
return {
/**
* Create a Payment to define if 3DS 2.0 flow needs to be activated
* @param response
*/
processPayment: function (data) {
var payload = {
"payload": JSON.stringify(data)
};
var serviceUrl = urlBuilder.createUrl('/adyen/payment', {});
return storage.post(
serviceUrl,
JSON.stringify(payload),
true
);
},
/**
* The results that the 3DS2 components returns in the onComplete callback needs to be sent to the
* backend to the /adyen/threeDS2Process endpoint and based on the response render a new threeDS2
......
......@@ -72,12 +72,13 @@ define(
checkoutCardComponentScriptTag.id = "AdyenCheckoutCardComponentScript";
checkoutCardComponentScriptTag.src = self.getCheckoutCardComponentSource();
checkoutCardComponentScriptTag.type = "text/javascript";
document.body.appendChild(checkoutCardComponentScriptTag);
document.head.appendChild(checkoutCardComponentScriptTag);
if (this.isGooglePayEnabled()) {
var googlepayscript = document.createElement('script');
googlepayscript.src = "https://pay.google.com/gp/p/js/pay.js";
googlepayscript.type = "text/javascript";
document.body.appendChild(googlepayscript);
document.head.appendChild(googlepayscript);
}
},
getCheckoutCardComponentSource: function() {
......
......@@ -37,9 +37,10 @@ define(
'Magento_Paypal/js/action/set-payment-method',
'Magento_Checkout/js/action/select-payment-method',
'Adyen_Payment/js/threeds2-js-utils',
'Adyen_Payment/js/model/threeds2'
'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor'
],
function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installmentsHelper, url, VaultEnabler, urlBuilder, storage, fullScreenLoader, setPaymentMethodAction, selectPaymentMethodAction, threeDS2Utils, threeds2) {
function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installmentsHelper, url, VaultEnabler, urlBuilder, storage, fullScreenLoader, setPaymentMethodAction, selectPaymentMethodAction, threeDS2Utils, threeds2, errorProcessor) {
'use strict';
......@@ -65,10 +66,7 @@ define(
// initialize adyen component for general use
this.checkout = new AdyenCheckout({
locale: this.getLocale(),
risk: {
enabled: false
}
locale: this.getLocale()
});
return this;
......@@ -195,7 +193,6 @@ define(
*/
renderThreeDS2Component: function (type, token) {
var self = this;
var threeDS2Node = document.getElementById('threeDS2Container');
if (type == "IdentifyShopper") {
......@@ -203,9 +200,11 @@ define(
.create('threeDS2DeviceFingerprint', {
fingerprintToken: token,
onComplete: function (result) {
self.threeDS2IdentifyComponent.unmount();
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () {
}).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
......@@ -237,18 +236,19 @@ define(
challengeToken: token,
size: '05',
onComplete: function (result) {
self.threeDS2ChallengeComponent.unmount();
self.closeModal(popupModal);
fullScreenLoader.startLoader();
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function () {
}).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
},
onError: function (error) {
self.closeModal(popupModal);
console.log(JSON.stringify(error));
}
});
......@@ -263,6 +263,7 @@ define(
popupModal.modal("closeModal");
$('.threeDS2Modal').remove();
$('.modals-overlay').remove();
$('body').removeClass('_has-modal');
// reconstruct the threeDS2Modal container again otherwise component can not find the threeDS2Modal
$('#threeDS2Wrapper').append("<div id=\"threeDS2Modal\">" +
......@@ -270,11 +271,10 @@ define(
"</div>");
},
/**
* Builds the payment details part of the payment information reqeust
*
* @returns {{method: *, additional_data: {cc_type: *, number: *, cvc: *, expiryMonth: *, expiryYear: *, holderName: *, store_cc: (boolean|*), number_of_installments: *, java_enabled: () => boolean, screen_color_depth: number, screen_width, screen_height, timezone_offset: *, language: *}}}
* Get data for place order
* @returns {{method: *}}
*/
getCcData: function () {
getData: function () {
const browserInfo = threeDS2Utils.getBrowserInfo();
var data = {
......@@ -297,24 +297,9 @@ define(
'language': browserInfo.language
}
};
this.vaultEnabler.visitAdditionalData(data);
return data;
},
/**
* Get data for place order
* @returns {{method: *}}
*/
getData: function () {
return {
'method': this.item.method,
additional_data: {
'cc_type': this.creditCardType(),
'store_cc': this.storeCc,
'number_of_installments': this.installment()
}
};
},
/**
* Returns state of place order button
* @returns {boolean}
......@@ -342,13 +327,20 @@ define(
fullScreenLoader.startLoader();
self.isPlaceOrderActionAllowed(false);
threeds2.processPayment(this.getCcData()).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function () {
self.getPlaceOrderDeferredObject()
.fail(
function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
});
}
).done(
function (response) {
self.afterPlaceOrder();
self.validateThreeDS2OrPlaceOrder(response);
}
);
}
return false;
},
/**
* Based on the response we can start a 3DS2 validation or place the order
......@@ -356,32 +348,16 @@ define(
*/
validateThreeDS2OrPlaceOrder: function (responseJSON) {
var self = this;
var response = JSON.parse(responseJSON);
if (!!response.threeDS2) {
// render component
self.renderThreeDS2Component(response.type, response.token);
} else {
self.getPlaceOrderDeferredObject()
.fail(
function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
if (self.redirectAfterPlaceOrder) {
// use custom redirect Link for supporting 3D secure
window.location.replace(url.build(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl)
);
}
}
);
}
},
/**
* Validates the payment date when clicking the pay button
......
......@@ -82,10 +82,7 @@ define(
* @type {AdyenCheckout}
*/
self.checkoutComponent = new AdyenCheckout({
locale: self.getLocale(),
risk: {
enabled: false
}
locale: self.getLocale()
});
// reset variable:
......
......@@ -39,9 +39,10 @@ define(
'Magento_Checkout/js/model/url-builder',
'mage/storage',
'Magento_Checkout/js/action/place-order',
'Adyen_Payment/js/model/threeds2'
'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor'
],
function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, url, threeDS2Utils, fullScreenLoader, setPaymentMethodAction, urlBuilder, storage, placeOrderAction, threeds2) {
function (ko, _, $, Component, selectPaymentMethodAction, additionalValidators, quote, checkoutData, redirectOnSuccessAction, layout, Messages, url, threeDS2Utils, fullScreenLoader, setPaymentMethodAction, urlBuilder, storage, placeOrderAction, threeds2, errorProcessor) {
'use strict';
......@@ -200,16 +201,19 @@ define(
fullScreenLoader.startLoader();
self.isPlaceOrderActionAllowed(false);
threeds2.processPayment(this.getCcData()).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON);
}).error(function () {
self.getPlaceOrderDeferredObject()
.fail(
function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
});
return false;
}
).done(
function (response) {
self.afterPlaceOrder();
self.validateThreeDS2OrPlaceOrder(response);
}
);
}
return false;
},
......@@ -276,32 +280,6 @@ define(
window.adyencheckout = oneClickCard;
},
/**
* Builds the payment details part of the payment information reqeust
*
* @returns {{method: *, additional_data: {card_brand: *, cc_type: *, number: *, cvc: *, expiryMonth: *, expiryYear: *, holderName: *, store_cc: (boolean|*), number_of_installments: *, java_enabled: boolean, screen_color_depth: number, screen_width, screen_height, timezone_offset: *}}}
*/
getCcData: function () {
var self = this;
var browserInfo = threeDS2Utils.getBrowserInfo();
var data = {
'method': self.method,
additional_data: {
'variant': variant(),
'recurring_detail_reference': recurringDetailReference(),
'store_cc': true,
'number_of_installments': numberOfInstallments(),
'cvc': self.encryptedCreditCardVerificationNumber,
'java_enabled': browserInfo.javaEnabled,
'screen_color_depth': browserInfo.colorDepth,
'screen_width': browserInfo.screenWidth,
'screen_height': browserInfo.screenHeight,
'timezone_offset': browserInfo.timeZoneOffset,
'language': browserInfo.language
}
};
return data;
},
/**
* Based on the response we can start a 3DS2 validation or place the order
* @param responseJSON
......@@ -314,18 +292,8 @@ define(
// render component
self.renderThreeDS2Component(response.type, response.token);
} else {
this.getPlaceOrderDeferredObject()
.fail(
function () {
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
}
);
}
},
/**
* Rendering the 3DS2.0 components
......@@ -349,7 +317,8 @@ define(
onComplete: function (result) {
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () {
}).fail(function (result) {
errorProcessor.process(result, self.getMessageContainer());
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
......@@ -380,7 +349,8 @@ define(
fullScreenLoader.startLoader();
threeds2.processThreeDS2(result.data).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON)
}).error(function () {
}).fail(function (result) {
errorProcessor.process(result, self.getMessageContainer());
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
......@@ -421,14 +391,22 @@ define(
*/
getData: function () {
var self = this;
var browserInfo = threeDS2Utils.getBrowserInfo();
return {
"method": self.method,
additional_data: {
variant: variant(),
recurring_detail_reference: recurringDetailReference(),
store_cc: true,
number_of_installments: numberOfInstallments(),
cvc: self.encryptedCreditCardVerificationNumber
cvc: self.encryptedCreditCardVerificationNumber,
java_enabled: browserInfo.javaEnabled,
screen_color_depth: browserInfo.colorDepth,
screen_width: browserInfo.screenWidth,
screen_height: browserInfo.screenHeight,
timezone_offset: browserInfo.timeZoneOffset,
language: browserInfo.language
}
};
},
......
......@@ -74,7 +74,7 @@
<!-- /ko -->
<div class="field number cardContainerField">
<div afterRender="renderSecureFields()" data-bind="attr: { id: 'cardContainer'}"></div>
<div class="checkout-component-dock" afterRender="renderSecureFields()" data-bind="attr: { id: 'cardContainer'}"></div>
</div>
<div id="threeDS2Wrapper">
......
......@@ -51,7 +51,7 @@
<!--/ko-->
</div>
<div class="field number googlePay">
<div afterRender="renderGooglePay()" data-bind="attr: { id: 'googlePay'}">
<div class="checkout-component-dock" afterRender="renderGooglePay()" data-bind="attr: { id: 'googlePay'}">
<!-- ko ifnot: isGooglePayAllowed() -->
Google Pay is not available
<!--/ko--></div>
......
......@@ -55,7 +55,7 @@
<fieldset class="fieldset" data-bind='attr: {id: "payment_fieldset_" + $parent.getCode() + "_" + value}'>
<!-- ko if: hasIssuersAvailable() -->
<!-- ko if: isIdeal() -->
<div afterRender="renderIdealComponent()" data-bind="attr: { id: 'iDealContainer'}"></div>
<div class="checkout-component-dock" afterRender="renderIdealComponent()" data-bind="attr: { id: 'iDealContainer'}"></div>
<!--/ko-->
<!-- ko ifnot: isIdeal() -->
<label data-bind="attr: {'for': 'issuerId'}" class="label">
......@@ -101,7 +101,7 @@
</div>
<!--/ko-->
<div afterRender="renderKlarnaComponent()" data-bind="attr: { id: 'klarnaContainer'}"></div>
<div class="checkout-component-dock" afterRender="renderKlarnaComponent()" data-bind="attr: { id: 'klarnaContainer'}"></div>
<!--/ko-->
<!-- ko if: isPaymentMethodAfterPay() -->
......@@ -128,7 +128,7 @@
</div>
<!--/ko-->
<div afterRender="renderAfterPayComponent()" data-bind="attr: { id: 'afterPayContainer'}"></div>
<div class="checkout-component-dock" afterRender="renderAfterPayComponent()" data-bind="attr: { id: 'afterPayContainer'}"></div>
<!--/ko-->
<!-- ko if: isPaymentMethodOtherOpenInvoiceMethod() -->
......@@ -218,7 +218,7 @@
<!--/ko-->
<!-- ko if: isSepaDirectDebit() -->
<div afterRender="renderSepaDirectDebitComponent()" data-bind="attr: { id: 'sepaDirectDebitContainer'}"></div>
<div class="checkout-component-dock" afterRender="renderSepaDirectDebitComponent()" data-bind="attr: { id: 'sepaDirectDebitContainer'}"></div>
<!--/ko-->
<!-- ko if: isAch() -->
......
......@@ -81,7 +81,7 @@
</div>
</div>
<div afterRender="renderSecureCVC()" data-bind="attr: { id: 'cvcContainer-' + value}"></div>
<div class="checkout-component-dock" afterRender="renderSecureCVC()" data-bind="attr: { id: 'cvcContainer-' + value}"></div>
<!--/ko-->
<!-- ko if: agreement_data.bank -->
......
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