diff --git a/Controller/Payment/Callback.php b/Controller/Payment/Callback.php
index 5aead60e..9233e6c2 100755
--- a/Controller/Payment/Callback.php
+++ b/Controller/Payment/Callback.php
@@ -27,7 +27,8 @@
Gateway\Request\Initiate\MerchantDataBuilder,
Gateway\Transaction\TransactionBuilder,
Model\OrderPlace,
- Model\QuoteLocator
+ Model\QuoteLocator,
+ Model\Gdpr\Compliance
};
use Magento\Quote\{
Api\Data\CartInterface, Model\Quote
@@ -72,6 +73,11 @@ class Callback extends Action
*/
private $quote;
+ /**
+ * @var Compliance
+ */
+ private $gdprCompliance;
+
/**
* Callback constructor.
*
@@ -88,6 +94,7 @@ public function __construct(
QuoteLocator $quoteLocator,
Json $jsonDecoder,
TransactionBuilder $transactionBuilder,
+ Compliance $compliance,
LoggerInterface $logger
) {
parent::__construct($context);
@@ -96,6 +103,7 @@ public function __construct(
$this->jsonDecoder = $jsonDecoder;
$this->transactionBuilder = $transactionBuilder;
$this->logger = $logger;
+ $this->gdprCompliance = $compliance;
}
/**
@@ -125,7 +133,8 @@ public function execute()
'message' => __('An error occurred during callback processing.')
]);
} finally {
- $this->logger->debug($this->getRequest()->getContent());
+ $compliant = $this->gdprCompliance->process($this->getRequest()->getContent());
+ $this->logger->debug($compliant);
}
return $result;
}
diff --git a/Controller/Payment/Fallback.php b/Controller/Payment/Fallback.php
index a9142cd0..61803929 100755
--- a/Controller/Payment/Fallback.php
+++ b/Controller/Payment/Fallback.php
@@ -23,7 +23,8 @@
};
use Vipps\Payment\{
Api\CommandManagerInterface, Gateway\Exception\MerchantException, Gateway\Request\Initiate\MerchantDataBuilder,
- Model\OrderLocator, Model\OrderPlace, Gateway\Transaction\TransactionBuilder, Model\QuoteLocator
+ Model\OrderLocator, Model\OrderPlace, Gateway\Transaction\TransactionBuilder, Model\QuoteLocator,
+ Model\Gdpr\Compliance
};
use Magento\Quote\{
Api\Data\CartInterface, Api\CartRepositoryInterface, Model\Quote
@@ -90,6 +91,11 @@ class Fallback extends Action
*/
private $logger;
+ /**
+ * @var Compliance
+ */
+ private $gdprCompliance;
+
/**
* Fallback constructor.
*
@@ -101,7 +107,10 @@ class Fallback extends Action
* @param CartRepositoryInterface $cartRepository
* @param QuoteLocator $quoteLocator
* @param OrderLocator $orderLocator
+ * @param Compliance $compliance
* @param LoggerInterface $logger
+ *
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
Context $context,
@@ -112,6 +121,7 @@ public function __construct(
CartRepositoryInterface $cartRepository,
QuoteLocator $quoteLocator,
OrderLocator $orderLocator,
+ Compliance $compliance,
LoggerInterface $logger
) {
parent::__construct($context);
@@ -123,6 +133,7 @@ public function __construct(
$this->quoteLocator = $quoteLocator;
$this->orderLocator = $orderLocator;
$this->logger = $logger;
+ $this->gdprCompliance = $compliance;
}
/**
@@ -154,7 +165,8 @@ public function execute()
$this->messageManager->addErrorMessage(__('An error occurred during payment status update.'));
$resultRedirect->setPath('checkout/onepage/failure', ['_secure' => true]);
} finally {
- $this->logger->debug($this->getRequest()->getRequestString());
+ $compliant = $this->gdprCompliance->process($this->getRequest()->getRequestString());
+ $this->logger->debug($compliant);
}
return $resultRedirect;
}
diff --git a/Controller/Payment/ShippingDetails.php b/Controller/Payment/ShippingDetails.php
index ba746cf2..25b59002 100644
--- a/Controller/Payment/ShippingDetails.php
+++ b/Controller/Payment/ShippingDetails.php
@@ -23,8 +23,11 @@
CartRepositoryInterface, Data\CartInterface, ShipmentEstimationInterface, Data\AddressInterfaceFactory
};
use Magento\Quote\Model\Quote;
+use Vipps\Payment\Model\Gdpr\Compliance;
use Vipps\Payment\Gateway\Transaction\ShippingDetails as TransactionShippingDetails;
-use Vipps\Payment\Model\QuoteLocator;
+use Vipps\Payment\Model\{
+ QuoteLocator, Quote\AddressUpdater
+};
use Zend\Http\Response as ZendResponse;
use Psr\Log\LoggerInterface;
@@ -65,6 +68,16 @@ class ShippingDetails extends Action
*/
private $logger;
+ /**
+ * @var Compliance
+ */
+ private $gdprCompliance;
+
+ /**
+ * @var AddressUpdater
+ */
+ private $addressUpdater;
+
/**
* ShippingDetails constructor.
*
@@ -73,6 +86,8 @@ class ShippingDetails extends Action
* @param QuoteLocator $quoteLocator
* @param ShipmentEstimationInterface $shipmentEstimation
* @param AddressInterfaceFactory $addressFactory
+ * @param AddressUpdater $addressUpdater
+ * @param Compliance $compliance
* @param Json $serializer
* @param LoggerInterface $logger
*/
@@ -82,6 +97,8 @@ public function __construct(
QuoteLocator $quoteLocator,
ShipmentEstimationInterface $shipmentEstimation,
AddressInterfaceFactory $addressFactory,
+ AddressUpdater $addressUpdater,
+ Compliance $compliance,
Json $serializer,
LoggerInterface $logger
) {
@@ -92,6 +109,8 @@ public function __construct(
$this->shipmentEstimation = $shipmentEstimation;
$this->addressFactory = $addressFactory;
$this->logger = $logger;
+ $this->addressUpdater = $addressUpdater;
+ $this->gdprCompliance = $compliance;
}
/**
@@ -119,6 +138,7 @@ public function execute()
* As Quote is deactivated, so we need to activate it for estimating shipping methods
*/
$quote = $this->cartRepository->get($quote->getId());
+ $this->addressUpdater->fromSourceAddress($quote, $address);
$quote->setIsActive(true);
$shippingMethods = $this->shipmentEstimation->estimateByExtendedAddress($quote->getId(), $address);
$responseData = [
@@ -151,7 +171,8 @@ public function execute()
'message' => __('An error occurred during Shipping Details processing.')
]);
} finally {
- $this->logger->debug($this->getRequest()->getContent());
+ $compliantString = $this->gdprCompliance->process($this->getRequest()->getContent());
+ $this->logger->debug($compliantString);
}
return $result;
}
diff --git a/Cron/FetchOrderFromVipps.php b/Cron/FetchOrderFromVipps.php
index 7c2d0a3e..d610448f 100644
--- a/Cron/FetchOrderFromVipps.php
+++ b/Cron/FetchOrderFromVipps.php
@@ -27,8 +27,10 @@
Model\OrderPlace,
Gateway\Transaction\TransactionBuilder
};
+use Vipps\Payment\Gateway\Exception\WrongAmountException;
use Zend\Http\Response as ZendResponse;
use Psr\Log\LoggerInterface;
+use Magento\Framework\Exception\LocalizedException;
/**
* Class FetchOrderStatus
@@ -110,7 +112,7 @@ public function __construct(
* Create orders from Vipps that are not created in Magento yet
*
* @throws NoSuchEntityException
- * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws LocalizedException
*/
public function execute()
{
@@ -132,15 +134,19 @@ public function execute()
// fetch order status from vipps
$transaction = $this->fetchOrderStatus($quote->getReservedOrderId());
-
if ($transaction->isTransactionAborted()) {
$this->cancelQuote($quote);
- } else {
- $this->processQuote($quote, $transaction);
+ continue;
+ }
+ if ($this->shouldCancelExpiredQuote($quote, $transaction)) {
+ $this->cancelQuote($quote, 'expired');
+ continue;
}
+ // process quote
+ $this->processQuote($quote, $transaction);
} catch (VippsException $e) {
$this->processVippsException($quote, $e);
- $this->logger->critical($e->getMessage());
+ $this->logger->critical($e->getMessage() . ', quote id = ' . $quote->getId());
} catch (\Throwable $e) {
$this->logger->critical($e->getMessage() . ', quote id = ' . $quote->getId());
} finally {
@@ -154,6 +160,23 @@ public function execute()
}
}
+ /**
+ * @param Quote $quote
+ * @param Transaction $transaction
+ *
+ * @return bool
+ * @throws \Exception
+ */
+ private function shouldCancelExpiredQuote(Quote $quote, Transaction $transaction)
+ {
+ $quoteExpiredAt = (new \DateTime($quote->getUpdatedAt()))->add(new \DateInterval('PT5M')); //@codingStandardsIgnoreLine
+ $isQuoteExpired = !$quoteExpiredAt->diff(new \DateTime())->invert; //@codingStandardsIgnoreLine
+
+ return $isQuoteExpired
+ && ($transaction->getTransactionInfo()->getStatus() == Transaction::TRANSACTION_STATUS_INITIATE);
+
+ }
+
/**
* @param $orderId
*
@@ -171,11 +194,13 @@ private function fetchOrderStatus($orderId)
* @param Transaction $transaction
*
* @return OrderInterface|null
+ * @throws AlreadyExistsException
* @throws CouldNotSaveException
+ * @throws InputException
* @throws NoSuchEntityException
* @throws VippsException
- * @throws AlreadyExistsException
- * @throws InputException
+ * @throws LocalizedException
+ * @throws WrongAmountException
*/
private function processQuote(CartInterface $quote, Transaction $transaction)
{
@@ -195,18 +220,12 @@ private function processQuote(CartInterface $quote, Transaction $transaction)
/**
* @param CartInterface $quote
* @param VippsException $e
- *
- * @throws \Magento\Framework\Exception\LocalizedException
*/
private function processVippsException(CartInterface $quote, VippsException $e)
{
if ($e->getCode() < ZendResponse::STATUS_CODE_500) {
/** @var Payment $payment */
- $payment = $quote->getPayment();
- $payment->setAdditionalInformation('reserved_order_id', $quote->getReservedOrderId());
- $payment->setAdditionalInformation('cancel_reason_code', $e->getCode());
- $payment->setAdditionalInformation('cancel_reason_phrase', $e->getMessage());
- $this->cancelQuote($quote);
+ $this->cancelQuote($quote, $e);
}
}
@@ -214,12 +233,32 @@ private function processVippsException(CartInterface $quote, VippsException $e)
* Cancel quote by setting reserved_order_id to null
*
* @param CartInterface $quote
+ * @param \Exception|string $info
*/
- private function cancelQuote(CartInterface $quote)
+ private function cancelQuote(CartInterface $quote, $info = null)
{
$reservedOrderId = $quote->getReservedOrderId();
-
$quote->setReservedOrderId(null);
+
+ $additionalInformation = [];
+ if ($info instanceof \Exception) {
+ $additionalInformation = [
+ 'cancel_reason_code' => $info->getCode(),
+ 'cancel_reason_phrase' => $info->getMessage()
+ ];
+ } elseif (\is_string($info)) {
+ $additionalInformation['cancel_reason_phrase'] = $info;
+ }
+
+ $additionalInformation = array_merge(
+ $additionalInformation,
+ [
+ 'reserved_order_id' => $reservedOrderId
+ ]
+ );
+ $payment = $quote->getPayment();
+ $payment->setAdditionalInformation('vipps', $additionalInformation);
+
$this->cartRepository->save($quote);
$this->logger->debug(sprintf(
@@ -241,7 +280,7 @@ private function createCollection($currentPage)
$collection->setPageSize(self::COLLECTION_PAGE_SIZE);
$collection->setCurPage($currentPage);
- $collection->addFieldToSelect(['entity_id', 'reserved_order_id', 'store_id']); //@codingStandardsIgnoreLine
+ $collection->addFieldToSelect(['entity_id', 'reserved_order_id', 'store_id', 'updated_at']); //@codingStandardsIgnoreLine
$collection->join(
['p' => $collection->getTable('quote_payment')],
'main_table.entity_id = p.quote_id',
@@ -249,7 +288,7 @@ private function createCollection($currentPage)
);
$collection->addFieldToFilter('p.method', ['eq' => 'vipps']);
$collection->addFieldToFilter('main_table.is_active', ['in' => ['0']]);
- $collection->addFieldToFilter('main_table.updated_at', ['to' => date("Y-m-d H:i:s", time() - 1800)]);
+ $collection->addFieldToFilter('main_table.updated_at', ['to' => date("Y-m-d H:i:s", time() - 300)]); // 5min
$collection->addFieldToFilter('main_table.reserved_order_id', ['neq' => '']);
return $collection;
}
diff --git a/Gateway/Exception/ExceptionFactory.php b/Gateway/Exception/ExceptionFactory.php
index 3be43f24..de06ed0a 100644
--- a/Gateway/Exception/ExceptionFactory.php
+++ b/Gateway/Exception/ExceptionFactory.php
@@ -73,7 +73,7 @@ public function create($errorCode, $errorMessage)
'code' => $errorCode
]);
}
- $errorMessage = $this->getMessageByErrorCode($errorCode, $errorMessage);
+// $errorMessage = $this->getMessageByErrorCode($errorCode, $errorMessage);
$exceptionObject = new $groupName(__($errorMessage), null, (int)$errorCode); //@codingStandardsIgnoreLine
return $exceptionObject;
}
diff --git a/Gateway/Exception/WrongAmountException.php b/Gateway/Exception/WrongAmountException.php
new file mode 100644
index 00000000..425341b3
--- /dev/null
+++ b/Gateway/Exception/WrongAmountException.php
@@ -0,0 +1,24 @@
+setCheckoutMethod(Onepage::METHOD_REGISTER);
}
}
+ $payment->setMethod('vipps');
$quote->setIsActive(false);
$this->cartRepository->save($quote);
diff --git a/Model/Adminhtml/Source/PaymentAction.php b/Model/Adminhtml/Source/PaymentAction.php
index 571b5a5f..8a385f92 100644
--- a/Model/Adminhtml/Source/PaymentAction.php
+++ b/Model/Adminhtml/Source/PaymentAction.php
@@ -25,12 +25,12 @@ class PaymentAction implements ArrayInterface
/**
* @var string
*/
- const ACTION_CAPTURE = 'capture';
+ const ACTION_AUTHORIZE = 'authorize';
/**
* @var string
*/
- const ACTION_DIRECT_CAPTURE = 'direct_capture';
+ const ACTION_AUTHORIZE_CAPTURE = 'authorize_capture';
/**
* Possible actions on order place
@@ -41,12 +41,12 @@ public function toOptionArray()
{
return [
[
- 'value' => self::ACTION_CAPTURE,
- 'label' => __('Capture'),
+ 'value' => self::ACTION_AUTHORIZE,
+ 'label' => __('Authorize'),
],
[
- 'value' => self::ACTION_DIRECT_CAPTURE,
- 'label' => __('Direct Capture'),
+ 'value' => self::ACTION_AUTHORIZE_CAPTURE,
+ 'label' => __('Authorize and Capture'),
]
];
}
diff --git a/Model/Gdpr/Compliance.php b/Model/Gdpr/Compliance.php
new file mode 100644
index 00000000..fd6e429b
--- /dev/null
+++ b/Model/Gdpr/Compliance.php
@@ -0,0 +1,108 @@
+serializer = $serializer;
+ $this->logger = $logger;
+ }
+
+ /**
+ * Fields that require masking.
+ *
+ * @return array
+ */
+ private function getReplacementSchema(): array
+ {
+ $schema = [
+ 'addressLine1' => 1,
+ 'addressLine2' => 1,
+ 'email' => 1,
+ 'firstName' => 1,
+ 'lastName' => 1,
+ 'mobileNumber' => 1,
+ ];
+
+ return $schema;
+ }
+
+ /**
+ * Mask response fields.
+ *
+ * @param array|string $responseData
+ *
+ * @return array|string
+ */
+ public function process($responseData)
+ {
+ $wasPacked = false;
+
+ try {
+ if (\is_string($responseData)) {
+ $responseData = $this->serializer->unserialize($responseData);
+ $wasPacked = true;
+ }
+
+ if (!\is_array($responseData)) {
+ throw new SerializationException(__('Unserialization result is not an array'));
+ }
+
+ array_walk_recursive($responseData, function (&$item, $key, $schema) {
+ if (isset($schema[$key])) {
+ $item = str_repeat('x', \strlen($item));
+ }
+ }, $this->getReplacementSchema());
+
+ if ($wasPacked) {
+ $responseData = $this->serializer->serialize($responseData);
+ }
+ } catch (\Exception $e) {
+ $this->logger->critical('Gdpr compliance failed');
+ $this->logger->critical($e->getMessage());
+ }
+
+ return $responseData;
+ }
+}
diff --git a/Model/OrderPlace.php b/Model/OrderPlace.php
index 20e3971e..47f0a51e 100644
--- a/Model/OrderPlace.php
+++ b/Model/OrderPlace.php
@@ -20,6 +20,7 @@
};
use Magento\Framework\Exception\LocalizedException;
use Magento\Payment\Helper\Formatter;
+use Magento\Payment\Gateway\ConfigInterface;
use Magento\Sales\Api\{
OrderManagementInterface, Data\OrderInterface, OrderRepositoryInterface
};
@@ -31,9 +32,12 @@
CartRepositoryInterface, CartManagementInterface, Data\CartInterface
};
use Magento\Quote\Model\Quote;
+use Magento\Store\Model\ScopeInterface;
+use Vipps\Payment\Gateway\Exception\WrongAmountException;
use Vipps\Payment\Gateway\{
Transaction\Transaction, Exception\VippsException
};
+use Vipps\Payment\Model\Adminhtml\Source\PaymentAction;
/**
* Class OrderManagement
@@ -89,6 +93,11 @@ class OrderPlace
*/
private $lockManager;
+ /**
+ * @var ConfigInterface
+ */
+ private $config;
+
/**
* OrderPlace constructor.
*
@@ -101,6 +110,9 @@ class OrderPlace
* @param Processor $processor
* @param QuoteUpdater $quoteUpdater
* @param LockManager $lockManager
+ * @param ConfigInterface $config
+ *
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
OrderRepositoryInterface $orderRepository,
@@ -111,7 +123,8 @@ public function __construct(
QuoteLocator $quoteLocator,
Processor $processor,
QuoteUpdater $quoteUpdater,
- LockManager $lockManager
+ LockManager $lockManager,
+ ConfigInterface $config
) {
$this->orderRepository = $orderRepository;
$this->cartRepository = $cartRepository;
@@ -122,6 +135,7 @@ public function __construct(
$this->processor = $processor;
$this->quoteUpdater = $quoteUpdater;
$this->lockManager = $lockManager;
+ $this->config = $config;
}
/**
@@ -132,8 +146,10 @@ public function __construct(
* @throws AlreadyExistsException
* @throws CouldNotSaveException
* @throws InputException
+ * @throws LocalizedException
* @throws NoSuchEntityException
* @throws VippsException
+ * @throws WrongAmountException
*/
public function execute(CartInterface $quote, Transaction $transaction)
{
@@ -149,7 +165,14 @@ public function execute(CartInterface $quote, Transaction $transaction)
try {
$order = $this->placeOrder($quote, $transaction);
if ($order) {
- $this->authorize($order, $transaction);
+ $paymentAction = $this->config->getValue('vipps_payment_action');
+ switch ($paymentAction) {
+ case PaymentAction::ACTION_AUTHORIZE_CAPTURE:
+ $this->capture($order, $transaction);
+ break;
+ default:
+ $this->authorize($order, $transaction);
+ }
}
return $order;
@@ -211,45 +234,63 @@ private function canPlaceOrder(Transaction $transaction)
}
/**
- * @param CartInterface|Quote $quote
+ * @param CartInterface $quote
* @param Transaction $transaction
*
* @return OrderInterface|null
* @throws CouldNotSaveException
+ * @throws LocalizedException
* @throws NoSuchEntityException
* @throws VippsException
+ * @throws WrongAmountException
*/
private function placeOrder(CartInterface $quote, Transaction $transaction)
{
- $reservedOrderId = $quote->getReservedOrderId();
+ $clonedQuote = clone $quote;
+
+ $reservedOrderId = $clonedQuote->getReservedOrderId();
if (!$reservedOrderId) {
return null;
}
$order = $this->orderLocator->get($reservedOrderId);
- if ($order) {
- return $order;
- }
+ if (!$order) {
+ //this is used only for express checkout
+ $this->quoteUpdater->execute($clonedQuote);
+ /** @var Quote $clonedQuote */
+ $clonedQuote = $this->cartRepository->get($clonedQuote->getId());
+ if ($clonedQuote->getReservedOrderId() !== $reservedOrderId) {
+ return null;
+ }
- //this is used only for express checkout
- $this->quoteUpdater->execute($quote);
+ $this->prepareQuote($clonedQuote);
+ $clonedQuote->collectTotals();
- /** @var Quote $quote */
- $quote = $this->cartRepository->get($quote->getId());
- if ($quote->getReservedOrderId() !== $reservedOrderId) {
- return null;
+ $this->validateAmount($clonedQuote, $transaction);
+
+ // set quote active, collect totals and place order
+ $clonedQuote->setIsActive(true);
+ $orderId = $this->cartManagement->placeOrder($clonedQuote->getId());
+
+ $order = $this->orderRepository->get($orderId);
}
- // set quote active, collect totals and place order
- $quote->setIsActive(true);
- $quote->collectTotals();
- $this->validateAmount($quote, $transaction);
- $orderId = $this->cartManagement->placeOrder($quote->getId());
+ $clonedQuote->setReservedOrderId(null);
+ $this->cartRepository->save($clonedQuote);
- $quote->setReservedOrderId(null);
- $this->cartRepository->save($quote);
+ return $order;
+ }
- return $this->orderRepository->get($orderId);
+ /**
+ * @param CartInterface|Quote $quote
+ */
+ private function prepareQuote($quote)
+ {
+ $websiteId = $quote->getStore()->getWebsiteId();
+ foreach ($quote->getAllItems() as $item) {
+ /** @var Quote\Item $item */
+ $item->getProduct()->setWebsiteId($websiteId);
+ }
}
/**
@@ -287,6 +328,43 @@ private function authorize(OrderInterface $order, Transaction $transaction)
$this->notify($order);
}
+ /**
+ * Capture
+ *
+ * @param OrderInterface $order
+ * @param Transaction $transaction
+ *
+ * @throws LocalizedException
+ */
+ private function capture(OrderInterface $order, Transaction $transaction)
+ {
+ if ($order->getState() !== Order::STATE_NEW) {
+ return;
+ }
+
+ // preconditions
+ $totalDue = $order->getTotalDue();
+ $baseTotalDue = $order->getBaseTotalDue();
+
+ /** @var Payment $payment */
+ $payment = $order->getPayment();
+ $payment->setAmountAuthorized($totalDue);
+ $payment->setBaseAmountAuthorized($baseTotalDue);
+
+ $transactionId = $transaction->getTransactionId();
+ $payment->setTransactionId($transactionId);
+ $payment->setTransactionAdditionalInfo(
+ PaymentTransaction::RAW_DETAILS,
+ $transaction->getTransactionInfo()->getData()
+ );
+
+ // do capture
+ $this->processor->capture($payment, null);
+ $this->orderRepository->save($order);
+
+ $this->notify($order);
+ }
+
/**
* Send order conformation email if not sent
*
@@ -305,7 +383,7 @@ private function notify($order)
* @param CartInterface $quote
* @param Transaction $transaction
*
- * @throws LocalizedException
+ * @throws WrongAmountException
*/
private function validateAmount(CartInterface $quote, Transaction $transaction)
{
@@ -313,7 +391,7 @@ private function validateAmount(CartInterface $quote, Transaction $transaction)
$vippsAmount = (int)$transaction->getTransactionInfo()->getAmount();
if ($quoteAmount !== $vippsAmount) {
- throw new LocalizedException(
+ throw new WrongAmountException(
__('Reserved amount in Vipps "%1" is not equal to order amount "%2".', $vippsAmount, $quoteAmount)
);
}
diff --git a/Model/Profiling/Profiler.php b/Model/Profiling/Profiler.php
index 24fada09..95bdfed0 100644
--- a/Model/Profiling/Profiler.php
+++ b/Model/Profiling/Profiler.php
@@ -18,11 +18,13 @@
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Payment\Gateway\Http\TransferInterface;
use Magento\Store\Model\ScopeInterface;
-use Vipps\Payment\Api\Profiling\Data\ItemInterface;
-use Vipps\Payment\Api\Profiling\Data\ItemInterfaceFactory;
-use Vipps\Payment\Api\Profiling\ItemRepositoryInterface;
+use Vipps\Payment\Api\Profiling\ {
+ Data\ItemInterface, Data\ItemInterfaceFactory, ItemRepositoryInterface
+};
+
use Zend\Http\Response;
use Magento\Framework\Json\DecoderInterface;
+use Vipps\Payment\Model\Gdpr\Compliance;
class Profiler implements ProfilerInterface
{
@@ -46,6 +48,11 @@ class Profiler implements ProfilerInterface
*/
private $jsonDecoder;
+ /**
+ * @var Compliance
+ */
+ private $gdprCompliance;
+
/**
* Profiler constructor.
*
@@ -53,17 +60,20 @@ class Profiler implements ProfilerInterface
* @param ItemInterfaceFactory $dataItemFactory
* @param ItemRepositoryInterface $itemRepository
* @param DecoderInterface $jsonDecoder
+ * @param Compliance $gdprCompliance
*/
public function __construct(
ScopeConfigInterface $config,
ItemInterfaceFactory $dataItemFactory,
ItemRepositoryInterface $itemRepository,
- DecoderInterface $jsonDecoder
+ DecoderInterface $jsonDecoder,
+ Compliance $gdprCompliance
) {
$this->config = $config;
$this->dataItemFactory = $dataItemFactory;
$this->itemRepository = $itemRepository;
$this->jsonDecoder = $jsonDecoder;
+ $this->gdprCompliance = $gdprCompliance;
}
/**
@@ -150,7 +160,8 @@ private function parseResponse(Response $response)
private function depersonalizedResponse($response)
{
unset($response['url']);
- return $response;
+
+ return $this->gdprCompliance->process($response);
}
/**
diff --git a/Model/Quote/AddressUpdater.php b/Model/Quote/AddressUpdater.php
new file mode 100644
index 00000000..ac2a1f05
--- /dev/null
+++ b/Model/Quote/AddressUpdater.php
@@ -0,0 +1,105 @@
+cartRepository = $cartRepository;
+ }
+
+ /**
+ * Update quote addresses from source address.
+ *
+ * @param Quote $quote
+ * @param Address $sourceAddress
+ */
+ public function fromSourceAddress(Quote $quote, Address $sourceAddress)
+ {
+ $quote->setMayEditShippingAddress(false);
+
+ $this->updateQuoteAddresses($quote, $sourceAddress);
+ $this->disabledQuoteAddressValidation($quote);
+
+ /**
+ * Unset shipping assignment to prevent from saving / applying outdated data
+ * @see \Magento\Quote\Model\QuoteRepository\SaveHandler::processShippingAssignment
+ */
+ if ($quote->getExtensionAttributes()) {
+ $quote->getExtensionAttributes()->setShippingAssignments(null);
+ }
+ $this->cartRepository->save($quote);
+ }
+
+ /**
+ * Update quote addresses from source address.
+ *
+ * @param Quote $quote
+ * @param Address $sourceAddress
+ */
+ private function updateQuoteAddresses(Quote $quote, Address $sourceAddress)
+ {
+ if (!$quote->getIsVirtual()) {
+ $shippingAddress = $quote->getShippingAddress();
+ $this->updateAddress($shippingAddress, $sourceAddress);
+ }
+
+ $billingAddress = $quote->getBillingAddress();
+ $this->updateAddress($billingAddress, $sourceAddress);
+ $billingAddress->setSameAsBilling(false);
+ }
+
+ /**
+ * Update destination address from source.
+ *
+ * @param Address $destAddress
+ * @param Address $sourceAddress
+ */
+ private function updateAddress(Address $destAddress, Address $sourceAddress)
+ {
+ $destAddress
+ ->setStreet($sourceAddress->getStreet())
+ ->setCity($sourceAddress->getCity())
+ ->setCountryId(ShippingDetails::NORWEGIAN_COUNTRY_ID)
+ ->setPostcode($sourceAddress->getPostcode())
+ ->setSaveInAddressBook(false)
+ ->setSameAsBilling(true)
+ ->setCustomerAddressId(null);
+ }
+}
\ No newline at end of file
diff --git a/Model/QuoteUpdater.php b/Model/QuoteUpdater.php
index a93dbc33..e44c8dbf 100644
--- a/Model/QuoteUpdater.php
+++ b/Model/QuoteUpdater.php
@@ -71,14 +71,12 @@ public function __construct(
*/
public function execute(CartInterface $quote)
{
+ /** @var Quote $quote */
$response = $this->paymentDetailsProvider->get(['orderId' => $quote->getReservedOrderId()]);
$transaction = $this->transactionBuilder->setData($response)->build();
if (!$transaction->isExpressCheckout()) {
return false;
}
- $payment = $quote->getPayment();
- $payment->setMethod('vipps');
-
$quote->setMayEditShippingAddress(false);
$quote->setMayEditShippingMethod(true);
@@ -122,15 +120,16 @@ private function updateShippingAddress(Quote $quote, Transaction $transaction)
$shippingAddress->setFirstname($userDetails->getFirstName());
$shippingAddress->setEmail($userDetails->getEmail());
$shippingAddress->setTelephone($userDetails->getMobileNumber());
- $shippingAddress->setCollectShippingRates(true);
$shippingAddress->setShippingMethod($shippingDetails->getShippingMethodId());
$shippingAddress->setShippingAmount($shippingDetails->getShippingCost());
- $this->updateAddressData($shippingAddress, $shippingDetails);
//We do not save user address from vipps in Magento
$shippingAddress->setSaveInAddressBook(false);
$shippingAddress->setSameAsBilling(true);
$shippingAddress->unsCustomerAddressId();
+
+ // initiate collect totals again because we have made changes
+ $shippingAddress->setCollectShippingRates(true);
}
/**
@@ -141,7 +140,6 @@ private function updateBillingAddress(Quote $quote, Transaction $transaction)
{
$userDetails = $transaction->getUserDetails();
$billingAddress = $quote->getBillingAddress();
- $this->updateAddressData($billingAddress, $transaction->getShippingDetails());
$billingAddress->setLastname($userDetails->getLastName());
$billingAddress->setFirstname($userDetails->getFirstName());
@@ -152,20 +150,4 @@ private function updateBillingAddress(Quote $quote, Transaction $transaction)
$billingAddress->setSameAsBilling(false);
$billingAddress->unsCustomerAddressId();
}
-
- /**
- * @param Address $address
- * @param ShippingDetails $shippingDetails
- */
- private function updateAddressData(Address $address, ShippingDetails $shippingDetails)
- {
- $address->setStreet($shippingDetails->getStreet());
- $address->setCity($shippingDetails->getCity());
- $address->setCountryId(ShippingDetails::NORWEGIAN_COUNTRY_ID);
- $address->setPostcode($shippingDetails->getPostCode());
-
- $address->setSaveInAddressBook(false);
- $address->setSameAsBilling(true);
- $address->setCustomerAddressId(null);
- }
}
diff --git a/composer.json b/composer.json
index 402733cb..faecd374 100644
--- a/composer.json
+++ b/composer.json
@@ -3,7 +3,7 @@
"type": "magento2-module",
"description": "Vipps Payment Method",
"license": "proprietary",
- "version": "1.0.11",
+ "version": "1.0.12",
"require": {
"magento/framework": "101.0.*",
"magento/module-sales": "101.0.*",
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index cafe0185..a3a2eea0 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -57,6 +57,12 @@
Magento\Config\Model\Config\Source\Yesno
payment/vipps/profiling
+
+
+ payment/vipps/vipps_payment_action
+ Vipps\Payment\Model\Adminhtml\Source\PaymentAction
+ 1
+
payment/vipps/merchant_serial_number
diff --git a/etc/di.xml b/etc/di.xml
index e7f7c61e..0ddb17d8 100644
--- a/etc/di.xml
+++ b/etc/di.xml
@@ -45,6 +45,12 @@
+
+
+ Vipps\Payment\Gateway\Config\Config
+
+
+
Vipps\Payment\Gateway\Config\Config