Skip to content

Commit

Permalink
Merge pull request #15 from alma/feature/ecom-1823-magento1-add-hmac-…
Browse files Browse the repository at this point in the history
…verification-on-ipn

feature : Add hmac validation to IPN controller
  • Loading branch information
joyet-simon authored Sep 23, 2024
2 parents 9aac703 + c9fd487 commit 9f4c1aa
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 3 deletions.
112 changes: 112 additions & 0 deletions src/app/code/community/Alma/Installments/Helper/Payment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* 2024 Alma / Nabla SAS
*
* THE MIT LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* @author Alma / Nabla SAS <[email protected]>
* @copyright 2024 Alma / Nabla SAS
* @license https://opensource.org/licenses/MIT The MIT License
*
*/

/**
* Alma_Installments_Helper_Payment
* Payment helper class
*/
class Alma_Installments_Helper_Payment extends Mage_Core_Helper_Abstract
{
const HEADER_SIGNATURE_KEY = 'X-Alma-Signature';

/**
* @var AlmaLogger
*/
private $logger;

public function __construct()
{
$this->logger = Mage::helper('alma/Logger')->getLogger();
}

/**
* Get header signature
*
* @return string
* @throws Alma_installments_Model_Exceptions_PaymentException
*/
private function getHeaderSignature()
{
$signature = null;

try {
$signature = $this->_getRequest()->getHeader(self::HEADER_SIGNATURE_KEY);
} catch (Zend_Controller_Request_Exception $e) {
$this->logger->error('Error retrieving header signature: ', [$e->getMessage()]);
} finally {
if (!$signature) {
throw new Alma_installments_Model_Exceptions_PaymentException('Header signature not found');
};
return $signature;
}
}

/**
* Check signature with payment id and API key with error handling
*
* @return void
* @throws Alma_installments_Model_Exceptions_PaymentException
*/
public function checkSignature($almaPaymentId)
{
if (!$this->isHmacValidated($almaPaymentId, $this->getApiKey(), $this->getHeaderSignature())) {
throw new Alma_installments_Model_Exceptions_PaymentException('Invalid signature');
}
}

/**
* Validate hmac signature
*
* @param string $almaPaymentId
* @param string $apiKey
* @param string $signature
* @return bool
*/
private function isHmacValidated($almaPaymentId, $apiKey, $signature)
{
return is_string($almaPaymentId) &&
is_string($apiKey) &&
hash_hmac('sha256', $almaPaymentId, $apiKey) === $signature;
}

/**
* Get Current API key in config with error handling
*
* @return string
* @throws Alma_installments_Model_Exceptions_PaymentException
*/
private function getApiKey()
{
/** @var Alma_Installments_Helper_Config $configHelper */
$configHelper = Mage::helper('alma/Config');
$apiKey = $configHelper->getActiveAPIKey();
if (!$apiKey) {
throw new Alma_installments_Model_Exceptions_PaymentException('API key not found');
}
return $apiKey;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

class Alma_installments_Model_Exceptions_PaymentException extends \Mage_Core_Exception
{

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
use Alma\API\Entities\Instalment;
use Alma\API\Entities\Payment;


/**
* Exception for payment validation errors
*/
class AlmaPaymentValidationError extends \Exception {
/**
* @var string
Expand All @@ -46,13 +48,26 @@ public function getReturnPath() {
}


/**
* Determine front controller actions for Alma payments
*/
class Alma_Installments_PaymentController extends Mage_Core_Controller_Front_Action
{
/**
* Cancel an order with a message
*
* @param Mage_Sales_Model_Order $order
* @param string $error
* @return void
* @throws Mage_Core_Exception
*/
private function cancelOrder($order, $error) {
$order->registerCancellation($error)->save();
}

/**
* Get checkout session model instance
*
* @return Mage_Checkout_Model_Session
*/
private function getSession()
Expand All @@ -61,8 +76,11 @@ private function getSession()
}

/**
* Validate payment and return redirect path
*
* @return string
* @throws AlmaPaymentValidationError
* @throws Mage_Core_Exception
*/
private function validatePayment()
{
Expand Down Expand Up @@ -96,7 +114,7 @@ private function validatePayment()
if (Alma_Installments_Helper_Functions::priceToCents($payment->getAmountAuthorized()) !== $almaPayment->purchase_amount) {
$internalError = $this->__(
"Paid amount (%1) does not match due amount (%2) for order %3",
Functions::priceFromCents($almaPayment->purchase_amount),
Alma_Installments_Helper_Functions::priceFromCents($almaPayment->purchase_amount),
$payment->getAmountAuthorized(),
$order->getIncrementId()
);
Expand Down Expand Up @@ -180,6 +198,12 @@ private function validatePayment()
throw new AlmaPaymentValidationError(null, 'checkout/cart');
}

/**
* Customer return action method name determine url params
*
* @return Mage_Core_Controller_Varien_Action
* @throws Mage_Core_Exception
*/
public function returnAction()
{
try {
Expand All @@ -192,11 +216,34 @@ public function returnAction()
return $this->_redirect($redirect_to, array('_secure' => true));
}

/**
* Ipn action method name determine url params
*
* @return void
* @throws Zend_Controller_Response_Exception
*/
public function ipnAction()
{
/** @var AlmaLogger $logger */
$logger = Mage::helper('alma/logger')->getLogger();

/** @var Alma_Installments_Helper_Payment $paymentHelper */
$paymentHelper = Mage::helper('alma/Payment');

$this->getResponse()->clearHeaders()->setHeader('Content-type','application/json',true);
$body = Mage::helper('core')->jsonEncode(array('success' => true));

$pid = $this->getRequest()->getParam('pid');

try {
$paymentHelper->checkSignature($pid);
} catch (Alma_installments_Model_Exceptions_PaymentException $e) {
$logger->error('Error with signature validation :', [$e->getMessage()]);
$body = Mage::helper('core')->jsonEncode(array('error' => $e->getMessage()));
$this->getResponse()->setBody($body);
return;
}

try {
$this->validatePayment();
} catch (Exception $e) {
Expand All @@ -207,9 +254,14 @@ public function ipnAction()
$this->getResponse()->setBody($body);
}

/**
* Cancel action method name determine url params
*
* @return Alma_Installments_PaymentController
* @throws Mage_Core_Exception
*/
public function cancelAction()
{
/** @var Mage_Sales_Model_Order $order */
$order = $this->getSession()->getLastRealOrder();
if ($order) {
$this->cancelOrder($order, $this->__("Order canceled by customer"));
Expand Down

0 comments on commit 9f4c1aa

Please sign in to comment.