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 050b260d authored by Rik ter Beek's avatar Rik ter Beek Committed by GitHub

Merge pull request #500 from Adyen/develop

Merge from develop
parents 4d1745b6 0514b25f
<?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\Block\Adminhtml\System\Config\Field;
class InstallmentsPosCloud extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray
{
/**
* @var \Adyen\Payment\Block\Adminhtml\System\Config\Field\Installment
*/
protected $_installmentRenderer = null;
/**
* Return renderer for installments
*
* @return Installment|\Magento\Framework\View\Element\BlockInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function getNumberOfInstallmentsRenderer()
{
if (!$this->_installmentRenderer) {
$this->_installmentRenderer = $this->getLayout()->createBlock(
'\Adyen\Payment\Block\Adminhtml\System\Config\Field\Installment',
'',
['data' => ['is_render_to_js_template' => true]]
);
}
return $this->_installmentRenderer;
}
/**
* Prepare to render
* @return void
*/
protected function _prepareToRender()
{
$this->addColumn(
'amount',
[
'label' => __('Amount Range'),
'renderer' => false,
]
);
$this->addColumn(
'installments',
[
'label' => __('Number Of Installments'),
'renderer' => $this->getNumberOfInstallmentsRenderer(),
]
);
$this->_addAfter = false;
$this->_addButtonLabel = __('Add Rule');
}
/**
* Prepare existing row data object
*
* @param \Magento\Framework\DataObject $row
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
$installlments = $row->getInstallments();
$options = [];
if ($installlments) {
$options['option_' . $this->getNumberOfInstallmentsRenderer()->calcOptionHash($installlments)]
= 'selected="selected"';
}
$row->setData('option_extra_attrs', $options);
}
}
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Block\Form;
class GooglePay extends \Magento\Payment\Block\Form
{
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $adyenHelper;
/**
* GooglePay constructor.
*
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Adyen\Payment\Helper\Data $adyenHelper,
array $data = []
) {
parent::__construct($context, $data);
$this->adyenHelper = $adyenHelper;
}
}
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Block\Info;
class GooglePay extends Cc
{
}
......@@ -117,6 +117,7 @@ class Redirect extends \Magento\Framework\App\Action\Action
$request = $this->getRequest();
if ($request instanceof Http && $request->isPost()) {
$request->setParam('isAjax', true);
$request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest');
}
}
}
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Setup\Exception;
class GooglePayAuthorizationDataBuilder implements BuilderInterface
{
/**
* @var \Adyen\Payment\Helper\Data
*/
private $adyenHelper;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
private $adyenLogger;
/**
* GooglePayAuthorizationDataBuilder constructor.
*
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/
public function __construct(
\Adyen\Payment\Helper\Data $adyenHelper,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger
) {
$this->adyenHelper = $adyenHelper;
$this->adyenLogger = $adyenLogger;
}
public function build(array $buildSubject)
{
$request = [];
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
$token = $payment->getAdditionalInformation('token');
$request['paymentMethod']['type'] = 'paywithgoogle';
// get payment data
if ($token) {
$parsedToken = json_decode($token);
try {
$request['paymentMethod']['paywithgoogle.token'] = $parsedToken;
} catch (\Exception $exception) {
$this->adyenLogger->addAdyenDebug("exception: " . $exception->getMessage());
}
} else {
$this->adyenLogger->addAdyenDebug("PaymentToken is empty");
}
return $request;
}
}
......@@ -140,6 +140,11 @@ class VaultDetailsHandler implements HandlerInterface
$paymentToken = $this->paymentTokenFactory->create(
PaymentTokenFactoryInterface::TOKEN_TYPE_CREDIT_CARD
);
if (strpos($cardType, "paywithgoogle") !== false && !empty($additionalData['paymentMethodVariant'])) {
$cardType = $additionalData['paymentMethodVariant'];
$paymentToken->setIsVisible(false);
}
$paymentToken->setGatewayToken($token);
$paymentToken->setExpiresAt($this->getExpirationDate($expirationDate));
......
......@@ -248,14 +248,12 @@ class Data extends AbstractHelper
];
}
/**
* Return the formatted currency. Adyen accepts the currency in multiple formats.
* @param $amount
* Return the number of decimals for the specified currency
* @param $currency
* @return string
* @return int
*/
public function formatAmount($amount, $currency)
public function decimalNumbers($currency)
{
switch ($currency) {
case "CVE":
......@@ -287,10 +285,21 @@ class Data extends AbstractHelper
default:
$format = 2;
}
return $format;
}
return (int)number_format($amount, $format, '', '');
/**
* Return the formatted amount. Adyen accepts the currency in multiple formats.
* @param $amount
* @param $currency
* @return int
*/
public function formatAmount($amount, $currency)
{
return (int)number_format($amount, $this->decimalNumbers($currency), '', '');
}
/**
* Tax Percentage needs to be in minor units for Adyen
*
......@@ -623,6 +632,39 @@ class Data extends AbstractHelper
}
}
/**
* Gives back adyen_google_pay configuration values
*
* @param $field
* @param null $storeId
* @return mixed
*/
public function getAdyenGooglePayConfigData($field, $storeId = null)
{
return $this->getConfigData($field, 'adyen_google_pay', $storeId);
}
/**
* Gives back adyen_google_pay configuration values
*
* @param $field
* @param null $storeId
* @return mixed
*/
public function isAdyenGooglePayEnabled($storeId = null)
{
return $this->getAdyenGooglePayConfigData('active', $storeId);
}
/**
* @param null $storeId
* @return mixed
*/
public function getAdyenGooglePayMerchantIdentifier($storeId = null)
{
return $this->getAdyenGooglePayConfigData('merchant_identifier', $storeId);
}
/**
* Retrieve decrypted hmac key
*
......
......@@ -153,14 +153,32 @@ class AdyenInitiateTerminalApi implements AdyenInitiateTerminalApiInterface
'RequestedAmount' => doubleval($quote->getGrandTotal()),
],
],
'PaymentData' =>
[
'PaymentType' => $transactionType,
],
],
],
];
if (!empty($payload['number_of_installments'])) {
$request['SaleToPOIRequest']['PaymentRequest']['PaymentData'] = [
"PaymentType" => "Instalment",
"Instalment" => [
"InstalmentType" => "EqualInstalments",
"SequenceNumber" => 1,
"Period" => 1,
"PeriodUnit" => "Monthly",
"TotalNbOfPayments" => (int)$payload['number_of_installments']
]
];
$request['SaleToPOIRequest']['PaymentRequest']['PaymentTransaction']['TransactionConditions'] = [
"DebitPreferredFlag" => false
];
} else {
$request['SaleToPOIRequest']['PaymentData'] = [
'PaymentType' => $transactionType,
];
}
$customerId = $this->getCustomerId($quote);
// If customer exists add it into the request to store request
......
......@@ -107,6 +107,9 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
// Billing agreement is CC
if (isset($data['card']['number'])) {
$ccType = $data['variant'];
if (strpos($ccType, "paywithgoogle") !== false && !empty($data['paymentMethodVariant'])) {
$ccType = $data['paymentMethodVariant'];
}
$ccTypes = $this->adyenHelper->getCcTypesAltData();
if (isset($ccTypes[$ccType])) {
......@@ -190,7 +193,10 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
}
// Billing agreement is CC
$ccType = $contractDetail['paymentMethod'];
$ccType = $variant = $contractDetail['paymentMethod'];
if (strpos($ccType, "paywithgoogle") !== false && !empty($contractDetail['paymentMethodVariant'])) {
$ccType = $variant = $contractDetail['paymentMethodVariant'];
}
$ccTypes = $this->adyenHelper->getCcTypesAltData();
if (isset($ccTypes[$ccType])) {
......@@ -243,7 +249,7 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
'expiryMonth' => $expiryDate[0],
'expiryYear' => $expiryDate[1]
],
'variant' => $contractDetail['paymentMethod'],
'variant' => $variant,
'contractTypes' => explode(',', $recurringType)
];
......
<?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\Model\Config\Backend;
class InstallmentsPosCloud extends \Magento\Framework\App\Config\Value
{
/**
* @var \Magento\Framework\Math\Random
*/
protected $mathRandom;
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
* @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
* @param \Magento\Framework\Math\Random $mathRandom
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\App\Config\ScopeConfigInterface $config,
\Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
\Magento\Framework\Math\Random $mathRandom,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
) {
$this->mathRandom = $mathRandom;
parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
}
/**
* Prepare data before save
*
* @return $this
*/
public function beforeSave()
{
$value = $this->getValue();
$unserialized = @unserialize($value);
if ($unserialized !== false) {
return $this;
}
$result = [];
foreach ($value as $data) {
if (!$data) {
continue;
}
if (!is_array($data)) {
continue;
}
if (count($data) < 2) {
continue;
}
$amount = $data['amount'];
$installments = $data['installments'];
$result[$amount] = $installments;
}
asort($result);
$this->setValue(serialize($result));
return $this;
}
/**
* Process data after load
*
* @return $this
*/
protected function _afterLoad()
{
$value = $this->getValue();
$value = unserialize($value);
if (is_array($value)) {
$value = $this->encodeArrayFieldValue($value);
$this->setValue($value);
}
return $this;
}
/**
* Encode value to be used in \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray
*
* @param array $items
* @return array
*/
protected function encodeArrayFieldValue(array $items)
{
$result = [];
// sort on amount
ksort($items);
foreach ($items as $amount => $installment) {
$resultId = $this->mathRandom->getUniqueHash('_');
$result[$resultId] = ['amount' => $amount, 'installments' => $installment];
}
return $result;
}
}
......@@ -332,111 +332,118 @@ class Cron
// loop over the notifications
$count = 0;
foreach ($notifications as $notification) {
$this->_adyenLogger->addAdyenNotificationCronjob(
sprintf("Processing notification %s", $notification->getEntityId())
);
// ignore duplicate notification
if ($this->_isDuplicate($notification)) {
try {
$this->_adyenLogger->addAdyenNotificationCronjob(
"This is a duplicate notification and will be ignored"
sprintf("Processing notification %s", $notification->getEntityId())
);
$this->_updateNotification($notification, false, true);
++$count;
continue;
}
// log the executed notification
$this->_adyenLogger->addAdyenNotificationCronjob(print_r($notification->debug(), 1));
// ignore duplicate notification
if ($this->_isDuplicate($notification)) {
$this->_adyenLogger->addAdyenNotificationCronjob(
"This is a duplicate notification and will be ignored"
);
$this->_updateNotification($notification, false, true);
++$count;
continue;
}
// log the executed notification
$this->_adyenLogger->addAdyenNotificationCronjob(print_r($notification->debug(), 1));
// get order
$incrementId = $notification->getMerchantReference();
// get order
$incrementId = $notification->getMerchantReference();
$searchCriteria = $this->searchCriteriaBuilder
->addFilter('increment_id', $incrementId, 'eq')
->create();
$searchCriteria = $this->searchCriteriaBuilder
->addFilter('increment_id', $incrementId, 'eq')
->create();
$orderList = $this->orderRepository->getList($searchCriteria)->getItems();
$orderList = $this->orderRepository->getList($searchCriteria)->getItems();
/** @var \Magento\Sales\Model\Order $order */
$order = reset($orderList);
$this->_order = $order;
/** @var \Magento\Sales\Model\Order $order */
$order = reset($orderList);
$this->_order = $order;
if (!$this->_order) {
// order does not exists remove from queue
$notification->delete();
continue;
}
if (!$this->_order) {
// order does not exists remove from queue
$notification->delete();
continue;
}
// declare all variables that are needed
$this->_declareVariables($notification);
// declare all variables that are needed
$this->_declareVariables($notification);
// add notification to comment history status is current status
$this->_addStatusHistoryComment();
// add notification to comment history status is current status
$this->_addStatusHistoryComment();
$previousAdyenEventCode = $this->_order->getData('adyen_notification_event_code');
$previousAdyenEventCode = $this->_order->getData('adyen_notification_event_code');
// update order details
$this->_updateAdyenAttributes($notification);
// update order details
$this->_updateAdyenAttributes($notification);
// check if success is true of false
if (strcmp($this->_success, 'false') == 0 || strcmp($this->_success, '0') == 0) {
/*
* Only cancel the order when it is in state pending, payment review or
* if the ORDER_CLOSED is failed (means split payment has not be successful)
*/
if ($this->_order->getState() === \Magento\Sales\Model\Order::STATE_PENDING_PAYMENT ||
$this->_order->getState() === \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW ||
$this->_eventCode == Notification::ORDER_CLOSED
) {
$this->_adyenLogger->addAdyenNotificationCronjob('Going to cancel the order');
// check if success is true of false
if (strcmp($this->_success, 'false') == 0 || strcmp($this->_success, '0') == 0) {
/*
* Only cancel the order when it is in state pending, payment review or
* if the ORDER_CLOSED is failed (means split payment has not be successful)
*/
if ($this->_order->getState() === \Magento\Sales\Model\Order::STATE_PENDING_PAYMENT ||
$this->_order->getState() === \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW ||
$this->_eventCode == Notification::ORDER_CLOSED
) {
$this->_adyenLogger->addAdyenNotificationCronjob('Going to cancel the order');
// if payment is API check, check if API result pspreference is the same as reference
if ($this->_eventCode == NOTIFICATION::AUTHORISATION && $this->_getPaymentMethodType() == 'api') {
// don't cancel the order becasue order was successfull through api
$this->_adyenLogger->addAdyenNotificationCronjob(
'order is not cancelled because api result was succesfull'
);
} else {
/*
* don't cancel the order if previous state is authorisation with success=true
* Split payments can fail if the second payment has failed the first payment is
* refund/cancelled as well so if it is a split payment that failed cancel the order as well
*/
if ($previousAdyenEventCode != "AUTHORISATION : TRUE" ||
$this->_eventCode == Notification::ORDER_CLOSED
) {
$this->_holdCancelOrder(false);
} else {
$this->_order->setData('adyen_notification_event_code', $previousAdyenEventCode);
// if payment is API check, check if API result pspreference is the same as reference
if ($this->_eventCode == NOTIFICATION::AUTHORISATION && $this->_getPaymentMethodType() == 'api') {
// don't cancel the order becasue order was successfull through api
$this->_adyenLogger->addAdyenNotificationCronjob(
'order is not cancelled because previous notification
was an authorisation that succeeded'
'order is not cancelled because api result was succesfull'
);
} else {
/*
* don't cancel the order if previous state is authorisation with success=true
* Split payments can fail if the second payment has failed the first payment is
* refund/cancelled as well so if it is a split payment that failed cancel the order as well
*/
if ($previousAdyenEventCode != "AUTHORISATION : TRUE" ||
$this->_eventCode == Notification::ORDER_CLOSED
) {
$this->_holdCancelOrder(false);
} else {
$this->_order->setData('adyen_notification_event_code', $previousAdyenEventCode);
$this->_adyenLogger->addAdyenNotificationCronjob(
'order is not cancelled because previous notification
was an authorisation that succeeded'
);
}
}
} else {
$this->_adyenLogger->addAdyenNotificationCronjob(
'Order is already processed so ignore this notification state is:' . $this->_order->getState()
);
}
} else {
$this->_adyenLogger->addAdyenNotificationCronjob(
'Order is already processed so ignore this notification state is:' . $this->_order->getState()
);
// Notification is successful
$this->_processNotification();
}
} else {
// Notification is successful
$this->_processNotification();
}
try {
// set done to true
$this->_order->save();
try {
// set done to true
$this->_order->save();
} catch (\Exception $e) {
$this->_adyenLogger->addAdyenNotificationCronjob($e->getMessage());
}
$this->_updateNotification($notification, false, true);
$this->_adyenLogger->addAdyenNotificationCronjob(
sprintf("Notification %s is processed", $notification->getEntityId())
);
++$count;
} catch (\Exception $e) {
$this->_adyenLogger->addAdyenNotificationCronjob($e->getMessage());
$this->_updateNotification($notification, false, false);
$this->_adyenLogger->addAdyenNotificationCronjob(
sprintf("Notification %s had an error: %s \n %s", $notification->getEntityId(), $e->getMessage(), $e->getTraceAsString())
);
}
$this->_updateNotification($notification, false, true);
$this->_adyenLogger->addAdyenNotificationCronjob(
sprintf("Notification %s is processed", $notification->getEntityId())
);
++$count;
}
if ($count > 0) {
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Model\Ui;
use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Payment\Helper\Data as PaymentHelper;
class AdyenGooglePayConfigProvider implements ConfigProviderInterface
{
const CODE = 'adyen_google_pay';
const GOOGLE_PAY_VAULT_CODE = 'adyen_google_pay_vault';
/**
* @var PaymentHelper
*/
protected $paymentHelper;
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $adyenHelper;
/**
* @var \Magento\Framework\UrlInterface
*/
protected $urlBuilder;
/**
* Request object
*
* @var \Magento\Framework\App\RequestInterface
*/
protected $_request;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
private $storeManager;
/**
* AdyenGooglePayConfigProvider constructor.
*
* @param PaymentHelper $paymentHelper
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\Framework\App\RequestInterface $request
* @param \Magento\Framework\UrlInterface $urlBuilder
*/
public function __construct(
PaymentHelper $paymentHelper,
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\UrlInterface $urlBuilder,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Checkout\Model\Session $checkoutSession
) {
$this->paymentHelper = $paymentHelper;
$this->adyenHelper = $adyenHelper;
$this->_request = $request;
$this->urlBuilder = $urlBuilder;
$this->storeManager = $storeManager;
$this->checkoutSession = $checkoutSession;
}
/**
* Retrieve assoc array of checkout configuration
*
* @return array
*/
public function getConfig()
{
// set to active
$config = [
'payment' => [
self::CODE => [
'isActive' => true,
'redirectUrl' => $this->urlBuilder->getUrl(
'checkout/onepage/success/',
['_secure' => $this->_getRequest()->isSecure()]
)
]
]
];
$config['payment']['adyenGooglePay']['active'] = (bool)$this->adyenHelper->isAdyenGooglePayEnabled($this->storeManager->getStore()->getId());
$config['payment']['adyenGooglePay']['checkoutEnvironment'] = $this->adyenHelper->getCheckoutEnvironment($this->storeManager->getStore()->getId());
$config['payment']['adyenGooglePay']['locale'] = $this->adyenHelper->getStoreLocale($this->storeManager->getStore()->getId());
$config['payment']['adyenGooglePay']['merchantAccount'] = $this->adyenHelper->getAdyenMerchantAccount("adyen_google_pay", $this->storeManager->getStore()->getId());
$quote = $this->checkoutSession->getQuote();
$currency = $quote->getCurrency();
$config['payment']['adyenGooglePay']['format'] = $this->adyenHelper->decimalNumbers($currency);
$config['payment']['adyenGooglePay']['merchantIdentifier'] = $this->adyenHelper->getAdyenGooglePayMerchantIdentifier($this->storeManager->getStore()->getId());
return $config;
}
/**
* Retrieve request object
*
* @return \Magento\Framework\App\RequestInterface
*/
protected function _getRequest()
{
return $this->_request;
}
}
......@@ -48,6 +48,11 @@ class AdyenPosCloudConfigProvider implements ConfigProviderInterface
*/
protected $paymentMethodsHelper;
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $adyenHelper;
/**
* AdyenHppConfigProvider constructor.
*
......@@ -57,11 +62,13 @@ class AdyenPosCloudConfigProvider implements ConfigProviderInterface
public function __construct(
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\UrlInterface $urlBuilder,
\Adyen\Payment\Helper\PaymentMethods $paymentMethodsHelper
\Adyen\Payment\Helper\PaymentMethods $paymentMethodsHelper,
\Adyen\Payment\Helper\Data $adyenHelper
) {
$this->request = $request;
$this->urlBuilder = $urlBuilder;
$this->paymentMethodsHelper = $paymentMethodsHelper;
$this->adyenHelper = $adyenHelper;
}
/**
......@@ -86,6 +93,20 @@ class AdyenPosCloudConfigProvider implements ConfigProviderInterface
$config['payment']['adyenPos']['connectedTerminals'] = $this->getConnectedTerminals();
// has installments by default false
$config['payment']['adyenPos']['hasInstallments'] = false;
// get Installments
$installmentsEnabled = $this->adyenHelper->getAdyenPosCloudConfigData('enable_installments');
$installments = $this->adyenHelper->getAdyenPosCloudConfigData('installments');
if ($installmentsEnabled && $installments) {
$config['payment']['adyenPos']['installments'] = unserialize($installments);
$config['payment']['adyenPos']['hasInstallments'] = true;
} else {
$config['payment']['adyenPos']['installments'] = [];
}
return $config;
}
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Model\Ui;
use Adyen\Payment\Helper\Data;
use Magento\Vault\Api\Data\PaymentTokenInterface;
use Magento\Vault\Model\Ui\TokenUiComponentInterface;
use Magento\Vault\Model\Ui\TokenUiComponentProviderInterface;
use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory;
use Magento\Framework\UrlInterface;
/**
* Class TokenGooglePayUiComponentProvider
*/
class TokenGooglePayUiComponentProvider implements TokenUiComponentProviderInterface
{
/**
* @var TokenUiComponentInterfaceFactory
*/
private $componentFactory;
/**
* @var Data
*/
private $adyenHelper;
/**
* @param TokenUiComponentInterfaceFactory $componentFactory
* @param UrlInterface $urlBuilder
*/
public function __construct(
TokenUiComponentInterfaceFactory $componentFactory,
Data $adyenHelper
) {
$this->componentFactory = $componentFactory;
$this->adyenHelper = $adyenHelper;
}
/**
* Get UI component for token
* @param PaymentTokenInterface $paymentToken
* @return TokenUiComponentInterface
*/
public function getComponentForToken(PaymentTokenInterface $paymentToken)
{
$details = json_decode($paymentToken->getTokenDetails() ?: '{}', true);
$details['icon'] = $this->adyenHelper->getVariantIcon($details['type']);
$component = $this->componentFactory->create(
[
'config' => [
'code' => AdyenGooglePayConfigProvider::GOOGLE_PAY_VAULT_CODE,
TokenUiComponentProviderInterface::COMPONENT_DETAILS => $details,
TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash()
],
'name' => 'Adyen_Payment/js/view/payment/method-renderer/vault'
]
);
return $component;
}
}
\ No newline at end of file
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Observer;
use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
/**
* Class AdyenGooglePayDataAssignObserver
*/
class AdyenGooglePayDataAssignObserver extends AbstractDataAssignObserver
{
const TOKEN = 'token';
/**
* @var array
*/
protected $additionalInformationList = [
self::TOKEN
];
/**
* @param Observer $observer
* @return void
*/
public function execute(Observer $observer)
{
$data = $this->readDataArgument($observer);
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return;
}
$paymentInfo = $this->readPaymentModelArgument($observer);
// set ccType
$paymentInfo->setCcType('google_pay');
foreach ($this->additionalInformationList as $additionalInformationKey) {
if (isset($additionalData[$additionalInformationKey])) {
$paymentInfo->setAdditionalInformation(
$additionalInformationKey,
$additionalData[$additionalInformationKey]
);
}
}
}
}
......@@ -32,12 +32,14 @@ use Magento\Quote\Api\Data\PaymentInterface;
class AdyenPosCloudDataAssignObserver extends AbstractDataAssignObserver
{
const TERMINAL_ID = 'terminal_id';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
/**
* @var array
*/
protected $additionalInformationList = [
self::TERMINAL_ID
self::TERMINAL_ID,
self::NUMBER_OF_INSTALLMENTS
];
/**
......
......@@ -2,7 +2,7 @@
"name": "adyen/module-payment",
"description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.",
"type": "magento2-module",
"version": "4.3.0",
"version": "4.4.0",
"license": [
"OSL-3.0",
"AFL-3.0"
......
......@@ -46,6 +46,7 @@
<include path="Adyen_Payment::system/adyen_pay_by_mail.xml"/>
<include path="Adyen_Payment::system/adyen_boleto.xml"/>
<include path="Adyen_Payment::system/adyen_apple_pay.xml"/>
<include path="Adyen_Payment::system/adyen_google_pay.xml"/>
</group>
</section>
</system>
......
<?xml version="1.0"?>
<!--
~ ######
~ ######
~ ############ ####( ###### #####. ###### ############ ############
~ ############# #####( ###### #####. ###### ############# #############
~ ###### #####( ###### #####. ###### ##### ###### ##### ######
~ ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
~ ###### ###### #####( ###### #####. ###### ##### ##### ######
~ ############# ############# ############# ############# ##### ######
~ ############ ############ ############# ############ ##### ######
~ ######
~ #############
~ ############
~
~ Adyen Payment Module
~
~ Copyright (c) 2019 Adyen B.V.
~ This file is open source and available under the MIT license.
~ See the LICENSE file for more info.
~
~ Author: Adyen <magento@adyen.com>
-->
<include xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_include.xsd">
<group id="adyen_google_pay" translate="label" type="text" sortOrder="460" showInDefault="1" showInWebsite="1" showInStore="1">
<label><![CDATA[Google Pay integration]]></label>
<frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment</frontend_model>
<fieldset_css>adyen-method-adyen-cc</fieldset_css>
<comment>Process Google Pay transactions</comment>
<field id="active" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Enabled</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<config_path>payment/adyen_google_pay/active</config_path>
</field>
<field id="title" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Title</label>
<config_path>payment/adyen_google_pay/title</config_path>
</field>
<field id="sort_order" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Sort Order</label>
<frontend_class>validate-number</frontend_class>
<config_path>payment/adyen_google_pay/sort_order</config_path>
</field>
<field id="merchant_identifier" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Google Merchant Identifier</label>
<comment><![CDATA[Your Google Merchant ID from Google Pay Developer Profile. For more information refer to <a href="https://developers.google.com/pay/api/web/guides/test-and-deploy/deploy-production-environment#obtain-your-merchantID">Obtain your merchantID</a>.]]></comment>
<config_path>payment/adyen_google_pay/merchant_identifier</config_path>
</field>
</group>
</include>
\ No newline at end of file
......@@ -78,6 +78,28 @@
<config_path>payment/adyen_pos_cloud/recurring_type</config_path>
<comment>If you want to store the credentials for ONECLICK or RECURRING or combination of these two you need to contact support@adyen.com and ask if they can enable to store cards on company level. Changing this setting without doing this will lead to failed payments!</comment>
</field>
<field id="enable_installments" translate="label" type="select" sortOrder="219" showInDefault="1"
showInWebsite="1" showInStore="1">
<label>Enable Installments</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<tooltip>Enable installments for each credit card type.</tooltip>
<config_path>payment/adyen_pos_cloud/enable_installments</config_path>
</field>
<field id="installments" translate="label" sortOrder="220" showInDefault="1" showInWebsite="1"
showInStore="1">
<label>Installments</label>
<depends>
<field id="enable_installments">1</field>
</depends>
<tooltip>Configure your installment: Insert the minimum amount required to
make the configured installment available in the amount range column.
Example: if the amount range is configured to 100 and the number of installments to 4x, the shopper
will see the 4x option only if the payment total is higher or equal than 100.
</tooltip>
<frontend_model>Adyen\Payment\Block\Adminhtml\System\Config\Field\InstallmentsPosCloud</frontend_model>
<backend_model>Adyen\Payment\Model\Config\Backend\InstallmentsPosCloud</backend_model>
<config_path>payment/adyen_pos_cloud/installments</config_path>
</field>
<group id="adyen_pos_country_specific" translate="label" showInDefault="1" showInWebsite="1" sortOrder="210">
<label>Country Specific Settings</label>
<frontend_model>Magento\Config\Block\System\Config\Form\Fieldset</frontend_model>
......
......@@ -73,6 +73,14 @@
<tokenFormat>Adyen\Payment\Model\InstantPurchase\CreditCard\TokenFormatter</tokenFormat>
</instant_purchase>
</adyen_cc_vault>
<adyen_google_pay_vault>
<model>AdyenPaymentGooglePayVaultFacade</model>
<title>Stored Cards (Adyen)</title>
<instant_purchase>
<available>Adyen\Payment\Model\InstantPurchase\CreditCard\AvailabilityChecker</available>
<tokenFormat>Adyen\Payment\Model\InstantPurchase\CreditCard\TokenFormatter</tokenFormat>
</instant_purchase>
</adyen_google_pay_vault>
<adyen_oneclick>
<active>1</active>
<model>AdyenPaymentOneclickFacade</model>
......@@ -201,6 +209,27 @@
<can_cancel>1</can_cancel>
<group>adyen</group>
</adyen_apple_pay>
<adyen_google_pay>
<active>0</active>
<model>AdyenPaymentGooglePayFacade</model>
<title>Adyen Google Pay</title>
<allowspecific>0</allowspecific>
<sort_order>10</sort_order>
<payment_action>authorize</payment_action>
<is_gateway>1</is_gateway>
<can_use_checkout>1</can_use_checkout>
<can_authorize>1</can_authorize>
<can_capture>1</can_capture>
<can_capture_partial>1</can_capture_partial>
<can_use_internal>0</can_use_internal>
<can_refund_partial_per_invoice>1</can_refund_partial_per_invoice>
<can_refund>1</can_refund>
<can_void>1</can_void>
<can_cancel>1</can_cancel>
<can_authorize_vault>1</can_authorize_vault>
<can_capture_vault>1</can_capture_vault>
<group>adyen</group>
</adyen_google_pay>
</payment>
</default>
</config>
......@@ -53,6 +53,16 @@
<argument name="vaultProvider" xsi:type="object">AdyenPaymentCcFacade</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayVaultFacade" type="Magento\Vault\Model\Method\Vault">
<arguments>
<argument name="code" xsi:type="const">Adyen\Payment\Model\Ui\AdyenGooglePayConfigProvider::GOOGLE_PAY_VAULT_CODE
</argument>
<argument name="config" xsi:type="object">AdyenPaymentCcVaultConfig</argument>
<argument name="valueHandlerPool" xsi:type="object">AdyenPaymentCcVaultPaymentValueHandlerPool</argument>
<argument name="vaultProvider" xsi:type="object">AdyenPaymentGooglePayFacade</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentOneclickFacade" type="Adyen\Payment\Model\Method\Adapter">
<arguments>
<argument name="code" xsi:type="const">Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider::CODE</argument>
......@@ -113,6 +123,16 @@
<argument name="commandPool" xsi:type="object">AdyenPaymentApplePayCommandPool</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayFacade" type="Magento\Payment\Model\Method\Adapter">
<arguments>
<argument name="code" xsi:type="const">Adyen\Payment\Model\Ui\AdyenGooglePayConfigProvider::CODE</argument>
<argument name="formBlockType" xsi:type="string">Adyen\Payment\Block\Form\GooglePay</argument>
<argument name="infoBlockType" xsi:type="string">Adyen\Payment\Block\Info\GooglePay</argument>
<argument name="valueHandlerPool" xsi:type="object">AdyenPaymentGooglePayValueHandlerPool</argument>
<argument name="validatorPool" xsi:type="object">AdyenPaymentGooglePayValidatorPool</argument>
<argument name="commandPool" xsi:type="object">AdyenPaymentGooglePayCommandPool</argument>
</arguments>
</virtualType>
<!-- Value handlers infrastructure -->
<virtualType name="AdyenPaymentCcVaultPaymentValueHandler" type="VaultPaymentDefaultValueHandler">
......@@ -232,6 +252,19 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayValueHandlerPool" type="Magento\Payment\Gateway\Config\ValueHandlerPool">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="default" xsi:type="string">AdyenPaymentGooglePayConfigValueHandler</item>
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayConfigValueHandler" type="Magento\Payment\Gateway\Config\ConfigValueHandler">
<arguments>
<argument name="configInterface" xsi:type="object">AdyenPaymentGooglePayConfig</argument>
</arguments>
</virtualType>
<!-- Configuration reader -->
<virtualType name="AdyenPaymentGenericConfig" type="Magento\Payment\Gateway\Config\Config">
<arguments>
......@@ -280,6 +313,11 @@
<argument name="methodCode" xsi:type="const">Adyen\Payment\Model\Ui\AdyenApplePayConfigProvider::CODE</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayConfig" type="Magento\Payment\Gateway\Config\Config">
<arguments>
<argument name="methodCode" xsi:type="const">Adyen\Payment\Model\Ui\AdyenGooglePayConfigProvider::CODE</argument>
</arguments>
</virtualType>
<!-- Commands infrastructure -->
......@@ -306,6 +344,7 @@
<arguments>
<argument name="executors" xsi:type="array">
<item name="adyen_cc" xsi:type="string">AdyenPaymentCcCommandManager</item>
<item name="adyen_google_pay" xsi:type="string">AdyenPaymentCcCommandManager</item>
</argument>
</arguments>
</type>
......@@ -393,6 +432,18 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayCommandPool" type="Magento\Payment\Gateway\Command\CommandPool">
<arguments>
<argument name="commands" xsi:type="array">
<item name="authorize" xsi:type="string">AdyenPaymentGooglePayAuthorizeCommand</item>
<item name="capture" xsi:type="string">AdyenPaymentCaptureCommand</item>
<item name="void" xsi:type="string">AdyenPaymentCancelCommand</item>
<item name="refund" xsi:type="string">AdyenPaymentRefundCommand</item>
<item name="cancel" xsi:type="string">AdyenPaymentCancelCommand</item>
</argument>
</arguments>
</virtualType>
<!-- Authorization command -->
<virtualType name="AdyenPaymentCcAuthorizeCommand" type="Magento\Payment\Gateway\Command\GatewayCommand">
<arguments>
......@@ -454,6 +505,16 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayAuthorizeCommand" type="Magento\Payment\Gateway\Command\GatewayCommand">
<arguments>
<argument name="requestBuilder" xsi:type="object">AdyenPaymentGooglePayAuthorizeRequest</argument>
<argument name="transferFactory" xsi:type="object">Adyen\Payment\Gateway\Http\TransferFactory</argument>
<argument name="client" xsi:type="object">Adyen\Payment\Gateway\Http\Client\TransactionPayment</argument>
<argument name="validator" xsi:type="object">CheckoutResponseValidator</argument>
<argument name="handler" xsi:type="object">AdyenPaymentGooglePayResponseHandlerComposite</argument>
</arguments>
</virtualType>
<!-- Capture command -->
<virtualType name="AdyenPaymentCaptureCommand" type="Magento\Payment\Gateway\Command\GatewayCommand">
<arguments>
......@@ -586,6 +647,21 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
<argument name="builders" xsi:type="array">
<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="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\GooglePayAuthorizationDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringDataBuilder</item>
</argument>
</arguments>
</virtualType>
<!-- Capture Request -->
<virtualType name="AdyenPaymentCaptureRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
<arguments>
......@@ -633,6 +709,15 @@
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayResponseHandlerComposite" type="Magento\Payment\Gateway\Response\HandlerChain">
<arguments>
<argument name="handlers" xsi:type="array">
<item name="payment_details" xsi:type="string">Adyen\Payment\Gateway\Response\CheckoutPaymentsDetailsHandler</item>
<item name="vault_details" xsi:type="string">Adyen\Payment\Gateway\Response\VaultDetailsHandler</item>
<item name="payment_comments" xsi:type="string">Adyen\Payment\Gateway\Response\CheckoutPaymentCommentHistoryHandler</item>
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenPaymentPosCloudResponseHandlerComposite" type="Magento\Payment\Gateway\Response\HandlerChain">
<arguments>
......@@ -769,6 +854,19 @@
</arguments>
</virtualType>
<virtualType name="AdyenPaymentGooglePayValidatorPool" type="Magento\Payment\Gateway\Validator\ValidatorPool">
<arguments>
<argument name="validators" xsi:type="array">
<item name="country" xsi:type="string">AdyenGooglePayCountryValidator</item>
</argument>
</arguments>
</virtualType>
<virtualType name="AdyenGooglePayCountryValidator" type="Magento\Payment\Gateway\Validator\CountryValidator">
<arguments>
<argument name="config" xsi:type="object">AdyenPaymentGooglePayConfig</argument>
</arguments>
</virtualType>
<!--General Response validator-->
<virtualType name="GeneralResponseValidator" type="Adyen\Payment\Gateway\Validator\GeneralResponseValidator">
......
......@@ -41,4 +41,7 @@
<event name="payment_method_assign_data_adyen_apple_pay">
<observer name="adyen_apple_pay_gateway_data_assign" instance="Adyen\Payment\Observer\AdyenApplePayDataAssignObserver" />
</event>
<event name="payment_method_assign_data_adyen_google_pay">
<observer name="adyen_google_pay_gateway_data_assign" instance="Adyen\Payment\Observer\AdyenGooglePayDataAssignObserver" />
</event>
</config>
......@@ -34,6 +34,7 @@
<item name="adyen_boleto_config_provider" xsi:type="object">Adyen\Payment\Model\Ui\AdyenBoletoConfigProvider</item>
<item name="adyen_pos_cloud_config_provider" xsi:type="object">Adyen\Payment\Model\Ui\AdyenPosCloudConfigProvider</item>
<item name="adyen_apple_pay_config_provider" xsi:type="object">Adyen\Payment\Model\Ui\AdyenApplePayConfigProvider</item>
<item name="adyen_google_pay_config_provider" xsi:type="object">Adyen\Payment\Model\Ui\AdyenGooglePayConfigProvider</item>
</argument>
</arguments>
</type>
......@@ -41,6 +42,7 @@
<arguments>
<argument name="tokenUiComponentProviders" xsi:type="array">
<item name="adyen_cc" xsi:type="object">Adyen\Payment\Model\Ui\TokenUiComponentProvider</item>
<item name="adyen_google_pay" xsi:type="object">Adyen\Payment\Model\Ui\TokenGooglePayUiComponentProvider</item>
</argument>
</arguments>
</type>
......
......@@ -24,7 +24,7 @@
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Adyen_Payment" setup_version="4.3.0">
<module name="Adyen_Payment" setup_version="4.4.0">
<sequence>
<module name="Magento_Sales"/>
<module name="Magento_Quote"/>
......
......@@ -28,7 +28,7 @@
<referenceContainer name="content">
<referenceBlock name="vault.cards.list">
<block class="Adyen\Payment\Block\Customer\CardRenderer" name="adyen.card.renderer"
template="Magento_Vault::customer_account/credit_card.phtml"/>
template="Magento_Vault::customer_account/credit_card.phtml" cacheable="false"/>
</referenceBlock>
</referenceContainer>
</body>
......
......@@ -103,6 +103,11 @@
height: 43px;
}
.checkout-payment-method .payment-method-title label div.adyen-sprite.adyen_google_pay {
background: url(../images/logos/Google-Pay-Mark.png) no-repeat;
height: 43px;
}
.checkout-payment-method .input-text._has-datepicker {
width: 20%;
margin-right: 10px;
......@@ -176,6 +181,11 @@
min-height: 42px; /* override magento min-height */
}
.gpay-button:hover, .gpay-button:active, .gpay-button:focus{
background-repeat: no-repeat;
background-position: center center;
}
/*
Custom style for ideal component
*/
......@@ -1223,7 +1233,7 @@
.threeDS2Modal #threeDS2Container {
height: 100vh;
margin-bottom: 5rem;
}
.adyen-checkout__threeds2, .adyen-checkout__threeds2__challenge {
......
......@@ -5,35 +5,36 @@
define(
[
'ko',
'jquery',
],
function (ko) {
function (ko, $) {
'use strict';
var installments = ko.observableArray(['key', 'value']);
return {
/**
* Populate the list of installments
* @param {Array} methods
*/
setInstallments: function (installmentData) {
// remove everything from the current list
installments.removeAll();
var i;
for (i = 0; i < installmentData.length; i++) {
installments.push(
{
key: installmentData[i].key,
value: installmentData[i].value
}
);
}
},
/**
* Get the list of available installments.
*
* @param installments
* @param grandTotal
* @param precision
* @param currencyCode
* @returns {Array}
*/
getInstallments: function () {
return installments;
getInstallmentsWithPrices: function (installments, grandTotal, precision, currencyCode) {
let numberOfInstallments = [];
let dividedAmount = 0;
let dividedString = "";
$.each(installments, function (amount, installment) {
if (grandTotal >= amount) {
dividedAmount = (grandTotal / installment).toFixed(precision);
dividedString = installment + " x " + dividedAmount + " " + currencyCode;
numberOfInstallments.push({
key: [dividedString],
value: installment
});
}
});
return numberOfInstallments;
}
};
}
......
......@@ -55,6 +55,10 @@ define(
{
type: 'adyen_pos_cloud',
component: 'Adyen_Payment/js/view/payment/method-renderer/adyen-pos-cloud-method'
},
{
type: 'adyen_google_pay',
component: 'Adyen_Payment/js/view/payment/method-renderer/adyen-google-pay-method'
}
);
/** Add view logic here if needed */
......@@ -69,10 +73,19 @@ define(
checkoutCardComponentScriptTag.src = self.getCheckoutCardComponentSource();
checkoutCardComponentScriptTag.type = "text/javascript";
document.body.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);
}
},
getCheckoutCardComponentSource: function() {
return window.checkoutConfig.payment.checkoutCardComponentSource;
},
isGooglePayEnabled: function() {
return window.checkoutConfig.payment.adyenGooglePay.active;
}
});
}
);
\ No newline at end of file
......@@ -39,7 +39,7 @@ define(
'Adyen_Payment/js/threeds2-js-utils',
'Adyen_Payment/js/model/threeds2'
],
function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installments, 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) {
'use strict';
......@@ -83,13 +83,13 @@ define(
'expiryMonth',
'expiryYear',
'installment',
'installments',
'creditCardDetailsValid',
'placeOrderAllowed'
]);
return this;
},
getInstallments: installments.getInstallments(),
/**
* Returns true if card details can be stored
* @returns {*|boolean}
......@@ -104,17 +104,17 @@ define(
* set up the installments
*/
renderSecureFields: function () {
var self = this;
let self = this;
if (!self.getOriginKey()) {
return;
}
installments.setInstallments(0);
self.installments(0);
// installments enabled ??
var allInstallments = self.getAllInstallments();
var cardNode = document.getElementById('cardContainer');
// installments
let allInstallments = self.getAllInstallments();
let cardNode = document.getElementById('cardContainer');
self.cardComponent = self.checkout.create('card', {
originKey: self.getOriginKey(),
......@@ -147,35 +147,24 @@ define(
if (creditCardType) {
// If the credit card type is already set, check if it changed or not
if (!self.creditCardType() || self.creditCardType() && self.creditCardType() != creditCardType) {
let numberOfInstallments = [];
if (creditCardType in allInstallments) {
// get for the creditcard the installments
var installmentCreditcard = allInstallments[creditCardType];
var grandTotal = quote.totals().grand_total;
var numberOfInstallments = [];
var dividedAmount = 0;
var dividedString = "";
$.each(installmentCreditcard, function (amount, installment) {
if (grandTotal >= amount) {
dividedAmount = (grandTotal / installment).toFixed(quote.getPriceFormat().precision);
dividedString = installment + " x " + dividedAmount + " " + quote.totals().quote_currency_code;
numberOfInstallments.push({
key: [dividedString],
value: installment
});
}
else {
return false;
}
});
let installmentCreditcard = allInstallments[creditCardType];
let grandTotal = quote.totals().grand_total;
let precision = quote.getPriceFormat().precision;
let currencyCode = quote.totals().quote_currency_code;
numberOfInstallments = installmentsHelper.getInstallmentsWithPrices(installmentCreditcard, grandTotal, precision, currencyCode);
}
if (numberOfInstallments) {
installments.setInstallments(numberOfInstallments);
self.installments(numberOfInstallments);
}
else {
installments.setInstallments(0);
self.installments(0);
}
}
......@@ -188,7 +177,7 @@ define(
}
} else {
self.creditCardType("")
installments.setInstallments(0);
self.installments(0);
}
}
}).mount(cardNode);
......
/*
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2019 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
/*browser:true*/
/*global define*/
define(
[
'ko',
'jquery',
'Magento_Checkout/js/view/payment/default',
'Magento_Checkout/js/action/place-order',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/url-builder',
'Magento_Checkout/js/model/full-screen-loader',
'mage/url',
'Magento_Vault/js/view/payment/vault-enabler'
],
function (ko, $, Component, placeOrderAction, quote, urlBuilder, fullScreenLoader, url, VaultEnabler) {
'use strict';
/**
* Shareble adyen checkout component
* @type {AdyenCheckout}
*/
var checkoutComponent;
return Component.extend({
self: this,
defaults: {
template: 'Adyen_Payment/payment/google-pay-form',
googlePayToken: null,
googlePayAllowed: null
},
/**
* @returns {Boolean}
*/
isShowLegend: function () {
return true;
},
setPlaceOrderHandler: function (handler) {
this.placeOrderHandler = handler;
},
setValidateHandler: function (handler) {
this.validateHandler = handler;
},
getCode: function () {
return 'adyen_google_pay';
},
getData: function () {
return {
'method': this.item.method,
'additional_data': {}
};
},
isActive: function () {
return true;
},
initObservable: function () {
this._super()
.observe([
'googlePayToken',
'googlePayAllowed'
]);
return this;
}, initialize: function () {
var self = this;
this.vaultEnabler = new VaultEnabler();
this.vaultEnabler.setPaymentCode(this.getVaultCode());
this.vaultEnabler.isActivePaymentTokenEnabler(false);
this._super();
},
renderGooglePay: function () {
var self = this;
var googlePayNode = document.getElementById('googlePay');
self.checkoutComponent = new AdyenCheckout({
locale: self.getLocale(),
risk: {
enabled: false
}
});
var googlepay = self.checkoutComponent.create('paywithgoogle', {
environment: self.getCheckoutEnvironment().toUpperCase(),
configuration: {
// Adyen's merchant account
gatewayMerchantId: self.getMerchantAccount(),
// https://developers.google.com/pay/api/web/reference/object#MerchantInfo
merchantIdentifier: self.getMerchantIdentifier(),
merchantName: self.getMerchantAccount()
},
// Payment
amount: self.formatAmount(quote.totals().grand_total, self.getFormat()),
currency: quote.totals().quote_currency_code,
totalPriceStatus: 'FINAL',
onChange: function (state) {
if (!!state.isValid) {
self.googlePayToken(state.data.paymentMethod["paywithgoogle.token"]);
self.getPlaceOrderDeferredObject()
.fail(
function () {
fullScreenLoader.stopLoader();
self.isPlaceOrderActionAllowed(true);
}
).done(
function () {
self.afterPlaceOrder();
window.location.replace(url.build(window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl));
}
);
}
},
buttonColor: 'black', // default/black/white
buttonType: 'long', // long/short
showButton: true // show or hide the Google Pay button
});
var promise = googlepay.isAvailable();
promise.then(function (success) {
self.googlePayAllowed(true);
googlepay.mount(googlePayNode);
}, function (error) {
console.log(error);
self.googlePayAllowed(false);
});
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyenGooglePay.checkoutEnvironment;
},
isGooglePayAllowed: function () {
if (this.googlePayAllowed()) {
return true;
}
return false;
},
getMerchantAccount: function () {
return window.checkoutConfig.payment.adyenGooglePay.merchantAccount;
},
showLogo: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
getLocale: function () {
return window.checkoutConfig.payment.adyenGooglePay.locale;
},
getFormat: function () {
return window.checkoutConfig.payment.adyenGooglePay.format;
},
getMerchantIdentifier: function () {
return window.checkoutConfig.payment.adyenGooglePay.merchantIdentifier;
},
context: function () {
return this;
},
validate: function () {
return true;
},
getControllerName: function () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
},
getPlaceOrderUrl: function () {
return window.checkoutConfig.payment.iframe.placeOrderUrl[this.getCode()];
},
/**
* Get data for place order
* @returns {{method: *}}
*/
getData: function () {
return {
'method': "adyen_google_pay",
'additional_data': {
'token': this.googlePayToken()
}
};
},
/**
* Return the formatted currency. Adyen accepts the currency in multiple formats.
* @param $amount
* @param $currency
* @return string
*/
formatAmount: function (amount, format) {
return Math.round(amount * (Math.pow(10, format)))
},
isVaultEnabled: function () {
return this.vaultEnabler.isVaultEnabled();
},
getVaultCode: function () {
return "adyen_google_pay_vault";
}
});
}
);
......@@ -37,9 +37,10 @@ define(
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Checkout/js/model/error-processor',
'Magento_Ui/js/model/messages',
'Magento_Checkout/js/action/redirect-on-success'
'Magento_Checkout/js/action/redirect-on-success',
'Adyen_Payment/js/model/installments'
],
function (ko, $, Component, additionalValidators, placeOrderAction, quote, agreementsAssigner, customer, urlBuilder, storage, fullScreenLoader, errorProcessor, Messages, redirectOnSuccessAction) {
function (ko, $, Component, additionalValidators, placeOrderAction, quote, agreementsAssigner, customer, urlBuilder, storage, fullScreenLoader, errorProcessor, Messages, redirectOnSuccessAction, installmentsHelper) {
'use strict';
return Component.extend({
......@@ -47,7 +48,34 @@ define(
defaults: {
template: 'Adyen_Payment/payment/pos-cloud-form'
},
initObservable: function () {
this._super()
.observe([
'terminalId',
'installments',
'installment'
]);
return this;
},
initialize: function () {
this._super();
let self = this;
// installments
let allInstallments = self.getAllInstallments();
let grandTotal = quote.totals().grand_total;
let precision = quote.getPriceFormat().precision;
let currencyCode = quote.totals().quote_currency_code;
let numberOfInstallments = installmentsHelper.getInstallmentsWithPrices(allInstallments, grandTotal, precision, currencyCode);
if (numberOfInstallments) {
self.installments(numberOfInstallments);
} else {
self.installments(0);
}
},
initiate: function () {
var self = this,
serviceUrl,
......@@ -59,7 +87,10 @@ define(
fullScreenLoader.startLoader();
let payload = {
"payload": JSON.stringify({terminal_id: self.terminalId()})
"payload": JSON.stringify({
terminal_id: self.terminalId(),
number_of_installments: self.installment()
})
}
return storage.post(
......@@ -69,21 +100,13 @@ define(
self.placeOrderPos()});
return false;
},
initObservable: function () {
this._super()
.observe([
'terminalId'
]);
return this;
},
posComplete: function () {
this.afterPlaceOrder();
if (this.redirectAfterPlaceOrder) {
redirectOnSuccessAction.execute();
}
},
placeOrderPos: function () {
var self = this;
return $.when(
......@@ -128,16 +151,33 @@ define(
return {
'method': this.item.method,
additional_data: {
'terminal_id': this.terminalId()
'terminal_id': this.terminalId(),
'number_of_installments': this.installment(),
}
};
},
hasInstallments: function () {
return window.checkoutConfig.payment.adyenPos.hasInstallments;
},
getAllInstallments: function () {
return window.checkoutConfig.payment.adyenPos.installments;
},
showLogo: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
validate: function () {
return true;
}
},
isActive: function () {
return true;
},
/**
* Returns state of place order button
* @returns {boolean}
*/
isButtonActive: function () {
return this.isActive() && this.getCode() == this.isChecked() && this.getConnectedTerminals().length > 0 && this.validate();
},
});
}
);
......@@ -87,7 +87,7 @@
<!-- ko if: (hasInstallments())-->
<div class="field required"
data-bind="attr: {id: getCode() + '_installments_div'}, visible: getInstallments().length > 0">
data-bind="attr: {id: getCode() + '_installments_div'}, visible: installments().length > 0">
<label data-bind="attr: {for: getCode() + '_installments'}" class="label">
<span><!-- ko text: $t('Installments')--><!-- /ko --></span>
</label>
......@@ -98,7 +98,7 @@
data-bind="attr: {id: getCode() + '_installments', 'data-container': getCode() + '-installments', 'data-validate': JSON.stringify({required:false})},
enable: isActive($parents),
options: getInstallments,
options: installments,
optionsValue: 'value',
optionsText: 'key',
optionsCaption: $t('Do not use Installments'),
......
<!--
~ ######
~ ######
~ ############ ####( ###### #####. ###### ############ ############
~ ############# #####( ###### #####. ###### ############# #############
~ ###### #####( ###### #####. ###### ##### ###### ##### ######
~ ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
~ ###### ###### #####( ###### #####. ###### ##### ##### ######
~ ############# ############# ############# ############# ##### ######
~ ############ ############ ############# ############ ##### ######
~ ######
~ #############
~ ############
~
~ Adyen Payment Module
~
~ Copyright (c) 2019 Adyen B.V.
~ This file is open source and available under the MIT license.
~ See the LICENSE file for more info.
~
~ Author: Adyen <magento@adyen.com>
-->
<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
<div class="payment-method-title field choice">
<input type="radio"
name="payment[method]"
class="radio"
data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
<label data-bind="attr: {'for': getCode()}" class="label">
<!-- ko if: showLogo() -->
<div data-bind="attr: { 'class': 'adyen-sprite ' + getCode() }"></div>
<!--/ko-->
<span data-bind="text: getTitle()"></span>
</label>
</div>
<div class="payment-method-content">
<div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<div class="checkout-agreements-block">
<!-- ko foreach: $parent.getRegion('before-place-order') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<div class="field number googlePay">
<div afterRender="renderGooglePay()" data-bind="attr: { id: 'googlePay'}">
<!-- ko ifnot: isGooglePayAllowed() -->
Google Pay is not available
<!--/ko--></div>
</div>
<div id="adyen-google-pay-button" class="google-pay-button-with-text google-pay-button-black-with-text"
data-bind= "click: placeOrder">
<span class="logo"></span>
</div>
</div>
</div>
......@@ -50,30 +50,61 @@
<!--/ko-->
</div>
<div class="field required"
data-bind="attr: {id: getCode() + '_connected_terminals_div'}, visible: getConnectedTerminals().length > 0">
<label data-bind="attr: {for: getCode() + '_connected_terminals'}" class="label">
<span><!-- ko text: $t('Connected terminals')--><!-- /ko --></span>
</label>
<div class="control">
<!-- ko if: (getConnectedTerminals().length > 0) -->
<select class="select"
name="paymentMethod[connected_terminals]"
data-bind="attr: {id: getCode() + '_connected_terminals', 'data-container': getCode() + '-connected-terminals', 'data-validate': JSON.stringify({required:true})},
options: getConnectedTerminals(),
optionsValue: 'value',
optionsText: 'key',
value: terminalId"
>
</select>
<div class="field required"
data-bind="attr: {id: getCode() + '_connected_terminals_div'}, visible: getConnectedTerminals().length > 0">
<label data-bind="attr: {for: getCode() + '_connected_terminals'}" class="label">
<span><!-- ko text: $t('Connected terminals')--><!-- /ko --></span>
</label>
<div class="control">
<select class="select"
name="paymentMethod[connected_terminals]"
data-bind="attr: {id: getCode() + '_connected_terminals', 'data-container': getCode() + '-connected-terminals', 'data-validate': JSON.stringify({required:true})},
options: getConnectedTerminals(),
optionsValue: 'value',
optionsText: 'key',
value: terminalId"
>
</select>
</div>
</div>
</div>
<div class="checkout-agreements-block">
<!-- ko foreach: $parent.getRegion('before-place-order') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<!-- ko if: (hasInstallments())-->
<div class="field required"
data-bind="attr: {id: getCode() + '_installments_div'}, visible: installments().length > 0">
<label data-bind="attr: {for: getCode() + '_installments'}" class="label">
<span><!-- ko text: $t('Installments')--><!-- /ko --></span>
</label>
<div class="control">
<select class="select"
name="payment[number_of_installments]"
data-bind="attr: {id: getCode() + '_installments', 'data-container': getCode() + '-installments', 'data-validate': JSON.stringify({required:false})},
enable: isActive($parents),
options: installments,
optionsValue: 'value',
optionsText: 'key',
optionsCaption: $t('Do not use Installments'),
value: installment"
data-validate="{required:true}">
</select>
</div>
</div>
<!-- /ko -->
<div class="checkout-agreements-block">
<!-- ko foreach: $parent.getRegion('before-place-order') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<!--/ko-->
<!-- ko ifnot: (getConnectedTerminals().length > 0) -->
<p><!-- ko text: $t('Please connect at least 1 terminal')--><!-- /ko --></p>
<!--/ko-->
<div class="actions-toolbar">
<div class="primary">
<button class="action primary checkout"
......@@ -81,7 +112,7 @@
data-bind="
click: initiate,
attr: {title: $t('Place Order')},
enable: getConnectedTerminals().length > 0
enable: isButtonActive()
"
disabled>
<span data-bind="text: $t('Place Order')"></span>
......
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