Commit ed625243 authored by attilak's avatar attilak

Merge branch 'PW-2212' into feature/generic-component

# Conflicts:
#	Block/Form/Cc.php
#	Gateway/Request/CcAuthorizationDataBuilder.php
#	Gateway/Request/CheckoutDataBuilder.php
#	Gateway/Request/RecurringDataBuilder.php
#	Gateway/Validator/CheckoutResponseValidator.php
#	Helper/PaymentMethods.php
#	Helper/Requests.php
#	Model/AdyenThreeDS2Process.php
#	Model/Ui/AdyenGenericConfigProvider.php
#	Observer/AdyenCcDataAssignObserver.php
#	Observer/AdyenHppDataAssignObserver.php
#	view/frontend/web/js/model/adyen-method-list.js
#	view/frontend/web/js/model/adyen-payment-service.js
#	view/frontend/web/js/view/payment/adyen-methods.js
#	view/frontend/web/js/view/payment/method-renderer/adyen-cc-method.js
#	view/frontend/web/js/view/payment/method-renderer/adyen-hpp-method.js
#	view/frontend/web/js/view/payment/method-renderer/adyen-oneclick-method.js
parents 7ee6f945 c6bdeeec
......@@ -67,22 +67,14 @@ class Cc extends \Magento\Payment\Block\Form\Cc
$this->checkoutSession = $checkoutSession;
}
/**
* @return string
*/
public function getCheckoutCardComponentJs()
{
return $this->adyenHelper->getCheckoutCardComponentJs($this->checkoutSession->getQuote()->getStore()->getId());
}
/**
* @return string
* @throws \Adyen\AdyenException
*/
public function getCheckoutOriginKeys()
{
return $this->adyenHelper->getOriginKeyForBaseUrl();
}
/**
* @return string
* @throws \Adyen\AdyenException
*/
public function getCheckoutOriginKeys()
{
return $this->adyenHelper->getOriginKeyForBaseUrl();
}
/**
* @return string
......
<?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\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
class CcAuthorizationDataBuilder implements BuilderInterface
{
/**
* @param array $buildSubject
* @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();
$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 and card type is credit card add it into the request
$numberOfInstallments = $payment->getAdditionalInformation(
AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS
) ?: 0;
$comboCardType = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::COMBO_CARD_TYPE) ?: 'credit';
if ($numberOfInstallments > 0) {
$requestBody['installments']['value'] = $numberOfInstallments;
}
// if card type is debit then change the issuer type and unset the installments field
if ($comboCardType == 'debit') {
if ($selectedDebitBrand = $this->getSelectedDebitBrand($payment->getAdditionalInformation('cc_type'))) {
$requestBody['additionalData']['overwriteBrand'] = true;
$requestBody['selectedBrand'] = $selectedDebitBrand;
$requestBody['paymentMethod']['type'] = $selectedDebitBrand;
}
unset($requestBody['installments']);
}
$request['body'] = $requestBody;
return $request;
}
/**
* @param string $brand
* @return string
*/
private function getSelectedDebitBrand($brand)
{
if ($brand == 'VI') {
return 'electron';
}
if ($brand == 'MC') {
return 'maestro';
}
return null;
}
}
......@@ -23,6 +23,7 @@
namespace Adyen\Payment\Gateway\Request;
use Adyen\Payment\Observer\AdyenCcDataAssignObserver;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Adyen\Payment\Observer\AdyenHppDataAssignObserver;
......@@ -82,14 +83,17 @@ class CheckoutDataBuilder implements BuilderInterface
// do not send email
$order->setCanSendNewEmailFlag(false);
$requestBodyPaymentMethod['type'] = $payment->getAdditionalInformation(
AdyenHppDataAssignObserver::BRAND_CODE
);
$componentStateData = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::STATE_DATA);
$requestBody = array_merge($requestBody, $componentStateData);
// Additional data for payment methods with issuer list
if ($payment->getAdditionalInformation(AdyenHppDataAssignObserver::ISSUER_ID)) {
$requestBodyPaymentMethod['issuer'] = $payment->getAdditionalInformation(
AdyenHppDataAssignObserver::ISSUER_ID
if (empty($requestBody['paymentMethod']['type']) && !empty(
$payment->getAdditionalInformation(
AdyenHppDataAssignObserver::BRAND_CODE
)
)) {
$requestBody['paymentMethod']['type'] = $payment->getAdditionalInformation(
AdyenHppDataAssignObserver::BRAND_CODE
);
}
......@@ -97,59 +101,24 @@ class CheckoutDataBuilder implements BuilderInterface
\Magento\Framework\UrlInterface::URL_TYPE_LINK
) . 'adyen/process/result';
// Additional data for ACH
if ($payment->getAdditionalInformation("bankAccountNumber")) {
$requestBody['bankAccount']['bankAccountNumber'] = $payment->getAdditionalInformation("bankAccountNumber");
}
if ($payment->getAdditionalInformation("bankLocationId")) {
$requestBody['bankAccount']['bankLocationId'] = $payment->getAdditionalInformation("bankLocationId");
}
if ($payment->getAdditionalInformation("bankAccountOwnerName")) {
$requestBody['bankAccount']['ownerName'] = $payment->getAdditionalInformation("bankAccountOwnerName");
}
// Additional data for open invoice payment
// TODO set order payment extra data -> mapping required
if ($payment->getAdditionalInformation("gender")) {
$order->setCustomerGender(
$this->gender->getMagentoGenderFromAdyenGender(
\Adyen\Payment\Model\Gender::getMagentoGenderFromAdyenGender(
$payment->getAdditionalInformation("gender")
)
);
$requestBodyPaymentMethod['personalDetails']['gender'] = $payment->getAdditionalInformation("gender");
}
if ($payment->getAdditionalInformation("dob")) {
$order->setCustomerDob($payment->getAdditionalInformation("dob"));
$requestBodyPaymentMethod['personalDetails']['dateOfBirth'] = $this->adyenHelper->formatDate(
$payment->getAdditionalInformation("dob"),
'Y-m-d'
);
}
if ($payment->getAdditionalInformation("telephone")) {
$order->getBillingAddress()->setTelephone($payment->getAdditionalInformation("telephone"));
$requestBodyPaymentMethod['personalDetails']['telephoneNumber'] = $payment->getAdditionalInformation(
"telephone"
);
}
if ($payment->getAdditionalInformation("ssn")) {
$requestBodyPaymentMethod['personalDetails']['socialSecurityNumber'] =
$payment->getAdditionalInformation("ssn");
}
// Additional data for sepa direct debit
if ($payment->getAdditionalInformation("ownerName")) {
$requestBodyPaymentMethod['sepa.ownerName'] = $payment->getAdditionalInformation("ownerName");
}
if ($payment->getAdditionalInformation("ibanNumber")) {
$requestBodyPaymentMethod['sepa.ibanNumber'] = $payment->getAdditionalInformation("ibanNumber");
}
// TODO new function isOpenInvoiceLineItemNeeded
if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod(
$payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE)
) || $this->adyenHelper->isPaymentMethodAfterpayTouchMethod(
......@@ -163,6 +132,7 @@ class CheckoutDataBuilder implements BuilderInterface
}
// Ratepay specific Fingerprint
// TODO check if this is still necessary or if there is a component that can handle this
if ($payment->getAdditionalInformation("df_value") && $this->adyenHelper->isPaymentMethodRatepayMethod(
$payment->getAdditionalInformation(AdyenHppDataAssignObserver::BRAND_CODE)
)) {
......@@ -183,16 +153,17 @@ class CheckoutDataBuilder implements BuilderInterface
}
if ($payment->getMethod() == \Adyen\Payment\Model\Ui\AdyenBoletoConfigProvider::CODE) {
$boletoTypes = $this->adyenHelper->getAdyenBoletoConfigData('boletotypes');
// TODO check if this is coming from the component now
/*$boletoTypes = $this->adyenHelper->getAdyenBoletoConfigData('boletotypes');
$boletoTypes = explode(',', $boletoTypes);
if (count($boletoTypes) == 1) {
$requestBody['selectedBrand'] = $boletoTypes[0];
$requestBodyPaymentMethod['type'] = $boletoTypes[0];
$requestBody['paymentMethod']['type'] = $boletoTypes[0];
} else {
$requestBody['selectedBrand'] = $payment->getAdditionalInformation("boleto_type");
$requestBodyPaymentMethod['type'] = $payment->getAdditionalInformation("boleto_type");
}
$requestBody['paymentMethod']['type'] = $payment->getAdditionalInformation("boleto_type");
}*/
$deliveryDays = (int)$this->adyenHelper->getAdyenBoletoConfigData("delivery_days", $storeId);
$deliveryDays = (!empty($deliveryDays)) ? $deliveryDays : 5;
......@@ -213,7 +184,23 @@ class CheckoutDataBuilder implements BuilderInterface
$order->setCanSendNewEmailFlag(true);
}
$requestBody['paymentMethod'] = $requestBodyPaymentMethod;
// if installments is set and card type is credit card add it into the request
$numberOfInstallments = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) ?: 0;
$comboCardType = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::COMBO_CARD_TYPE) ?: 'credit';
if ($numberOfInstallments > 0) {
$requestBody['installments']['value'] = $numberOfInstallments;
}
// if card type is debit then change the issuer type and unset the installments field
if ($comboCardType == 'debit') {
if ($selectedDebitBrand = $this->getSelectedDebitBrand($payment->getAdditionalInformation('cc_type'))) {
$requestBody['additionalData']['overwriteBrand'] = true;
$requestBody['selectedBrand'] = $selectedDebitBrand;
$requestBody['paymentMethod']['type'] = $selectedDebitBrand;
}
unset($requestBody['installments']);
}
$request['body'] = $requestBody;
return $request;
......@@ -312,4 +299,19 @@ class CheckoutDataBuilder implements BuilderInterface
return $formFields;
}
/**
* @param string $brand
* @return string
*/
private function getSelectedDebitBrand($brand)
{
if ($brand == 'VI') {
return 'electron';
}
if ($brand == 'MC') {
return 'maestro';
}
return null;
}
}
......@@ -63,13 +63,7 @@ class RecurringDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment();
$storeId = $payment->getOrder()->getStoreId();
$areaCode = $this->appState->getAreaCode();
$additionalInformation = $payment->getAdditionalInformation();
$request['body'] = $this->adyenRequestsHelper->buildRecurringData(
$areaCode,
$storeId,
$additionalInformation,
[]
);
$request['body'] = $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId);
return $request;
}
}
......@@ -69,21 +69,9 @@ class CheckoutResponseValidator extends AbstractValidator
// validate result
if (!empty($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']);
case "IdentifyShopper":
$payment->setAdditionalInformation('action', $response['action']);
break;
case "Authorised":
case "Received":
......
......@@ -39,11 +39,6 @@ class InstallmentValidator extends AbstractValidator
*/
private $adyenHelper;
/**
* @var \Magento\Framework\Serialize\SerializerInterface
*/
private $serializer;
/**
* @var \Magento\Quote\Model\QuoteRepository
*/
......@@ -55,19 +50,16 @@ class InstallmentValidator extends AbstractValidator
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\Framework\Serialize\SerializerInterface $serializer
* @param \Magento\Quote\Model\QuoteRepository $quoteRepository
*/
public function __construct(
\Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Framework\Serialize\SerializerInterface $serializer,
\Magento\Quote\Model\QuoteRepository $quoteRepository
) {
$this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
$this->serializer = $serializer;
$this->quoteRepository = $quoteRepository;
parent::__construct($resultFactory);
}
......@@ -87,27 +79,14 @@ class InstallmentValidator extends AbstractValidator
$installmentsEnabled = $this->adyenHelper->getAdyenCcConfigData('enable_installments');
if ($quote && $installmentsEnabled) {
$grandTotal = $quote->getGrandTotal();
$installmentsAvailable = $this->adyenHelper->getAdyenCcConfigData('installments');
$installments = $this->adyenHelper->getAdyenCcConfigData('installments');
$installmentSelected = $payment->getAdditionalInformation('number_of_installments');
$ccType = $payment->getAdditionalInformation('cc_type');
if ($installmentsAvailable) {
$installments = $this->serializer->unserialize($installmentsAvailable);
}
if ($installmentSelected && $installmentsAvailable) {
$isValid = false;
$fails[] = __('Installments not valid.');
if ($installments) {
foreach ($installments as $ccTypeInstallment => $installment) {
if ($ccTypeInstallment == $ccType) {
foreach ($installment as $amount => $installmentsData) {
if ($installmentSelected == $installmentsData) {
if ($grandTotal >= $amount) {
$isValid = true;
}
}
}
}
}
//TODO how implement custom validation of generated installments code against selected value?
}
}
}
......
......@@ -34,8 +34,6 @@ 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.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
......@@ -1626,19 +1624,6 @@ class Data extends AbstractHelper
return new \Adyen\Service\CheckoutUtility($client);
}
/**
* @param int|null $storeId
* @return string
*/
public function getCheckoutCardComponentJs($storeId = null)
{
if ($this->isDemoMode($storeId)) {
return self::CHECKOUT_COMPONENT_JS_TEST;
}
return self::CHECKOUT_COMPONENT_JS_LIVE;
}
/**
* @param $order
* @param $additionalData
......@@ -1827,27 +1812,6 @@ class Data extends AbstractHelper
return $timeStamp->format($format);
}
/**
* @param string|null $type
* @param string|null $token
* @return string
*/
public function buildThreeDS2ProcessResponseJson($type = null, $token = null)
{
$response = ['threeDS2' => false];
if (!empty($type)) {
$response['type'] = $type;
}
if ($type && $token) {
$response['threeDS2'] = true;
$response['token'] = $token;
}
return json_encode($response);
}
/**
* @param int $storeId
* @return mixed|string
......
......@@ -90,6 +90,11 @@ class PaymentMethods extends AbstractHelper
*/
protected $quote;
/**
* @var \Magento\Checkout\Model\PaymentDetailsFactory
*/
protected $paymentDetailsFactory;
/**
* PaymentMethods constructor.
*
......@@ -104,6 +109,7 @@ class PaymentMethods extends AbstractHelper
* @param \Magento\Framework\View\Asset\Source $assetSource
* @param \Magento\Framework\View\DesignInterface $design
* @param \Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider
* @param \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory
*/
public function __construct(
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
......@@ -116,7 +122,8 @@ class PaymentMethods extends AbstractHelper
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\View\Asset\Source $assetSource,
\Magento\Framework\View\DesignInterface $design,
\Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider
\Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider,
\Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory
) {
$this->quoteRepository = $quoteRepository;
$this->config = $config;
......@@ -129,6 +136,7 @@ class PaymentMethods extends AbstractHelper
$this->assetSource = $assetSource;
$this->design = $design;
$this->themeProvider = $themeProvider;
$this->paymentDetailsFactory = $paymentDetailsFactory;
}
/**
......@@ -146,7 +154,7 @@ class PaymentMethods extends AbstractHelper
$this->setQuote($quote);
$paymentMethods = $this->fetchAlternativeMethods($country);
$paymentMethods = $this->fetchPaymentMethods($country);
return $paymentMethods;
}
......@@ -154,7 +162,7 @@ class PaymentMethods extends AbstractHelper
* @param $country
* @return array
*/
protected function fetchAlternativeMethods($country)
protected function fetchPaymentMethods($country)
{
$quote = $this->getQuote();
$store = $quote->getStore();
......@@ -192,64 +200,78 @@ class PaymentMethods extends AbstractHelper
$responseData = $this->getPaymentMethodsResponse($adyFields, $store);
$paymentMethods = [];
if (isset($responseData['paymentMethods'])) {
foreach ($responseData['paymentMethods'] as $paymentMethod) {
if (empty($responseData['paymentMethods'])) {
return [];
}
$paymentMethods = $responseData['paymentMethods'];
$response['paymentMethodsResponse'] = $responseData;
// Add extra details per payment mmethod
$paymentMethodsExtraDetails = [];
if ($this->adyenHelper->showLogos()) {
// Explicitly setting theme
$themeCode = "Magento/blank";
$themeId = $this->design->getConfigurationDesignTheme(\Magento\Framework\App\Area::AREA_FRONTEND);
if (!empty($themeId)) {
$theme = $this->themeProvider->getThemeById($themeId);
if ($theme && !empty($theme->getCode())) {
$themeCode = $theme->getCode();
}
}
$params = [];
$params = array_merge(
[
'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
'_secure' => $this->request->isSecure(),
'theme' => $themeCode
],
$params
);
foreach ($paymentMethods as $paymentMethod) {
$paymentMethodCode = $paymentMethod['type'];
$paymentMethod = $this->fieldMapPaymentMethod($paymentMethod);
$asset = $this->assetRepo->createAsset(
'Adyen_Payment::images/logos/' .
$paymentMethodCode . '.png',
$params
);
$placeholder = $this->assetSource->findSource($asset);
$icon = [];
if ($placeholder) {
list($width, $height) = getimagesize($asset->getSourceFile());
$icon = [
'url' => $asset->getUrl(),
'width' => $width,
'height' => $height
];
} else {
$icon = [
'url' => 'https://checkoutshopper-live.adyen.com/checkoutshopper/images/logos/medium/' .$paymentMethodCode . '.png',
'width' => 77,
'height' => 50
];
}
$paymentMethodsExtraDetails[$paymentMethodCode]['icon'] = $icon;
// check if payment method is an openinvoice method
$paymentMethod['isPaymentMethodOpenInvoiceMethod'] =
$paymentMethodsExtraDetails[$paymentMethodCode]['isOpenInvoice'] =
$this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethodCode);
// add icon location in result
if ($this->adyenHelper->showLogos()) {
// Fix for MAGETWO-70402 https://github.com/magento/magento2/pull/7686
// Explicitly setting theme
$themeCode = "Magento/blank";
$themeId = $this->design->getConfigurationDesignTheme(\Magento\Framework\App\Area::AREA_FRONTEND);
if (!empty($themeId)) {
$theme = $this->themeProvider->getThemeById($themeId);
if ($theme && !empty($theme->getCode())) {
$themeCode = $theme->getCode();
}
}
$params = [];
$params = array_merge(
[
'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
'_secure' => $this->request->isSecure(),
'theme' => $themeCode
],
$params
);
$asset = $this->assetRepo->createAsset(
'Adyen_Payment::images/logos/' .
$paymentMethodCode . '.png',
$params
);
$placeholder = $this->assetSource->findSource($asset);
$icon = null;
if ($placeholder) {
list($width, $height) = getimagesize($asset->getSourceFile());
$icon = [
'url' => $asset->getUrl(),
'width' => $width,
'height' => $height
];
}
$paymentMethod['icon'] = $icon;
}
$paymentMethods[$paymentMethodCode] = $paymentMethod;
}
}
return $paymentMethods;
$response['paymentMethodsExtraDetails'] = $paymentMethodsExtraDetails;
//TODO this should be the implemented with an interface
return json_encode($response);
}
/**
......@@ -306,28 +328,6 @@ class PaymentMethods extends AbstractHelper
return "";
}
/**
* @var array
*/
protected $fieldMapPaymentMethod = [
'name' => 'title'
];
/**
* @param $paymentMethod
* @return mixed
*/
protected function fieldMapPaymentMethod($paymentMethod)
{
foreach ($this->fieldMapPaymentMethod as $field => $newField) {
if (isset($paymentMethod[$field])) {
$paymentMethod[$newField] = $paymentMethod[$field];
unset($paymentMethod[$field]);
}
}
return $paymentMethod;
}
/**
* @param $requestParams
* @param $store
......
......@@ -315,17 +315,6 @@ class Requests extends AbstractHelper
$request['additionalData']['allow3DS2'] = true;
$request['origin'] = $this->adyenHelper->getOrigin();
$request['channel'] = 'web';
$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 = $additionalData[AdyenCcDataAssignObserver::JAVA_ENABLED]) {
$request['browserInfo']['javaEnabled'] = $javaEnabled;
} else {
$request['browserInfo']['javaEnabled'] = false;
}
} else {
$request['additionalData']['allow3DS2'] = false;
$request['origin'] = $this->adyenHelper->getOrigin();
......@@ -341,7 +330,7 @@ class Requests extends AbstractHelper
* @param $storeId
* @param $payment
*/
public function buildRecurringData($areaCode, int $storeId, $additionalData, $request = [])
public function buildRecurringData($areaCode, int $storeId, $request = [])
{
// If the vault feature is on this logic is handled in the VaultDataBuilder
if (!$this->adyenHelper->isCreditCardVaultEnabled()) {
......@@ -363,11 +352,6 @@ class Requests extends AbstractHelper
} else {
$request['enableRecurring'] = false;
}
// value can be 0,1 or true
if (!empty($additionalData[AdyenCcDataAssignObserver::STORE_CC])) {
$request['paymentMethod']['storeDetails'] = true;
}
}
return $request;
......
......@@ -75,18 +75,11 @@ class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentSta
) {
$additionalInformation = $payment->getAdditionalInformation();
$type = null;
if (!empty($additionalInformation['threeDSType'])) {
$type = $additionalInformation['threeDSType'];
if (!empty($additionalInformation['action'])) {
return json_encode($additionalInformation['action']);
}
$token = null;
if (!empty($additionalInformation['threeDS2Token'])) {
$token = $additionalInformation['threeDS2Token'];
}
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($type, $token);
}
return true;
}
}
......@@ -75,6 +75,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
public function initiate($payload)
{
// Decode payload from frontend
// TODO implement interface to handle the request the correct way
$payload = json_decode($payload, true);
// Validate JSON that has just been parsed if it was in a valid format
......@@ -84,6 +85,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
);
}
// Validate if order id is present
if (empty($payload['orderId'])) {
$order = $this->getOrder();
// In the next major release remove support for retrieving order from session and throw exception instead
......@@ -96,30 +98,16 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
$payment = $order->getPayment();
// Init payments/details request
$result = [];
if ($paymentData = $payment->getAdditionalInformation("threeDS2PaymentData")) {
// Add payment data into the request object
$request = [
"paymentData" => $payment->getAdditionalInformation("threeDS2PaymentData")
];
// unset payment data from additional information
$payment->unsAdditionalInformation("threeDS2PaymentData");
} else {
$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')
);
}
// Unset action from additional info since it is not needed anymore
$payment->unsAdditionalInformation("action");
// Depends on the component's response we send a fingerprint or the challenge result
if (!empty($payload['details']['threeds2.fingerprint'])) {
$request['details']['threeds2.fingerprint'] = $payload['details']['threeds2.fingerprint'];
} elseif (!empty($payload['details']['threeds2.challengeResult'])) {
$request['details']['threeds2.challengeResult'] = $payload['details']['threeds2.challengeResult'];
}
// TODO validate and format the request root level keys
$request = $payload;
// Init payments/details request
$result = [];
// Send the request
try {
......@@ -135,12 +123,9 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// Check if result is challenge shopper, if yes return the token
if (!empty($result['resultCode']) &&
$result['resultCode'] === 'ChallengeShopper' &&
!empty($result['authentication']['threeds2.challengeToken'])
!empty($result['action'])
) {
return $this->adyenHelper->buildThreeDS2ProcessResponseJson(
$result['resultCode'],
$result['authentication']['threeds2.challengeToken']
);
return json_encode($result['action']);
}
// Save the payments response because we are going to need it during the place order flow
......
......@@ -59,6 +59,8 @@ class GuestAdyenPaymentMethodManagement implements \Adyen\Payment\Api\GuestAdyen
// if shippingAddress is provided use this country
$country = null;
// TODO check why the frontend doesn't have the shipping address
// or get it from the cart
if ($shippingAddress) {
$country = $shippingAddress->getCountryId();
}
......
......@@ -67,11 +67,6 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
*/
private $storeManager;
/**
* @var \Magento\Framework\Serialize\SerializerInterface
*/
private $serializer;
/**
* AdyenCcConfigProvider constructor.
*
......@@ -82,7 +77,6 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
* @param \Magento\Framework\View\Asset\Source $assetSource
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Payment\Model\CcConfig $ccConfig
* @param \Magento\Framework\Serialize\SerializerInterface $serializer
*/
public function __construct(
\Magento\Payment\Helper\Data $paymentHelper,
......@@ -91,8 +85,7 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
\Magento\Framework\UrlInterface $urlBuilder,
\Magento\Framework\View\Asset\Source $assetSource,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Payment\Model\CcConfig $ccConfig,
\Magento\Framework\Serialize\SerializerInterface $serializer
\Magento\Payment\Model\CcConfig $ccConfig
) {
$this->_paymentHelper = $paymentHelper;
$this->_adyenHelper = $adyenHelper;
......@@ -101,7 +94,6 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
$this->_assetSource = $assetSource;
$this->ccConfig = $ccConfig;
$this->storeManager = $storeManager;
$this->serializer = $serializer;
}
/**
......@@ -170,7 +162,7 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
$installments = $this->_adyenHelper->getAdyenCcConfigData('installments');
if ($installmentsEnabled && $installments) {
$config['payment']['adyenCc']['installments'] = $this->serializer->unserialize($installments);
$config['payment']['adyenCc']['installments'] = $installments;
$config['payment']['adyenCc']['hasInstallments'] = true;
} else {
$config['payment']['adyenCc']['installments'] = [];
......
......@@ -69,10 +69,6 @@ class AdyenGenericConfigProvider implements ConfigProviderInterface
$config['payment']['adyen']['showLogo'] = false;
}
$config['payment']['checkoutCardComponentSource'] = $this->_adyenHelper->getCheckoutCardComponentJs(
$this->storeManager->getStore()->getId()
);
return $config;
}
......
<?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\Observer;
use Magento\Framework\DataObject;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
abstract class AdyenAbstractDataAssignObserver extends AbstractDataAssignObserver
{
const BRAND_CODE = 'brand_code';
const STATE_DATA = 'state_data';
const BROWSER_INFO = 'browserInfo';
const PAYMENT_METHOD = 'paymentMethod';
const RISK_DATA = 'riskData';
const STORE_PAYMENT_METHOD = 'storePaymentMethod';
const CC_TYPE = 'cc_type';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const COMBO_CARD_TYPE = 'combo_card_type';
/**
* @param DataObject $data
* @return array
*/
protected function getValidatedAdditionalData(DataObject $data)
{
// Get additional data array
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return [];
}
// Get a validated additional data array
$additionalData = $this->getArrayOnlyWithApprovedKeys($additionalData, $this->approvedAdditionalDataKeys);
// json decode state data
$stateData = [];
if (!empty($additionalData[self::STATE_DATA])) {
$stateData = json_decode($additionalData[self::STATE_DATA], true);
}
// Get validated state data array
if (!empty($stateData)) {
$stateData = $this->getArrayOnlyWithApprovedKeys($stateData, $this->approvedStateDataKeys);
}
// Replace state data with the decoded and validated state data
$additionalData[self::STATE_DATA] = $stateData;
return $additionalData;
}
/**
* Returns an array with only the approved keys
*
* @param array $array
* @param array $approvedKeys
* @return array
*/
private function getArrayOnlyWithApprovedKeys($array, $approvedKeys)
{
$result = [];
foreach ($approvedKeys as $approvedKey) {
if (isset($array[$approvedKey])) {
$result[$approvedKey] = $array[$approvedKey];
}
}
return $result;
}
}
......@@ -24,50 +24,31 @@
namespace Adyen\Payment\Observer;
use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
{
const CC_TYPE = 'cc_type';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const STORE_CC = 'store_cc';
const ENCRYPTED_CREDIT_CARD_NUMBER = 'number';
const ENCRYPTED_SECURITY_CODE = 'cvc';
const ENCRYPTED_EXPIRY_MONTH = 'expiryMonth';
const ENCRYPTED_EXPIRY_YEAR = 'expiryYear';
const HOLDER_NAME = 'holderName';
const VARIANT = 'variant';
const JAVA_ENABLED = 'java_enabled';
const SCREEN_COLOR_DEPTH = 'screen_color_depth';
const SCREEN_WIDTH = 'screen_width';
const SCREEN_HEIGHT = 'screen_height';
const TIMEZONE_OFFSET = 'timezone_offset';
const LANGUAGE = 'language';
const GUEST_EMAIL = 'guestEmail';
const COMBO_CARD_TYPE = 'combo_card_type';
/**
* Approved root level keys from additional data array
*
* @var array
*/
protected $approvedAdditionalDataKeys = [
self::STATE_DATA,
self::COMBO_CARD_TYPE,
self::NUMBER_OF_INSTALLMENTS
];
/**
* Approved root level keys from the checkout component's state data object
*
* @var array
*/
protected $additionalInformationList = [
self::CC_TYPE,
self::NUMBER_OF_INSTALLMENTS,
self::STORE_CC,
self::ENCRYPTED_CREDIT_CARD_NUMBER,
self::ENCRYPTED_SECURITY_CODE,
self::ENCRYPTED_EXPIRY_MONTH,
self::ENCRYPTED_EXPIRY_YEAR,
self::HOLDER_NAME,
self::VARIANT,
self::JAVA_ENABLED,
self::SCREEN_COLOR_DEPTH,
self::SCREEN_WIDTH,
self::SCREEN_HEIGHT,
self::TIMEZONE_OFFSET,
self::LANGUAGE,
self::GUEST_EMAIL,
self::COMBO_CARD_TYPE
protected $approvedStateDataKeys = [
self::BROWSER_INFO,
self::PAYMENT_METHOD,
self::RISK_DATA,
self::STORE_PAYMENT_METHOD
];
/**
......@@ -76,27 +57,20 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
*/
public function execute(Observer $observer)
{
// Get request fields
$data = $this->readDataArgument($observer);
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return;
}
$additionalData = $this->getValidatedAdditionalData($data);
// Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer);
// set ccType
if (!empty($additionalData['cc_type'])) {
$paymentInfo->setCcType($additionalData['cc_type']);
foreach ($additionalData as $key => $data) {
$paymentInfo->setAdditionalInformation($key, $data);
}
foreach ($this->additionalInformationList as $additionalInformationKey) {
if (isset($additionalData[$additionalInformationKey])) {
$paymentInfo->setAdditionalInformation(
$additionalInformationKey,
$additionalData[$additionalInformationKey]
);
}
// set ccType
if (!empty($additionalData[self::CC_TYPE])) {
$paymentInfo->setCcType($additionalData[self::CC_TYPE]);
}
}
}
......@@ -24,40 +24,29 @@
namespace Adyen\Payment\Observer;
use Magento\Framework\Event\Observer;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\PaymentInterface;
class AdyenHppDataAssignObserver extends AbstractDataAssignObserver
{
const BRAND_CODE = 'brand_code';
const ISSUER_ID = 'issuer_id';
const GENDER = 'gender';
const DOB = 'dob';
const TELEPHONE = 'telephone';
const DF_VALUE = 'df_value';
const SSN = 'ssn';
const OWNER_NAME = 'ownerName';
const BANK_ACCOUNT_OWNER_NAME = 'bankAccountOwnerName';
const IBAN_NUMBER = 'ibanNumber';
const BANK_ACCOUNT_NUMBER = 'bankAccountNumber';
const BANK_LOCATIONID = 'bankLocationId';
/**
* Approved root level keys from additional data array
*
* @var array
*/
protected $approvedAdditionalDataKeys = [
self::STATE_DATA,
self::BRAND_CODE
];
/**
* Approved root level keys from the checkout component's state data object
*
* @var array
*/
protected $additionalInformationList = [
self::BRAND_CODE,
self::ISSUER_ID,
self::GENDER,
self::DOB,
self::TELEPHONE,
self::DF_VALUE,
self::SSN,
self::OWNER_NAME,
self::BANK_ACCOUNT_OWNER_NAME,
self::IBAN_NUMBER,
self::BANK_ACCOUNT_NUMBER,
self::BANK_LOCATIONID
protected $approvedStateDataKeys = [
self::BROWSER_INFO,
self::PAYMENT_METHOD,
self::RISK_DATA
];
/**
......@@ -66,26 +55,20 @@ class AdyenHppDataAssignObserver extends AbstractDataAssignObserver
*/
public function execute(Observer $observer)
{
// Get request fields
$data = $this->readDataArgument($observer);
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) {
return;
}
$additionalData = $this->getValidatedAdditionalData($data);
// Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer);
foreach ($additionalData as $key => $data) {
$paymentInfo->setAdditionalInformation($key, $data);
}
// Set BrandCode into CCType
if (isset($additionalData[self::BRAND_CODE])) {
$paymentInfo->setCcType($additionalData[self::BRAND_CODE]);
}
foreach ($this->additionalInformationList as $additionalInformationKey) {
if (isset($additionalData[$additionalInformationKey])) {
$paymentInfo->setAdditionalInformation(
$additionalInformationKey,
$additionalData[$additionalInformationKey]
);
}
}
}
}
......@@ -77,20 +77,17 @@
<tooltip>Enable installments for each credit card type.</tooltip>
<config_path>payment/adyen_cc/enable_installments</config_path>
</field>
<field id="installments" translate="label" sortOrder="220" showInDefault="1" showInWebsite="1"
showInStore="1">
<field id="installments" type="textarea" 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 for each credit card type: 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\Installments</frontend_model>
<backend_model>Adyen\Payment\Model\Config\Backend\Installments</backend_model>
<config_path>payment/adyen_cc/installments</config_path>
<validate>required-entry</validate>
<comment><![CDATA[
Generate the desired installments configuration <a href="">here</a> and paste it on this field.
]]></comment>
<config_path>payment/adyen_cc/installments_code</config_path>
</field>
</group>
......
......@@ -557,7 +557,7 @@
<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="transaction" xsi:type="string">Adyen\Payment\Gateway\Request\CheckoutDataBuilder</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>
......@@ -990,11 +990,6 @@
<argument name="serializer" xsi:type="object">Magento\Framework\Serialize\Serializer\Serialize</argument>
</arguments>
</type>
<type name="Adyen\Payment\Gateway\Validator\InstallmentValidator">
<arguments>
<argument name="serializer" xsi:type="object">Magento\Framework\Serialize\Serializer\Serialize</argument>
</arguments>
</type>
<type name="Adyen\Payment\Model\Ui\AdyenPosCloudConfigProvider">
<arguments>
<argument name="serializer" xsi:type="object">Magento\Framework\Serialize\Serializer\Serialize</argument>
......
......@@ -229,1394 +229,48 @@
display: none;
}
/* Checkout component Adyen v3.2.0 styling start */
.adyen-checkout__field{
display:block;
margin-bottom:16px;
width:100%
}
.adyen-checkout__field:last-of-type{
margin-bottom:0
}
.adyen-checkout__label{
display:block
}
.adyen-checkout__helper-text,.adyen-checkout__label__text{
color:#00112c;
display:block;
font-size:.81em;
font-weight:400;
line-height:13px;
padding-bottom:5px
}
.adyen-checkout__helper-text{
color:#687282
}
.adyen-checkout__label__text{
display:block;
overflow:hidden;
text-overflow:ellipsis;
transition:color .1s ease-out;
white-space:nowrap
}
.adyen-checkout__label__text--error{
color:#d10244
}
.adyen-checkout__label--focused .adyen-checkout__label__text{
color:#06f
}
.adyen-checkout__error-text{
align-items:center;
color:#d10244;
display:flex;
font-size:.75em;
font-weight:400;
margin-top:4px
}
.adyen-checkout__spinner__wrapper{
align-items:center;
display:flex;
height:100%;
justify-content:center
}
.adyen-checkout__spinner__wrapper--inline{
display:inline-block;
height:auto;
margin-right:8px
}
.adyen-checkout__spinner{
-webkit-animation:rotateSpinner 1.5s infinite linear;
animation:rotateSpinner 1.5s infinite linear;
border:3px solid #06f;
border-radius:50%;
border-top-color:transparent;
height:43px;
width:43px
}
.adyen-checkout__spinner--large{
height:43px;
width:43px
}
.adyen-checkout__spinner--small{
border-width:2px;
height:16px;
width:16px
}
.adyen-checkout__spinner--medium{
height:28px;
width:28px
}
@-webkit-keyframes rotateSpinner{
0%{
-webkit-transform:rotate(0deg);
transform:rotate(0deg)
}
to{
-webkit-transform:rotate(1turn);
transform:rotate(1turn)
}
}
@keyframes rotateSpinner{
0%{
-webkit-transform:rotate(0deg);
transform:rotate(0deg)
}
to{
-webkit-transform:rotate(1turn);
transform:rotate(1turn)
}
}
.adyen-checkout__icon svg{
fill:currentColor
}
.adyen-checkout__open-invoice .adyen-checkout__input-wrapper--socialSecurityNumber+.adyen-checkout__error-text{
max-width:380px
}
.adyen-checkout__radio_group+.adyen-checkout-input__inline-validation{
display:none
}
.adyen-checkout__radio_group__input{
opacity:0;
position:absolute
}
.adyen-checkout__radio_group__label{
color:inherit;
display:block;
font-size:.81em;
font-weight:400;
line-height:16px;
margin-bottom:8px;
overflow:visible;
padding-bottom:0;
padding-left:24px;
position:relative
}
.adyen-checkout__label--focused .adyen-checkout__radio_group__label{
color:inherit
}
.adyen-checkout__radio_group__label:before{
background-color:#fff;
border:1px solid #b9c4c9;
border-radius:50%;
content:"";
height:16px;
left:0;
position:absolute;
top:0;
transition:border-color .2s ease-out,box-shadow .2s ease-out;
width:16px
}
.adyen-checkout__radio_group__label:hover:before{
border-color:#99a3ad;
box-shadow:0 0 0 2px #d4d9db;
cursor:pointer
}
.adyen-checkout__radio_group__label:after{
-webkit-transform:scale(0);
background-color:#fff;
border-radius:50%;
box-shadow:0 1px 1px rgba(0,15,45,.25);
content:"";
display:block;
height:6px;
left:5px;
margin:0 auto;
position:absolute;
top:5px;
transform:scale(0);
transition:-webkit-transform .2s ease-out;
transition:transform .2s ease-out;
transition:transform .2s ease-out,-webkit-transform .2s ease-out;
width:6px
}
.adyen-checkout__radio_group__label:hover{
border-color:#06f;
cursor:pointer
}
.adyen-checkout__radio_group__input:checked+.adyen-checkout__radio_group__label:before,.adyen-checkout__radio_group__label--selected{
background-color:#06f;
border:0;
transition:all .2s ease-out
}
.adyen-checkout__radio_group__input:checked+.adyen-checkout__radio_group__label:after{
-webkit-transform:scale(1);
transform:scale(1)
}
.adyen-checkout__radio_group__input:checked+.adyen-checkout__radio_group__label:hover:before,.adyen-checkout__radio_group__input:checked:active+.adyen-checkout__radio_group__label:before,.adyen-checkout__radio_group__input:checked:focus+.adyen-checkout__radio_group__label:before{
box-shadow:0 0 0 2px rgba(0,102,255,.4)
}
.adyen-checkout__radio_group__label.adyen-checkout__radio_group__label--invalid:before{
border:1px solid #d10244
}
.adyen-checkout__checkbox{
display:block
}
.adyen-checkout__checkbox__input{
opacity:0;
pointer-events:none;
position:absolute
}
.adyen-checkout__checkbox__label{
-moz-user-select:none;
-ms-user-select:none;
-webkit-user-select:none;
color:#00112c;
cursor:pointer;
display:inline-block;
font-size:.81em;
font-weight:400;
line-height:16px;
padding-left:24px;
position:relative;
user-select:none
}
.adyen-checkout__checkbox__input+span:before{
-webkit-transform:rotate(37deg);
-webkit-transform-origin:100% 100%;
border-color:transparent #fff #fff transparent;
border-radius:0 2px 1px 2px;
border-style:solid;
border-width:1px 2px 2px 1px;
content:"";
height:11px;
left:1px;
opacity:0;
position:absolute;
top:2px;
transform:rotate(37deg);
transform-origin:100% 100%;
transition:opacity .2s ease-out;
width:6px;
z-index:1
}
.adyen-checkout__checkbox__input:checked+.adyen-checkout__checkbox__label:before{
opacity:1
}
.adyen-checkout__checkbox__input+.adyen-checkout__checkbox__label:after{
background-color:#fff;
border:1px solid #b9c4c9;
border-radius:3px;
content:"";
height:16px;
left:0;
position:absolute;
top:0;
transition:background .15s ease-out,border .05s ease-out,box-shadow .1s ease-out;
width:16px;
z-index:0
}
.adyen-checkout__checkbox__input--invalid+.adyen-checkout__checkbox__label:after{
border:1px solid #d10244
}
.adyen-checkout__checkbox__input:checked+.adyen-checkout__checkbox__label:after{
background-color:#06f;
border:1px solid #06f
}
.adyen-checkout__checkbox__input:hover:not(:focus)+.adyen-checkout__checkbox__label:after{
border-color:#99a3ad;
box-shadow:0 0 0 2px #d4d9db
}
.adyen-checkout__checkbox__input:checked:hover+.adyen-checkout__checkbox__label:after{
border-color:#06f;
box-shadow:0 0 0 2px rgba(0,102,255,.4)
}
.adyen-checkout__checkbox__input:focus+span:after{
border:1px solid #06f;
box-shadow:0 0 0 2px #99c2ff
}
.adyen-checkout__dropdown{
font-size:1em;
max-width:100%;
width:100%
}
.adyen-checkout__dropdown__button{
-moz-user-select:none;
-ms-user-select:none;
-webkit-user-select:none;
background:#fff;
border:1px solid #b9c4c9;
border-radius:6px;
font-size:1em;
height:40px;
line-height:20px;
outline:0;
padding:9px 24px 9px 12px;
transition:border .2s ease-out,box-shadow .2s ease-out;
user-select:none;
width:100%
}
.adyen-checkout__dropdown__button__icon{
margin-right:8px;
max-height:26px;
max-width:40px
}
.adyen-checkout__dropdown__button--active,.adyen-checkout__dropdown__button:active,.adyen-checkout__dropdown__button:focus{
border-color:#06f;
box-shadow:0 0 0 2px #99c2ff
}
.adyen-checkout__dropdown__button--readonly,.adyen-checkout__dropdown__button--readonly.adyen-checkout__dropdown__button--active{
background:#e6e9eb;
color:#00112c;
cursor:not-allowed
}
.adyen-checkout__dropdown__button--invalid{
border-color:#d10244
}
.adyen-checkout__dropdown__button__text{
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap
}
.adyen-checkout__dropdown__list{
border-radius:6px;
box-shadow:0 2px 7px rgba(0,15,45,.3);
max-height:375px;
z-index:2
}
.adyen-checkout__dropdown__list.adyen-checkout__dropdown__list--active{
margin-top:2px
}
.adyen-checkout__dropdown__element{
-moz-user-select:none;
-ms-hyphens:auto;
-ms-user-select:none;
-webkit-hyphens:auto;
-webkit-user-select:none;
border:1px solid transparent;
cursor:pointer;
font-size:.81em;
hyphens:auto;
line-height:20px;
outline:0;
padding:8px;
transition:background .2s ease-out,border-color .2s ease-out;
user-select:none;
word-break:break-word
}
.adyen-checkout__dropdown__element:last-child{
border-bottom:0
}
.adyen-checkout__dropdown__element:active,.adyen-checkout__dropdown__element:focus,.adyen-checkout__dropdown__element:hover{
background:rgba(230,233,235,.6)
}
.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active{
background:rgba(0,102,255,.1)
}
.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active:active,.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active:focus,.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active:hover{
background:rgba(0,102,255,.15)
}
.adyen-checkout__dropdown__element__icon{
border-radius:3px;
margin-right:8px;
max-height:26px;
max-width:40px
}
.adyen-checkout__dropdown+.adyen-checkout-input__inline-validation{
right:32px
}
.adyen-checkout__select-list{
background:#fff;
border:1px solid #b9c4c9;
border-radius:6px;
margin:0;
max-height:140px;
min-height:100px;
min-width:300px;
overflow-y:scroll;
padding:0;
width:100%
}
.adyen-checkout__select-list__item{
background:#fff;
border:1px solid transparent;
border-bottom-color:#e6e9eb;
cursor:pointer;
display:inline-block;
font-size:1em;
line-height:20px;
outline:0;
padding:9px;
width:100%
}
.adyen-checkout__select-list__item:first-child{
border-top:0
}
.adyen-checkout__select-list__item:active,.adyen-checkout__select-list__item:focus,.adyen-checkout__select-list__item:hover{
background:rgba(230,233,235,.6)
}
.adyen-checkout__select-list__item--selected{
background:rgba(0,102,255,.1);
font-weight:500
}
.adyen-checkout__select-list__item--selected:active,.adyen-checkout__select-list__item--selected:focus,.adyen-checkout__select-list__item--selected:hover{
background:rgba(0,102,255,.15)
}
.adyen-checkout__field-wrapper{
display:flex
}
.adyen-checkout__field--50{
width:50%
}
.adyen-checkout__field--50:first-child{
margin-right:8px
}
.adyen-checkout__field--50:nth-child(2){
margin-left:8px
}
.adyen-checkout__input{
background:#fff;
border:1px solid #b9c4c9;
border-radius:6px;
color:#00112c;
display:block;
font-family:inherit;
font-size:1em;
height:40px;
outline:none;
padding:5px 8px;
position:relative;
transition:border .2s ease-out,box-shadow .2s ease-out;
width:100%
}
.adyen-checkout__input:hover{
border-color:#99a3ad
}
.adyen-checkout__input:required{
box-shadow:none
}
.adyen-checkout__input--disabled,.adyen-checkout__input[readonly]{
background:#e6e9eb;
border-color:#e6e9eb
}
.adyen-checkout__input--disabled:hover{
border-color:#e6e9eb
}
.adyen-checkout__input-wrapper{
display:block;
position:relative
}
.adyen-checkout__input-wrapper--block{
display:block
}
.adyen-checkout-input__inline-validation{
-webkit-transform:translateY(-50%);
height:16px;
position:absolute;
right:14px;
top:50%;
transform:translateY(-50%);
width:16px
}
.adyen-checkout-input__inline-validation--valid{
color:#0abf53
}
.adyen-checkout-input__inline-validation--invalid{
color:#d10244
}
.adyen-checkout__input--invalid{
border-color:#d10244
}
.adyen-checkout__input--valid{
border-bottom-color:#0abf53
}
.adyen-checkout__input--error,.adyen-checkout__input--error:hover,.adyen-checkout__input--invalid,.adyen-checkout__input--invalid:hover{
border-color:#d10244;
color:#d10244
}
.adyen-checkout__input::-webkit-input-placeholder{
color:#b9c4c9;
font-weight:200
}
.adyen-checkout__input:-ms-input-placeholder{
color:#b9c4c9;
font-weight:200
}
.adyen-checkout__input::-ms-input-placeholder{
color:#b9c4c9;
font-weight:200
}
.adyen-checkout__input::placeholder{
color:#b9c4c9;
font-weight:200
}
.adyen-checkout__input--focus,.adyen-checkout__input--focus:hover,.adyen-checkout__input:active,.adyen-checkout__input:active:hover,.adyen-checkout__input:focus,.adyen-checkout__input:focus:hover{
border:1px solid #06f;
box-shadow:0 0 0 2px #99c2ff
}
.adyen-checkout__input[readonly],.adyen-checkout__input[readonly]:hover{
background-color:#e6e9eb;
border-color:transparent;
color:#687282;
cursor:default
}
.adyen-checkout__fieldset{
display:block;
padding-bottom:8px;
width:100%
}
.adyen-checkout__fieldset:last-of-type{
padding-bottom:0
}
.adyen-checkout__fieldset+.adyen-checkout__fieldset{
margin-top:16px
}
.adyen-checkout__fieldset__title{
color:#687282;
display:block;
font-size:.68em;
font-weight:700;
letter-spacing:1px;
margin:0;
padding:0 0 8px;
text-transform:uppercase
}
.adyen-checkout__field-group,.adyen-checkout__fieldset__fields{
display:flex;
flex-wrap:wrap;
justify-content:space-between;
width:100%
}
.adyen-checkout__field-group:last-of-type .adyen-checkout__field{
margin-bottom:0
}
.adyen-checkout__field--col-70{
width:calc(70% - 8px)
}
.adyen-checkout__field--col-30{
width:calc(30% - 8px)
}
.adyen-checkout__field--col-50{
width:calc(50% - 8px)
}
.adyen-checkout__fieldset--readonly{
color:#00112c;
font-size:.81em;
line-height:19px;
margin:0
}
.adyen-checkout__open-invoice .adyen-checkout__checkbox--consent-checkbox{
max-width:540px
}
.adyen-checkout__open-invoice .adyen-checkout__checkbox{
margin:0 0 8px
}
.adyen-checkout__open-invoice .adyen-checkout__checkbox:only-of-type{
margin-bottom:0
}
.adyen-checkout__open-invoice .adyen-checkout__checkbox--consent-checkbox{
margin:0
}
.adyen-checkout__open-invoice .adyen-checkout__field--gender .adyen-checkout__radio_group{
display:flex
}
.adyen-checkout__open-invoice .adyen-checkout__field--gender .adyen-checkout__radio_group>label{
margin-right:16px
}
.adyen-checkout__open-invoice .adyen-checkout__field--gender .adyen-checkout__label--focused .adyen-checkout__label__text,.adyen-checkout__open-invoice .adyen-checkout__field--gender .adyen-checkout__label__text{
color:#00112c
}
.adyen-checkout__open-invoice .adyen-checkout__fieldset--billingAddress{
padding-bottom:8px
}
.adyen-checkout__open-invoice .adyen-checkout__fieldset--deliveryAddress{
margin-top:24px;
padding-bottom:8px
}
.adyen-checkout__open-invoice .adyen-checkout__input--separateDeliveryAddress{
margin-bottom:0
}
.adyen-checkout__open-invoice .adyen-checkout__field--dateOfBirth{
width:calc(50% - 8px)
}
.adyen-checkout__open-invoice .adyen-checkout__field--country,.adyen-checkout__open-invoice .adyen-checkout__field--street{
width:calc(70% - 8px)
}
.adyen-checkout__open-invoice .adyen-checkout__field--houseNumberOrName,.adyen-checkout__open-invoice .adyen-checkout__field--postalCode{
width:calc(30% - 8px)
}
.adyen-checkout__button{
background:#00112c;
border:0;
border-radius:6px;
color:#fff;
cursor:pointer;
font-size:1em;
font-weight:500;
height:48px;
margin:0;
padding:15px;
text-decoration:none;
transition:background .3s ease-out,box-shadow .3s ease-out;
width:100%
}
.adyen-checkout__button--pay{
margin-top:24px
}
.adyen-checkout__button--standalone{
margin-top:0
}
.adyen-checkout__button:disabled{
-moz-user-select:all;
-ms-user-select:all;
-webkit-user-select:all;
background:#e6e9eb;
box-shadow:none;
cursor:not-allowed;
user-select:all
}
.adyen-checkout__button:focus{
box-shadow:0 0 0 2px #99c2ff;
outline:0
}
.adyen-checkout__button:hover{
background:#1c3045;
box-shadow:0 0,0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14)
}
.adyen-checkout__button:active{
background:#3a4a5c
}
.adyen-checkout__button:hover:focus{
box-shadow:0 0 0 2px #99c2ff,0 3px 4px rgba(0,15,45,.2)
}
.adyen-checkout__button--loading{
-moz-user-select:none;
-ms-user-select:none;
-webkit-user-select:none;
background:#687282;
box-shadow:none;
pointer-events:none;
user-select:none
}
.adyen-checkout__button .adyen-checkout__spinner{
border-color:transparent #fff #fff
}
.adyen-checkout__button__content{
align-items:center;
display:flex;
justify-content:center
}
.adyen-checkout__button__icon{
margin-right:12px
}
.adyen-checkout__button__text{
display:block;
justify-content:center;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap
}
.adyen-checkout__button.adyen-checkout__button--inline{
display:block;
font-size:.81em;
height:auto;
padding:10px 8px;
width:auto
}
.adyen-checkout__button.adyen-checkout__button--secondary{
background:rgba(0,102,255,.1);
border:1px solid transparent;
color:#06f;
padding:10px 12px
}
.adyen-checkout__button.adyen-checkout__button--secondary:hover{
background:rgba(0,102,255,.2);
box-shadow:none
}
.adyen-checkout__button.adyen-checkout__button--secondary:active,.adyen-checkout__button.adyen-checkout__button--secondary:active:hover{
background:rgba(0,102,255,.3);
box-shadow:none
}
.adyen-checkout__button.adyen-checkout__button--completed,.adyen-checkout__button.adyen-checkout__button--completed:active,.adyen-checkout__button.adyen-checkout__button--completed:active:hover,.adyen-checkout__button.adyen-checkout__button--completed:hover{
background:#0abf53;
color:#fff
}
.adyen-checkout__button.adyen-checkout__button--completed .adyen-checkout__button__icon{
-webkit-filter:brightness(0) invert(1);
filter:brightness(0) invert(1)
}
.adyen-checkout__applepay__button{
height:40px;
width:240px
}
.adyen-checkout__dropin .adyen-checkout__applepay__button{
width:100%
}
.adyen-checkout__card-input__form{
transition:opacity .25s ease-out
}
.adyen-checkout__card__cardNumber{
max-width:400px
}
.adyen-checkout__card__cardNumber__input{
padding:5px 8px
}
.adyen-checkout__card__exp-date__input--oneclick{
font-weight:400;
line-height:30px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap
}
.adyen-checkout__card__holderName,.adyen-checkout__field--expiryDate,.adyen-checkout__field--storedCard{
margin-bottom:0
}
.adyen-checkout__card__holderName,.adyen-checkout__store-details{
margin-top:16px
}
.adyen-checkout__field--cardNumber .adyen-checkout__input--error .adyen-checkout__card__cardNumber__brandIcon{
display:none
}
.adyen-checkout__field--cardNumber .adyen-checkout__input--valid:not(.adyen-checkout__card__cardNumber__input--noBrand)+.adyen-checkout-input__inline-validation--valid{
display:none
}
.adyen-checkout__giropay__no-results{
color:#687282;
display:block;
font-size:.81em;
padding:0 0 0 2px
}
.adyen-checkout__giropay__placeholder{
color:#b9c4c9;
display:block;
font-weight:200;
padding:0 0 0 2px
}
.adyen-checkout__giropay__loading{
display:block;
min-height:100px
}
.adyen-checkout__giropay__loading .adyen-checkout__spinner__wrapper{
display:inline-block;
vertical-align:middle
}
.adyen-checkout__giropay__loading-text{
color:#687282;
font-size:.81em;
line-height:16px;
vertical-align:middle
}
.adyen-checkout__giropay__error{
color:#d10244;
font-size:.81em
}
.adyen-checkout__dropin .gpay-button.long{
height:48px;
padding:15px 24px 13px;
transition:background-color .3s ease-out,box-shadow .3s ease-out;
width:100%
}
.adyen-checkout__field--issuer-list{
margin-bottom:0
}
.adyen-checkout__econtext-input__field{
display:flex;
flex-wrap:wrap
}
.adyen-checkout__econtext-input__field .adyen-checkout__field--firstName,.adyen-checkout__econtext-input__field .adyen-checkout__field--lastName{
max-width:100%;
min-width:250px;
width:calc(50% - 8px)
}
.adyen-checkout__econtext-input__field .adyen-checkout__field--firstName{
margin-right:16px
}
.adyen-checkout__voucher-result{
border-radius:12px;
box-sizing:border-box;
position:relative;
text-align:center
}
.adyen-checkout__voucher-result__bottom,.adyen-checkout__voucher-result__top{
background:#fff;
border:1px solid #d4d9db
}
.adyen-checkout__voucher-result__top{
border-bottom:0;
border-radius:12px 12px 0 0;
padding:40px 0 24px
}
.adyen-checkout__voucher-result__bottom{
border-radius:0 0 12px 12px;
border-top:0
}
.adyen-checkout__voucher-result__separator{
align-items:center;
background:#fff;
display:flex;
height:13px;
margin:0 auto;
position:relative;
width:calc(100% - 14px)
}
.adyen-checkout__voucher-result__separator:after,.adyen-checkout__voucher-result__separator:before{
background-image:url(data:image/svg+xml;
base64,PHN2ZyB3aWR0aD0iNyIgaGVpZ2h0PSIxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBjbGlwLXBhdGg9InVybCgjY2xpcDApIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTAgMGw1IDIgMS41IDRIN1YwSDB6bTAgMTNsNS0yIDEuNS00SDd2NkgweiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik02LjQyMyA2LjVDNi40MjMgMy4zMTIgMy43ODMuNzU2LjUuNTE4YzMuMzg2LjIzNiA2IDIuODU1IDYgNS45ODIgMCAzLjEyNy0yLjYxNCA1Ljc0Ni02IDUuOTgzdi0uMDAxYzMuMjg0LS4yMzcgNS45MjMtMi43OTQgNS45MjMtNS45ODJ6IiBzdHJva2U9IiNENEQ5REIiLz48cGF0aCBmaWxsPSIjRDREOURCIiBkPSJNMCAwaDF2MUgwek0wIDEyaDF2MUgweiIvPjwvZz48ZGVmcz48Y2xpcFBhdGggaWQ9ImNsaXAwIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwaDd2MTNIMHoiLz48L2NsaXBQYXRoPjwvZGVmcz48L3N2Zz4=)
}
.adyen-checkout__voucher-result__separator:before{
background-position:100%;
background-repeat:no-repeat;
content:"";
height:13px;
left:-7px;
position:absolute;
top:0;
width:7px
}
.adyen-checkout__voucher-result__separator:after{
-webkit-transform:rotate(-180deg);
background-position:100%;
background-repeat:no-repeat;
content:"";
height:13px;
position:absolute;
right:-7px;
top:0;
transform:rotate(-180deg);
width:7px
}
.adyen-checkout__voucher-result__separator__inner{
border-top:1px solid #e6e9eb;
width:100%
}
.adyen-checkout__voucher-result__image{
align-items:center;
display:flex;
justify-content:center;
margin-bottom:40px;
width:100%
}
.adyen-checkout__voucher-result__image__wrapper{
display:block;
height:48px;
margin:0 24px;
position:relative
}
.adyen-checkout__voucher-result__image__wrapper:after{
border:1px solid rgba(0,27,43,.17);
border-radius:3px;
content:"";
height:100%;
left:0;
position:absolute;
top:0;
width:100%
}
.adyen-checkout__voucher-result__image__wrapper:nth-child(2):before{
border-left:1px solid #d4d9db;
content:"";
height:64px;
left:-24.5px;
position:absolute;
top:-8px;
width:1px
}
.adyen-checkout__voucher-result__image__brand,.adyen-checkout__voucher-result__image__issuer{
border-radius:3px;
height:48px
}
.adyen-checkout__voucher-result__introduction{
color:#00112c;
font-size:.81em;
line-height:19px;
margin:0 auto;
max-width:400px;
text-align:center
}
.adyen-checkout__voucher-result__amount{
color:#00112c;
font-size:1em;
font-weight:700;
margin:24px auto 0;
text-align:center
}
.adyen-checkout__voucher-result__surcharge{
color:#687282;
display:block;
font-size:.81em;
font-weight:400;
line-height:19px;
text-align:center
}
.adyen-checkout__voucher-result__code__label{
-moz-user-select:none;
-ms-user-select:none;
-webkit-user-select:none;
display:block;
font-weight:400;
left:0;
line-height:19px;
margin:0 auto;
position:absolute;
right:0;
top:-2px;
user-select:none;
width:auto
}
.adyen-checkout__voucher-result__code__label:before{
content:"";
position:absolute
}
.adyen-checkout__voucher-result__code__label__text{
background:#fff;
color:#00112c;
font-size:13px;
letter-spacing:normal;
line-height:1;
padding:0 8px
}
.adyen-checkout__voucher-result__code__barcode{
-moz-user-select:none;
-ms-user-select:none;
-webkit-user-select:none;
display:block;
height:56px;
margin:0 auto 8px;
max-width:100%;
user-select:none
}
.adyen-checkout__voucher-result__code{
-moz-user-select:all;
-ms-user-select:all;
-webkit-user-select:all;
border-width:1px 0;
color:#00112c;
display:inline-block;
font-size:1.5em;
font-weight:700;
letter-spacing:1px;
line-height:1.2;
margin:0 auto;
padding:16px 48px;
position:relative;
text-align:center;
user-select:all;
width:100%;
word-break:break-word
}
.adyen-checkout__voucher-result__details{
list-style:none;
margin:-1px auto 0;
padding:0
}
.adyen-checkout__voucher-result__details__item{
border-top:1px solid #e6e9eb;
color:#00112c;
display:flex;
font-size:.81em;
justify-content:space-between;
padding:16px 24px;
word-break:break-word
}
.adyen-checkout__voucher-result__details__item:last-child{
margin-bottom:0
}
.adyen-checkout__voucher-result__details__label{
max-width:50%;
text-align:left
}
.adyen-checkout__voucher-result__details__value{
font-weight:700;
max-width:50%;
text-align:right
}
.adyen-checkout__voucher-result__actions{
align-items:center;
display:flex;
justify-content:center;
list-style:none;
margin:0 auto 32px;
max-width:100%;
min-width:200px;
padding:0;
width:300px
}
.adyen-checkout__voucher-result__actions__item{
margin:0 4px
}
.adyen-checkout__link--more-information{
display:block;
font-size:.81em;
font-weight:400;
margin:16px 0;
text-align:center
}
.adyen-checkout__phone-input__container{
display:flex
}
.adyen-checkout__phone-input__prefix{
margin-bottom:0;
margin-right:.5em;
width:30%
}
.adyen-checkout__input--phone-number{
margin-bottom:0;
width:70%
}
.adyen-checkout__iban-input__number{
padding:5px 36px 5px 8px;
text-transform:uppercase
}
.adyen-checkout__threeds2__challenge,.adyen-checkout__threeds2__challenge-container{
background-color:transparent;
box-sizing:border-box;
display:block;
overflow:auto;
width:100%
}
.adyen-checkout__threeds2__challenge-container--01{
height:400px;
width:250px
}
.adyen-checkout__threeds2__challenge-container--02{
height:400px;
width:390px
}
.adyen-checkout__threeds2__challenge-container--03{
height:600px;
width:500px
}
.adyen-checkout__threeds2__challenge-container--04{
height:400px;
width:600px
}
.adyen-checkout__threeds2_challenge-container--05{
height:100%;
width:100%
}
.adyen-checkout__threeds2__challenge.adyen-checkout__threeds2__challenge--05{
overflow:hidden;
padding-top:56.25%;
position:relative
}
.adyen-checkout__threeds2__challenge.adyen-checkout__threeds2__challenge--05 .adyen-checkout__iframe--threeDSIframe{
border:0;
height:100%;
left:0;
position:absolute;
top:0;
width:100%
}
.adyen-checkout__qr-loader{
background:#fff;
border:1px solid #d4d9db;
border-radius:6px;
padding:40px;
text-align:center
}
.adyen-checkout__qr-loader--app{
border:0;
border-radius:0;
padding:0
}
.adyen-checkout__qr-loader__brand-logo{
max-height:50px;
width:110px
}
.adyen-checkout__qr-loader__subtitle{
margin-top:32px
}
.adyen-checkout__qr-loader__subtitle--result{
margin-bottom:32px
}
.adyen-checkout__qr-loader__payment_amount,.adyen-checkout__qr-loader__subtitle{
color:#00112c;
font-size:1em;
line-height:19px
}
.adyen-checkout__qr-loader__icon{
height:88px;
width:88px
}
.adyen-checkout__qr-loader__icon--result{
margin-bottom:100px
}
.adyen-checkout__qr-loader__payment_amount{
font-weight:700
}
.adyen-checkout__qr-loader__progress{
background:#d4d9db;
border-radius:24px;
height:4px;
margin:32px auto 12px;
padding-right:3%;
width:152px
}
.adyen-checkout__qr-loader__percentage{
background:#06f;
border-radius:24px;
display:block;
height:100%
}
.adyen-checkout__qr-loader__countdown{
color:#687282;
font-size:.81em
}
.adyen-checkout__qr-loader>.adyen-checkout__spinner__wrapper{
margin:60px 0
}
.adyen-checkout__qr-loader__separator__label{
background:#fff;
border-radius:50%;
color:#687282;
display:inline-block;
height:34px;
line-height:34px;
position:relative;
width:34px;
z-index:1
}
.adyen-checkout__qr-loader__separator__line{
-webkit-transform:translateY(-17px);
border-top:1px solid #d4d9db;
display:block;
transform:translateY(-17px)
}
.adyen-checkout__button.adyen-checkout__button--qr-loader{
display:block;
text-decoration:none
}
.adyen-checkout__doku-input__field{
display:flex;
flex-wrap:wrap
}
.adyen-checkout__doku-input__field .adyen-checkout__field--firstName,.adyen-checkout__doku-input__field .adyen-checkout__field--lastName{
max-width:100%;
min-width:250px;
width:calc(50% - 8px)
}
.adyen-checkout__doku-input__field .adyen-checkout__field--firstName{
margin-right:16px
}
.adyen-checkout__voucher-result--boletobancario .adyen-checkout__voucher-result__code{
font-size:.81em;
line-height:19px;
padding:24px;
word-break:break-all
}
.adyen-checkout__voucher-result--oxxo .adyen-checkout__voucher-result__code{
font-size:.81em;
line-height:19px;
padding:24px;
word-break:break-all
}
.adyen-checkout__payment-method{
background:#fff;
border:1px solid #e6e9eb;
cursor:pointer;
margin-top:-1px;
position:relative;
transition:opacity .3s ease-out;
width:100%
}
.adyen-checkout__payment-method:focus{
outline:0
}
.adyen-checkout__payment-method--selected+.adyen-checkout__payment-method,.adyen-checkout__payment-method:first-child{
border-top-left-radius:12px;
border-top-right-radius:12px;
margin-top:0
}
.adyen-checkout__payment-method--next-selected,.adyen-checkout__payment-method:last-child{
border-bottom-left-radius:12px;
border-bottom-right-radius:12px;
margin-bottom:0
}
.adyen-checkout__payment-method--loading{
opacity:.2
}
.adyen-checkout__payment-method--selected.adyen-checkout__payment-method--loading{
opacity:.9
}
.adyen-checkout__payment-method--disabling{
opacity:.3
}
.adyen-checkout__payment-method__header{
align-items:center;
color:#00112c;
display:flex;
flex-wrap:nowrap;
font-size:1em;
font-weight:400;
justify-content:space-between;
padding:16px 16px 16px 48px;
position:relative;
transition:background .1s ease-out;
width:100%
}
.adyen-checkout__payment-method--standalone .adyen-checkout__payment-method__header{
padding:16px
}
.adyen-checkout__payment-method__header__title{
align-items:center;
display:flex;
flex-shrink:0;
margin-right:16px;
max-width:100%
}
.adyen-checkout__payment-method__surcharge{
color:#687282;
margin-left:5px
}
.adyen-checkout__payment-method--selected{
background:#f7f8f9;
border:1px solid #e6e9eb;
border-radius:12px;
cursor:default;
margin:8px 0;
transition:margin .15s cubic-bezier(.4,0,.2,1) 0ms,opacity .3s ease-out
}
.adyen-checkout__payment-method--selected .adyen-checkout__payment-method__header{
flex-wrap:wrap
}
.adyen-checkout__payment-method__name{
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap
}
.adyen-checkout__payment-method__name--selected{
font-weight:500
}
.adyen-checkout__payment-method__details{
padding:0 16px
}
.adyen-checkout__payment-method__details__content{
margin:0 0 16px
}
.adyen-checkout__payment-method__image__wrapper{
height:26px;
opacity:0;
position:relative;
transition:opacity .15s ease-out;
width:40px
}
.adyen-checkout__payment-method__image__wrapper--loaded{
opacity:1
}
.adyen-checkout__payment-method__image__wrapper:after{
border:1px solid rgba(0,27,43,.17);
border-radius:3px;
content:"";
height:100%;
left:0;
position:absolute;
top:0;
width:100%
}
.adyen-checkout__payment-method__image{
border-radius:3px
}
.adyen-checkout__payment-method__brands{
display:flex;
flex-basis:auto;
flex-shrink:1;
flex-wrap:wrap;
height:16px;
margin:4px 0;
overflow:hidden;
text-align:right
}
.adyen-checkout__payment-method--selected .adyen-checkout__payment-method__brands{
height:auto;
overflow:visible;
text-align:left
}
.adyen-checkout__payment-method__brands .adyen-checkout__payment-method__image__wrapper{
display:inline-block;
height:16px;
margin-right:4px;
transition:opacity .2s ease-out;
width:24px
}
.adyen-checkout__payment-method__brands .adyen-checkout__payment-method__image__wrapper:last-child{
margin:0
}
.adyen-checkout__payment-method--selected .adyen-checkout__payment-method__brands .adyen-checkout__payment-method__image__wrapper{
margin-bottom:4px
}
.adyen-checkout__payment-method__brands img{
height:16px;
width:24px
}
.adyen-checkout__payment-method__image__wrapper--disabled{
opacity:.25
}
.adyen-checkout__payment-method__disable-confirmation{
align-items:center;
background:#e6e9eb;
color:#00112c;
display:flex;
font-size:1em;
justify-content:space-between;
margin-bottom:10px;
padding:8px 16px
}
.adyen-checkout__payment-method__disable-confirmation__buttons{
display:flex
}
.adyen-checkout__payment-method__disable-confirmation__button{
border:1px solid transparent;
border-radius:6px;
cursor:pointer;
font-size:.81em;
line-height:15px;
margin:0 0 0 8px;
padding:8px
}
.adyen-checkout__payment-method__disable-confirmation__button--remove{
background:#d10244;
border-color:#d10244;
color:#fff
}
.adyen-checkout__payment-method__disable-confirmation__button--cancel{
background:transparent;
border-color:#00112c;
color:#00112c
}
.adyen-checkout__payment-method__radio{
background-color:#fff;
border:1px solid #b9c4c9;
border-radius:50%;
height:16px;
left:16px;
position:absolute;
transition:border-color .2s ease-out,box-shadow .2s ease-out;
width:16px
}
.adyen-checkout__payment-method--standalone .adyen-checkout__payment-method__radio{
display:none
}
.adyen-checkout__payment-method__radio:after{
-webkit-transform:translateY(-50%) scale(0);
background-color:#fff;
border-radius:50%;
content:"";
display:block;
height:6px;
left:0;
margin:0 auto;
position:absolute;
right:0;
top:50%;
transform:translateY(-50%) scale(0);
transition:-webkit-transform .3s ease-out;
transition:transform .3s ease-out;
transition:transform .3s ease-out,-webkit-transform .3s ease-out;
width:6px
}
.adyen-checkout__payment-method__radio:hover{
border-color:#99a3ad;
box-shadow:0 0 0 2px #d4d9db;
cursor:pointer
}
.adyen-checkout__payment-method__radio--selected{
background-color:#06f;
border:0;
transition:all .3s ease-out
}
.adyen-checkout__payment-method__radio--selected:hover{
box-shadow:0 0 0 2px rgba(0,102,255,.4)
}
.adyen-checkout__payment-method__radio--selected:after{
-webkit-transform:translateY(-50%) scale(1);
transform:translateY(-50%) scale(1)
}
.adyen-checkout__status{
align-items:center;
background-color:#fff;
border:1px solid #d4d9db;
border-radius:6px;
color:#00112c;
display:flex;
flex-direction:column;
font-size:1em;
height:350px;
justify-content:center;
margin:0;
padding:32px;
text-align:center
}
.adyen-checkout__status__icon{
margin-bottom:24px
}
.adyen-checkout__dropin,.adyen-checkout__dropin *,.adyen-checkout__dropin :after,.adyen-checkout__dropin :before{
box-sizing:border-box
}
.adyen-checkout__payment-methods-list--loading{
-moz-user-select:none;
-ms-user-select:none;
-webkit-user-select:none;
pointer-events:none;
user-select:none
}
.adyen-checkout__link{
color:#06f;
text-decoration:none
}
.adyen-checkout__link:hover{
text-decoration:underline
}
/* Checkout component Adyen v3.7.0 styling start */
.adyen-checkout__fieldset{display:block;padding-bottom:8px;width:100%}.adyen-checkout__fieldset:last-of-type{padding-bottom:0}.adyen-checkout__fieldset+.adyen-checkout__fieldset{margin-top:16px}.adyen-checkout__fieldset__title{color:#687282;display:block;font-size:.68em;font-weight:700;letter-spacing:1px;margin:0;padding:0 0 12px;text-transform:uppercase}.adyen-checkout__field-group,.adyen-checkout__fieldset__fields{display:-webkit-box;display:flex;flex-wrap:wrap;-webkit-box-pack:justify;justify-content:space-between;width:100%}.adyen-checkout__field-group:last-of-type .adyen-checkout__field{margin-bottom:0}.adyen-checkout__fieldset--readonly .adyen-checkout__fieldset__fields{color:#00112c;font-size:.81em;line-height:19px;margin:0}
.adyen-checkout__field{display:block;margin-bottom:16px;width:100%}.adyen-checkout__field:last-of-type{margin-bottom:0}.adyen-checkout__label{display:block}.adyen-checkout__helper-text,.adyen-checkout__label__text{color:#00112c;display:block;font-size:.81em;font-weight:400;line-height:13px;padding-bottom:5px}.adyen-checkout__helper-text{color:#687282}.adyen-checkout__label__text{-webkit-transition:color .1s ease-out;transition:color .1s ease-out;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.adyen-checkout__label__text--error{color:#d10244}.adyen-checkout__label--focused .adyen-checkout__label__text{color:#06f}.adyen-checkout__error-text{display:-webkit-box;display:flex;color:#d10244;font-weight:400;margin-top:4px;font-size:.75em;-webkit-box-align:center;align-items:center}
.adyen-checkout__spinner__wrapper{height:100%;display:-webkit-box;display:flex;-webkit-box-pack:center;justify-content:center;-webkit-box-align:center;align-items:center}.adyen-checkout__spinner__wrapper--inline{height:auto;display:inline-block;margin-right:8px}.adyen-checkout__spinner{border-radius:50%;height:43px;width:43px;border:3px solid #06f;border-top-color:transparent;-webkit-animation:rotateSpinner 1.5s linear infinite;animation:rotateSpinner 1.5s linear infinite}.adyen-checkout__spinner--large{height:43px;width:43px}.adyen-checkout__spinner--small{height:16px;width:16px;border-width:2px}.adyen-checkout__spinner--medium{height:28px;width:28px}@-webkit-keyframes rotateSpinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotateSpinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
.adyen-checkout__radio_group+.adyen-checkout-input__inline-validation{display:none}.adyen-checkout__radio_group__input{opacity:0;position:absolute}.adyen-checkout__radio_group__label{padding-bottom:0;padding-left:24px;position:relative;display:block;color:inherit;font-size:.81em;font-weight:400;line-height:16px;overflow:visible}.adyen-checkout__label--focused .adyen-checkout__radio_group__label{color:inherit}.adyen-checkout__radio_group__label:before{content:"";position:absolute;background-color:#fff;border:1px solid #b9c4c9;border-radius:50%;height:16px;width:16px;left:0;top:0;-webkit-transition:border-color .2s ease-out,box-shadow .2s ease-out;transition:border-color .2s ease-out,box-shadow .2s ease-out}.adyen-checkout__radio_group__label:hover:before{border-color:#99a3ad;box-shadow:0 0 0 2px #d4d9db;cursor:pointer}.adyen-checkout__radio_group__label:after{content:"";display:block;position:absolute;margin:0 auto;left:5px;top:5px;height:6px;width:6px;background-color:#fff;border-radius:50%;-webkit-transform:scale(0);transform:scale(0);-webkit-transition:-webkit-transform .2s ease-out;transition:-webkit-transform .2s ease-out;transition:transform .2s ease-out;transition:transform .2s ease-out,-webkit-transform .2s ease-out;box-shadow:0 1px 1px rgba(0,15,45,.25)}.adyen-checkout__radio_group__label:hover{border-color:#06f;cursor:pointer}.adyen-checkout__radio_group__input:checked+.adyen-checkout__radio_group__label:before,.adyen-checkout__radio_group__label--selected{background-color:#06f;border:0;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.adyen-checkout__radio_group__input:checked+.adyen-checkout__radio_group__label:after{-webkit-transform:scale(1);transform:scale(1)}.adyen-checkout__radio_group__input:focus+.adyen-checkout__radio_group__label:before{border-color:#06f;box-shadow:0 0 0 2px rgba(0,102,255,.4)}.adyen-checkout__radio_group__input:checked+.adyen-checkout__radio_group__label:hover:before,.adyen-checkout__radio_group__input:checked:active+.adyen-checkout__radio_group__label:before,.adyen-checkout__radio_group__input:checked:focus+.adyen-checkout__radio_group__label:before{box-shadow:0 0 0 2px rgba(0,102,255,.4)}.adyen-checkout__radio_group__label.adyen-checkout__radio_group__label--invalid:before{border:1px solid #d10244}
.adyen-checkout__checkbox{display:block}.adyen-checkout__checkbox__label{position:relative;padding-left:24px;cursor:pointer;display:inline-block;line-height:19px;color:#00112c;font-size:.81em;font-weight:400;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.adyen-checkout__checkbox__input{position:absolute;opacity:0;pointer-events:none}.adyen-checkout__checkbox__input:checked+.adyen-checkout__checkbox__label:before{opacity:1}.adyen-checkout__checkbox__input:checked+.adyen-checkout__checkbox__label:after{border:1px solid #06f;background-color:#06f}.adyen-checkout__checkbox__input:checked:hover+.adyen-checkout__checkbox__label:after{box-shadow:0 0 0 2px rgba(0,102,255,.4);border-color:#06f}.adyen-checkout__checkbox__input:focus+.adyen-checkout__checkbox__label:after{border:1px solid #06f;box-shadow:0 0 0 2px #99c2ff}.adyen-checkout__checkbox__input:hover:not(:focus)+.adyen-checkout__checkbox__label:after{border-color:#99a3ad;box-shadow:0 0 0 2px #d4d9db}.adyen-checkout__checkbox__input+.adyen-checkout__checkbox__label:before{border-bottom:1px solid transparent;border-right:1px solid transparent;border-color:transparent #fff #fff transparent;border-style:solid;border-width:1px 2px 2px 1px;border-radius:0 2px 1px 2px;content:"";height:11px;left:1px;opacity:0;position:absolute;top:2px;-webkit-transform:rotate(37deg);transform:rotate(37deg);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out;width:6px;z-index:1}.adyen-checkout__checkbox__input+.adyen-checkout__checkbox__label:after{content:"";position:absolute;top:0;left:0;width:16px;height:16px;border-radius:3px;background-color:#fff;border:1px solid #b9c4c9;z-index:0;-webkit-transition:background .15s ease-out,border .05s ease-out,box-shadow .1s ease-out;transition:background .15s ease-out,border .05s ease-out,box-shadow .1s ease-out}.adyen-checkout__field--consentCheckbox{background:#e6e9eb;border:1px solid #e6e9eb;border-radius:6px;padding:14px 40px 13px 14px}.adyen-checkout__field--consentCheckbox.adyen-checkout__field--error{border-color:#d10244}.adyen-checkout__field--consentCheckbox .adyen-checkout-input__inline-validation{right:-27px;top:10px}
._2kGp2i5c0AbQ-xsf7RXRPw{position:relative}.waz0IrxZYBVZZIGFHebqH{display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;cursor:pointer;-webkit-box-pack:justify;justify-content:space-between}.waz0IrxZYBVZZIGFHebqH:after{position:absolute;content:"";height:6px;right:16px;width:8px;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='8' height='7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.195 6.565a1 1 0 001.6 0l2.992-3.98a1 1 0 00-.8-1.602H1.013a1 1 0 00-.8 1.6l2.983 3.982z' fill='%23687282'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:50%}._1EqeUznxl6cw_k2HT8KvN4:after{-webkit-transform:rotate(180deg);transform:rotate(180deg)}._2UxApCd88Bra9uwR-b2sbD{position:absolute;width:100%;background:#fff;list-style:none;padding:0;z-index:1;margin:0 0 50px;overflow-y:auto;display:none}._2UxApCd88Bra9uwR-b2sbD.Mlt8tYX1JPlpkrnVPe-r8{display:block}._3nIQRo76neVHr0CKuCZHKc{display:-webkit-box;display:flex;-webkit-box-pack:justify;justify-content:space-between;-webkit-box-align:center;align-items:center}
.adyen-checkout__dropdown{max-width:100%;width:100%;font-size:1em}.adyen-checkout__dropdown__button{padding:9px 24px 9px 12px;border:1px solid #b9c4c9;background:#fff;color:#00112c;text-decoration:none;border-radius:6px;outline:0;width:100%;font-size:1em;height:40px;line-height:20px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:border .2s ease-out,box-shadow .2s ease-out;transition:border .2s ease-out,box-shadow .2s ease-out}.adyen-checkout__dropdown__button:hover{border-color:#99a3ad}.adyen-checkout__dropdown__button__icon{margin-right:8px;margin-left:auto;max-width:40px;max-height:26px;border-radius:3px}.adyen-checkout__dropdown__button--active,.adyen-checkout__dropdown__button--active:hover,.adyen-checkout__dropdown__button:active,.adyen-checkout__dropdown__button:focus{border-color:#06f;box-shadow:0 0 0 2px #99c2ff}.adyen-checkout__dropdown__button--readonly,.adyen-checkout__dropdown__button--readonly--active,.adyen-checkout__dropdown__button--readonly:focus,.adyen-checkout__dropdown__button--readonly:hover{background:#e6e9eb;border-color:transparent;color:#00112c;cursor:not-allowed}.adyen-checkout__dropdown__button--readonly:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='8' height='7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.195 6.565a1 1 0 001.6 0l2.992-3.98a1 1 0 00-.8-1.602H1.013a1 1 0 00-.8 1.6l2.983 3.982z' fill='%23B9C4C9'/%3E%3C/svg%3E")}.adyen-checkout__dropdown__button--invalid{border-color:#d10244}.adyen-checkout__dropdown__button__text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.adyen-checkout__dropdown__list{z-index:2;border-radius:6px;max-height:375px;box-shadow:0 2px 7px rgba(0,15,45,.3)}.adyen-checkout__dropdown__list.adyen-checkout__dropdown__list--active{margin-top:2px}.adyen-checkout__dropdown__element{padding:8px;line-height:20px;border:1px solid transparent;word-break:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;cursor:pointer;font-size:.81em;outline:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:background .2s ease-out,border-color .2s ease-out;transition:background .2s ease-out,border-color .2s ease-out}.adyen-checkout__dropdown__element:last-child{border-bottom:0}.adyen-checkout__dropdown__element:active,.adyen-checkout__dropdown__element:focus,.adyen-checkout__dropdown__element:hover{background:rgba(230,233,235,.6)}.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active{background:rgba(0,102,255,.1)}.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active:active,.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active:focus,.adyen-checkout__dropdown__element.adyen-checkout__dropdown__element--active:hover{background:rgba(0,102,255,.15)}.adyen-checkout__dropdown__element__icon{border-radius:3px;margin-right:8px;max-width:40px;max-height:26px}.adyen-checkout__dropdown+.adyen-checkout-input__inline-validation{right:32px}
.adyen-checkout__select-list{margin:0;padding:0;background:#fff;border:1px solid #b9c4c9;border-radius:6px;max-height:140px;min-height:100px;min-width:300px;overflow-y:scroll;width:100%}.adyen-checkout__select-list__item{display:inline-block;padding:9px;border:1px solid transparent;border-bottom-color:#e6e9eb;background:#fff;outline:0;width:100%;font-size:1em;cursor:pointer;line-height:20px}.adyen-checkout__select-list__item:first-child{border-top:0}.adyen-checkout__select-list__item:active,.adyen-checkout__select-list__item:focus,.adyen-checkout__select-list__item:hover{background:rgba(230,233,235,.6)}.adyen-checkout__select-list__item--selected{background:rgba(0,102,255,.1);font-weight:500}.adyen-checkout__select-list__item--selected:active,.adyen-checkout__select-list__item--selected:focus,.adyen-checkout__select-list__item--selected:hover{background:rgba(0,102,255,.15)}
.adyen-checkout__field-wrapper{display:-webkit-box;display:flex;width:100%}.adyen-checkout__field--20{width:20%}.adyen-checkout__field--30{width:30%}.adyen-checkout__field--40{width:40%}.adyen-checkout__field--50{width:50%}.adyen-checkout__field--60{width:60%}.adyen-checkout__field--70{width:70%}.adyen-checkout__field--80{width:80%}.adyen-checkout__field--col-70{width:calc(70% - 8px)}.adyen-checkout__field--col-30{width:calc(30% - 8px)}.adyen-checkout__field--col-50{width:calc(50% - 8px)}.adyen-checkout__field-wrapper>.adyen-checkout__field:first-child{margin-right:8px}.adyen-checkout__field-wrapper>.adyen-checkout__field:nth-child(2){margin-left:8px}.adyen-checkout__field-wrapper:last-of-type>.adyen-checkout__field{margin-bottom:0}.adyen-checkout__input{color:#00112c;caret-color:#06f;font-size:1em;font-family:inherit;display:block;height:40px;background:#fff;border:1px solid #b9c4c9;border-radius:6px;padding:5px 8px;position:relative;outline:none;width:100%;-webkit-transition:border .2s ease-out,box-shadow .2s ease-out;transition:border .2s ease-out,box-shadow .2s ease-out}.adyen-checkout__input:hover{border-color:#99a3ad}.adyen-checkout__input:required{box-shadow:none}.adyen-checkout__input--disabled,.adyen-checkout__input[readonly]{background:#e6e9eb;border-color:#e6e9eb}.adyen-checkout__input--disabled:hover{border-color:#e6e9eb}.adyen-checkout__input-wrapper{position:relative;display:block}.adyen-checkout__input-wrapper--block{display:block}.adyen-checkout-input__inline-validation{position:absolute;width:16px;height:16px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);right:14px}.adyen-checkout-input__inline-validation--valid{color:#0abf53}.adyen-checkout-input__inline-validation--invalid{color:#d10244}.adyen-checkout__input--invalid{border-color:#d10244}.adyen-checkout__input--valid{border-bottom-color:#0abf53}.adyen-checkout__input--error,.adyen-checkout__input--error:hover,.adyen-checkout__input--invalid,.adyen-checkout__input--invalid:hover{border-color:#d10244}.adyen-checkout__input::-webkit-input-placeholder{color:#b9c4c9;font-weight:200}.adyen-checkout__input::-moz-placeholder{color:#b9c4c9;font-weight:200}.adyen-checkout__input:-ms-input-placeholder{color:#b9c4c9;font-weight:200}.adyen-checkout__input::-ms-input-placeholder{color:#b9c4c9;font-weight:200}.adyen-checkout__input::placeholder{color:#b9c4c9;font-weight:200}.adyen-checkout__input--date{padding-right:30px}.adyen-checkout__input--focus,.adyen-checkout__input--focus:hover,.adyen-checkout__input:active,.adyen-checkout__input:active:hover,.adyen-checkout__input:focus,.adyen-checkout__input:focus:hover{border:1px solid #06f;box-shadow:0 0 0 2px #99c2ff}.adyen-checkout__input[readonly],.adyen-checkout__input[readonly]:hover{background-color:#e6e9eb;border-color:transparent;color:#687282;cursor:default}
.adyen-checkout__open-invoice .adyen-checkout__field--gender .adyen-checkout__radio_group{display:-webkit-box;display:flex}.adyen-checkout__open-invoice .adyen-checkout__field--gender .adyen-checkout__radio_group>label{margin-right:20px}.adyen-checkout__open-invoice .adyen-checkout__fieldset--billingAddress{padding-bottom:8px}.adyen-checkout__open-invoice .adyen-checkout__fieldset--deliveryAddress{margin-top:24px;padding-bottom:8px}.adyen-checkout__open-invoice .adyen-checkout__input--separateDeliveryAddress{margin-bottom:0}.adyen-checkout__open-invoice .adyen-checkout__radio_group{display:-webkit-box;display:flex;margin:8px 0}.adyen-checkout__open-invoice .adyen-checkout__radio_group__input-wrapper{margin-right:16px}.adyen-checkout__open-invoice .adyen-checkout__radio_group__input-wrapper:last-child{margin:0}.adyen-checkout__open-invoice .adyen-checkout__field--consentCheckbox{margin-top:22px}.adyen-checkout__input--separateDeliveryAddress+.adyen-checkout__checkbox__label{margin-top:16px}
.adyen-checkout__button{background:#00112c;border:0;border-radius:6px;color:#fff;cursor:pointer;font-size:1em;font-weight:500;height:48px;margin:0;padding:15px;text-decoration:none;-webkit-transition:background .3s ease-out,box-shadow .3s ease-out;transition:background .3s ease-out,box-shadow .3s ease-out;width:100%}.adyen-checkout__button:focus{box-shadow:0 0 0 2px #99c2ff;outline:0}.adyen-checkout__button:hover{background:#1c3045;box-shadow:0 0,0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14)}.adyen-checkout__button:active{background:#3a4a5c}.adyen-checkout__button:hover:focus{box-shadow:0 0 0 2px #99c2ff,0 3px 4px rgba(0,15,45,.2)}.adyen-checkout__button:disabled,.adyen-checkout__button:disabled:hover{box-shadow:none;cursor:not-allowed;opacity:.4;-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}.adyen-checkout__button.adyen-checkout__button--loading{background:#687282;box-shadow:none;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.adyen-checkout__button.adyen-checkout__button--pay{margin-top:24px}.adyen-checkout__button.adyen-checkout__button--standalone{margin-top:0}.adyen-checkout__button.adyen-checkout__button--inline{display:block;width:auto;height:auto;padding:10px 8px;font-size:.81em}.adyen-checkout__button.adyen-checkout__button--ghost{background:none;border:0;color:#00112c}.adyen-checkout__button.adyen-checkout__button--ghost:hover{background:#f7f8f9;box-shadow:none}.adyen-checkout__button.adyen-checkout__button--ghost:active{background:#e6e9eb;box-shadow:none}.adyen-checkout__button.adyen-checkout__button--secondary{padding:10px 12px;background:rgba(0,102,255,.1);border:1px solid transparent;color:#06f}.adyen-checkout__button.adyen-checkout__button--secondary:hover{background:rgba(0,102,255,.2);box-shadow:none}.adyen-checkout__button.adyen-checkout__button--secondary:active,.adyen-checkout__button.adyen-checkout__button--secondary:active:hover{background:rgba(0,102,255,.3);box-shadow:none}.adyen-checkout__button.adyen-checkout__button--link{background:transparent;border:1px solid transparent;color:#06f;font-weight:400;border-radius:3px;padding:2px}.adyen-checkout__button.adyen-checkout__button--link:hover{background:transparent;text-decoration:underline;box-shadow:none}.adyen-checkout__button.adyen-checkout__button--completed,.adyen-checkout__button.adyen-checkout__button--completed:active,.adyen-checkout__button.adyen-checkout__button--completed:active:hover,.adyen-checkout__button.adyen-checkout__button--completed:hover{background:#0abf53;color:#fff}.adyen-checkout__button.adyen-checkout__button--completed .adyen-checkout__button__icon{-webkit-filter:brightness(0) invert(1);filter:brightness(0) invert(1)}.adyen-checkout__button__content{height:100%;-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;-webkit-box-pack:center;justify-content:center}.adyen-checkout__button__icon{margin-right:12px}.adyen-checkout__button__text{display:block;-webkit-box-pack:center;justify-content:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.adyen-checkout__button .adyen-checkout__spinner{border-color:transparent #fff #fff}
@supports (-webkit-appearance:-apple-pay-button){._26P3-497Bo_kcWzSC3HwGB{display:inline-block;-webkit-appearance:-apple-pay-button;cursor:pointer}._3Ml54cUbtBzCVkvsUVCz2j{-apple-pay-button-style:#000}._1qE8Ax1p0lKQo48G-CCVqZ{-apple-pay-button-style:#fff}.j9FE548KYNuE6WmBWaiNC{-apple-pay-button-style:white-outline}._2mnnXXIeaYr6ejFqAw5LVo{-apple-pay-button-type:plain}.eMnIyuX5G0zZyai40-cM_{-apple-pay-button-type:buy}._3zvI8car845xrwaqzFfO2W{-apple-pay-button-type:donate}.ipg0J6WFnN7o8UJJFmC4s{-apple-pay-button-type:check-out}._155XskC0jg67fCvlP3APVl{-apple-pay-button-type:book}._3uPJ53ZiJwUi1Ccq9H4PsZ{-apple-pay-button-type:subscribe}}@supports not (-webkit-appearance:-apple-pay-button){._26P3-497Bo_kcWzSC3HwGB{display:inline-block;background-size:100% 60%;background-repeat:no-repeat;background-position:50% 50%;border-radius:5px;padding:0;box-sizing:border-box;min-width:200px;min-height:32px;max-height:64px}._3Ml54cUbtBzCVkvsUVCz2j{background-image:-webkit-named-image(apple-pay-logo-white);background-color:#000}._1qE8Ax1p0lKQo48G-CCVqZ,.j9FE548KYNuE6WmBWaiNC{background-image:-webkit-named-image(apple-pay-logo-black);background-color:#fff}.j9FE548KYNuE6WmBWaiNC{border:.5px solid #000}}
.adyen-checkout__applepay__button{width:240px;height:40px}.adyen-checkout__dropin .adyen-checkout__applepay__button{width:100%}
.adyen-checkout__field--issuer-list{margin-bottom:0}
._2tAzuCpLXISBbB0i1w8DVZ{position:relative}._2tAzuCpLXISBbB0i1w8DVZ *,._2tAzuCpLXISBbB0i1w8DVZ :after,._2tAzuCpLXISBbB0i1w8DVZ :before{box-sizing:border-box}._2Iaf5OCcFDHNbg4xIfIudh{border-radius:3px;position:absolute;right:10px;margin-left:7px;-webkit-transform:translateY(-50%);transform:translateY(-50%);top:50%;height:18px;width:27px}._2Ij_ndRDnCol2zr5QeQTDc{opacity:1}._1wHzqkXPXckZF1L7O0lJcl{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;display:none}._1DzoelWVqVVxPpbFf_P8CW{display:block}._3zh3YASnApBoXd9ZdXmHBz{opacity:0}._3JmldYKADXTctIE9oP8lcu{display:block;max-height:100px}._1Z1lpTOoiszbauxOoGwrWf{display:none}
._1jpVsksYS5faJOp2y0Tpl4{opacity:1}._3LDWzlGXC0eWQ4YCw4-qjD{opacity:0}._3eCyK2bUQJ0swg0UM0nnQN{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;display:none}._3UDtXj7dWSJxI8TptPZ6N2{display:block}
.adyen-checkout__card-input__form{-webkit-transition:opacity .25s ease-out;transition:opacity .25s ease-out}.adyen-checkout__card__cardNumber{max-width:400px}.adyen-checkout__card__cardNumber__input{padding:5px 8px}.adyen-checkout__card__exp-date__input--oneclick{line-height:30px;font-weight:400;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.adyen-checkout__card__holderName,.adyen-checkout__field--expiryDate,.adyen-checkout__field--storedCard{margin-bottom:0}.adyen-checkout__card__holderName,.adyen-checkout__card__kcp-authentication,.adyen-checkout__installments,.adyen-checkout__store-details{margin-top:16px}.adyen-checkout__field--cardNumber .adyen-checkout__input--error .adyen-checkout__card__cardNumber__brandIcon{display:none}.adyen-checkout__field--cardNumber .adyen-checkout__input--valid:not(.adyen-checkout__card__cardNumber__input--noBrand)+.adyen-checkout-input__inline-validation--valid{display:none}.adyen-checkout__card-input .adyen-checkout__fieldset--address{margin-top:16px}.adyen-checkout__field--securityCode.adyen-checkout__field--error .adyen-checkout__card__cvc__hint,.adyen-checkout__field--securityCode.adyen-checkout__field--valid .adyen-checkout__card__cvc__hint{opacity:0}@-webkit-keyframes cvcIndicateLocation{0%{opacity:1}to{opacity:.3}}@keyframes cvcIndicateLocation{0%{opacity:1}to{opacity:.3}}.adyen-checkout__label--focused .adyen-checkout__card__cvc__hint__location{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-name:cvcIndicateLocation;animation-name:cvcIndicateLocation;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-direction:alternate;animation-direction:alternate}.adyen-checkout__card__cvc__hint__wrapper{position:absolute;right:0;top:0;height:100%;width:27px;display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;margin:0 10px;-webkit-transition:-webkit-transform .3s cubic-bezier(.455,.03,.515,.955);transition:-webkit-transform .3s cubic-bezier(.455,.03,.515,.955);transition:transform .3s cubic-bezier(.455,.03,.515,.955);transition:transform .3s cubic-bezier(.455,.03,.515,.955),-webkit-transform .3s cubic-bezier(.455,.03,.515,.955);-webkit-transform-origin:center;transform-origin:center;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;will-change:transform;-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-transform:translateZ(0);transform:translateZ(0)}.adyen-checkout__field__cvc--front-hint.adyen-checkout__card__cvc__hint__wrapper{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.adyen-checkout__card__cvc__hint{-webkit-backface-visibility:hidden;backface-visibility:hidden;position:absolute;-webkit-transition:opacity .1s linear;transition:opacity .1s linear}.adyen-checkout__card__cvc__hint--front{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}@media (prefers-reduced-motion:reduce){.adyen-checkout__card__cvc__hint__wrapper{-webkit-transition:none;transition:none}}
.adyen-checkout__image{opacity:0;-webkit-transition:opacity .6s ease-out;transition:opacity .6s ease-out}.adyen-checkout__image--loaded{opacity:1}
.adyen-checkout__button-group{background:transparent;display:-webkit-box;display:flex;-webkit-box-pack:justify;justify-content:space-between}.adyen-checkout__button-group .adyen-checkout__button{background:transparent;border:0;box-shadow:inset 0 0 0 1px #99a3ad;color:#00112c;font-size:.81em;font-weight:400;line-height:40px;margin-right:8px;height:40px;padding:0;text-align:center}.adyen-checkout__button-group .adyen-checkout__button:last-child{margin-right:0}.adyen-checkout__button-group .adyen-checkout__button:hover{background:transparent;box-shadow:inset 0 0 0 2px #99a3ad}.adyen-checkout__button-group .adyen-checkout__button:active{background:#f7f8f9;box-shadow:inset 0 0 0 2px #99a3ad}.adyen-checkout__button-group .adyen-checkout__button--disabled,.adyen-checkout__button-group .adyen-checkout__button--disabled:hover{cursor:not-allowed;opacity:.4;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.adyen-checkout__button-group .adyen-checkout__button--selected,.adyen-checkout__button-group .adyen-checkout__button--selected:active,.adyen-checkout__button-group .adyen-checkout__button--selected:active:hover,.adyen-checkout__button-group .adyen-checkout__button--selected:hover{background:#e5efff;box-shadow:inset 0 0 0 2px #06f;color:#06f;font-weight:500;height:40px;-webkit-transition:none;transition:none}.adyen-checkout__button-group .adyen-checkout__button .adyen-checkout__button-group__input{opacity:0;pointer-events:none;position:absolute}
.adyen-checkout__adyen-giving .adyen-checkout__status__icon{display:block;margin:56px auto 32px}.adyen-checkout__adyen-giving .adyen-checkout__status__text{color:#00112c;margin-bottom:56px;text-align:center}.adyen-checkout__campaign{border-radius:6px;background:#00112c;height:227px;overflow:hidden;position:relative}.adyen-checkout__campaign-link:hover .adyen-checkout__campaign-description{text-decoration:underline}.adyen-checkout__campaign-container{height:100%}.adyen-checkout__campaign-logo{border:2px solid hsla(0,0%,100%,.4);border-radius:3px;display:block;height:48px;margin-bottom:16px;overflow:hidden;width:48px}.adyen-checkout__campaign-background-image{background-color:#00112c;background-position:50%;background-size:cover;height:100%}.adyen-checkout__campaign-link .adyen-checkout__campaign-background-image:before{background:inherit;content:"";height:100%;position:absolute;-webkit-transition:-webkit-transform .6s ease-out;transition:-webkit-transform .6s ease-out;transition:transform .6s ease-out;transition:transform .6s ease-out,-webkit-transform .6s ease-out;width:100%}.adyen-checkout__campaign-link .adyen-checkout__campaign-background-image:hover:before{-webkit-transform:scale(1.1);transform:scale(1.1)}.adyen-checkout__campaign-link .adyen-checkout__campaign-content{pointer-events:none}.adyen-checkout__campaign-content{bottom:0;padding:16px;position:absolute;z-index:2}.adyen-checkout__campaign-description,.adyen-checkout__campaign-title{color:#fff;font-weight:400;margin:0}.adyen-checkout__campaign-title{font-size:1em;margin-bottom:8px}.adyen-checkout__campaign-description{font-size:.81em;line-height:19px}.adyen-checkout__adyen-giving-actions{margin-top:16px}.adyen-checkout__button.adyen-checkout__button--donate{margin:16px auto 8px}.adyen-checkout__button.adyen-checkout__button--decline{display:block;margin:auto;width:auto}
.adyen-checkout__paywithgoogle .gpay-button.long{width:100%;padding:15px 24px 13px;height:48px;-webkit-transition:background-color .3s ease-out,box-shadow .3s ease-out;transition:background-color .3s ease-out,box-shadow .3s ease-out}.adyen-checkout__paywithgoogle .gpay-button.long:focus{box-shadow:0 0 0 2px #99c2ff;outline:0}
.adyen-checkout__econtext-input__field{display:-webkit-box;display:flex;flex-wrap:wrap}.adyen-checkout__econtext-input__field .adyen-checkout__field--firstName,.adyen-checkout__econtext-input__field .adyen-checkout__field--lastName{width:calc(50% - 8px);min-width:250px;max-width:100%}.adyen-checkout__econtext-input__field .adyen-checkout__field--firstName{margin-right:16px}
.adyen-checkout__voucher-result{box-sizing:border-box;border-radius:12px;text-align:center;position:relative}.adyen-checkout__voucher-result__bottom,.adyen-checkout__voucher-result__top{background:#fff;border:1px solid #d4d9db}.adyen-checkout__voucher-result__top{padding:40px 0 24px;border-radius:12px 12px 0 0;border-bottom:0}.adyen-checkout__voucher-result__bottom{border-top:0;border-radius:0 0 12px 12px}.adyen-checkout__voucher-result__separator{background:#fff;position:relative;width:calc(100% - 14px);height:13px;margin:0 auto;display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center}.adyen-checkout__voucher-result__separator:after,.adyen-checkout__voucher-result__separator:before{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNyIgaGVpZ2h0PSIxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBjbGlwLXBhdGg9InVybCgjY2xpcDApIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTAgMGw1IDIgMS41IDRIN1YwSDB6bTAgMTNsNS0yIDEuNS00SDd2NkgweiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik02LjQyMyA2LjVDNi40MjMgMy4zMTIgMy43ODMuNzU2LjUuNTE4djBjMy4zODYuMjM2IDYgMi44NTUgNiA1Ljk4MiAwIDMuMTI3LTIuNjE0IDUuNzQ2LTYgNS45ODN2LS4wMDFjMy4yODQtLjIzNyA1LjkyMy0yLjc5NCA1LjkyMy01Ljk4MnoiIHN0cm9rZT0iI0Q0RDlEQiIvPjxwYXRoIGZpbGw9IiNENEQ5REIiIGQ9Ik0wIDBoMXYxSDB6TTAgMTJoMXYxSDB6Ii8+PC9nPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0wIDBoN3YxM0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==)}.adyen-checkout__voucher-result__separator:before{background-position:100%;background-repeat:no-repeat;content:"";left:-7px;top:0;position:absolute;width:7px;height:13px}.adyen-checkout__voucher-result__separator:after{background-position:100%;background-repeat:no-repeat;content:"";right:-7px;top:0;position:absolute;width:7px;height:13px;-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}.adyen-checkout__voucher-result__separator__inner{width:100%;border-top:1px solid #e6e9eb}.adyen-checkout__voucher-result__image{display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;width:100%;margin-bottom:40px}.adyen-checkout__voucher-result__image__wrapper{display:block;position:relative;height:48px;margin:0 24px}.adyen-checkout__voucher-result__image__wrapper:after{border:1px solid rgba(0,27,43,.17);border-radius:3px;content:"";height:100%;left:0;position:absolute;top:0;width:100%}.adyen-checkout__voucher-result__image__wrapper:nth-child(2):before{border-left:1px solid #d4d9db;content:"";height:64px;left:-24.5px;position:absolute;top:-8px;width:1px}.adyen-checkout__voucher-result__image__brand,.adyen-checkout__voucher-result__image__issuer{height:48px;border-radius:3px}.adyen-checkout__voucher-result__introduction{line-height:19px;font-size:.81em;text-align:center;color:#00112c;max-width:400px;margin:0 auto}.adyen-checkout__voucher-result__amount{margin:24px auto 0;font-size:1em;color:#00112c;text-align:center;font-weight:700}.adyen-checkout__voucher-result__surcharge{font-size:.81em;line-height:19px;text-align:center;color:#687282;display:block;font-weight:400}.adyen-checkout__voucher-result__code__label{position:absolute;display:block;font-weight:400;right:0;left:0;width:auto;line-height:19px;top:-2px;margin:0 auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.adyen-checkout__voucher-result__code__label:before{content:"";position:absolute}.adyen-checkout__voucher-result__code__label__text{font-size:13px;color:#00112c;background:#fff;padding:0 8px;letter-spacing:normal;line-height:1}.adyen-checkout__voucher-result__code__barcode{display:block;margin:0 auto 8px;max-width:100%;height:56px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.adyen-checkout__voucher-result__code{position:relative;font-size:1.5em;text-align:center;letter-spacing:1px;color:#00112c;border-width:1px 0;padding:16px 48px;display:inline-block;margin:0 auto;width:100%;font-weight:700;-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all;word-break:break-word;line-height:1.2}.adyen-checkout__voucher-result__details{list-style:none;padding:0;margin:-1px auto 0}.adyen-checkout__voucher-result__details__item{display:-webkit-box;display:flex;-webkit-box-pack:justify;justify-content:space-between;font-size:.81em;color:#00112c;padding:16px 24px;border-top:1px solid #e6e9eb;word-break:break-word}.adyen-checkout__voucher-result__details__item:last-child{margin-bottom:0}.adyen-checkout__voucher-result__details__label{max-width:50%;text-align:left}.adyen-checkout__voucher-result__details__value{max-width:50%;text-align:right;font-weight:700}.adyen-checkout__voucher-result__actions{margin:0 auto 32px;max-width:100%;min-width:200px;width:300px;display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;list-style:none;padding:0}.adyen-checkout__voucher-result__actions__item{margin:0 4px}
.adyen-checkout__paypal__button{display:-webkit-box;display:flex;margin-bottom:16px}.adyen-checkout__paypal__button:empty{display:none}.adyen-checkout__paypal__status--pending{margin:16px 0}.adyen-checkout__paypal__status--processing{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex;font-size:13px;-webkit-box-pack:center;justify-content:center;padding:24px 0}.adyen-checkout__payment-method .adyen-checkout__paypal__status--pending{margin:-16px 0 38px}.adyen-checkout__payment-method .adyen-checkout__paypal__status--processing{padding:20px 0 65px}
.adyen-checkout__iban-input__number{text-transform:uppercase;padding:5px 36px 5px 8px}
.adyen-checkout__threeds2__challenge,.adyen-checkout__threeds2__challenge-container{background-color:transparent;box-sizing:border-box;display:block;overflow:auto;width:100%}.adyen-checkout__threeds2__challenge-container--01{height:400px;width:250px}.adyen-checkout__threeds2__challenge-container--02{height:400px;width:390px}.adyen-checkout__threeds2__challenge-container--03{height:600px;width:500px}.adyen-checkout__threeds2__challenge-container--04{height:400px;width:600px}.adyen-checkout__threeds2__challenge-container--05{height:100%;width:100%}.adyen-checkout__threeds2__challenge.adyen-checkout__threeds2__challenge--05{position:relative;overflow:hidden;padding-top:56.25%}.adyen-checkout__threeds2__challenge.adyen-checkout__threeds2__challenge--05 .adyen-checkout__iframe--threeDSIframe{position:absolute;top:0;left:0;width:100%;height:100%;border:0}
.adyen-checkout__qr-loader{background:#fff;padding:40px;border:1px solid #d4d9db;border-radius:12px;text-align:center}.adyen-checkout__qr-loader--result{padding:100px}.adyen-checkout__qr-loader--app{border:0;border-radius:0;padding:0}.adyen-checkout__qr-loader__brand-logo{width:74px;border-radius:3px}.adyen-checkout__qr-loader__subtitle{margin-top:32px}.adyen-checkout__qr-loader__subtitle--result{margin-bottom:32px}.adyen-checkout__qr-loader__payment_amount,.adyen-checkout__qr-loader__subtitle{color:#00112c;font-size:1em;line-height:19px}.adyen-checkout__qr-loader__icon{width:88px;height:88px}.adyen-checkout__qr-loader__payment_amount{font-weight:700}.adyen-checkout__qr-loader__progress{height:4px;background:#d4d9db;border-radius:24px;margin:32px auto 12px;width:152px;padding-right:3%}.adyen-checkout__qr-loader__percentage{display:block;height:100%;border-radius:24px;background:#06f}.adyen-checkout__qr-loader__countdown{color:#687282;font-size:.81em}.adyen-checkout__qr-loader>.adyen-checkout__spinner__wrapper{margin:60px 0}.adyen-checkout__qr-loader__app-link{margin-top:16px;display:none}.adyen-checkout__qr-loader__separator__label{position:relative;font-size:13px;color:#687282;overflow:hidden;text-align:center;z-index:1;display:block}.adyen-checkout__qr-loader__separator__label:after,.adyen-checkout__qr-loader__separator__label:before{position:absolute;top:51%;overflow:hidden;width:50%;height:1px;content:"\A0";background-color:#e6e9eb}.adyen-checkout__qr-loader__separator__label:before{margin-left:-52%;text-align:right}.adyen-checkout__qr-loader__separator__label:after{margin-left:2%}.adyen-checkout__button.adyen-checkout__button--qr-loader{text-decoration:none;margin-top:24px}@media only screen and (max-device-width:1200px){.adyen-checkout__qr-loader__app-link{display:block}}
.adyen-checkout__doku-input__field{display:-webkit-box;display:flex;flex-wrap:wrap}.adyen-checkout__doku-input__field .adyen-checkout__field--firstName,.adyen-checkout__doku-input__field .adyen-checkout__field--lastName{width:calc(50% - 8px);min-width:250px;max-width:100%}.adyen-checkout__doku-input__field .adyen-checkout__field--firstName{margin-right:16px}
.adyen-checkout__voucher-result--boletobancario .adyen-checkout__voucher-result__code{font-size:.81em;line-height:19px;word-break:break-all;padding:24px}
.adyen-checkout__voucher-result--oxxo .adyen-checkout__voucher-result__code{font-size:.81em;line-height:19px;word-break:break-all;padding:24px}
.adyen-checkout__giftcard-result{position:relative;background:#fff;border:1px solid #e6e9eb;width:100%;padding:16px;margin-bottom:8px;border-radius:12px}.adyen-checkout__giftcard-result__header{flex-wrap:nowrap;font-size:1em;font-weight:400;-webkit-box-pack:justify;justify-content:space-between;position:relative;width:100%}.adyen-checkout__giftcard-result__header,.adyen-checkout__giftcard-result__header__title{-webkit-box-align:center;align-items:center;display:-webkit-box;display:flex}.adyen-checkout__giftcard-result__name{margin-left:8px}.adyen-checkout__giftcard-result__balance{padding:0;list-style:none;margin:16px 0 0}.adyen-checkout__giftcard-result__balance__item{display:-webkit-box;display:flex;-webkit-box-pack:justify;justify-content:space-between;margin-bottom:8px}.adyen-checkout__giftcard-result__balance__item:last-child{margin-bottom:0}.adyen-checkout__giftcard-result__balance__item--remaining-balance{font-size:.81em}.adyen-checkout__giftcard-result__balance__value--amount{font-weight:700}
._2T9kQExpijVM_P8ZmbWqAT{list-style:none;margin:0;padding:0}._2ZCloBYWlRv9GTkR9J7a0_{display:block;max-height:60px}._2_jFPDCxgbayWBQMKR2rMi{display:none}.Fg2uwnDU3lpWzjoffGQq{width:40px;height:26px}.pTTKrAW94J1fqrzM_--G3{margin-right:8px}._1zXEAefSOOUzgA_cpgWdSX{max-height:100%}._1zXEAefSOOUzgA_cpgWdSX ._2_jFPDCxgbayWBQMKR2rMi{display:block}
.adyen-checkout__payment-method__disable-confirmation{background:#d10244;font-size:.81em;color:#fff;border-right:1px solid #c70241;border-left:1px solid #c70241;overflow:hidden;opacity:0;margin:0 -17px;max-height:0;-webkit-transition:opacity .15s ease-out,max-height .15s linear,margin-bottom .1s linear;transition:opacity .15s ease-out,max-height .15s linear,margin-bottom .1s linear}.adyen-checkout__payment-method__disable-confirmation.adyen-checkout__payment-method__disable-confirmation--open{max-height:62px;opacity:1;margin-bottom:16px}.adyen-checkout__payment-method__disable-confirmation__content{display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;-webkit-box-pack:justify;justify-content:space-between;padding:8px 16px}.adyen-checkout__payment-method__disable-confirmation__buttons{display:-webkit-box;display:flex}.adyen-checkout__payment-method__disable-confirmation__button{background:#d10244;border:1px solid transparent;border-radius:6px;color:#fff;cursor:pointer;display:block;height:auto;line-height:14px;margin:0 0 0 8px;padding:8px;width:auto}.adyen-checkout__payment-method__disable-confirmation__button:hover,.adyen-checkout__payment-method__disable-confirmation__button:hover:focus{box-shadow:none;background:#b8023c}.adyen-checkout__payment-method__disable-confirmation__button:active,.adyen-checkout__payment-method__disable-confirmation__button:hover:active{background:#9e0234;box-shadow:none}.adyen-checkout__payment-method__disable-confirmation__button--remove,.adyen-checkout__payment-method__disable-confirmation__button--remove:disabled{border-color:#fff}.adyen-checkout__payment-method__disable-confirmation__button--cancel,.adyen-checkout__payment-method__disable-confirmation__button--cancel:disabled{border-color:transparent}
.adyen-checkout__payment-method{position:relative;background:#fff;border:1px solid #e6e9eb;cursor:pointer;margin-top:-1px;width:100%;-webkit-transition:opacity .3s ease-out;transition:opacity .3s ease-out}.adyen-checkout__payment-method:focus{outline:0}.adyen-checkout__payment-method--selected+.adyen-checkout__payment-method,.adyen-checkout__payment-method:first-child{margin-top:0;border-top-left-radius:12px;border-top-right-radius:12px}.adyen-checkout__payment-method--next-selected,.adyen-checkout__payment-method:last-child{margin-bottom:0;border-bottom-left-radius:12px;border-bottom-right-radius:12px}.adyen-checkout__payment-method--loading{opacity:.2}.adyen-checkout__payment-method--selected.adyen-checkout__payment-method--loading{opacity:.9}.adyen-checkout__payment-method--confirming .adyen-checkout__payment-method__details__content,.adyen-checkout__payment-method--disabling{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.adyen-checkout__payment-method--disabling{opacity:.3}.adyen-checkout__payment-method__header{-webkit-box-align:center;align-items:center;color:#00112c;display:-webkit-box;display:flex;flex-wrap:nowrap;-webkit-box-pack:justify;justify-content:space-between;font-weight:400;font-size:1em;padding:16px 16px 16px 48px;position:relative;-webkit-transition:background .1s ease-out;transition:background .1s ease-out;width:100%}.adyen-checkout__payment-method--standalone .adyen-checkout__payment-method__header{padding:16px}.adyen-checkout__payment-method__header__title{display:-webkit-box;display:flex;-webkit-box-align:center;align-items:center;flex-shrink:0;margin-right:16px;max-width:100%}.adyen-checkout__payment-method__surcharge{color:#687282;margin-left:5px}.adyen-checkout__payment-method--selected{-webkit-transition:margin .15s cubic-bezier(.4,0,.2,1) 0ms,opacity .3s ease-out;transition:margin .15s cubic-bezier(.4,0,.2,1) 0ms,opacity .3s ease-out;background:#f7f8f9;border:1px solid #e6e9eb;margin:8px 0;border-radius:12px;cursor:default}.adyen-checkout__payment-method--selected .adyen-checkout__payment-method__header{flex-wrap:wrap}.adyen-checkout__payment-method__name{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.adyen-checkout__payment-method__name--selected{font-weight:500}.adyen-checkout__payment-method__details{padding:0 16px;position:relative}.adyen-checkout__payment-method__details__content{margin:0 0 16px}.adyen-checkout__payment-method__image__wrapper{height:26px;width:40px;position:relative}.adyen-checkout__payment-method__image__wrapper:after{content:"";position:absolute;top:0;width:100%;height:100%;left:0;border-radius:3px;border:1px solid rgba(0,27,43,.17)}.adyen-checkout__payment-method__image{display:block;border-radius:3px}.adyen-checkout__payment-method__brands{display:-webkit-box;display:flex;flex-wrap:wrap;margin:4px 0;height:16px;flex-basis:auto;flex-shrink:1;text-align:right;overflow:hidden}.adyen-checkout__payment-method--selected .adyen-checkout__payment-method__brands{text-align:left;overflow:visible;height:auto}.adyen-checkout__payment-method__brands .adyen-checkout__payment-method__image__wrapper{display:inline-block;margin-right:4px;height:16px;width:24px;-webkit-transition:opacity .2s ease-out;transition:opacity .2s ease-out}.adyen-checkout__payment-method__brands .adyen-checkout__payment-method__image__wrapper:last-child{margin:0}.adyen-checkout__payment-method--selected .adyen-checkout__payment-method__brands .adyen-checkout__payment-method__image__wrapper{margin-bottom:4px}.adyen-checkout__payment-method__brands img{width:24px;height:16px}.adyen-checkout__payment-method__image__wrapper--disabled{opacity:.25}.adyen-checkout__payment-method__radio{position:absolute;background-color:#fff;border:1px solid #b9c4c9;border-radius:50%;height:16px;width:16px;left:16px;-webkit-transition:border-color .2s ease-out,box-shadow .2s ease-out;transition:border-color .2s ease-out,box-shadow .2s ease-out}.adyen-checkout__payment-method--standalone .adyen-checkout__payment-method__radio{display:none}.adyen-checkout__payment-method__radio:after{content:"";display:block;position:absolute;margin:0 auto;left:0;right:0;top:50%;height:6px;width:6px;background-color:#fff;border-radius:50%;-webkit-transform:translateY(-50%) scale(0);transform:translateY(-50%) scale(0);-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out}.adyen-checkout__payment-method:hover:not(.adyen-checkout__payment-method--selected) .adyen-checkout__payment-method__radio{border-color:#99a3ad;box-shadow:0 0 0 2px #d4d9db;cursor:pointer}.adyen-checkout__payment-method__radio--selected{background-color:#06f;border:0;-webkit-transition:all .3s ease-out;transition:all .3s ease-out}.adyen-checkout__payment-method__radio--selected:hover{box-shadow:0 0 0 2px rgba(0,102,255,.4)}.adyen-checkout__payment-method__radio--selected:after{-webkit-transform:translateY(-50%) scale(1);transform:translateY(-50%) scale(1)}
.adyen-checkout__status{display:-webkit-box;display:flex;text-align:center;-webkit-box-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;-webkit-box-pack:center;justify-content:center;height:350px;margin:0;padding:32px;background-color:#fff;border-radius:6px;border:1px solid #d4d9db;font-size:1em;color:#00112c}.adyen-checkout__status__icon{margin-bottom:24px}.adyen-checkout__status .adyen-checkout__spinner__wrapper{max-height:88px}
.adyen-checkout__dropin,.adyen-checkout__dropin *,.adyen-checkout__dropin :after,.adyen-checkout__dropin :before{box-sizing:border-box}.adyen-checkout__payment-methods-list--loading{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}.adyen-checkout__link{color:#06f;text-decoration:none}.adyen-checkout__link:hover{text-decoration:underline}
._1V7mk6_fpUl6IOE-QqH-JR{position:relative}._1V7mk6_fpUl6IOE-QqH-JR *,._1V7mk6_fpUl6IOE-QqH-JR :after,._1V7mk6_fpUl6IOE-QqH-JR :before{box-sizing:border-box}._1SeSlzVXGcIdgO40pvhfro{display:block;max-height:100px}
.adyen-checkout__loading-input__form{-webkit-transition:opacity .25s ease-out;transition:opacity .25s ease-out}.adyen-checkout__pm__holderName{margin-bottom:0}.adyen-checkout__ach-input .adyen-checkout__fieldset--address,.adyen-checkout__ach-sf__form{margin-top:16px}
._1K_z0mRj6YvwYsYK1dJ2r2{display:block;max-height:100px}
.adyen-checkout__loading-input__form{-webkit-transition:opacity .25s ease-out;transition:opacity .25s ease-out}
.adyen-checkout__await{background:#fff;padding:40px;border:1px solid #d4d9db;border-radius:12px;text-align:center}.adyen-checkout__await--result{padding:100px}.adyen-checkout__qr-loader--app{border:0;border-radius:0;padding:0}.adyen-checkout__await__brand-logo{width:74px;border-radius:3px}.adyen-checkout__await__indicator-text,.adyen-checkout__await__subtitle{color:#00112c;font-size:1em;line-height:19px;margin-top:32px}.adyen-checkout__await__indicator-holder .adyen-checkout__await__indicator-text{margin-top:6px;margin-left:10px}.adyen-checkout__await__indicator-holder{display:-webkit-box;display:flex;-webkit-box-pack:center;justify-content:center;margin-top:32px;margin-bottom:20px}.adyen-checkout__await__subtitle--result{margin-bottom:32px}.adyen-checkout__await__icon{width:88px;height:88px}.adyen-checkout__await__progress{height:4px;background:#d4d9db;border-radius:24px;margin:32px auto 12px;width:152px}.adyen-checkout__await__percentage{display:block;height:100%;border-radius:24px;background:#06f}.adyen-checkout__await__countdown{color:#687282;font-size:.81em}.adyen-checkout__await>.adyen-checkout__spinner__wrapper{margin:60px 0}.adyen-checkout__qr-loader__app-link{margin-top:16px;display:none}.adyen-checkout__qr-loader__separator__label{position:relative;font-size:13px;color:#687282;overflow:hidden;text-align:center;z-index:1;display:block}.adyen-checkout__qr-loader__separator__label:after,.adyen-checkout__qr-loader__separator__label:before{position:absolute;top:51%;overflow:hidden;width:50%;height:1px;content:"\A0";background-color:#e6e9eb}.adyen-checkout__qr-loader__separator__label:before{margin-left:-52%;text-align:right}.adyen-checkout__qr-loader__separator__label:after{margin-left:2%}@media only screen and (max-device-width:1200px){.adyen-checkout__qr-loader__app-link{display:block}}
/* Checkout component Adyen styling end */
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* 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>
*/
define(
[
],
function () {
'use strict';
return {
getOriginKey: function () {
return window.checkoutConfig.payment.adyenCc.originKey;
},
showLogo: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
getLocale: function () {
return window.checkoutConfig.payment.adyenCc.locale;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyenCc.checkoutEnvironment;
},
};
}
);
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
define(
[
'ko'
],
function (ko) {
'use strict';
return ko.observableArray([]);
}
);
......@@ -4,37 +4,23 @@
*/
define(
[
'ko',
'underscore',
'Magento_Checkout/js/model/quote',
'Adyen_Payment/js/model/adyen-method-list',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/url-builder',
'mage/storage'
'mage/storage',
'Adyen_Payment/js/bundle',
],
function (_, quote, methodList, customer, urlBuilder, storage) {
function (ko, _, quote, customer, urlBuilder, storage, adyenComponent) {
'use strict';
var checkoutComponent = {};
var paymentMethods = ko.observable({})
return {
/**
* Populate the list of payment methods
* @param {Array} methods
*/
setPaymentMethods: function (methods) {
methodList(methods);
},
/**
* Get the list of available payment methods.
* @returns {Array}
*/
getAvailablePaymentMethods: function () {
return methodList();
},
/**
* Retrieve the list of available payment methods from the server
*/
retrieveAvailablePaymentMethods: function (callback) {
var self = this;
retrieveAvailablePaymentMethods: function () {
// retrieve payment methods
var serviceUrl,
payload;
......@@ -51,28 +37,60 @@ define(
shippingAddress: quote.shippingAddress()
};
storage.post(
return storage.post(
serviceUrl,
JSON.stringify(payload)
).done(
function (response) {
self.setPaymentMethods(response);
if (callback) {
callback();
}
}
).fail(
function () {
self.setPaymentMethods([]);
}
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
* component or place the order (validateThreeDS2OrPlaceOrder)
* @param response
*/
processThreeDS2: function (data) {
var payload = {
"payload": JSON.stringify(data)
};
var serviceUrl = urlBuilder.createUrl('/adyen/threeDS2Process', {});
return storage.post(
serviceUrl,
JSON.stringify(payload),
true
);
},
getOrderPaymentStatus: function (orderId) {
var serviceUrl = urlBuilder.createUrl('/adyen/orders/:orderId/payment-status', {
orderId: orderId
});
return storage.get(serviceUrl);
},
initCheckoutComponent: function(paymentMethodsResponse, originKey, locale, environment, ) {
checkoutComponent = new AdyenCheckout({
locale: locale,
originKey: originKey,
environment: environment,
paymentMethodsResponse: paymentMethodsResponse,
consentCheckbox: false,
visibility: {
personalDetails: 'editable',
billingAddress: 'editable',
separateDeliveryAddress: 'hidden',
deliveryAddress: 'hidden'
}
});
paymentMethods(paymentMethodsResponse.paymentMethods);
},
getCheckoutComponent: function() {
return checkoutComponent;
},
getPaymentMethodsObservable: function() {
return paymentMethods;
}
};
}
......
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
define(
[
'ko',
'jquery',
],
function (ko, $) {
'use strict';
return {
/**
*
* @param installments
* @param grandTotal
* @param precision
* @param currencyCode
* @returns {Array}
*/
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;
}
};
}
);
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
define(
[
'Magento_Checkout/js/model/url-builder',
'mage/storage'
],
function (urlBuilder, storage) {
'use strict';
return {
/**
* 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
* component or place the order (validateThreeDS2OrPlaceOrder)
* @param response
*/
processThreeDS2: function (data) {
var payload = {
"payload": JSON.stringify(data)
};
var serviceUrl = urlBuilder.createUrl('/adyen/threeDS2Process', {});
return storage.post(
serviceUrl,
JSON.stringify(payload),
true
);
}
};
}
);
......@@ -24,11 +24,19 @@
define(
[
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list'
'Magento_Checkout/js/model/payment/renderer-list',
'Adyen_Payment/js/model/adyen-payment-service',
'Adyen_Payment/js/model/adyen-configuration',
'Magento_Checkout/js/model/quote',
'Magento_Customer/js/model/customer'
],
function (
Component,
rendererList
rendererList,
adyenPaymentService,
adyenConfiguration,
quote,
customer
) {
'use strict';
rendererList.push(
......@@ -63,16 +71,13 @@ define(
);
/** Add view logic here if needed */
return Component.extend({
defaults: {
countryCode: ""
},
initialize: function () {
var self = this;
this._super();
// include checkout card component javascript
var checkoutCardComponentScriptTag = document.createElement('script');
checkoutCardComponentScriptTag.id = "AdyenCheckoutCardComponentScript";
checkoutCardComponentScriptTag.src = self.getCheckoutCardComponentSource();
checkoutCardComponentScriptTag.type = "text/javascript";
document.head.appendChild(checkoutCardComponentScriptTag);
this._super();
if (this.isGooglePayEnabled()) {
var googlepayscript = document.createElement('script');
......@@ -80,13 +85,59 @@ define(
googlepayscript.type = "text/javascript";
document.head.appendChild(googlepayscript);
}
if (customer.isLoggedIn()) {
self.setAdyenPaymentMethods();
}
quote.shippingAddress.subscribe(function() {
if (!!quote.shippingAddress().countryId && self.countryCode !== quote.shippingAddress().countryId) {
self.countryCode = quote.shippingAddress().countryId;
self.setAdyenPaymentMethods();
}
})
},
getCheckoutCardComponentSource: function () {
return window.checkoutConfig.payment.checkoutCardComponentSource;
setAdyenPaymentMethods: function() {
adyenPaymentService.retrieveAvailablePaymentMethods().done(function (response) {
var responseJson = JSON.parse(response);
var paymentMethodsResponse = responseJson.paymentMethodsResponse;
// TODO check if this is still required or if can be outsourced for the generic component, or checkout can create a ratepay component
/*if (!!window.checkoutConfig.payment.adyenHpp) {
if (JSON.stringify(paymentMethods).indexOf("ratepay") > -1) {
var ratePayId = window.checkoutConfig.payment.adyenHpp.ratePayId;
var dfValueRatePay = self.getRatePayDeviceIdentToken();
window.di = {
t: dfValueRatePay.replace(':', ''),
v: ratePayId,
l: 'Checkout'
};
// Load Ratepay script
var ratepayScriptTag = document.createElement('script');
ratepayScriptTag.src = "//d.ratepay.com/" + ratePayId + "/di.js";
ratepayScriptTag.type = "text/javascript";
document.body.appendChild(ratepayScriptTag);
}
}*/
// Initialises adyen checkout main component with default configuration
adyenPaymentService.initCheckoutComponent(
paymentMethodsResponse,
adyenConfiguration.getOriginKey(),
adyenConfiguration.getLocale(),
adyenConfiguration.getCheckoutEnvironment()
);
})
},
isGooglePayEnabled: function () {
return window.checkoutConfig.payment.adyenGooglePay.active;
},
getRatePayDeviceIdentToken: function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
}
});
}
);
\ No newline at end of file
);
......@@ -28,7 +28,6 @@ define(
'Magento_Payment/js/model/credit-card-validation/credit-card-data',
'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Checkout/js/model/quote',
'Adyen_Payment/js/model/installments',
'mage/url',
'Magento_Vault/js/view/payment/vault-enabler',
'Magento_Checkout/js/model/url-builder',
......@@ -36,10 +35,9 @@ define(
'Magento_Checkout/js/model/full-screen-loader',
'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',
'Magento_Checkout/js/model/error-processor',
'Adyen_Payment/js/model/adyen-payment-service'
'Adyen_Payment/js/model/adyen-payment-service',
'Adyen_Payment/js/model/adyen-configuration'
],
function (
$,
......@@ -49,7 +47,6 @@ define(
creditCardData,
additionalValidators,
quote,
installmentsHelper,
url,
VaultEnabler,
urlBuilder,
......@@ -57,10 +54,9 @@ define(
fullScreenLoader,
setPaymentMethodAction,
selectPaymentMethodAction,
threeDS2Utils,
threeds2,
errorProcessor,
adyenPaymentService
adyenPaymentService,
adyenConfiguration
) {
'use strict';
......@@ -72,10 +68,10 @@ define(
defaults: {
template: 'Adyen_Payment/payment/cc-form',
creditCardOwner: '',
storeCc: false,
installment: '',
creditCardDetailsValid: false
stateData: {},
checkoutComponent: {},
cardComponent: {}
},
/**
* @returns {exports.initialize}
......@@ -85,26 +81,14 @@ define(
this.vaultEnabler = new VaultEnabler();
this.vaultEnabler.setPaymentCode(this.getVaultCode());
this.vaultEnabler.isActivePaymentTokenEnabler(false);
// initialize adyen component for general use
this.checkout = new AdyenCheckout({
locale: this.getLocale()
});
this.checkoutComponent = adyenPaymentService.getCheckoutComponent();
return this;
},
initObservable: function () {
this._super()
.observe([
'creditCardType',
'creditCardOwner',
'creditCardNumber',
'securityCode',
'expiryMonth',
'expiryYear',
'installment',
'installments',
'creditCardDetailsValid',
'placeOrderAllowed'
]);
......@@ -112,92 +96,57 @@ define(
},
/**
* Returns true if card details can be stored
* The user is logged in and
* Billing agreement or vault is ebabled
*
* @returns {*|boolean}
*/
getEnableStoreDetails: function () {
return this.canCreateBillingAgreement() && !this.isVaultEnabled();
if (customer.isLoggedIn()) {
// TODO create new configuration to enable stored details without vault and billing agreement
// since we noew use the payment Methods response to fetch the stored payment methods
return this.canCreateBillingAgreement() || this.isVaultEnabled();
}
return false;
},
/**
* Renders the secure fields,
* creates the card component,
* sets up the callbacks for card components and
* set up the installments
* Renders checkout card component
*/
renderSecureFields: function () {
var self = this;
if (!self.getOriginKey()) {
renderCardComponent: function () {
if (!adyenConfiguration.getOriginKey()) {
return;
}
self.installments(0);
// installments
var allInstallments = self.getAllInstallments();
var cardNode = document.getElementById('cardContainer');
var self = this;
// installments configuration
var installmentsConfiguration = this.getAllInstallments();
// TODO get config from admin configuration
installmentsConfiguration = '[[0,2,3],[2,3,3]]'; // DUmmy data for testing
var placeOrderAllowed = self.placeOrderAllowed.bind(self);
function handleOnChange(state, component) {
if (!!state.isValid) {
self.stateData = state.data;
placeOrderAllowed(true);
} else {
placeOrderAllowed(false);
}
};
self.cardComponent = self.checkout.create('card', {
originKey: self.getOriginKey(),
environment: self.getCheckoutEnvironment(),
type: 'card',
// Extra configuration object for card payments
const configuration = {
hasHolderName: true,
holderNameRequired: true,
enableStoreDetails: self.getEnableStoreDetails(),
groupTypes: self.getAvailableCardTypeAltCodes(),
installments: installmentsConfiguration,
onChange: handleOnChange
};
onChange: function (state, component) {
if (!!state.isValid && !component.state.errors.encryptedSecurityCode) {
self.storeCc = !!state.data.storePaymentMethod;
self.creditCardNumber(state.data.paymentMethod.encryptedCardNumber);
self.expiryMonth(state.data.paymentMethod.encryptedExpiryMonth);
self.expiryYear(state.data.paymentMethod.encryptedExpiryYear);
self.securityCode(state.data.paymentMethod.encryptedSecurityCode);
self.creditCardOwner(state.data.paymentMethod.holderName);
self.creditCardDetailsValid(true);
self.placeOrderAllowed(true);
} else {
self.creditCardDetailsValid(false);
self.placeOrderAllowed(false);
}
},
onBrand: function (state) {
// Define the card type
// translate adyen card type to magento card type
var creditCardType = self.getCcCodeByAltCode(state.brand);
if (creditCardType) {
// If the credit card type is already set, check if it changed or not
if (!self.creditCardType() || self.creditCardType() && self.creditCardType() != creditCardType) {
var numberOfInstallments = [];
if (creditCardType in allInstallments) {
// get for the creditcard the installments
var installmentCreditcard = allInstallments[creditCardType];
var grandTotal = quote.totals().grand_total;
var precision = quote.getPriceFormat().precision;
var currencyCode = quote.totals().quote_currency_code;
numberOfInstallments = installmentsHelper.getInstallmentsWithPrices(installmentCreditcard, grandTotal, precision, currencyCode);
}
if (numberOfInstallments) {
self.installments(numberOfInstallments);
} else {
self.installments(0);
}
}
// for BCMC as this is not a core payment method inside magento use maestro as brand detection
if (creditCardType == "BCMC") {
self.creditCardType("MI");
} else {
self.creditCardType(creditCardType);
}
} else {
self.creditCardType("")
self.installments(0);
}
}
}).mount(cardNode);
// create and mount
this.cardComponent = this.checkoutComponent.create('card', configuration).mount('#cardContainer');
},
/**
* Rendering the 3DS2.0 components
......@@ -210,33 +159,28 @@ define(
* @param type
* @param token
*/
renderThreeDS2Component: function (type, token, orderId) {
renderThreeDS2Component: function (action, orderId) {
var self = this;
var threeDS2Node = document.getElementById('threeDS2Container');
if (type == "IdentifyShopper") {
self.threeDS2IdentifyComponent = self.checkout
.create('threeDS2DeviceFingerprint', {
fingerprintToken: token,
onComplete: function (result) {
self.threeDS2IdentifyComponent.unmount();
var request = result.data;
request.orderId = orderId;
threeds2.processThreeDS2(request).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON, orderId)
}).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
},
onError: function (error) {
console.log(JSON.stringify(error));
// Handle identify shopper action
if (action.type == 'threeDS2Fingerprint') {
var configuration = {
onAdditionalDetails: function (result) {
var request = result.data;
request.orderId = orderId;
adyenPaymentService.processThreeDS2(request).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON, orderId)
}).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
}
});
};
}
self.threeDS2IdentifyComponent.mount(threeDS2Node);
} else if (type == "ChallengeShopper") {
// Handle challenge shopper action
if (action.type == "threeDS2Challenge") {
fullScreenLoader.stopLoader();
var popupModal = $('#threeDS2Modal').modal({
......@@ -251,30 +195,25 @@ define(
popupModal.modal("openModal");
self.threeDS2ChallengeComponent = self.checkout
.create('threeDS2Challenge', {
challengeToken: token,
size: '05',
onComplete: function (result) {
self.threeDS2ChallengeComponent.unmount();
self.closeModal(popupModal);
fullScreenLoader.startLoader();
var request = result.data;
request.orderId = orderId;
threeds2.processThreeDS2(request).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON, orderId);
}).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
},
onError: function (error) {
console.log(JSON.stringify(error));
var configuration = {
size: '05',
onAdditionalDetails: function (result) {
self.closeModal(popupModal);
fullScreenLoader.startLoader();
var request = result.data;
request.orderId = orderId;
adyenPaymentService.processThreeDS2(request).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON, orderId);
}).fail(function (result) {
errorProcessor.process(result, self.messageContainer);
self.isPlaceOrderActionAllowed(true);
fullScreenLoader.stopLoader();
});
}
});
self.threeDS2ChallengeComponent.mount(threeDS2Node);
};
}
self.checkoutComponent.createFromAction(action, configuration).mount('#threeDS2Container');
},
/**
* This method is a workaround to close the modal in the right way and reconstruct the threeDS2Modal.
......@@ -296,27 +235,12 @@ define(
* @returns {{method: *}}
*/
getData: function () {
const browserInfo = threeDS2Utils.getBrowserInfo();
var data = {
'method': this.item.method,
additional_data: {
'guestEmail': quote.guestEmail,
'cc_type': this.creditCardType(),
'number': this.creditCardNumber(),
'cvc': this.securityCode(),
'expiryMonth': this.expiryMonth(),
'expiryYear': this.expiryYear(),
'holderName': this.creditCardOwner(),
'store_cc': this.storeCc,
'number_of_installments': this.installment(),
'java_enabled': browserInfo.javaEnabled,
'screen_color_depth': browserInfo.colorDepth,
'screen_width': browserInfo.screenWidth,
'screen_height': browserInfo.screenHeight,
'timezone_offset': browserInfo.timeZoneOffset,
'language': browserInfo.language,
'combo_card_type': this.comboCardOption()
'state_data': JSON.stringify(this.stateData),
'combo_card_type': this.comboCardOption(),
'channel': 'Web' //TODO pass channel from frontend
}
};
this.vaultEnabler.visitAdditionalData(data);
......@@ -375,9 +299,12 @@ define(
var self = this;
var response = JSON.parse(responseJSON);
if (!!response.threeDS2) {
if (!!response.type && (
response.type == "threeDS2Fingerprint" ||
response.type == "threeDS2Challenge"
)) {
// render component
self.renderThreeDS2Component(response.type, response.token, orderId);
self.renderThreeDS2Component(response, orderId);
} else {
window.location.replace(url.build(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl
......@@ -402,28 +329,6 @@ define(
return true;
},
/**
* Validates if the typed in card holder is valid
* - length validation, can not be empty
*
* @returns {boolean}
*/
isCardOwnerValid: function () {
if (this.creditCardOwner().length == 0) {
return false;
}
return true;
},
/**
* The card component send the card details validity in a callback which is saved in the
* creditCardDetailsValid observable
*
* @returns {*}
*/
isCreditCardDetailsValid: function () {
return this.creditCardDetailsValid();
},
/**
* Translates the card type alt code (used in Adyen) to card type code (used in Magento) if it's available
*
......@@ -457,13 +362,7 @@ define(
return window.checkoutConfig.payment.adyenCc.methodCode;
},
getOriginKey: function () {
return window.checkoutConfig.payment.adyenCc.originKey;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyenCc.checkoutEnvironment;
},
getLocale: function () {
return window.checkoutConfig.payment.adyenCc.locale;
return adyenConfiguration.getOriginKey;
},
isActive: function () {
return true;
......@@ -481,23 +380,44 @@ define(
return false;
},
//TODO create configuration for this on admin
isShowLegend: function () {
return true;
},
//TODO create a configuration for information on admin
getLegend: function () {
return '';
},
showLogo: function () {
return window.checkoutConfig.payment.adyen.showLogo;
return adyenConfiguration.showLogo;
},
/**
*
* @param type
* @returns {*}
*/
getIcons: function (type) {
return window.checkoutConfig.payment.adyenCc.icons.hasOwnProperty(type)
? window.checkoutConfig.payment.adyenCc.icons[type]
: false
},
/**
*
* @returns {any}
*/
hasInstallments: function () {
return this.comboCardOption() === 'credit' && window.checkoutConfig.payment.adyenCc.hasInstallments;
},
/**
*
* @returns {*}
*/
getAllInstallments: function () {
return window.checkoutConfig.payment.adyenCc.installments;
},
/**
* @returns {*|boolean}
*/
areComboCardsEnabled: function () {
if (quote.billingAddress() === null) {
return false;
......@@ -517,6 +437,9 @@ define(
setValidateHandler: function (handler) {
this.validateHandler = handler;
},
/**
* @returns {exports}
*/
context: function () {
return this;
},
......
......@@ -29,21 +29,38 @@ define(
'Magento_Checkout/js/checkout-data',
'Magento_Checkout/js/model/payment/additional-validators',
'mage/storage',
'Magento_Checkout/js/model/url-builder',
'Adyen_Payment/js/model/adyen-payment-service',
'Magento_Checkout/js/model/url-builder',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Checkout/js/action/place-order',
'uiLayout',
'Magento_Ui/js/model/messages'
'Magento_Ui/js/model/messages',
'Adyen_Payment/js/bundle',
'Adyen_Payment/js/model/adyen-configuration'
],
function (ko, $, Component, selectPaymentMethodAction, quote, checkoutData, additionalValidators, storage, urlBuilder, adyenPaymentService, customer, fullScreenLoader, placeOrderAction, layout, Messages) {
function (ko,
$,
Component,
selectPaymentMethodAction,
quote,
checkoutData,
additionalValidators,
storage,
adyenPaymentService,
urlBuilder,
customer,
fullScreenLoader,
placeOrderAction,
layout,
Messages,
AdyenComponent,
adyenConfiguration) {
'use strict';
var brandCode = ko.observable(null);
var paymentMethod = ko.observable(null);
var messageComponents;
var shippingAddressCountryCode = quote.shippingAddress().countryId;
var unsupportedPaymentMethods = ['scheme', 'boleto', 'bcmc_mobile_QR', 'wechatpay', /^bcmc$/, "applepay", "paywithgoogle"];
var unsupportedPaymentMethods = ['scheme', 'boleto', 'bcmc_mobile_QR', 'wechatpay', /^bcmc$/, "applepay", "paywithgoogle", "paypal"];
/**
* Shareble adyen checkout component
* @type {AdyenCheckout}
......@@ -54,21 +71,14 @@ define(
self: this,
defaults: {
template: 'Adyen_Payment/payment/hpp-form',
brandCode: ''
brandCode: '',
stateData: {}
},
initObservable: function () {
this._super()
.observe([
'brandCode',
'issuer',
'gender',
'dob',
'telephone',
'ownerName',
'ibanNumber',
'ssn',
'bankAccountNumber',
'bankLocationId'
'paymentListObservable'
]);
return this;
}, initialize: function () {
......@@ -76,79 +86,55 @@ define(
var self = this;
this._super();
fullScreenLoader.startLoader();
var paymentMethodsObservable = adyenPaymentService.getPaymentMethodsObservable();
/**
* Create sherable checkout component
* @type {AdyenCheckout}
*/
self.checkoutComponent = new AdyenCheckout({
locale: self.getLocale()
});
// reset variable:
adyenPaymentService.setPaymentMethods();
self.checkoutComponent = adyenPaymentService.getCheckoutComponent();
self.setAdyenHppPaymentMethods();
adyenPaymentService.retrieveAvailablePaymentMethods(function () {
var paymentMethods = adyenPaymentService.getAvailablePaymentMethods();
if (JSON.stringify(paymentMethods).indexOf("ratepay") > -1) {
var ratePayId = window.checkoutConfig.payment.adyenHpp.ratePayId;
var dfValueRatePay = self.getRatePayDeviceIdentToken();
window.di = {
t: dfValueRatePay.replace(':', ''),
v: ratePayId,
l: 'Checkout'
};
// Load Ratepay script
var ratepayScriptTag = document.createElement('script');
ratepayScriptTag.src = "//d.ratepay.com/" + ratePayId + "/di.js";
ratepayScriptTag.type = "text/javascript";
document.body.appendChild(ratepayScriptTag);
}
// create component needs to be in initialize method
var messageComponents = {};
_.map(paymentMethods, function (value) {
var messageContainer = new Messages();
var name = 'messages-' + self.getBrandCodeFromPaymentMethod(value);
var messagesComponent = {
parent: self.name,
name: 'messages-' + self.getBrandCodeFromPaymentMethod(value),
displayArea: 'messages-' + self.getBrandCodeFromPaymentMethod(value),
component: 'Magento_Ui/js/view/messages',
config: {
messageContainer: messageContainer
}
};
layout([messagesComponent]);
messageComponents[name] = messageContainer;
});
self.messageComponents = messageComponents;
fullScreenLoader.stopLoader();
paymentMethodsObservable.subscribe(function() {
self.checkoutComponent = adyenPaymentService.getCheckoutComponent();
self.setAdyenHppPaymentMethods();
});
},
getAdyenHppPaymentMethods: function () {
return this.paymentListObservable;
},
setAdyenHppPaymentMethods: function () {
var self = this;
var currentShippingAddressCountryCode = quote.shippingAddress().countryId;
// retrieve new payment methods if country code changed
if (shippingAddressCountryCode != currentShippingAddressCountryCode) {
fullScreenLoader.startLoader();
adyenPaymentService.retrieveAvailablePaymentMethods();
shippingAddressCountryCode = currentShippingAddressCountryCode;
fullScreenLoader.stopLoader();
}
var paymentMethods = adyenPaymentService.getAvailablePaymentMethods();
fullScreenLoader.startLoader();
var paymentMethods = self.checkoutComponent.paymentMethodsResponse.paymentMethods;
// create component needs to be in initialize method
var messageComponents = {};
_.map(paymentMethods, function (value) {
var messageContainer = new Messages();
var name = 'messages-' + self.getBrandCodeFromPaymentMethod(value);
var messagesComponent = {
parent: self.name,
name: 'messages-' + self.getBrandCodeFromPaymentMethod(value),
displayArea: 'messages-' + self.getBrandCodeFromPaymentMethod(value),
component: 'Magento_Ui/js/view/messages',
config: {
messageContainer: messageContainer
}
};
layout([messagesComponent]);
messageComponents[name] = messageContainer;
});
var paymentList = _.reduce(paymentMethods, function (accumulator, value) {
self.messageComponents = messageComponents;
if (!self.isPaymentMethodSupported(value.type)) {
// Iterate through the payment methods and render them
var paymentList = _.reduce(paymentMethods, function (accumulator, paymentMethod) {
if (!self.isPaymentMethodSupported(paymentMethod.type)) {
return accumulator;
}
......@@ -159,11 +145,11 @@ define(
* @returns {*}
*/
result.getBrandCode = function () {
return self.getBrandCodeFromPaymentMethod(value);
return self.getBrandCodeFromPaymentMethod(paymentMethod);
};
result.value = result.getBrandCode();
result.name = value;
result.brandCode = result.getBrandCode();
result.name = paymentMethod.name;
result.method = self.item.method;
/**
* Observable to enable and disable place order buttons for payment methods
......@@ -195,333 +181,72 @@ define(
result.afterPlaceOrder = function () {
return self.afterPlaceOrder();
};
/**
* Checks if payment method is open invoice
* @returns {*|isPaymentMethodOpenInvoiceMethod}
*/
result.isPaymentMethodOpenInvoiceMethod = function () {
return value.isPaymentMethodOpenInvoiceMethod;
};
/**
* Checks if payment method is open invoice but not in the list below
* [klarna, afterpay]
* @returns {boolean}
*/
result.isPaymentMethodOtherOpenInvoiceMethod = function () {
if (
!result.isPaymentMethodAfterPay() &&
!result.isPaymentMethodKlarna() &&
!result.isPaymentMethodAfterPayTouch() &&
value.isPaymentMethodOpenInvoiceMethod
) {
return true;
}
return false;
};
/**
* Checks if payment method is klarna
* @returns {boolean}
*/
result.isPaymentMethodKlarna = function () {
if (result.getBrandCode() === "klarna") {
return true;
}
return false;
};
/**
* Checks if payment method is after pay
* @returns {boolean}
*/
result.isPaymentMethodAfterPay = function () {
if (result.getBrandCode() === "afterpay_default") {
return true;
}
return false;
};
/**
* Checks if payment method is after pay touch
* @returns {boolean}
*/
result.isPaymentMethodAfterPayTouch = function () {
if (result.getBrandCode() === "afterpaytouch") {
return true;
}
return false;
};
/**
* Get personal number (SSN) length based on the buyer's country
* @returns {number}
*/
result.getSsnLength = function () {
if (quote.billingAddress().countryId == "NO") {
//14 digits for Norway ÅÅÅÅMMDD-XXXXX
return 14;
} else {
//13 digits for other Nordic countries ÅÅÅÅMMDD-XXXX
return 13;
}
};
/**
* Get max length for the Bank account number
*/
result.getBankAccountNumberMaxLength = function () {
return 17;
};
/**
* Finds the issuer property in the payment method's response and if available returns it's index
* @returns
*/
result.findIssuersProperty = function () {
var issuerKey = false;
if (typeof value.details !== 'undefined') {
$.each(value.details, function (key, detail) {
if (typeof detail.items !== 'undefined' && detail.key == 'issuer') {
issuerKey = key;
}
});
}
return issuerKey;
}
/**
* Checks if the payment method has issuers property available
* @returns {boolean}
*/
result.hasIssuersProperty = function () {
if (result.findIssuersProperty() !== false) {
return true;
}
return false;
};
/**
* Checks if the payment method has issuer(s) available
* @returns {boolean}
*/
result.hasIssuersAvailable = function () {
if (result.hasIssuersProperty() && value.details[result.findIssuersProperty()].items.length > 0) {
return true;
}
return false;
};
/**
* Returns the issuers for a payment method
* @returns {*}
*/
result.getIssuers = function () {
if (result.hasIssuersAvailable()) {
return value.details[result.findIssuersProperty()].items;
}
return [];
};
/**
* Checks if payment method is iDeal
* @returns {boolean}
*/
result.isIdeal = function () {
if (result.getBrandCode().indexOf("ideal") >= 0) {
return true;
}
return false;
};
/**
* Checks if payment method is ACH
* @returns {boolean}
*/
result.isAch = function () {
if (result.getBrandCode().indexOf("ach") == 0) {
return true;
}
return false;
};
/**
* Checks if payment method is sepa direct debit
*/
result.isSepaDirectDebit = function () {
if (result.getBrandCode().indexOf("sepadirectdebit") >= 0) {
return true;
}
return false;
};
/**
* Renders the secure fields,
* creates the ideal component,
* sets up the callbacks for ideal components and
*/
result.renderIdealComponent = function () {
result.renderCheckoutComponent = function () {
result.isPlaceOrderAllowed(false);
var idealNode = document.getElementById('iDealContainer');
var showPayButton = false;
const showPayButtonPaymentMethods = [
'paypal'
];
var ideal = self.checkoutComponent.create('ideal', {
items: result.getIssuers(),
onChange: function (state) {
if (!!state.isValid) {
result.issuer(state.data.paymentMethod.issuer);
result.isPlaceOrderAllowed(true);
} else {
result.isPlaceOrderAllowed(false);
}
}
});
ideal.mount(idealNode);
};
/**
* Creates the sepa direct debit component,
* sets up the callbacks for sepa components
*/
result.renderSepaDirectDebitComponent = function () {
result.isPlaceOrderAllowed(false);
var sepaDirectDebitNode = document.getElementById('sepaDirectDebitContainer');
var sepaDirectDebit = self.checkoutComponent.create('sepadirectdebit', {
countryCode: self.getLocale(),
onChange: function (state) {
if (!!state.isValid) {
result.ownerName(state.data.paymentMethod["sepa.ownerName"]);
result.ibanNumber(state.data.paymentMethod["sepa.ibanNumber"]);
result.isPlaceOrderAllowed(true);
} else {
result.isPlaceOrderAllowed(false);
}
}
});
sepaDirectDebit.mount(sepaDirectDebitNode);
};
/**
* Creates the klarna component,
* sets up the callbacks for klarna components
*/
result.renderKlarnaComponent = function () {
if (showPayButtonPaymentMethods.includes(paymentMethod.type)) {
showPayButton = true;
}
/* The new Klarna integration doesn't return details and the component does not handle it */
if (!value.details) {
// If the details are empty and the pay button does not needs to be rendered by the component
// simply skip rendering the adyen checkout component
if (!paymentMethod.details && !showPayButton) {
result.isPlaceOrderAllowed(true);
return;
}
var klarnaNode = document.getElementById('klarnaContainer');
var klarna = self.checkoutComponent.create('klarna', {
countryCode: self.getLocale(),
details: self.filterOutOpenInvoiceComponentDetails(value.details),
visibility: {
personalDetails: "editable"
},
onChange: function (state) {
if (!!state.isValid) {
result.dob(state.data.paymentMethod.personalDetails.dateOfBirth);
result.telephone(state.data.paymentMethod.personalDetails.telephoneNumber);
result.gender(state.data.paymentMethod.personalDetails.gender);
result.isPlaceOrderAllowed(true);
} else {
result.isPlaceOrderAllowed(false);
/*Use the storedPaymentMethod object and the custom onChange function as the configuration object together*/
var configuration = {
showPayButton: showPayButton,
data: {
billingAddress: {
city: quote.shippingAddress().city,
country: quote.shippingAddress().countryId,
houseNumberOrName: '',
postalCode: quote.shippingAddress().postcode,
street: quote.shippingAddress().street.join(" ")
}
}
}).mount(klarnaNode);
};
/**
* Creates the afterpay component,
* sets up the callbacks for klarna components
*/
result.renderAfterPayComponent = function () {
var afterPay = self.checkoutComponent.create('afterpay', {
countryCode: self.getLocale(),
details: self.filterOutOpenInvoiceComponentDetails(value.details),
visibility: {
personalDetails: "editable"
},
onChange: function (state) {
if (!!state.isValid) {
result.dob(state.data.paymentMethod.personalDetails.dateOfBirth);
result.telephone(state.data.paymentMethod.personalDetails.telephoneNumber);
result.gender(state.data.paymentMethod.personalDetails.gender);
result.stateData = state.data;
result.isPlaceOrderAllowed(true);
} else {
result.stateData = {};
result.isPlaceOrderAllowed(false);
}
}
}).mount(document.getElementById('afterPayContainer'));
};
};
if (result.hasIssuersProperty()) {
if (!result.hasIssuersAvailable()) {
return false;
try {
self.checkoutComponent.create(result.getBrandCode(), configuration).mount('#adyen-alternative-payment-container-' + result.getBrandCode());
} catch (err) {
// The component does not exist yet
}
};
result.issuerIds = result.getIssuers();
result.issuer = ko.observable(null);
} else if (value.isPaymentMethodOpenInvoiceMethod) {
result.telephone = ko.observable(quote.shippingAddress().telephone);
result.gender = ko.observable(window.checkoutConfig.payment.adyenHpp.gender);
result.dob = ko.observable(window.checkoutConfig.payment.adyenHpp.dob);
result.datepickerValue = ko.observable(); // needed ??
result.ssn = ko.observable();
result.getRatePayDeviceIdentToken = function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
};
result.showSsn = function () {
if (result.getBrandCode().indexOf("klarna") >= 0) {
var ba = quote.billingAddress();
if (ba != null) {
var nordicCountriesList = window.checkoutConfig.payment.adyenHpp.nordicCountries;
if (nordicCountriesList.indexOf(ba.countryId) >= 0) {
return true;
}
}
}
return false;
};
} else if (result.isSepaDirectDebit()) {
result.ownerName = ko.observable(null);
result.ibanNumber = ko.observable(null);
} else if (result.isAch()) {
result.ownerName = ko.observable(null);
result.bankAccountNumber = ko.observable(null);
result.bankLocationId = ko.observable(null);
}
result.getRatePayDeviceIdentToken = function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
};
accumulator.push(result);
return accumulator;
}, []);
return paymentList;
},
/**
* Some payment methods we do not want to render as it requires extra implementation
* or is already implemented in a separate payment method.
* Using a match as we want to prevent to render all Boleto and most of the WeChat types
* @param paymentMethod
* @returns {boolean}
*/
isPaymentMethodSupported: function (paymentMethod) {
if (paymentMethod == 'wechatpayWeb') {
return true;
}
for (var i = 0; i < unsupportedPaymentMethods.length; i++) {
var match = paymentMethod.match(unsupportedPaymentMethods[i]);
if (match) {
return false;
}
}
return true;
self.paymentListObservable(paymentList);
fullScreenLoader.stopLoader();
},
// TODO prefill gender in components where it is available
getGenderTypes: function () {
return _.map(window.checkoutConfig.payment.adyenHpp.genderTypes, function (value, key) {
return {
......@@ -539,25 +264,11 @@ define(
data.method = self.method;
var additionalData = {};
additionalData.brand_code = self.value;
if (self.hasIssuersAvailable()) {
additionalData.issuer_id = this.issuer();
} else if (self.isPaymentMethodOpenInvoiceMethod()) {
additionalData.gender = this.gender();
additionalData.dob = this.dob();
additionalData.telephone = this.telephone();
additionalData.ssn = this.ssn();
if (brandCode() == "ratepay") {
additionalData.df_value = this.getRatePayDeviceIdentToken();
}
} else if (self.isSepaDirectDebit()) {
additionalData.ownerName = this.ownerName();
additionalData.ibanNumber = this.ibanNumber();
} else if (self.isAch()) {
additionalData.bankAccountOwnerName = this.ownerName();
additionalData.bankAccountNumber = this.bankAccountNumber();
additionalData.bankLocationId = this.bankLocationId();
additionalData.brand_code = self.brandCode;
additionalData.state_data = JSON.stringify(self.stateData);
if (brandCode() == "ratepay") {
additionalData.df_value = this.getRatePayDeviceIdentToken();
}
data.additional_data = additionalData;
......@@ -566,26 +277,16 @@ define(
return false;
},
selectPaymentMethodBrandCode: function () {
var self = this;
// set payment method to adyen_hpp
var data = {
"method": self.method,
"po_number": null,
"additional_data": {
brand_code: self.value
}
};
// set the brandCode
brandCode(self.value);
// set payment method
paymentMethod(self.method);
// DEFAULT FUNCTIONS
validate: function (brandCode) {
var form = '#payment_form_' + this.getCode() + '_' + brandCode;
var validate = $(form).validation() && $(form).validation('isValid');
selectPaymentMethodAction(data);
checkoutData.setSelectedPaymentMethod(self.method);
if (!validate) {
return false;
}
return true;
},
......@@ -628,8 +329,48 @@ define(
}
)
},
isBrandCodeChecked: ko.computed(function () {
/**
*
* @returns {boolean}
*/
selectPaymentMethodBrandCode: function () {
var self = this;
// set payment method to adyen_hpp
var data = {
"method": self.method,
"po_number": null,
"additional_data": {
brand_code: self.brandCode
}
};
// set the brandCode
brandCode(self.brandCode);
// set payment method
paymentMethod(self.method);
selectPaymentMethodAction(data);
checkoutData.setSelectedPaymentMethod(self.method);
return true;
},
// CONFIGURATIONS
isIconEnabled: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
getRatePayDeviceIdentToken: function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
},
/**
*
*/
isBrandCodeChecked: ko.computed(function () {
if (!quote.paymentMethod()) {
return null;
}
......@@ -637,19 +378,27 @@ define(
if (quote.paymentMethod().method == paymentMethod()) {
return brandCode();
}
return null;
}),
isIconEnabled: function () {
return window.checkoutConfig.payment.adyen.showLogo;
},
validate: function (brandCode) {
var form = '#payment_form_' + this.getCode() + '_' + brandCode;
var validate = $(form).validation() && $(form).validation('isValid');
if (!validate) {
return false;
/**
* Some payment methods we do not want to render as it requires extra implementation
* or is already implemented in a separate payment method.
* Using a match as we want to prevent to render all Boleto and most of the WeChat types
* @param paymentMethod
* @returns {boolean}
*/
isPaymentMethodSupported: function (paymentMethod) {
if (paymentMethod == 'wechatpayWeb') {
return true;
}
for (var i = 0; i < unsupportedPaymentMethods.length; i++) {
var match = paymentMethod.match(unsupportedPaymentMethods[i]);
if (match) {
return false;
}
}
return true;
},
/**
......@@ -663,52 +412,6 @@ define(
}
return '';
},
getRatePayDeviceIdentToken: function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
},
getLocale: function () {
return window.checkoutConfig.payment.adyenHpp.locale;
},
/**
* In the open invoice components we need to validate only the personal details and only the
* dateOfBirth, telephoneNumber and gender if it's set in the admin
* @param details
* @returns {Array}
*/
filterOutOpenInvoiceComponentDetails: function (details) {
var self = this;
var filteredDetails = _.map(details, function (parentDetail) {
if (parentDetail.key == "personalDetails") {
var detailObject = _.map(parentDetail.details, function (detail) {
if (detail.key == 'dateOfBirth' ||
detail.key == 'telephoneNumber' ||
detail.key == 'gender') {
return detail;
}
});
if (!!detailObject) {
return {
"key": parentDetail.key,
"type": parentDetail.type,
"details": self.filterUndefinedItemsInArray(detailObject)
};
}
}
});
return self.filterUndefinedItemsInArray(filteredDetails);
},
/**
* Helper function to filter out the undefined items from an array
* @param arr
* @returns {*}
*/
filterUndefinedItemsInArray: function (arr) {
return arr.filter(function (item) {
return typeof item !== 'undefined';
});
}
});
}
......
......@@ -33,15 +33,15 @@ define(
'uiLayout',
'Magento_Ui/js/model/messages',
'mage/url',
'Adyen_Payment/js/threeds2-js-utils',
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Paypal/js/action/set-payment-method',
'Magento_Checkout/js/model/url-builder',
'mage/storage',
'Magento_Checkout/js/action/place-order',
'Adyen_Payment/js/model/threeds2',
'Magento_Checkout/js/model/error-processor',
'Adyen_Payment/js/model/adyen-payment-service'
'Adyen_Payment/js/model/adyen-payment-service',
'Adyen_Payment/js/bundle',
'Adyen_Payment/js/model/adyen-configuration'
],
function (
ko,
......@@ -56,17 +56,16 @@ define(
layout,
Messages,
url,
threeDS2Utils,
fullScreenLoader,
setPaymentMethodAction,
urlBuilder,
storage,
placeOrderAction,
threeds2,
errorProcessor,
adyenPaymentService
adyenPaymentService,
adyenComponentBundle,
adyenConfiguration
) {
'use strict';
var messageComponents;
......@@ -74,7 +73,6 @@ define(
var recurringDetailReference = ko.observable(null);
var variant = ko.observable(null);
var paymentMethod = ko.observable(null);
var numberOfInstallments = ko.observable(null);
var isValid = ko.observable(false);
return Component.extend({
......@@ -83,16 +81,15 @@ define(
template: 'Adyen_Payment/payment/oneclick-form',
recurringDetailReference: '',
variant: '',
numberOfInstallments: ''
checkoutComponent: {},
storedPayments: []
},
initObservable: function () {
this._super()
.observe([
'recurringDetailReference',
'creditCardType',
'encryptedCreditCardVerificationNumber',
'variant',
'numberOfInstallments'
'variant'
]);
return this;
},
......@@ -100,17 +97,20 @@ define(
var self = this;
this._super();
this.checkoutComponent = adyenPaymentService.getCheckoutComponent();
this.storedPayments = this.checkoutComponent.paymentMethodsResponse.storedPaymentMethods;
// create component needs to be in initialize method
var messageComponents = {};
_.map(window.checkoutConfig.payment.adyenOneclick.billingAgreements, function (value) {
_.map(this.storedPayments, function (storedPayment) {
var messageContainer = new Messages();
var name = 'messages-' + value.reference_id;
var name = 'messages-' + storedPayment.id;
var messagesComponent = {
parent: self.name,
name: 'messages-' + value.reference_id,
name: 'messages-' + storedPayment.id,
// name: self.name + '.messages',
displayArea: 'messages-' + value.reference_id,
displayArea: 'messages-' + storedPayment.id,
component: 'Magento_Ui/js/view/messages',
config: {
messageContainer: messageContainer
......@@ -128,48 +128,12 @@ define(
*
* @returns {Array}
*/
getAdyenBillingAgreements: function () {
getAdyenStoredPayments: function () {
var self = this;
// shareable adyen checkout component
var checkout = new AdyenCheckout({
locale: self.getLocale(),
originKey: self.getOriginKey(),
environment: self.getCheckoutEnvironment(),
risk: {
enabled: false
}
});
// convert to list so you can iterate
var paymentList = _.map(window.checkoutConfig.payment.adyenOneclick.billingAgreements, function (value) {
var creditCardExpMonth, creditCardExpYear = false;
if (value.agreement_data.card) {
creditCardExpMonth = value.agreement_data.card.expiryMonth;
creditCardExpYear = value.agreement_data.card.expiryYear;
}
// pre-define installments if they are set
var i, installments = [];
var grandTotal = quote.totals().grand_total;
var dividedString = "";
var dividedAmount = 0;
if (value.number_of_installments) {
for (i = 0; i < value.number_of_installments.length; i++) {
dividedAmount = (grandTotal / value.number_of_installments[i]).toFixed(quote.getPriceFormat().precision);
dividedString = value.number_of_installments[i] + " x " + dividedAmount + " " + quote.totals().quote_currency_code;
installments.push({
key: [dividedString],
value: value.number_of_installments[i]
});
}
}
var messageContainer = self.messageComponents['messages-' + value.reference_id];
var paymentList = _.map(this.storedPayments, function (storedPayment) {
var messageContainer = self.messageComponents['messages-' + storedPayment.id];
// for recurring enable the placeOrder button at all times
var placeOrderAllowed = true;
......@@ -180,21 +144,18 @@ define(
isValid(true);
}
var agreementLabel = storedPayment.name + ', ' + storedPayment.holderName + ', **** ' + storedPayment.lastFour;
return {
'label': value.agreement_label,
'value': value.reference_id,
'agreement_data': value.agreement_data,
'logo': value.logo,
'label': agreementLabel,
'value': storedPayment.storedPaymentMethodId,
'brand': storedPayment.brand,
'logo': {},
'installment': '',
'number_of_installments': value.number_of_installments,
'method': self.item.method,
'encryptedCreditCardVerificationNumber': '',
'creditCardExpMonth': ko.observable(creditCardExpMonth),
'creditCardExpYear': ko.observable(creditCardExpYear),
'getInstallments': ko.observableArray(installments),
'placeOrderAllowed': ko.observable(placeOrderAllowed),
checkoutComponent: self.checkoutComponent,
isButtonActive: function () {
return self.isActive() && this.getCode() == self.isChecked() && self.isBillingAgreementChecked() && this.placeOrderAllowed() && self.isPlaceOrderActionAllowed();
},
......@@ -213,13 +174,6 @@ define(
if (event) {
event.preventDefault();
}
// only use installments for cards
if (self.agreement_data.card) {
if (self.hasVerification()) {
var options = {enableValidations: false};
}
numberOfInstallments(self.installment);
}
if (this.validate() && additionalValidators.validate()) {
fullScreenLoader.startLoader();
......@@ -245,67 +199,37 @@ define(
},
/**
* Renders the secure CVC field,
* creates the card component,
* sets up the callbacks for card components
* Renders the stored payment component,
*/
renderSecureCVC: function () {
renderStoredPaymentComponent: function () {
var self = this;
if (!self.getOriginKey()) {
if (!adyenConfiguration.getOriginKey()) {
return;
}
var oneClickCardNode = document.getElementById('cvcContainer-' + self.value);
// this should be fixed in new version of checkout card component
var hideCVC = false;
if (this.hasVerification()) {
if (self.agreement_data.variant == "maestro") {
// for maestro cvc is optional
self.placeOrderAllowed(true);
}
} else {
if (!this.hasVerification()) {
hideCVC = true;
}
var oneClickCard = checkout
.create('card', {
type: self.agreement_data.variant,
hideCVC: hideCVC,
details: self.getOneclickDetails(),
storedDetails: {
"card": {
"expiryMonth": self.agreement_data.card.expiryMonth,
"expiryYear": self.agreement_data.card.expiryYear,
"holderName": self.agreement_data.card.holderName,
"number": self.agreement_data.card.number
}
},
onChange: function (state, component) {
if (state.isValid) {
self.placeOrderAllowed(true);
isValid(true);
if (typeof state.data !== 'undefined' &&
typeof state.data.paymentMethod !== 'undefined' &&
typeof state.data.paymentMethod.encryptedSecurityCode !== 'undefined'
) {
self.encryptedCreditCardVerificationNumber = state.data.paymentMethod.encryptedSecurityCode;
}
} else {
self.encryptedCreditCardVerificationNumber = '';
if (self.agreement_data.variant != "maestro") {
self.placeOrderAllowed(false);
isValid(false);
}
}
/*Use the storedPaymentMethod object and the custom onChange function as the configuration object together*/
var configuration = Object.assign(storedPayment, {
hideCVC: hideCVC,
'onChange': function (state) {
if (!!state.isValid) {
self.stateData = state.data;
self.placeOrderAllowed = true;
} else {
self.placeOrderAllowed = false;
self.stateData = {};
}
})
.mount(oneClickCardNode);
}
});
window.adyencheckout = oneClickCard;
self.checkoutComponent
.create(storedPayment.type, configuration)
.mount('#storedPaymentContainer-' + self.value);
},
/**
* Based on the response we can start a 3DS2 validation or place the order
......@@ -344,7 +268,7 @@ define(
onComplete: function (result) {
var request = result.data;
request.orderId = orderId;
threeds2.processThreeDS2(request).done(function (responseJSON) {
adyenPaymentService.processThreeDS2(request).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON, orderId)
}).fail(function (result) {
errorProcessor.process(result, self.getMessageContainer());
......@@ -380,7 +304,7 @@ define(
fullScreenLoader.startLoader();
var request = result.data;
request.orderId = orderId;
threeds2.processThreeDS2(request).done(function (responseJSON) {
adyenPaymentService.processThreeDS2(request).done(function (responseJSON) {
self.validateThreeDS2OrPlaceOrder(responseJSON, orderId)
}).fail(function (result) {
errorProcessor.process(result, self.getMessageContainer());
......@@ -396,50 +320,18 @@ define(
self.threeDS2Component.mount(threeDS2Node);
},
/**
* We use the billingAgreements to save the oneClick stored payments but we don't store the
* details object that we get from the paymentMethods call. This function is a fix for BCMC.
* When we render the stored payments dynamically from the paymentMethods call response it
* should be removed
* @returns {*}
*/
getOneclickDetails: function () {
var self = this;
if (self.agreement_data.variant === 'bcmc') {
return [];
} else {
return [
{
"key": "cardDetails.cvc",
"type": "cvc"
}
];
}
},
/**
* Builds the payment details part of the payment information reqeust
*
* @returns {{method: *, additional_data: {variant: *, recurring_detail_reference: *, number_of_installments: *, cvc: (string|*), expiryMonth: *, expiryYear: *}}}
* @returns {{additional_data: {state_data: string}, method: *}}
*/
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,
java_enabled: browserInfo.javaEnabled,
screen_color_depth: browserInfo.colorDepth,
screen_width: browserInfo.screenWidth,
screen_height: browserInfo.screenHeight,
timezone_offset: browserInfo.timeZoneOffset,
language: browserInfo.language
'state_data': JSON.stringify(this.stateData),
}
};
},
......@@ -467,13 +359,13 @@ define(
return self.hasVerification()
},
getMessageName: function () {
return 'messages-' + value.reference_id;
return 'messages-' + storedPayment.id;
},
getMessageContainer: function () {
return messageContainer;
},
getOriginKey: function () {
return self.getOriginKey();
return adyenConfiguration.getOriginKey();
},
isPlaceOrderActionAllowed: function () {
return self.isPlaceOrderActionAllowed(); // needed for placeOrder method
......@@ -510,7 +402,7 @@ define(
// set the brandCode
recurringDetailReference(self.value);
variant(self.agreement_data.variant);
variant(self.brand);
// set payment method
paymentMethod(self.method);
......@@ -554,24 +446,17 @@ define(
context: function () {
return this;
},
canCreateBillingAgreement: function () {
return window.checkoutConfig.payment.adyenCc.canCreateBillingAgreement;
},
//TODO create configuration for this on admin
isShowLegend: function () {
return true;
},
//TODO create a configuration for information on admin
getLegend: function () {
return '';
},
hasVerification: function () {
return window.checkoutConfig.payment.adyenOneclick.hasCustomerInteraction;
},
getLocale: function () {
return window.checkoutConfig.payment.adyenOneclick.locale;
},
getOriginKey: function () {
return window.checkoutConfig.payment.adyenOneclick.originKey;
},
getCheckoutEnvironment: function () {
return window.checkoutConfig.payment.adyenOneclick.checkoutEnvironment;
}
});
}
);
......@@ -92,7 +92,7 @@
<!-- /ko -->
<div class="field number cardContainerField">
<div class="checkout-component-dock" afterRender="renderSecureFields()" data-bind="attr: { id: 'cardContainer'}"></div>
<div class="checkout-component-dock" afterRender="renderCardComponent()" data-bind="attr: { id: 'cardContainer'}"></div>
</div>
<div id="threeDS2Wrapper">
......@@ -101,34 +101,6 @@
</div>
</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 -->
<!-- ko if: (isVaultEnabled())-->
<div class="field choice">
<input type="checkbox"
......
......@@ -23,24 +23,24 @@
-->
<!-- ko foreach: getAdyenHppPaymentMethods() -->
<div class="payment-method" data-bind="css: {'_active': (value == $parent.isBrandCodeChecked())}">
<div class="payment-method" data-bind="css: {'_active': (brandCode == $parent.isBrandCodeChecked())}">
<div class="payment-method-title field choice">
<input type="radio"
name="payment[method]"
class="radio"
data-bind="attr: {'id': value}, value: value, checked: $parent.isBrandCodeChecked, click: $parent.selectPaymentMethodBrandCode"/>
<label data-bind="attr: {'for': value}" class="label">
data-bind="attr: {'id': 'adyen_' + brandCode}, value: 'adyen_' + brandCode, checked: brandCode == $parent.isBrandCodeChecked, click: $parent.selectPaymentMethodBrandCode"/>
<label data-bind="attr: {'for': 'adyen_' + brandCode}" class="label">
<!-- ko if: name.icon -->
<img data-bind="attr: {
'src': name.icon.url,
'width': name.icon.url.width,
'height': name.icon.url.height
'src': icon.url,
'width': icon.url,
'height': icon.height
}">
<!--/ko-->
<span data-bind="text: name.title"></span>
<span data-bind="text: name"></span>
</label>
</div>
<div class="payment-method-content">
......@@ -51,244 +51,13 @@
<!--/ko-->
</div>
<form class="form" data-role="adyen-hpp-form" action="#" method="post" data-bind="mageInit: { 'validation':[]}, attr: {id: 'payment_form_' + $parent.getCode() + '_' + value}">
<fieldset class="fieldset" data-bind='attr: {id: "payment_fieldset_" + $parent.getCode() + "_" + value}'>
<!-- ko if: hasIssuersAvailable() -->
<!-- ko if: isIdeal() -->
<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">
<span><!-- ko text: $t('Select Your Bank') --><!-- /ko --></span>
</label>
<div class="field">
<select name="payment[issuer_id]" data-bind="
options: getIssuers(),
optionsText: 'name',
optionsValue: 'id',
value: issuer,
optionsCaption: $t('Choose Your Bank')">
</select>
</div>
<!--/ko-->
<!--/ko-->
<!-- ko if: isPaymentMethodKlarna() -->
<!-- ko if: showSsn() -->
<div class="field ssn type required">
<label data-bind="attr: {for: getCode() + '_ssn_' + value}" class="adyen-checkout__label__text">
<span><!-- ko text: $t('Personal number')--><!-- /ko --></span>
</label>
<div class="control">
<input type="text" class="input-text"
name="payment[ssn]"
data-bind="
attr: {
id: getCode() + '_ssn_' + value,
title: $t('Social Security Number'),
'data-container': getCode() + '-ssn',
maxlength : getSsnLength()
},
value: ssn"
data-validate="{required:true}"
/>
</div>
</div>
<!--/ko-->
<div class="checkout-component-dock" afterRender="renderKlarnaComponent()" data-bind="attr: { id: 'klarnaContainer'}"></div>
<!--/ko-->
<!-- ko if: isPaymentMethodAfterPay() -->
<!-- ko if: showSsn() -->
<div class="field ssn type required">
<label data-bind="attr: {for: getCode() + '_ssn_' + value}" class="adyen-checkout__label__text">
<span><!-- ko text: $t('Personal number')--><!-- /ko --></span>
</label>
<div class="control">
<input type="text" class="input-text"
name="payment[ssn]"
data-bind="
attr: {
id: getCode() + '_ssn_' + value,
title: $t('Social Security Number'),
'data-container': getCode() + '-ssn',
maxlength : getSsnLength()
},
value: ssn"
data-validate="{required:true}"
/>
</div>
</div>
<!--/ko-->
<div class="checkout-component-dock" afterRender="renderAfterPayComponent()" data-bind="attr: { id: 'afterPayContainer'}"></div>
<!--/ko-->
<!-- ko if: isPaymentMethodOtherOpenInvoiceMethod() -->
<div class="field gender required">
<label data-bind="attr: {for: getCode() + '_gender_type_' + value}" class="label">
<span><!-- ko text: $t('Gender')--><!-- /ko --></span>
</label>
<div class="control">
<select class="select select-gender-type"
name="payment[gender]"
data-bind="attr: {id: getCode() + '_gender_type_' + value, 'data-container': getCode() + '-gender-type'},
options: $parent.getGenderTypes(),
optionsValue: 'key',
optionsText: 'value',
optionsCaption: $t('-Please select-'),
value: gender"
data-validate="{required:true}">
</select>
</div>
</div>
<div class="field dob type required">
<label data-bind="attr: {for: getCode() + '_dob_' + value}" class="label">
<span><!-- ko text: $t('Date of Birth')--><!-- /ko --></span>
</label>
<div class="control">
<input type="text" class="input-text"
name="payment[dob]"
data-bind="
attr: {
id: getCode() + '_dob_' + value,
title: $t('Date of Birth'),
'data-container': getCode() + '-dob_' + value,
},
datepicker: {
storage: datepickerValue,
options: { showOn: 'both', changeYear: true, yearRange: '-99:-1', defaultDate: '-20y' }
},
value: dob"
data-validate="{required:true}"
/>
</div>
</div>
<div class="field telephone type required">
<label data-bind="attr: {for: getCode() + '_telephone_' + value}" class="label">
<span><!-- ko text: $t('Telephone')--><!-- /ko --></span>
</label>
<div class="control">
<input type="number" class="input-text"
name="payment[telephone]"
data-bind="
attr: {
id: getCode() + '_telephone_' + value,
title: $t('Telephone'),
'data-container': getCode() + '-telephone_' + value,
'data-validate': JSON.stringify({'required-number':true})
},
value: telephone"
data-validate="{required:true}"
/>
</div>
</div>
<!-- ko if: showSsn() -->
<div class="field ssn type required">
<label data-bind="attr: {for: getCode() + '_ssn_' + value}" class="adyen-checkout__label__text">
<span><!-- ko text: $t('Personal number')--><!-- /ko --></span>
</label>
<div class="control">
<input type="text" class="input-text"
name="payment[ssn]"
data-bind="
attr: {
id: getCode() + '_ssn_' + value,
title: $t('Social Security Number'),
'data-container': getCode() + '-ssn',
maxlength : getSsnLength()
},
value: ssn"
data-validate="{required:true}"
/>
</div>
</div>
<!--/ko-->
<!--/ko-->
<!-- ko if: isSepaDirectDebit() -->
<div class="checkout-component-dock" afterRender="renderSepaDirectDebitComponent()" data-bind="attr: { id: 'sepaDirectDebitContainer'}"></div>
<!--/ko-->
<!-- ko if: isAch() -->
<div class="field ownerName type required">
<label data-bind="attr: {for: getCode() + '_ownerName_' + value}" class="label">
<span><!-- ko text: $t('Owner name')--><!-- /ko --></span>
</label>
<div class="control">
<input type="text" class="input-text"
name="payment[ownerName]"
data-bind="
attr: {
id: getCode() + '_ownerName_' + value,
title: $t('Owner name'),
'data-container': getCode() + '-ownerName_' + value,
'data-validate': JSON.stringify({'required':true})
},
value: ownerName"
data-validate="{required:true}"
/>
</div>
</div>
<div class="field bankAccountNumber type required">
<label data-bind="attr: {for: getCode() + '_bankAccountNumber_' + value}" class="label">
<span><!-- ko text: $t('Bank account number')--><!-- /ko --></span>
</label>
<div class="control">
<input type="number" class="input-text"
name="payment[bankAccountNumber]"
data-bind="
attr: {
id: getCode() + '_bankAccountNumber_' + value,
title: $t('Bank account number'),
'data-container': getCode() + '-bankAccountNumber_' + value,
'data-validate': JSON.stringify({'required':true}),
minlength: 3,
maxlength : getBankAccountNumberMaxLength()
},
value: bankAccountNumber"
data-validate="{required:true}"
/>
</div>
</div>
<div class="field bankLocationId type required">
<label data-bind="attr: {for: getCode() + '_bankLocationId_' + value}" class="label">
<span><!-- ko text: $t('Bank location ID')--><!-- /ko --></span>
</label>
<div class="control">
<input type="number" class="input-text"
name="payment[bankLocationId]"
data-bind="
attr: {
id: getCode() + '_bankLocationId_' + value,
title: $t('Bank location ID'),
'data-container': getCode() + '-bankLocationId_' + value,
'data-validate': JSON.stringify({'required-number':true}),
minlength: 9,
maxlength: 9
},
value: bankLocationId"
data-validate="{required:true}"
/>
</div>
</div>
<!--/ko-->
<form class="form" data-role="adyen-hpp-form" action="#" method="post" data-bind="mageInit: { 'validation':[]}, attr: {id: 'payment_form_' + $parent.getCode() + '_' + brandCode}">
<fieldset class="fieldset" data-bind='attr: {id: "payment_fieldset_" + $parent.getCode() + "_" + brandCode}'>
<div data-bind='attr: {id: "adyen-alternative-payment-container-" + brandCode}'
afterRender="renderCheckoutComponent()"></div>
</fieldset>
<div class="checkout-agreements-block">
<!-- ko foreach: $parents[1].getRegion('before-place-order') -->
<!-- ko template: getTemplate() --><!-- /ko -->
......@@ -296,7 +65,7 @@
</div>
<div>
<span class="message message-error error hpp-message" data-bind="attr: {id: 'messages-' + value}"></span>
<span class="message message-error error hpp-message" data-bind="attr: {id: 'messages-' + brandCode}"></span>
</div>
<div class="actions-toolbar">
......@@ -305,7 +74,7 @@
type="submit"
data-bind="
click: $parent.continueToAdyenBrandCode,
enable: placeOrderAllowed() && (value == $parent.isBrandCodeChecked()),
enable: placeOrderAllowed() && (brandCode == $parent.isBrandCodeChecked()),
css: {disabled: !$parent.isPlaceOrderActionAllowed()}"
disabled>
<span data-bind="text: $t('Place Order')"></span>
......
......@@ -21,7 +21,7 @@
* Author: Adyen <magento@adyen.com>
*/
-->
<!-- ko foreach: getAdyenBillingAgreements() -->
<!-- ko foreach: getAdyenStoredPayments() -->
<div class="payment-method" data-bind="css: {'_active': (value == $parent.isBillingAgreementChecked())}">
<div class="payment-method-title field choice">
<input type="radio"
......@@ -46,7 +46,8 @@
<div class="payment-method-content">
<!-- ko ifnot: (getOriginKey()) -->
<span class="message message-error error"><!-- ko text: $t('Please configure an API Key and a live endpoint prefix(if in Production Mode) in your Adyen Required Settings')--><!-- /ko --></span>
<span class="message message-error error"><!-- ko text: $t('Please configure an API Key and a live endpoint prefix(if in Production Mode) in your Adyen Required Settings')-->
<!-- /ko --></span>
<!--/ko-->
<!-- ko foreach: $parent.getRegion(getMessageName()) -->
......@@ -69,72 +70,12 @@
}, 'validation':[]}">
<fieldset
data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}">
<!-- ko if: agreement_data.card -->
<div class="field number">
<label class="label">
<span><!-- ko text: $t('Credit Card Number')--><!-- /ko --></span>
</label>
<div class="control">
<span data-bind="text: '**** **** **** ' + agreement_data.card.number"></span>
</div>
</div>
<div class="checkout-component-dock" afterRender="renderSecureCVC()" data-bind="attr: { id: 'cvcContainer-' + value}"></div>
<!--/ko-->
<!-- ko if: agreement_data.bank -->
<div class="field number">
<label class="label">
<span><!-- ko text: $t('Bank account holder name')--><!-- /ko --></span>
</label>
<div class="control">
<span data-bind="text: agreement_data.bank.ownerName"></span>
</div>
</div>
<div class="field number">
<label class="label">
<span><!-- ko text: $t('Iban')--><!-- /ko --></span>
</label>
<div class="control">
<span data-bind="text: agreement_data.bank.iban"></span>
</div>
</div>
<div class="field number">
<label class="label">
<span><!-- ko text: $t('Country')--><!-- /ko --></span>
</label>
<div class="control">
<span data-bind="text: agreement_data.bank.countryCode"></span>
</div>
</div>
data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}">
<div class="checkout-component-dock" afterRender="renderStoredPaymentComponent()"
data-bind="attr: { id: 'storedPaymentContainer-' + value}"></div>
<!--/ko-->
<!-- ko if: number_of_installments.length > 0 -->
<div class="field required"
data-bind="attr: {id: getCode() + '_installments_div'}, visible: getInstallments().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: $parent.isActive($parents),
options: getInstallments,
optionsValue: 'value',
optionsText: 'key',
optionsCaption: $t('Do not use Installments'),
value: installment"
data-validate="{required:true}">
</select>
</div>
</div>
<!-- /ko -->
<div id="threeDS2ModalOneClick">
<div id="threeDS2ContainerOneClick"></div>
</div>
......
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