Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions src/Plugin/Commerce/PaymentGateway/FormIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,29 @@ public function onReturn(OrderInterface $order, Request $request) {
$logContext = $sagepayError['logContext'];
$this->loggerChannelFactory->get('commerce_sagepay')
->log($logLevel, $logMessage, $logContext);
\Drupal::messenger()->{$sagepayError['drupalMessageType']}($sagepayError['drupalMessage']);
$this->messenger()->addMessage($sagepayError['drupalMessage'], $sagepayError['drupalMessageType']);
throw new PaymentGatewayException('ERROR result from Sagepay for order ' . $decryptedSagepayResponse['VendorTxCode']);
}
}

/**
* {@inheritdoc}
*/
public function onCancel(OrderInterface $order, Request $request) {
$formPassword = $this->getMode() == SAGEPAY_ENV_LIVE ? $this->configuration['enc_key'] : $this->configuration['test_enc_key'];
$decryptedSagepayResponse = $this->decryptSagepayResponse($formPassword, $this->requestStack->getCurrentRequest()->query->get('crypt'));
$sagepayError = $this->decipherSagepayError($order, $decryptedSagepayResponse);
$logLevel = $sagepayError['logLevel'];
$logMessage = $sagepayError['logMessage'];
$logContext = $sagepayError['logContext'];
$this->loggerChannelFactory->get('commerce_sagepay')
->log($logLevel, $logMessage, $logContext);
$this->messenger()->addMessage($sagepayError['drupalMessage'], $sagepayError['drupalMessageType']);
$this->messenger()->addMessage($this->t('If you canceled checkout at @gateway you may resume the checkout process here when you are ready. If you didn\'t cancel payment, there was an error taking payment with the provider. Please try later or contact us.', [
'@gateway' => $this->getDisplayLabel(),
]));
}

/**
* Create a Commerce Payment from a Sagepay form request successful result.
*
Expand Down Expand Up @@ -295,26 +313,39 @@ private function decryptSagepayResponse($formPassword, $encryptedResponse) {
public function buildTransaction(PaymentInterface $payment) {
/** @var OrderInterface $order */
$order = $payment->getOrder();

$sagepayFormApi = $this->getSagepayApi($order);

if (!$basket = $this->getBasketFromProducts($order)) {
throw new PaymentGatewayException('No basket found');
}

$basket->setDescription($this->configuration['sagepay_order_description']);
$basket->setId($order->getOrderNumber() ?? $order->id());
$sagepayFormApi->setBasket($basket);

$sagepayFormApi->addAddress($this->getBillingAddress($order));

$discounts = [];
$taxAmount = 0;
if ($adjustments = $order->getAdjustments()) {
foreach ($adjustments as $adjustment) {
if ($adjustment->getType() == 'tax') {
$taxAmount += (float) $adjustment->getAmount()->getNumber();
}
elseif (!$adjustment->isIncluded() && $adjustment->getAmount()->isNegative()) {
// Label might not be unique. Need an associative array. Add the
// count.
$discounts[] = [
'fixed' => (float) abs($adjustment->getAmount()->getNumber()),
'description' => $adjustment->getLabel(),
];
}
}
}
$basket->setDeliveryTaxAmount($taxAmount);
if (count($discounts)) {
$basket->setDiscounts($discounts);
}

if ($this->moduleHandler->moduleExists('commerce_shipping')) {
/** @var \Drupal\commerce_shipping\Entity\ShipmentInterface[] $shipments */
Expand All @@ -329,7 +360,18 @@ public function buildTransaction(PaymentInterface $payment) {
}
}
$basket->setDeliveryNetAmount($delivery);
$basket->setDeliveryTaxAmount($taxAmount);
}

// Sanity check. If the basket total isn't correct override it and log it.
if ($order->getTotalPrice()->getNumber() != (string) $basket->getAmount()) {
$basket->setOverrideAmount((float) $order->getTotalPrice()->getNumber());
$this->loggerChannelFactory->get('commerce_sagepay')->error(
'Order id @id basket total was @basket instead of @total', [
'@id' => $order->id(),
'@basket' => $basket->getAmount(),
'@total' => $order->getTotalPrice()->getNumber(),
]
);
}

$request = $sagepayFormApi->createRequest();
Expand Down
26 changes: 16 additions & 10 deletions src/Plugin/Commerce/PaymentGateway/SagepayCommon.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ protected function getBasketFromProducts(OrderInterface $order) {

/** @var ProductVariationInterface $product */
$product = $item->getPurchasedEntity();
if (!$product) {
continue;
}

if ($basket === FALSE) {
$basket = new SagepayBasket();
Expand Down Expand Up @@ -171,7 +174,10 @@ protected function getBasketFromProducts(OrderInterface $order) {
$basketItem = new SagepayItem();
$basketItem->setDescription($item->label());
$basketItem->setProductCode($product->id());
$basketItem->setProductSku(substr($product->getSku(), 0, 12));
# Can't find documentation of characters it doesn't like in a SKU but
# there seem to be plenty so this is pretty extreme.
$sku = preg_replace('/[^a-z0-9]+/i', '-', substr($product->getSku(), 0, 12));
$basketItem->setProductSku($sku);
$basketItem->setQuantity($item->getQuantity());
$basketItem->setUnitNetAmount($net);
$basketItem->setUnitTaxAmount($tax);
Expand All @@ -198,13 +204,13 @@ private function decipherSagepayError(OrderInterface $order, array $decryptedSag
switch ($decryptedSagepayResponse['Status']) {
case 'ABORT':
$logLevel = 'alert';
$logMessage = 'ABORT error from SagePay for order %order_id with message %msg';
$logMessage = 'ABORT response from SagePay for order %order_id with message %msg';
$logContext = [
'%order_id' => $order->id(),
'%msg' => $decryptedSagepayResponse['StatusDetail'],
];
$drupalMessage = $this->t('Your SagePay transaction was aborted.');
$drupalMessageType = 'addError';
$drupalMessage = $this->t('Your SagePay transaction was cancelled.');
$drupalMessageType = 'warning';
break;

case 'NOTAUTHED':
Expand All @@ -215,7 +221,7 @@ private function decipherSagepayError(OrderInterface $order, array $decryptedSag
'%msg' => $decryptedSagepayResponse['StatusDetail'],
];
$drupalMessage = $this->t('Your transaction was not authorised by SagePay.');
$drupalMessageType = 'addError';
$drupalMessageType = 'error';
break;

case 'REJECTED':
Expand All @@ -226,7 +232,7 @@ private function decipherSagepayError(OrderInterface $order, array $decryptedSag
'%msg' => $decryptedSagepayResponse['StatusDetail'],
];
$drupalMessage = $this->t('Your transaction was rejected by SagePay.');
$drupalMessageType = 'addError';
$drupalMessageType = 'error';
break;

case 'MALFORMED':
Expand All @@ -237,7 +243,7 @@ private function decipherSagepayError(OrderInterface $order, array $decryptedSag
'%msg' => $decryptedSagepayResponse['StatusDetail'],
];
$drupalMessage = $this->t('Sorry the transaction has failed.');
$drupalMessageType = 'addError';
$drupalMessageType = 'error';
break;

case 'INVALID':
Expand All @@ -248,7 +254,7 @@ private function decipherSagepayError(OrderInterface $order, array $decryptedSag
'%msg' => $decryptedSagepayResponse['StatusDetail'],
];
$drupalMessage = $this->t('Sorry the transaction has failed.');
$drupalMessageType = 'addError';
$drupalMessageType = 'error';
break;

case 'ERROR':
Expand All @@ -260,7 +266,7 @@ private function decipherSagepayError(OrderInterface $order, array $decryptedSag
'%msg' => $decryptedSagepayResponse['StatusDetail'],
];
$drupalMessage = $this->t('Sorry an error occurred while processing your transaction.');
$drupalMessageType = 'addError';
$drupalMessageType = 'error';

break;

Expand All @@ -272,7 +278,7 @@ private function decipherSagepayError(OrderInterface $order, array $decryptedSag
'%msg' => $decryptedSagepayResponse['StatusDetail'],
];
$drupalMessage = $this->t('Sorry an error occurred while processing your transaction.');
$drupalMessageType = 'addError';
$drupalMessageType = 'error';
}

return [
Expand Down
Loading