Commit 11633b90 authored by cyattilakiss's avatar cyattilakiss Committed by GitHub

Merge pull request #698 from Adyen/attila/PW-2212

Card payments finalised
parents c3dae75f 8cfb5272
...@@ -67,14 +67,6 @@ class Cc extends \Magento\Payment\Block\Form\Cc ...@@ -67,14 +67,6 @@ class Cc extends \Magento\Payment\Block\Form\Cc
$this->checkoutSession = $checkoutSession; $this->checkoutSession = $checkoutSession;
} }
/**
* @return string
*/
public function getCheckoutCardComponentJs()
{
return $this->adyenHelper->getCheckoutCardComponentJs($this->checkoutSession->getQuote()->getStore()->getId());
}
/** /**
* @return string * @return string
* @throws \Adyen\AdyenException * @throws \Adyen\AdyenException
......
<?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;
}
}
\ No newline at end of file
This diff is collapsed.
...@@ -64,8 +64,7 @@ class RecurringDataBuilder implements BuilderInterface ...@@ -64,8 +64,7 @@ class RecurringDataBuilder implements BuilderInterface
$payment = $paymentDataObject->getPayment(); $payment = $paymentDataObject->getPayment();
$storeId = $payment->getOrder()->getStoreId(); $storeId = $payment->getOrder()->getStoreId();
$areaCode = $this->appState->getAreaCode(); $areaCode = $this->appState->getAreaCode();
$additionalInformation = $payment->getAdditionalInformation(); $request['body'] = $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId);
$request['body'] = $this->adyenRequestsHelper->buildRecurringData([], $areaCode, $storeId, $additionalInformation);
return $request; return $request;
} }
} }
...@@ -69,15 +69,9 @@ class CheckoutResponseValidator extends AbstractValidator ...@@ -69,15 +69,9 @@ class CheckoutResponseValidator extends AbstractValidator
// validate result // validate result
if (!empty($response['resultCode'])) { if (!empty($response['resultCode'])) {
switch ($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": case "ChallengeShopper":
$payment->setAdditionalInformation('threeDSType', $response['resultCode']); case "IdentifyShopper":
$payment->setAdditionalInformation('threeDS2Token', $response['authentication']['threeds2.challengeToken']); $payment->setAdditionalInformation('action', $response['action']);
$payment->setAdditionalInformation('threeDS2PaymentData', $response['paymentData']);
break; break;
case "Authorised": case "Authorised":
case "Received": case "Received":
......
...@@ -34,8 +34,6 @@ class Data extends AbstractHelper ...@@ -34,8 +34,6 @@ class Data extends AbstractHelper
const MODULE_NAME = 'adyen-magento2'; const MODULE_NAME = 'adyen-magento2';
const TEST = 'test'; const TEST = 'test';
const LIVE = 'live'; 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 * @var \Magento\Framework\Encryption\EncryptorInterface
...@@ -1603,19 +1601,6 @@ class Data extends AbstractHelper ...@@ -1603,19 +1601,6 @@ class Data extends AbstractHelper
return new \Adyen\Service\CheckoutUtility($client); 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 $order
* @param $additionalData * @param $additionalData
...@@ -1807,27 +1792,6 @@ class Data extends AbstractHelper ...@@ -1807,27 +1792,6 @@ class Data extends AbstractHelper
return $timeStamp->format($format); 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 * @param int $storeId
* @return mixed|string * @return mixed|string
......
...@@ -154,7 +154,7 @@ class PaymentMethods extends AbstractHelper ...@@ -154,7 +154,7 @@ class PaymentMethods extends AbstractHelper
$this->setQuote($quote); $this->setQuote($quote);
$paymentMethods = $this->fetchAlternativeMethods($country); $paymentMethods = $this->fetchPaymentMethods($country);
return $paymentMethods; return $paymentMethods;
} }
...@@ -162,7 +162,7 @@ class PaymentMethods extends AbstractHelper ...@@ -162,7 +162,7 @@ class PaymentMethods extends AbstractHelper
* @param $country * @param $country
* @return array * @return array
*/ */
protected function fetchAlternativeMethods($country) protected function fetchPaymentMethods($country)
{ {
$quote = $this->getQuote(); $quote = $this->getQuote();
$store = $quote->getStore(); $store = $quote->getStore();
...@@ -200,31 +200,17 @@ class PaymentMethods extends AbstractHelper ...@@ -200,31 +200,17 @@ class PaymentMethods extends AbstractHelper
$responseData = $this->getPaymentMethodsResponse($adyFields, $store); $responseData = $this->getPaymentMethodsResponse($adyFields, $store);
// TODO this should be the implemented with the PaymentDetailsInterface but for now we json encode it and if (empty($responseData['paymentMethods'])) {
// on the fronend we decode it so we can move forward return [];
// /** @var \Magento\Checkout\Api\Data\PaymentDetailsInterface $paymentDetails */ }
// $paymentDetails = $this->paymentDetailsFactory->create();
// $paymentDetails->setPaymentMethods($responseData);
//$paymentDetails->setTotals($this->cartTotalsRepository->get($cartId));
//return $paymentDetails;
return json_encode($responseData); $paymentMethods = $responseData['paymentMethods'];
$response['paymentMethodsResponse'] = $responseData;
$paymentMethods = []; // Add extra details per payment mmethod
if (isset($responseData['paymentMethods'])) { $paymentMethodsExtraDetails = [];
foreach ($responseData['paymentMethods'] as $paymentMethod) {
$paymentMethodCode = $paymentMethod['type'];
$paymentMethod = $this->fieldMapPaymentMethod($paymentMethod);
// check if payment method is an openinvoice method
//$paymentMethod['isPaymentMethodOpenInvoiceMethod'] =
//$this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethodCode);
//TODO create the icons on the frontend or in a separate function but not here!
// add icon location in result
if ($this->adyenHelper->showLogos()) { if ($this->adyenHelper->showLogos()) {
// Fix for MAGETWO-70402 https://github.com/magento/magento2/pull/7686
// Explicitly setting theme // Explicitly setting theme
$themeCode = "Magento/blank"; $themeCode = "Magento/blank";
...@@ -237,18 +223,28 @@ class PaymentMethods extends AbstractHelper ...@@ -237,18 +223,28 @@ class PaymentMethods extends AbstractHelper
} }
$params = []; $params = [];
$params = array_merge([ $params = array_merge(
[
'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
'_secure' => $this->request->isSecure(), '_secure' => $this->request->isSecure(),
'theme' => $themeCode 'theme' => $themeCode
], $params); ],
$params
);
$asset = $this->assetRepo->createAsset('Adyen_Payment::images/logos/' .
$paymentMethodCode . '.png', $params); foreach ($paymentMethods as $paymentMethod) {
$paymentMethodCode = $paymentMethod['type'];
$asset = $this->assetRepo->createAsset(
'Adyen_Payment::images/logos/' .
$paymentMethodCode . '.png',
$params
);
$placeholder = $this->assetSource->findSource($asset); $placeholder = $this->assetSource->findSource($asset);
$icon = null; $icon = [];
if ($placeholder) { if ($placeholder) {
list($width, $height) = getimagesize($asset->getSourceFile()); list($width, $height) = getimagesize($asset->getSourceFile());
$icon = [ $icon = [
...@@ -256,14 +252,26 @@ class PaymentMethods extends AbstractHelper ...@@ -256,14 +252,26 @@ class PaymentMethods extends AbstractHelper
'width' => $width, 'width' => $width,
'height' => $height 'height' => $height
]; ];
} else {
$icon = [
'url' => 'https://checkoutshopper-live.adyen.com/checkoutshopper/images/logos/medium/' .$paymentMethodCode . '.png',
'width' => 77,
'height' => 50
];
} }
$paymentMethod['icon'] = $icon;
} $paymentMethodsExtraDetails[$paymentMethodCode]['icon'] = $icon;
$paymentMethods[$paymentMethodCode] = $paymentMethod;
// check if payment method is an openinvoice method
$paymentMethodsExtraDetails[$paymentMethodCode]['isOpenInvoice'] =
$this->adyenHelper->isPaymentMethodOpenInvoiceMethod($paymentMethodCode);
} }
} }
return $paymentMethods; $response['paymentMethodsExtraDetails'] = $paymentMethodsExtraDetails;
//TODO this should be the implemented with an interface
return json_encode($response);
} }
/** /**
...@@ -321,28 +329,6 @@ class PaymentMethods extends AbstractHelper ...@@ -321,28 +329,6 @@ class PaymentMethods extends AbstractHelper
return ""; 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 $requestParams
* @param $store * @param $store
...@@ -351,7 +337,6 @@ class PaymentMethods extends AbstractHelper ...@@ -351,7 +337,6 @@ class PaymentMethods extends AbstractHelper
*/ */
protected function getPaymentMethodsResponse($requestParams, $store) protected function getPaymentMethodsResponse($requestParams, $store)
{ {
// initialize the adyen client // initialize the adyen client
$client = $this->adyenHelper->initializeAdyenClient($store->getId()); $client = $this->adyenHelper->initializeAdyenClient($store->getId());
...@@ -401,7 +386,6 @@ class PaymentMethods extends AbstractHelper ...@@ -401,7 +386,6 @@ class PaymentMethods extends AbstractHelper
*/ */
public function getConnectedTerminals() public function getConnectedTerminals()
{ {
$storeId = $this->getQuote()->getStoreId(); $storeId = $this->getQuote()->getStoreId();
// initialize the adyen client // initialize the adyen client
......
...@@ -311,17 +311,6 @@ class Requests extends AbstractHelper ...@@ -311,17 +311,6 @@ class Requests extends AbstractHelper
$request['additionalData']['allow3DS2'] = true; $request['additionalData']['allow3DS2'] = true;
$request['origin'] = $this->adyenHelper->getOrigin(); $request['origin'] = $this->adyenHelper->getOrigin();
$request['channel'] = 'web'; $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 { } else {
$request['additionalData']['allow3DS2'] = false; $request['additionalData']['allow3DS2'] = false;
$request['origin'] = $this->adyenHelper->getOrigin(); $request['origin'] = $this->adyenHelper->getOrigin();
...@@ -337,7 +326,7 @@ class Requests extends AbstractHelper ...@@ -337,7 +326,7 @@ class Requests extends AbstractHelper
* @param $storeId * @param $storeId
* @param $payment * @param $payment
*/ */
public function buildRecurringData($request = [], $areaCode, int $storeId, $additionalData) public function buildRecurringData($request = [], $areaCode, int $storeId)
{ {
// If the vault feature is on this logic is handled in the VaultDataBuilder // If the vault feature is on this logic is handled in the VaultDataBuilder
if (!$this->adyenHelper->isCreditCardVaultEnabled()) { if (!$this->adyenHelper->isCreditCardVaultEnabled()) {
...@@ -360,11 +349,6 @@ class Requests extends AbstractHelper ...@@ -360,11 +349,6 @@ class Requests extends AbstractHelper
} else { } else {
$request['enableRecurring'] = false; $request['enableRecurring'] = false;
} }
// value can be 0,1 or true
if (!empty($additionalData[AdyenCcDataAssignObserver::STORE_CC])) {
$request['paymentMethod']['storeDetails'] = true;
}
} }
return $request; return $request;
......
...@@ -75,18 +75,11 @@ class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentSta ...@@ -75,18 +75,11 @@ class AdyenOrderPaymentStatus implements \Adyen\Payment\Api\AdyenOrderPaymentSta
) { ) {
$additionalInformation = $payment->getAdditionalInformation(); $additionalInformation = $payment->getAdditionalInformation();
$type = null; if (!empty($additionalInformation['action'])) {
if (!empty($additionalInformation['threeDSType'])) { return json_encode($additionalInformation['action']);
$type = $additionalInformation['threeDSType'];
} }
$token = null;
if (!empty($additionalInformation['threeDS2Token'])) {
$token = $additionalInformation['threeDS2Token'];
} }
return $this->adyenHelper->buildThreeDS2ProcessResponseJson($type, $token);
}
return true; return true;
} }
} }
...@@ -76,6 +76,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -76,6 +76,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
public function initiate($payload) public function initiate($payload)
{ {
// Decode payload from frontend // Decode payload from frontend
// TODO implement interface to handle the request the correct way
$payload = json_decode($payload, true); $payload = json_decode($payload, true);
// Validate JSON that has just been parsed if it was in a valid format // Validate JSON that has just been parsed if it was in a valid format
...@@ -83,6 +84,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -83,6 +84,7 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed because the request was not a valid JSON')); throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed because the request was not a valid JSON'));
} }
// Validate if order id is present
if (empty($payload['orderId'])) { if (empty($payload['orderId'])) {
throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed because of a missing order id')); throw new \Magento\Framework\Exception\LocalizedException(__('3D secure 2.0 failed because of a missing order id'));
} }
...@@ -91,28 +93,16 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -91,28 +93,16 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
$order = $this->orderFactory->create()->load($payload['orderId']); $order = $this->orderFactory->create()->load($payload['orderId']);
$payment = $order->getPayment(); $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'));
}
// Depends on the component's response we send a fingerprint or the challenge result // Unset action from additional info since it is not needed anymore
if (!empty($payload['details']['threeds2.fingerprint'])) { $payment->unsAdditionalInformation("action");
$request['details']['threeds2.fingerprint'] = $payload['details']['threeds2.fingerprint'];
} elseif (!empty($payload['details']['threeds2.challengeResult'])) { // TODO validate and format the request root level keys
$request['details']['threeds2.challengeResult'] = $payload['details']['threeds2.challengeResult']; $request = $payload;
}
// Init payments/details request
$result = [];
// Send the request // Send the request
try { try {
...@@ -128,9 +118,9 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface ...@@ -128,9 +118,9 @@ class AdyenThreeDS2Process implements AdyenThreeDS2ProcessInterface
// Check if result is challenge shopper, if yes return the token // Check if result is challenge shopper, if yes return the token
if (!empty($result['resultCode']) && if (!empty($result['resultCode']) &&
$result['resultCode'] === 'ChallengeShopper' && $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 // Save the payments response because we are going to need it during the place order flow
......
...@@ -69,8 +69,6 @@ class AdyenGenericConfigProvider implements ConfigProviderInterface ...@@ -69,8 +69,6 @@ class AdyenGenericConfigProvider implements ConfigProviderInterface
$config['payment']['adyen']['showLogo'] = false; $config['payment']['adyen']['showLogo'] = false;
} }
$config['payment']['checkoutCardComponentSource'] = $this->_adyenHelper->getCheckoutCardComponentJs($this->storeManager->getStore()->getId());
return $config; return $config;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
* *
* Author: Adyen <magento@adyen.com> * Author: Adyen <magento@adyen.com>
*/ */
namespace Adyen\Payment\Observer; namespace Adyen\Payment\Observer;
use Magento\Framework\Event\Observer; use Magento\Framework\Event\Observer;
...@@ -31,45 +32,39 @@ use Magento\Quote\Api\Data\PaymentInterface; ...@@ -31,45 +32,39 @@ use Magento\Quote\Api\Data\PaymentInterface;
*/ */
class AdyenCcDataAssignObserver extends AbstractDataAssignObserver class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
{ {
//TODO do we need these?
const VARIANT = 'variant';
const STATE_DATA = 'state_data';
const STORE_PAYMENT_METHOD = 'storePaymentMethod';
const CC_TYPE = 'cc_type'; const CC_TYPE = 'cc_type';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments'; 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'; const COMBO_CARD_TYPE = 'combo_card_type';
const BROWSER_INFO = 'browserInfo';
const PAYMENT_METHOD = 'paymentMethod';
const RISK_DATA = 'riskData';
/** /**
* Approved root level keys from additional data array
*
* @var array * @var array
*/ */
protected $additionalInformationList = [ private static $approvedAdditionalDataKeys = [
self::CC_TYPE, self::STATE_DATA,
self::NUMBER_OF_INSTALLMENTS, self::COMBO_CARD_TYPE,
self::STORE_CC, self::NUMBER_OF_INSTALLMENTS
self::ENCRYPTED_CREDIT_CARD_NUMBER, ];
self::ENCRYPTED_SECURITY_CODE,
self::ENCRYPTED_EXPIRY_MONTH, /**
self::ENCRYPTED_EXPIRY_YEAR, * Approved root level keys from the checkout component's state data object
self::HOLDER_NAME, *
self::VARIANT, * @var array
self::JAVA_ENABLED, */
self::SCREEN_COLOR_DEPTH, private static $approvedStateDataKeys = [
self::SCREEN_WIDTH, self::BROWSER_INFO,
self::SCREEN_HEIGHT, self::PAYMENT_METHOD,
self::TIMEZONE_OFFSET, self::RISK_DATA,
self::LANGUAGE, self::STORE_PAYMENT_METHOD
self::GUEST_EMAIL,
self::COMBO_CARD_TYPE
]; ];
/** /**
...@@ -78,27 +73,61 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -78,27 +73,61 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
*/ */
public function execute(Observer $observer) public function execute(Observer $observer)
{ {
// Get request fields
$data = $this->readDataArgument($observer); $data = $this->readDataArgument($observer);
// Get additional data array
$additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA);
if (!is_array($additionalData)) { if (!is_array($additionalData)) {
return; return;
} }
// Get a validated additional data array
$additionalData = $this->getArrayOnlyWithApprovedKeys($additionalData, self::$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, self::$approvedStateDataKeys);
}
// Replace state data with the decoded and validated state data
$additionalData[self::STATE_DATA] = $stateData;
// Set additional data in the payment
$paymentInfo = $this->readPaymentModelArgument($observer); $paymentInfo = $this->readPaymentModelArgument($observer);
foreach ($additionalData as $key => $data) {
$paymentInfo->setAdditionalInformation($key, $data);
}
// set ccType // set ccType
if (!empty($additionalData['cc_type'])) { if (!empty($additionalData[self::CC_TYPE])) {
$paymentInfo->setCcType($additionalData['cc_type']); $paymentInfo->setCcType($additionalData[self::CC_TYPE]);
}
} }
foreach ($this->additionalInformationList as $additionalInformationKey) { /**
if (isset($additionalData[$additionalInformationKey])) { * Returns an array with only the approved keys
$paymentInfo->setAdditionalInformation( *
$additionalInformationKey, * @param array $array
$additionalData[$additionalInformationKey] * @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;
} }
} }
...@@ -557,7 +557,7 @@ ...@@ -557,7 +557,7 @@
<item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item> <item name="payment" xsi:type="string">Adyen\Payment\Gateway\Request\PaymentDataBuilder</item>
<item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item> <item name="browserinfo" xsi:type="string">Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder</item>
<item name="recurring" xsi:type="string">Adyen\Payment\Gateway\Request\RecurringDataBuilder</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="vault" xsi:type="string">Adyen\Payment\Gateway\Request\VaultDataBuilder</item>
<item name="threeds2" xsi:type="string">Adyen\Payment\Gateway\Request\ThreeDS2DataBuilder</item> <item name="threeds2" xsi:type="string">Adyen\Payment\Gateway\Request\ThreeDS2DataBuilder</item>
</argument> </argument>
......
This diff is collapsed.
This diff is collapsed.
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* 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([]);
}
);
...@@ -6,35 +6,19 @@ define( ...@@ -6,35 +6,19 @@ define(
[ [
'underscore', 'underscore',
'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/quote',
'Adyen_Payment/js/model/adyen-method-list',
'Magento_Customer/js/model/customer', 'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/url-builder', 'Magento_Checkout/js/model/url-builder',
'mage/storage' 'mage/storage',
'Adyen_Payment/js/bundle',
], ],
function (_, quote, methodList, customer, urlBuilder, storage) { function (_, quote, customer, urlBuilder, storage, adyenComponent) {
'use strict'; 'use strict';
var checkoutComponent = {};
return { 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 * Retrieve the list of available payment methods from the server
*/ */
retrieveAvailablePaymentMethods: function (callback) { retrieveAvailablePaymentMethods: function () {
var self = this;
// retrieve payment methods // retrieve payment methods
var serviceUrl, var serviceUrl,
payload; payload;
...@@ -51,30 +35,48 @@ define( ...@@ -51,30 +35,48 @@ define(
shippingAddress: quote.shippingAddress() shippingAddress: quote.shippingAddress()
}; };
storage.post( return storage.post(
serviceUrl, JSON.stringify(payload) serviceUrl,
).done( JSON.stringify(payload),
function (response) { true
var jsonResponse = JSON.parse(response);
console.log(jsonResponse);
self.setPaymentMethods(jsonResponse);
if (callback) {
callback();
}
}
).fail(
function () {
self.setPaymentMethods([]);
}
) )
}, },
/**
* 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) { getOrderPaymentStatus: function (orderId) {
var serviceUrl = urlBuilder.createUrl('/adyen/orders/:orderId/payment-status', { var serviceUrl = urlBuilder.createUrl('/adyen/orders/:orderId/payment-status', {
orderId: orderId orderId: orderId
}); });
return storage.get(serviceUrl); return storage.get(serviceUrl);
},
initCheckoutComponent: function(paymentMethodsResponse, originKey, locale, environment, ) {
checkoutComponent = new AdyenCheckout({
locale: locale,
originKey: originKey,
environment: environment,
paymentMethodsResponse: paymentMethodsResponse,
});
},
getCheckoutComponent: function() {
return checkoutComponent;
} }
}; };
} }
......
/**
* 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
);
}
};
}
);
...@@ -25,12 +25,14 @@ define( ...@@ -25,12 +25,14 @@ define(
[ [
'uiComponent', '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-payment-service',
'Adyen_Payment/js/model/adyen-configuration'
], ],
function ( function (
Component, Component,
rendererList, rendererList,
adyenPaymentService adyenPaymentService,
adyenConfiguration
) { ) {
'use strict'; 'use strict';
rendererList.push( rendererList.push(
...@@ -66,17 +68,17 @@ define( ...@@ -66,17 +68,17 @@ define(
/** Add view logic here if needed */ /** Add view logic here if needed */
return Component.extend({ return Component.extend({
initialize: function () { initialize: function () {
var self = this;
this._super(); this._super();
// reset variable: adyenPaymentService.retrieveAvailablePaymentMethods().done(function (response) {
adyenPaymentService.setPaymentMethods();
adyenPaymentService.retrieveAvailablePaymentMethods(function () { var responseJson = JSON.parse(response);
var paymentMethods = adyenPaymentService.getAvailablePaymentMethods(); var paymentMethodsResponse = responseJson.paymentMethodsResponse;
console.log(paymentMethods);
if (!!window.checkoutConfig.payment.adyenHpp) { // 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) { if (JSON.stringify(paymentMethods).indexOf("ratepay") > -1) {
var ratePayId = window.checkoutConfig.payment.adyenHpp.ratePayId; var ratePayId = window.checkoutConfig.payment.adyenHpp.ratePayId;
var dfValueRatePay = self.getRatePayDeviceIdentToken(); var dfValueRatePay = self.getRatePayDeviceIdentToken();
...@@ -92,15 +94,16 @@ define( ...@@ -92,15 +94,16 @@ define(
ratepayScriptTag.type = "text/javascript"; ratepayScriptTag.type = "text/javascript";
document.body.appendChild(ratepayScriptTag); document.body.appendChild(ratepayScriptTag);
} }
} }*/
});
// include checkout card component javascript // Initialises adyen checkout main component with default configuration
var checkoutCardComponentScriptTag = document.createElement('script'); adyenPaymentService.initCheckoutComponent(
checkoutCardComponentScriptTag.id = "AdyenCheckoutCardComponentScript"; paymentMethodsResponse,
checkoutCardComponentScriptTag.src = self.getCheckoutCardComponentSource(); adyenConfiguration.getOriginKey(),
checkoutCardComponentScriptTag.type = "text/javascript"; adyenConfiguration.getLocale(),
document.head.appendChild(checkoutCardComponentScriptTag); adyenConfiguration.getCheckoutEnvironment()
);
})
if (this.isGooglePayEnabled()) { if (this.isGooglePayEnabled()) {
var googlepayscript = document.createElement('script'); var googlepayscript = document.createElement('script');
...@@ -109,15 +112,12 @@ define( ...@@ -109,15 +112,12 @@ define(
document.head.appendChild(googlepayscript); document.head.appendChild(googlepayscript);
} }
}, },
getCheckoutCardComponentSource: function() {
return window.checkoutConfig.payment.checkoutCardComponentSource;
},
isGooglePayEnabled: function() { isGooglePayEnabled: function() {
return window.checkoutConfig.payment.adyenGooglePay.active; return window.checkoutConfig.payment.adyenGooglePay.active;
}, },
getRatePayDeviceIdentToken: function () { getRatePayDeviceIdentToken: function () {
return window.checkoutConfig.payment.adyenHpp.deviceIdentToken; return window.checkoutConfig.payment.adyenHpp.deviceIdentToken;
}, }
}); });
} }
); );
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
<!-- /ko --> <!-- /ko -->
<div class="field number cardContainerField"> <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>
<div id="threeDS2Wrapper"> <div id="threeDS2Wrapper">
...@@ -101,34 +101,6 @@ ...@@ -101,34 +101,6 @@
</div> </div>
</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())--> <!-- ko if: (isVaultEnabled())-->
<div class="field choice"> <div class="field choice">
<input type="checkbox" <input type="checkbox"
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
* Author: Adyen <magento@adyen.com> * 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" data-bind="css: {'_active': (value == $parent.isBillingAgreementChecked())}">
<div class="payment-method-title field choice"> <div class="payment-method-title field choice">
<input type="radio" <input type="radio"
...@@ -46,7 +46,8 @@ ...@@ -46,7 +46,8 @@
<div class="payment-method-content"> <div class="payment-method-content">
<!-- ko ifnot: (getOriginKey()) --> <!-- 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-->
<!-- ko foreach: $parent.getRegion(getMessageName()) --> <!-- ko foreach: $parent.getRegion(getMessageName()) -->
...@@ -71,70 +72,10 @@ ...@@ -71,70 +72,10 @@
<fieldset <fieldset
data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}"> data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}">
<!-- ko if: agreement_data.card --> <div class="checkout-component-dock" afterRender="renderStoredPaymentComponent()"
<div class="field number"> data-bind="attr: { id: 'storedPaymentContainer-' + value}"></div>
<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-->
<!-- 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>
<!--/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="threeDS2ModalOneClick">
<div id="threeDS2ContainerOneClick"></div> <div id="threeDS2ContainerOneClick"></div>
</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