diff --git a/README.md b/README.md index e044e07..687c74f 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,48 @@ # mod-magento_2 -PayFast Magento Module v2.4.0 for Magento 2.4.4+ on PHP 8.1 +Payfast Magento Module v2.4.0 for Magento 2.4.4+ on PHP 8.1 ----------------------------------------------------------------------------- Copyright (c) 2023 Payfast (Pty) Ltd -You (being anyone who is not Payfast (Pty) Ltd) may download and use this plugin / code in your own website in conjunction with a registered and active Payfast account. If your Payfast account is terminated for any reason, you may not use this plugin / code or part thereof. -Except as expressly indicated in this licence, you may not use, copy, modify or distribute this plugin / code or part thereof in any way. +You (being anyone who is not Payfast (Pty) Ltd) may download and use this plugin / code in your own website in +conjunction with a registered and active Payfast account. If your Payfast account is terminated for any reason, you may +not use this plugin / code or part thereof. +Except as expressly indicated in this licence, you may not use, copy, modify or distribute this plugin / code or part +thereof in any way. -In order to use Payfast with Magento 2, you will need a working Magento installation. To install Payfast follow the below instructions: +In order to use Payfast with Magento 2, you will need a working Magento installation. To install Payfast follow the +below instructions: 1. Setup ZAR on your Magento site. - In the admin panel navigate to 'Stores', and add ZAR under currency Symbols and Rates. -2. Copy the PayFast app folder to your root Magento folder. - This will not override any files on your system. + In the admin panel navigate to 'Stores', and add ZAR under currency Symbols and Rates. +2. Copy the Payfast app folder to your root Magento folder. + This will not override any files on your system. 3. You will now need to run the following commands in the given order: - 3.1 php ./bin/magento module:enable PayFast_Payfast + 3.1 php ./bin/magento module:enable Payfast_Payfast - 3.2 php ./bin/magento setup:di:compile + 3.2 php ./bin/magento setup:di:compile - 3.3 php ./bin/magento setup:static-content:deploy + 3.3 php ./bin/magento setup:static-content:deploy - 3.4 php ./bin/magento cache:clean + 3.4 php ./bin/magento cache:clean 4. Log into the admin panel and navigate to 'Stores'>'Configuration'>'Sales'>'Payment Method' and click on Payfast -5. Enable the module, as well as debugging. To test in sandbox insert 'test' in the 'server' field and use the following credentials: +5. Enable the module, as well as debugging. To test in sandbox insert 'test' in the 'server' field and use the following + credentials: - Merchant ID: 10000100 + Merchant ID: 10000100 - Merchant Key: 46f0cd694581a + Merchant Key: 46f0cd694581a - Leave the passphrase blank and setup the other options as required. + Leave the passphrase blank and setup the other options as required. - ##NB: configure sending of emails by default magento source code does not allow sending of emails when a payment module does a redirect. + ##NB: configure sending of emails by default magento source code does not allow sending of emails when a payment + module does a redirect. 6. Click 'Save Config', you are now ready to test in sandbox, click 'Save Config'. -7. Once you are ready to go live, insert 'live' into the 'server' field and input your Payfast credentials. Set debug log to 'No', and the other options as required. +7. Once you are ready to go live, insert 'live' into the 'server' field and input your Payfast credentials. Set debug + log to 'No', and the other options as required. 8. Click 'Save Config', you are now ready to process live transactions via Payfast. Please [click here](https://payfast.io/integration/shopping-carts/magento/) for more information concerning this module. diff --git a/app/code/Payfast/Payfast/Block/Form.php b/app/code/Payfast/Payfast/Block/Form.php index eb80f4c..7cf05b1 100644 --- a/app/code/Payfast/Payfast/Block/Form.php +++ b/app/code/Payfast/Payfast/Block/Form.php @@ -1,9 +1,10 @@ _payfastData = $payfastData; + $pre = __METHOD__ . " : "; + $this->_payfastData = $payfastData; $this->payfastConfigFactory = $payfastConfigFactory; parent::__construct($context, $data); $this->_logger->debug($pre . 'bof'); @@ -79,27 +80,27 @@ public function __construct( } /** - * Set template and redirect message + * Payment method code getter * - * @return void + * @return string 'payfast' */ - protected function _construct() + public function getMethodCode() { $pre = __METHOD__ . " : "; $this->_logger->debug($pre . 'bof'); - $this->_config = $this->payfastConfigFactory->create()->setMethod($this->getMethodCode()); + + return $this->_methodCode; } /** - * Payment method code getter + * Set template and redirect message * - * @return string 'payfast' + * @return void */ - public function getMethodCode() + protected function _construct() { $pre = __METHOD__ . " : "; $this->_logger->debug($pre . 'bof'); - - return $this->_methodCode; + $this->_config = $this->payfastConfigFactory->create()->setMethod($this->getMethodCode()); } } diff --git a/app/code/Payfast/Payfast/Block/Info.php b/app/code/Payfast/Payfast/Block/Info.php index 12e9a9d..8287318 100644 --- a/app/code/Payfast/Payfast/Block/Info.php +++ b/app/code/Payfast/Payfast/Block/Info.php @@ -1,4 +1,5 @@ -_hssHelper = $pfHelper; - $this->_orderFactory = $orderFactory; + $this->_hssHelper = $pfHelper; + $this->_orderFactory = $orderFactory; $this->_checkoutSession = $checkoutSession; parent::__construct($context, $data); $this->_isScopePrivate = true; - $this->readFactory = $readFactory; - $this->reader = $reader; - $this->_paymentMethod = $paymentMethod; + $this->readFactory = $readFactory; + $this->reader = $reader; + $this->_paymentMethod = $paymentMethod; } public function _prepareLayout() { $this->setMessage('Redirecting to Payfast') - ->setId('payfast_checkout') - ->setName('payfast_checkout') - ->setFormMethod('POST') - ->setFormAction($this->_paymentMethod->getPayFastUrl()) - ->setFormData($this->_paymentMethod->getStandardCheckoutFormFields()) - ->setSubmitForm(''); + ->setId('payfast_checkout') + ->setName('payfast_checkout') + ->setFormMethod('POST') + ->setFormAction($this->_paymentMethod->getPayfastUrl()) + ->setFormData($this->_paymentMethod->getStandardCheckoutFormFields()) + ->setSubmitForm( + '' + ); return parent::_prepareLayout(); // TODO: Change the autogenerated stub } diff --git a/app/code/Payfast/Payfast/Controller/AbstractPayfast.php b/app/code/Payfast/Payfast/Controller/AbstractPayfast.php index 245c666..b7ba5a0 100644 --- a/app/code/Payfast/Payfast/Controller/AbstractPayfast.php +++ b/app/code/Payfast/Payfast/Controller/AbstractPayfast.php @@ -1,7 +1,7 @@ _logger = $logger; $this->_logger->debug($pre . 'bof'); - $this->_request = $context->getRequest(); - $this->_response = $context->getResponse(); - $this->customerSession = $customerSession; - $this->checkoutSession = $checkoutSession; - $this->orderFactory = $orderFactory; - $this->_payfastSession = $payfastSession; - $this->urlHelper = $urlHelper; - $this->orderResourceModel = $orderResourceModel; - $this->pageFactory = $pageFactory; - $this->transactionFactory = $transactionFactory; - $this->paymentMethod = $paymentMethod; - $this->orderSender = $orderSender; - $this->invoiceSender = $invoiceSender; + $this->_request = $context->getRequest(); + $this->_response = $context->getResponse(); + $this->customerSession = $customerSession; + $this->checkoutSession = $checkoutSession; + $this->orderFactory = $orderFactory; + $this->_payfastSession = $payfastSession; + $this->urlHelper = $urlHelper; + $this->orderResourceModel = $orderResourceModel; + $this->pageFactory = $pageFactory; + $this->transactionFactory = $transactionFactory; + $this->paymentMethod = $paymentMethod; + $this->orderSender = $orderSender; + $this->invoiceSender = $invoiceSender; $this->salesTransactionResourceModel = $salesTransactionResourceModel; - $this->rawResult = $rawResult; - $parameters = ['params' => [$this->_configMethod]]; - $this->_objectManager = $context->getObjectManager(); - $this->_url = $context->getUrl(); - $this->_actionFlag = $context->getActionFlag(); - $this->_redirect = $context->getRedirect(); - $this->_response = $context->getResponse(); - $this->_actionFlag = $context->getActionFlag(); - $this->messageManager = $context->getMessageManager(); + $this->rawResult = $rawResult; + $parameters = ['params' => [$this->_configMethod]]; + $this->_objectManager = $context->getObjectManager(); + $this->_url = $context->getUrl(); + $this->_actionFlag = $context->getActionFlag(); + $this->_redirect = $context->getRedirect(); + $this->_response = $context->getResponse(); + $this->_actionFlag = $context->getActionFlag(); + $this->messageManager = $context->getMessageManager(); $this->_config = $this->_objectManager->create($this->_configType, $parameters); @@ -257,6 +256,60 @@ public function getConfigData($field) return $this->_config->getValue($field); } + /** + * Returns a list of action flags [flag_key] => boolean + * + * @return array + */ + public function getActionFlagList() + { + return []; + } + + /** + * Returns login url parameter for redirect + * + * @return string + */ + public function getLoginUrl() + { + return $this->orderResourceModel->getLoginUrl(); + } + + /** + * Returns action name which requires redirect + * + * @return string + */ + public function getRedirectActionName() + { + return 'index'; + } + + /** + * Redirect to login page + * + * @return void + */ + public function redirectLogin() + { + $this->_actionFlag->set('', 'no-dispatch', true); + $this->customerSession->setBeforeAuthUrl($this->_redirect->getRefererUrl()); + $this->getResponse()->setRedirect( + $this->urlHelper->addRequestParam($this->orderResourceModel->getLoginUrl(), ['context' => 'checkout']) + ); + } + + /** + * handle response + * + * @return ResponseInterface + */ + public function getResponse(): ResponseInterface + { + return $this->_response; + } + /** * Instantiate * @@ -303,11 +356,11 @@ protected function _initCheckout() } /** - * PayFast session instance getter + * Payfast session instance getter * * @return Generic */ - protected function _getSession() : Generic + protected function _getSession(): Generic { return $this->_payfastSession; } @@ -336,70 +389,18 @@ protected function _getQuote() return $this->_quote; } - /** - * Returns a list of action flags [flag_key] => boolean - * - * @return array - */ - public function getActionFlagList() - { - return []; - } - - /** - * Returns login url parameter for redirect - * - * @return string - */ - public function getLoginUrl() - { - return $this->orderResourceModel->getLoginUrl(); - } - - /** - * Returns action name which requires redirect - * - * @return string - */ - public function getRedirectActionName() - { - return 'index'; - } - - /** - * Redirect to login page - * - * @return void - */ - public function redirectLogin() - { - $this->_actionFlag->set('', 'no-dispatch', true); - $this->customerSession->setBeforeAuthUrl($this->_redirect->getRefererUrl()); - $this->getResponse()->setRedirect( - $this->urlHelper->addRequestParam($this->orderResourceModel->getLoginUrl(), ['context' => 'checkout']) - ); - } - - /** - * handle response - * - * @return ResponseInterface - */ - public function getResponse(): ResponseInterface - { - return $this->_response; - } - /** * Used to be part of inherited abstractAction now we need to code it in. * * @param $path * @param array $arguments + * * @return ResponseInterface */ - protected function _redirect($path, $arguments = []) : ResponseInterface + protected function _redirect($path, $arguments = []): ResponseInterface { $this->_redirect->redirect($this->getResponse(), $path, $arguments); + return $this->getResponse(); } diff --git a/app/code/Payfast/Payfast/Controller/Notify/Index.php b/app/code/Payfast/Payfast/Controller/Notify/Index.php index 8d02e59..a7ed8d9 100644 --- a/app/code/Payfast/Payfast/Controller/Notify/Index.php +++ b/app/code/Payfast/Payfast/Controller/Notify/Index.php @@ -1,10 +1,14 @@ _logger->debug('Notify: ' . json_encode($_POST)); $pre = __METHOD__ . " : "; $this->_logger->debug($pre . 'bof'); // Variable Initialization - $pfError = false; - $pfErrMsg = ''; - $pfData = []; - $serverMode = $this->getConfigData('server'); + $pfError = false; + $pfErrMsg = ''; + $pfData = []; + $serverMode = $this->getConfigData('server'); $pfParamString = ''; $pfHost = $this->paymentMethod->getPayfastHost($serverMode); - pflog(' PayFast ITN call received'); + pflog(' Payfast ITN call received'); pflog('Server = ' . $pfHost); - //// Notify PayFast that information has been received + //// Notify Payfast that information has been received if (!$pfError) { header('HTTP/1.0 200 OK'); flush(); } - //// Get data sent by PayFast + $passPhrase = $this->_config->getValue('passphrase'); + if (empty($passPhrase)) { + $passPhrase = null; + } + + //// Get data sent by Payfast if (!$pfError) { // Posted variables from ITN $pfData = pfGetData(); if (empty($pfData)) { - $pfError = true; + $pfError = true; $pfErrMsg = PF_ERR_BAD_ACCESS; } } @@ -71,10 +81,9 @@ public function execute(): ResultInterface if (!pfValidSignature( $pfData, $pfParamString, - $this->getConfigData('passphrase'), - $this->getConfigData('server') + $passPhrase )) { - $pfError = true; + $pfError = true; $pfErrMsg = PF_ERR_INVALID_SIGNATURE; } } @@ -84,7 +93,7 @@ public function execute(): ResultInterface pflog('Verify source IP'); if (!pfValidIP($_SERVER['REMOTE_ADDR'], $serverMode)) { - $pfError = true; + $pfError = true; $pfErrMsg = PF_ERR_BAD_SOURCE_IP; } } @@ -102,7 +111,7 @@ public function execute(): ResultInterface // Check order is in "pending payment" state if ($this->_order->getState() !== Order::STATE_PENDING_PAYMENT) { - $pfError = true; +// $pfError = true; $pfErrMsg = PF_ERR_ORDER_PROCESSED; } } @@ -112,7 +121,7 @@ public function execute(): ResultInterface pflog('Verify data received'); if (!pfValidData($pfHost, $pfParamString)) { - $pfError = true; + $pfError = true; $pfErrMsg = PF_ERR_BAD_ACCESS; } } @@ -122,7 +131,7 @@ public function execute(): ResultInterface pflog('Check status and update order'); // Successful - if ($pfData[Info::PAYMENT_STATUS] == "COMPLETE") { + if ($pfData[Info::PAYMENT_STATUS] === "COMPLETE") { $this->setPaymentAdditionalInformation($pfData); // Save invoice $this->saveInvoice(); @@ -133,6 +142,7 @@ public function execute(): ResultInterface if ($pfError) { pflog('Error occurred: ' . $pfErrMsg); $this->_logger->critical($pre . "Error occured : " . $pfErrMsg); + return $this->rawResult ->setHttpResponseCode(400) ->setHeader('Content-Type', 'text/html') @@ -145,6 +155,32 @@ public function execute(): ResultInterface ->setContents('HTTP/1.0 200'); } + /** + * Create exception in case CSRF validation failed. + * Return null if default exception will suffice. + * + * @param RequestInterface $request + * + * @return InvalidRequestException|null + */ + public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException + { + return null; + } + + /** + * Perform custom request validation. + * Return null if default validation is needed. + * + * @param RequestInterface $request + * + * @return bool|null + */ + public function validateForCsrf(RequestInterface $request): ?bool + { + return true; + } + /** * saveInvoice * @@ -156,18 +192,28 @@ protected function saveInvoice() pflog(__METHOD__ . ' : bof'); try { - $invoice = $this->_order->prepareInvoice(); /** @var \Magento\Sales\Model\Order $order */ - $order = $invoice->getOrder(); + $order = $invoice->getOrder(); + $status = $this->getConfigData('successful_order_status'); + $state = $this->getConfigData('successful_order_state'); + if (!$status || $status === '') { + $status = Order::STATE_PROCESSING; + } + if (!$state || $state === '') { + $state = Order::STATE_PROCESSING; + } $order->setIsInProcess(true); + $order->setState($state); + $order->setStatus($status); + $order->save(); $transaction = $this->transactionFactory->create(); $transaction->addObject($order)->save(); $this->orderResourceModel->save($this->_order); - if ($this->_config->getValue(PayFastConfig::KEY_SEND_CONFIRMATION_EMAIL)) { + if ($this->_config->getValue(PayfastConfig::KEY_SEND_CONFIRMATION_EMAIL)) { pflog( 'before sending order email, canSendNewEmailFlag is ' . boolval( $this->_order->getCanSendNewEmailFlag() @@ -178,7 +224,7 @@ protected function saveInvoice() pflog('after sending order email'); } - if ($this->_config->getValue(PayFastConfig::KEY_SEND_INVOICE_EMAIL)) { + if ($this->_config->getValue(PayfastConfig::KEY_SEND_INVOICE_EMAIL)) { pflog('before sending invoice email is ' . boolval($this->_order->getCanSendNewEmailFlag())); foreach ($this->_order->getInvoiceCollection() as $invoice) { pflog('sending invoice #' . $invoice->getId()); @@ -204,6 +250,7 @@ protected function saveInvoice() /** * @param $pfData + * * @throws LocalizedException * @throws \Magento\Framework\Exception\AlreadyExistsException */ @@ -234,30 +281,4 @@ private function setPaymentAdditionalInformation($pfData) pflog(__METHOD__ . ' : eof'); } - - /** - * Create exception in case CSRF validation failed. - * Return null if default exception will suffice. - * - * @param RequestInterface $request - * - * @return InvalidRequestException|null - */ - public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException - { - return null; - } - - /** - * Perform custom request validation. - * Return null if default validation is needed. - * - * @param RequestInterface $request - * - * @return bool|null - */ - public function validateForCsrf(RequestInterface $request): ?bool - { - return true; - } } diff --git a/app/code/Payfast/Payfast/Controller/Redirect/Cancel.php b/app/code/Payfast/Payfast/Controller/Redirect/Cancel.php index 4cd3aad..6e5bb04 100644 --- a/app/code/Payfast/Payfast/Controller/Redirect/Cancel.php +++ b/app/code/Payfast/Payfast/Controller/Redirect/Cancel.php @@ -1,9 +1,10 @@ _order = $this->checkoutSession->getLastRealOrder(); - $this->messageManager->addNoticeMessage('You have successfully canceled the order using PayFast Checkout.'); + $this->messageManager->addNoticeMessage('You have successfully canceled the order using Payfast Checkout.'); if ($this->_order->getId() && $this->_order->getState() != \Magento\Sales\Model\Order::STATE_CANCELED) { $this->_order->registerCancellation('Cancelled by user from ' . $this->_configMethod)->save(); @@ -54,7 +55,7 @@ public function execute() $this->_redirect('checkout/cart'); } catch (\Exception $e) { $this->_logger->error($pre . $e->getMessage()); - $this->messageManager->addExceptionMessage($e, __('We can\'t start PayFast Checkout.')); + $this->messageManager->addExceptionMessage($e, __('We can\'t start Payfast Checkout.')); $this->_redirect('checkout/cart'); } diff --git a/app/code/Payfast/Payfast/Controller/Redirect/Index.php b/app/code/Payfast/Payfast/Controller/Redirect/Index.php index a96dee4..3cc792b 100644 --- a/app/code/Payfast/Payfast/Controller/Redirect/Index.php +++ b/app/code/Payfast/Payfast/Controller/Redirect/Index.php @@ -1,15 +1,15 @@ _redirect('checkout/cart'); } catch (\Exception $e) { $this->_logger->error($pre . $e->getMessage()); - $this->messageManager->addExceptionMessage($e, __('We can\'t start PayFast Checkout.')); + $this->messageManager->addExceptionMessage($e, __('We can\'t start Payfast Checkout.')); $this->_redirect('checkout/cart'); } diff --git a/app/code/Payfast/Payfast/Controller/Redirect/Success.php b/app/code/Payfast/Payfast/Controller/Redirect/Success.php index d3d791e..c08d3f8 100644 --- a/app/code/Payfast/Payfast/Controller/Redirect/Success.php +++ b/app/code/Payfast/Payfast/Controller/Redirect/Success.php @@ -1,9 +1,10 @@ _logger->debug($pre . 'bof'); try { - return $this->_redirect('checkout/onepage/success', $this->_request->getParams()); - } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->_logger->error($pre . $e->getMessage()); $this->messageManager->addExceptionMessage($e, $e->getMessage()); + return $this->_redirect('checkout/cart'); } catch (\Exception $e) { $this->_logger->error($pre . $e->getMessage()); - $this->messageManager->addExceptionMessage($e, __('We can\'t start PayFast Checkout.')); + $this->messageManager->addExceptionMessage($e, __('We can\'t start Payfast Checkout.')); + return $this->_redirect('checkout/cart'); } - } } diff --git a/app/code/Payfast/Payfast/Gateway/Config/CanAuthorizeHandler.php b/app/code/Payfast/Payfast/Gateway/Config/CanAuthorizeHandler.php index 8980fbd..ef0e23d 100644 --- a/app/code/Payfast/Payfast/Gateway/Config/CanAuthorizeHandler.php +++ b/app/code/Payfast/Payfast/Gateway/Config/CanAuthorizeHandler.php @@ -1,8 +1,9 @@ -subjectReader->readPayment($subject); $payment = $paymentDO->getPayment(); + return $payment instanceof Payment && !(bool)$payment->getAmountPaid(); } } diff --git a/app/code/Payfast/Payfast/Gateway/Config/CanCaptureHandler.php b/app/code/Payfast/Payfast/Gateway/Config/CanCaptureHandler.php index c5a8aba..0d79b59 100644 --- a/app/code/Payfast/Payfast/Gateway/Config/CanCaptureHandler.php +++ b/app/code/Payfast/Payfast/Gateway/Config/CanCaptureHandler.php @@ -1,7 +1,9 @@ -subjectReader->readPayment($subject); $payment = $paymentDO->getPayment(); + return $payment instanceof Payment && !(bool)$payment->getAmountPaid(); } } diff --git a/app/code/Payfast/Payfast/Gateway/Http/Client/ClientMock.php b/app/code/Payfast/Payfast/Gateway/Http/Client/ClientMock.php index 5957f76..a49ff08 100644 --- a/app/code/Payfast/Payfast/Gateway/Http/Client/ClientMock.php +++ b/app/code/Payfast/Payfast/Gateway/Http/Client/ClientMock.php @@ -1,8 +1,9 @@ -generateResponseForCode( $this->getResultCode( @@ -41,8 +41,8 @@ public function placeRequest(TransferInterface $transferObject) $this->logger->debug( [ - 'method' => __METHOD__, - 'request' => $transferObject->getBody(), + 'method' => __METHOD__, + 'request' => $transferObject->getBody(), 'response' => $response ] ); @@ -50,24 +50,6 @@ public function placeRequest(TransferInterface $transferObject) return $response; } - /** - * Returns result code - * will always return false for now since PayFast needs to do a redirect. - * - * @param TransferInterface $transfer - * @return int - */ - private function getResultCode(TransferInterface $transfer) - { - $headers = $transfer->getHeaders(); - - if (isset($headers['force_result'])) { - return (int)$headers['force_result']; - } - - return self::SUCCESS; - } - /** * Generates response * @@ -80,7 +62,7 @@ protected function generateResponseForCode($resultCode) return array_merge( [ 'RESULT_CODE' => $resultCode, - 'TXN_ID' => $this->generateTxnId() + 'TXN_ID' => $this->generateTxnId() ], $this->getFieldsBasedOnResponseType($resultCode) ); @@ -94,17 +76,37 @@ protected function generateTxnId() return md5(mt_rand(0, 1000)); } + /** + * Returns result code + * will always return false for now since Payfast needs to do a redirect. + * + * @param TransferInterface $transfer + * + * @return int + */ + private function getResultCode(TransferInterface $transfer) + { + $headers = $transfer->getHeaders(); + + if (isset($headers['force_result'])) { + return (int)$headers['force_result']; + } + + return self::SUCCESS; + } + /** * Returns response fields for result code * - * @param int $resultCode + * @param int $resultCode + * * @return array */ private function getFieldsBasedOnResponseType($resultCode) { switch ($resultCode) { - case self::FAILURE: - return [ + case self::FAILURE: + return [ 'FRAUD_MSG_LIST' => [ 'Stolen card', 'Customer location differs' diff --git a/app/code/Payfast/Payfast/Gateway/Http/TransferFactory.php b/app/code/Payfast/Payfast/Gateway/Http/TransferFactory.php index 170d89d..4d0144c 100644 --- a/app/code/Payfast/Payfast/Gateway/Http/TransferFactory.php +++ b/app/code/Payfast/Payfast/Gateway/Http/TransferFactory.php @@ -1,4 +1,5 @@ -logger->debug($pre . 'bof'); @@ -71,50 +73,50 @@ public function build(array $buildSubject) $address = $order->getBillingAddress(); - $merchantId = $this->config->getValue('merchant_id', $order->getStoreId()); + $merchantId = $this->config->getValue('merchant_id', $order->getStoreId()); $merchantKey = $this->config->getValue('merchant_key', $order->getStoreId()); - $data = [ + $data = [ // Merchant details - 'merchant_id' => $merchantId, - 'merchant_key' => $merchantKey, - 'return_url' => $this->payfastConfig->getPaidSuccessUrl(), - 'cancel_url' => $this->payfastConfig->getPaidCancelUrl(), - 'notify_url' => $this->payfastConfig->getPaidNotifyUrl(), + 'merchant_id' => $merchantId, + 'merchant_key' => $merchantKey, + 'return_url' => $this->payfastConfig->getPaidSuccessUrl(), + 'cancel_url' => $this->payfastConfig->getPaidCancelUrl(), + 'notify_url' => $this->payfastConfig->getPaidNotifyUrl(), // Buyer details - 'name_first' => $address->getFirstname(), - 'name_last' => $address->getLastname(), + 'name_first' => $address->getFirstname(), + 'name_last' => $address->getLastname(), 'email_address' => $address->getEmail(), // Item details - 'm_payment_id' => $order->getOrderIncrementId(), - 'amount' => $order->getGrandTotalAmount(), + 'm_payment_id' => $order->getOrderIncrementId(), + 'amount' => $order->getGrandTotalAmount(), // 'item_name' => $this->_storeManager->getStore()->getName() .', Order #'. $order->getOrderIncrementId(), - 'item_name' => 'Order #' . $order->getOrderIncrementId(), - 'currency' => $order->getCurrencyCode(), + 'item_name' => 'Order #' . $order->getOrderIncrementId(), + 'currency' => $order->getCurrencyCode(), ]; - $pfOutput = ''; + $pfOutput = ''; // Create output string foreach ($data as $key => $val) { - if (!empty($val)) { + if (!empty($val) && $key !== 'currency') { $pfOutput .= $key . '=' . urlencode($val) . '&'; } } - $passPhrase = $this->config->getValue('passphrase', $order->getStoreId()); - $pfOutput = substr($pfOutput, 0, -1); - - if (!empty($passPhrase) && $this->config->getValue('server', $order->getStoreId()) !== 'test') { - $pfOutput = $pfOutput . "&passphrase=" . urlencode($passPhrase); + $passPhrase = $this->config->getValue('passphrase', $order->getStoreId()) ?? ''; + if (!empty($passPhrase)) { + $pfOutput .= 'passphrase=' . urlencode($passPhrase); + } else { + $pfOutput = rtrim($pfOutput, '&'); } $this->logger->debug($pre . 'pfOutput for signature is : ' . $pfOutput); $pfSignature = md5($pfOutput); - $data['signature'] = $pfSignature; + $data['signature'] = $pfSignature; $data['user_agent'] = 'Magento ' . $this->getAppVersion(); $this->logger->debug($pre . 'generated signature : ' . $data['signature']); @@ -136,8 +138,8 @@ public function build(array $buildSubject) private function getAppVersion() { $objectManager = ObjectManager::getInstance(); - $version = $objectManager->get('Magento\Framework\App\ProductMetadataInterface')->getVersion(); + $version = $objectManager->get('Magento\Framework\App\ProductMetadataInterface')->getVersion(); - return (preg_match('([0-9])', $version)) ? $version : '2.0.0'; + return (preg_match('([0-9])', $version)) ? $version : '2.0.0'; } } diff --git a/app/code/Payfast/Payfast/Gateway/Request/CaptureRequest.php b/app/code/Payfast/Payfast/Gateway/Request/CaptureRequest.php index 06ce4ac..465e65f 100644 --- a/app/code/Payfast/Payfast/Gateway/Request/CaptureRequest.php +++ b/app/code/Payfast/Payfast/Gateway/Request/CaptureRequest.php @@ -1,8 +1,9 @@ -logger->debug($pre . 'bof'); return [ - 'TXN_TYPE' => 'S', - 'TXN_ID' => $payment->getLastTransId(), - 'MERCHANT_KEY' => $this->config->getValue('merchant_gateway_key', $order->getStoreId()) - ]; + 'TXN_TYPE' => 'S', + 'TXN_ID' => $payment->getLastTransId(), + 'MERCHANT_KEY' => $this->config->getValue('merchant_gateway_key', $order->getStoreId()) + ]; } } diff --git a/app/code/Payfast/Payfast/Gateway/Request/MockDataRequest.php b/app/code/Payfast/Payfast/Gateway/Request/MockDataRequest.php index 0c940fc..5f8935c 100644 --- a/app/code/Payfast/Payfast/Gateway/Request/MockDataRequest.php +++ b/app/code/Payfast/Payfast/Gateway/Request/MockDataRequest.php @@ -1,10 +1,12 @@ -getPayment(); + $payment = $paymentDO->getPayment(); $transactionResult = $payment->getAdditionalInformation('transaction_result'); + return [ self::FORCE_RESULT => $transactionResult === null ? ClientMock::SUCCESS diff --git a/app/code/Payfast/Payfast/Gateway/Request/VoidRequest.php b/app/code/Payfast/Payfast/Gateway/Request/VoidRequest.php index e94da17..75ee989 100644 --- a/app/code/Payfast/Payfast/Gateway/Request/VoidRequest.php +++ b/app/code/Payfast/Payfast/Gateway/Request/VoidRequest.php @@ -1,8 +1,9 @@ -logger->debug($pre . 'bof'); return [ - 'TXN_TYPE' => 'V', - 'TXN_ID' => $payment->getLastTransId(), - 'MERCHANT_KEY' => $this->config->getValue('merchant_key', $order->getStoreId()) - ]; + 'TXN_TYPE' => 'V', + 'TXN_ID' => $payment->getLastTransId(), + 'MERCHANT_KEY' => $this->config->getValue('merchant_key', $order->getStoreId()) + ]; } } diff --git a/app/code/Payfast/Payfast/Gateway/Response/ItnHandler.php b/app/code/Payfast/Payfast/Gateway/Response/ItnHandler.php index 91387f4..778b010 100644 --- a/app/code/Payfast/Payfast/Gateway/Response/ItnHandler.php +++ b/app/code/Payfast/Payfast/Gateway/Response/ItnHandler.php @@ -1,4 +1,5 @@ -isSuccessfulTransaction($response)) { return $this->createResult( true, - [__('Gateway will now call PayFast via redirect method.')] + [__('Gateway will now call Payfast via redirect method.')] ); } else { return $this->createResult( false, - [__('Gateway is not called just yet, we will now call PayFast via redirect.')] + [__('Gateway is not called just yet, we will now call Payfast via redirect.')] ); } } /** - * @param array $response + * @param array $response + * * @return bool */ private function isSuccessfulTransaction(array $response) { return isset($response[self::RESULT_CODE]) - && $response[self::RESULT_CODE] !== ClientMock::FAILURE; + && $response[self::RESULT_CODE] !== ClientMock::FAILURE; } } diff --git a/app/code/Payfast/Payfast/Helper/Data.php b/app/code/Payfast/Payfast/Helper/Data.php index 359ad8f..66d46fa 100644 --- a/app/code/Payfast/Payfast/Helper/Data.php +++ b/app/code/Payfast/Payfast/Helper/Data.php @@ -1,22 +1,23 @@ _logger = $context->getLogger(); $pre = __METHOD__ . " : "; @@ -88,7 +90,7 @@ public function shouldAskToCreateBillingAgreement() * Retrieve available billing agreement methods * * @param null|string|bool|int|Store $store - * @param Quote|null $quote + * @param Quote|null $quote * * @return MethodInterface[] */ @@ -96,7 +98,7 @@ public function getBillingAgreementMethods($store = null, $quote = null) { $pre = __METHOD__ . " : "; $this->_logger->debug($pre . 'bof'); - $result = [ ]; + $result = []; // foreach ($this->_paymentData->getStoreMethods($store, $quote) as $method) { foreach ($this->_paymentData->getPaymentMethodList() as $method) { diff --git a/app/code/Payfast/Payfast/Model/AbstractConfig.php b/app/code/Payfast/Payfast/Model/AbstractConfig.php index e563eb3..f77f13a 100644 --- a/app/code/Payfast/Payfast/Model/AbstractConfig.php +++ b/app/code/Payfast/Payfast/Model/AbstractConfig.php @@ -1,9 +1,10 @@ _scopeConfig = $scopeConfig; } - /** - * @var MethodInterface - */ - protected $methodInstance; - /** * @return null|string */ @@ -84,6 +80,7 @@ public function isActive() { return $this->getValue('active'); } + /** * Sets method instance used for retrieving method specific data * @@ -144,7 +141,7 @@ public function setStoreId($storeId) * Returns payment configuration value * * @param string $key - * @param null $storeId + * @param null $storeId * * @return null|string * @@ -153,7 +150,7 @@ public function setStoreId($storeId) public function getValue($key, $storeId = null) { $underscored = strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $key)); - $path = $this->_getSpecificConfigPath($underscored); + $path = $this->_getSpecificConfigPath($underscored); if ($path !== null) { $value = $this->_scopeConfig->getValue( @@ -193,35 +190,6 @@ public function setPathPattern($pathPattern) $this->pathPattern = $pathPattern; } - /** - * Map any supported payment method into a config path by specified field name - * - * @param string $fieldName - * - * @return string|null - */ - protected function _getSpecificConfigPath($fieldName) - { - if ($this->pathPattern) { - return sprintf($this->pathPattern, $this->_methodCode, $fieldName); - } - - return "payment/{$this->_methodCode}/{$fieldName}"; - } - - /** - * Perform additional config value preparation and return new value if needed - * - * @param string $key Underscored key - * @param string $value Old value - * - * @return string Modified value or old value - */ - protected function _prepareValue($key, $value) - { - return $value; - } - /** * Check whether method available for checkout or not * @@ -248,25 +216,25 @@ public function isMethodAvailable($methodCode = null) public function isMethodActive($method) { switch ($method) { - case Config::METHOD_CODE: - $isEnabled = $this->_scopeConfig->isSetFlag( - 'payment/' . $this->getMethodCode() . '/active', - ScopeInterface::SCOPE_STORE, - $this->_storeId - ) || - $this->_scopeConfig->isSetFlag( - 'payment/' . $this->getMethodCode() . '/active', + case Config::METHOD_CODE: + $isEnabled = $this->_scopeConfig->isSetFlag( + 'payment/' . $this->getMethodCode() . '/active', + ScopeInterface::SCOPE_STORE, + $this->_storeId + ) || + $this->_scopeConfig->isSetFlag( + 'payment/' . $this->getMethodCode() . '/active', + ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + $method = $this->getMethodCode(); + break; + default: + $isEnabled = $this->_scopeConfig->isSetFlag( + "payment/{$method}/active", ScopeInterface::SCOPE_STORE, $this->_storeId ); - $method = $this->getMethodCode(); - break; - default: - $isEnabled = $this->_scopeConfig->isSetFlag( - "payment/{$method}/active", - ScopeInterface::SCOPE_STORE, - $this->_storeId - ); } return $this->isMethodSupportedForCountry($method) && $isEnabled; @@ -286,4 +254,33 @@ public function isMethodSupportedForCountry($method = null, $countryCode = null) { return true; } + + /** + * Map any supported payment method into a config path by specified field name + * + * @param string $fieldName + * + * @return string|null + */ + protected function _getSpecificConfigPath($fieldName) + { + if ($this->pathPattern) { + return sprintf($this->pathPattern, $this->_methodCode, $fieldName); + } + + return "payment/{$this->_methodCode}/{$fieldName}"; + } + + /** + * Perform additional config value preparation and return new value if needed + * + * @param string $key Underscored key + * @param string $value Old value + * + * @return string Modified value or old value + */ + protected function _prepareValue($key, $value) + { + return $value; + } } diff --git a/app/code/Payfast/Payfast/Model/Cart.php b/app/code/Payfast/Payfast/Model/Cart.php index 6fb4922..4bd7811 100644 --- a/app/code/Payfast/Payfast/Model/Cart.php +++ b/app/code/Payfast/Payfast/Model/Cart.php @@ -1,9 +1,10 @@ _amounts; } + /** + * Check whether any item has negative amount + * + * @return bool + */ + public function hasNegativeItemAmount() + { + foreach ($this->_customItems as $item) { + if ($item->getAmount() < 0) { + return true; + } + } + + return false; + } + /** * Calculate subtotal from custom items * @@ -57,13 +74,13 @@ protected function _calculateCustomItemsSubtotal() } /** - * Check the line items and totals according to PayFast business logic limitations + * Check the line items and totals according to Payfast business logic limitations * * @return void */ protected function _validate() { - $areItemsValid = false; + $areItemsValid = false; $this->_areAmountsValid = false; $referenceAmount = $this->_salesModel->getDataUsingMethod('base_grand_total'); @@ -81,7 +98,6 @@ protected function _validate() if (empty($this->_transferFlags[self::AMOUNT_DISCOUNT])) { $sum -= $this->getDiscount(); - // PayPal requires to have discount less than items subtotal $this->_areAmountsValid = round($this->getDiscount(), 4) < round($itemsSubtotal, 4); } else { $this->_areAmountsValid = $itemsSubtotal > 0.00001; @@ -100,12 +116,12 @@ protected function _validate() if (!$areItemsValid) { $this->_salesModelItems = []; - $this->_customItems = []; + $this->_customItems = []; } } /** - * Import items from sales model with workarounds for PayFast + * Import items from sales model with workarounds for Payfast * * @return void */ @@ -119,23 +135,22 @@ protected function _importItemsFromSalesModel() } $amount = $item->getPrice(); - $qty = $item->getQty(); + $qty = $item->getQty(); $subAggregatedLabel = ''; - // workaround in case if item subtotal precision is not compatible with PayPal (.2) if ($amount - round($amount, 2)) { - $amount = $amount * $qty; + $amount = $amount * $qty; $subAggregatedLabel = ' x' . $qty; - $qty = 1; + $qty = 1; } // aggregate item price if item qty * price does not match row total $itemBaseRowTotal = $item->getOriginalItem()->getBaseRowTotal(); if ($amount * $qty != $itemBaseRowTotal) { - $amount = (double)$itemBaseRowTotal; + $amount = (double)$itemBaseRowTotal; $subAggregatedLabel = ' x' . $qty; - $qty = 1; + $qty = 1; } $this->_salesModelItems[] = $this->_createItemFromData( @@ -168,9 +183,9 @@ protected function _importItemsFromSalesModel() * - Apply Customer Tax = After Discount * - Create a cart price rule with % discount applied to the Shipping Amount * - run shopping cart and estimate shipping - * - go to PayPal * - * @param \Magento\Payment\Model\Cart\SalesModel\SalesModelInterface $salesEntity + * @param \Magento\Payment\Model\Cart\SalesModel\SalesModelInterface $salesEntity + * * @return void */ protected function _applyDiscountTaxCompensationWorkaround( @@ -180,19 +195,4 @@ protected function _applyDiscountTaxCompensationWorkaround( $this->addTax((double)$dataContainer->getBaseDiscountTaxCompensationAmount()); $this->addTax((double)$dataContainer->getBaseShippingDiscountTaxCompensationAmnt()); } - - /** - * Check whether any item has negative amount - * - * @return bool - */ - public function hasNegativeItemAmount() - { - foreach ($this->_customItems as $item) { - if ($item->getAmount() < 0) { - return true; - } - } - return false; - } } diff --git a/app/code/Payfast/Payfast/Model/Config.php b/app/code/Payfast/Payfast/Model/Config.php index 3bfe6c3..5620da8 100644 --- a/app/code/Payfast/Payfast/Model/Config.php +++ b/app/code/Payfast/Payfast/Model/Config.php @@ -1,7 +1,7 @@ _logger = $logger; parent::__construct($scopeConfig); $this->directoryHelper = $directoryHelper; - $this->_storeManager = $storeManager; - $this->_assetRepo = $assetRepo; - $this->_urlBuilder = $urlBuilder; + $this->_storeManager = $storeManager; + $this->_assetRepo = $assetRepo; + $this->_urlBuilder = $urlBuilder; if ($params) { $method = array_shift($params); @@ -102,9 +102,9 @@ public function __construct( /** * Checkout redirect URL getter for onepage checkout (hardcode) * - * @see \Magento\Checkout\Controller\Onepage::savePaymentAction() - * @see \Magento\Quote\Model\Quote\Payment::getCheckoutRedirectUrl() * @return string + * @see \Magento\Quote\Model\Quote\Payment::getCheckoutRedirectUrl() + * @see \Magento\Checkout\Controller\Onepage::savePaymentAction() */ public function getCheckoutRedirectUrl() { @@ -113,12 +113,13 @@ public function getCheckoutRedirectUrl() return $this->_urlBuilder->getUrl('payfast/redirect'); } + /** * getPaidSuccessUrl */ public function getPaidSuccessUrl() { - return $this->_urlBuilder->getUrl('payfast/redirect/success', [ '_secure' => true ]); + return $this->_urlBuilder->getUrl('payfast/redirect/success', ['_secure' => true]); } /** @@ -126,21 +127,23 @@ public function getPaidSuccessUrl() */ public function getPaidCancelUrl() { - return $this->_urlBuilder->getUrl('payfast/redirect/cancel', [ '_secure' => true ]); + return $this->_urlBuilder->getUrl('payfast/redirect/cancel', ['_secure' => true]); } + /** * getPaidNotifyUrl */ public function getPaidNotifyUrl() { - return $this->_urlBuilder->getUrl('payfast/notify', [ '_secure' => true ]); + return $this->_urlBuilder->getUrl('payfast/notify', ['_secure' => true]); } /** * Check whether method available for checkout or not * Logic based on merchant country, methods dependence * - * @param string|null $methodCode + * @param string|null $methodCode + * * @return bool * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ @@ -150,7 +153,7 @@ public function isMethodAvailable($methodCode = null) } /** - * Return buyer country codes supported by PayFast + * Return buyer country codes supported by Payfast * * @return string[] */ @@ -173,8 +176,9 @@ public function getMerchantCountry() * Check whether method supported for specified country or not * Use $_methodCode and merchant country by default * - * @param string|null $method - * @param string|null $countryCode + * @param string|null $method + * @param string|null $countryCode + * * @return bool */ public function isMethodSupportedForCountry($method = null, $countryCode = null) @@ -193,7 +197,8 @@ public function isMethodSupportedForCountry($method = null, $countryCode = null) /** * Return list of allowed methods for specified country iso code * - * @param string|null $countryCode 2-letters iso code + * @param string|null $countryCode 2-letters iso code + * * @return array * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -208,40 +213,41 @@ public function getCountryMethods($countryCode = null) if ($countryCode === null) { return $countryMethods; } + return isset($countryMethods[$countryCode]) ? $countryMethods[$countryCode] : $countryMethods['other']; } /** - * Get PayFast "mark" image URL + * Get Payfast "mark" image URL * may be his can be place in the config xml * * @return string */ public function getPaymentMarkImageUrl() { - return $this->_assetRepo->getUrl('Payfast_Payfast::images/logo.png'); + return $this->_assetRepo->getUrl('Payfast_Payfast::images/logo.svg'); } /** - * Get "What Is PayFast" localized URL + * Get "What Is Payfast" localized URL * Supposed to be used with "mark" as popup window * * @return string */ public function getPaymentMarkWhatIsPayfast() { - return 'PayFast Payment gateway'; + return 'Payfast Payment gateway'; } /** - * Mapper from PayFast-specific payment actions to Magento payment actions + * Mapper from Payfast-specific payment actions to Magento payment actions * * @return string|null */ public function getPaymentAction() { $paymentAction = null; - $pre = __METHOD__ . ' : '; + $pre = __METHOD__ . ' : '; $this->_logger->debug($pre . 'bof'); $action = $this->getValue('paymentAction'); @@ -249,15 +255,15 @@ public function getPaymentAction() $this->_logger->debug($pre . 'payment action is : ' . $action); switch ($action) { - case self::PAYMENT_ACTION_AUTH: - $paymentAction = self::ACTION_AUTHORIZE; - break; - case self::PAYMENT_ACTION_SALE: - $paymentAction = self::ACTION_AUTHORIZE_CAPTURE; - break; - case self::PAYMENT_ACTION_ORDER: - $paymentAction = self::ACTION_ORDER; - break; + case self::PAYMENT_ACTION_AUTH: + $paymentAction = self::ACTION_AUTHORIZE; + break; + case self::PAYMENT_ACTION_SALE: + $paymentAction = self::ACTION_AUTHORIZE_CAPTURE; + break; + case self::PAYMENT_ACTION_ORDER: + $paymentAction = self::ACTION_ORDER; + break; } $this->_logger->debug($pre . 'eof : paymentAction is ' . $paymentAction); @@ -268,13 +274,14 @@ public function getPaymentAction() /** * Check whether specified currency code is supported * - * @param string $code + * @param string $code + * * @return bool */ public function isCurrencyCodeSupported($code) { $supported = false; - $pre = __METHOD__ . ' : '; + $pre = __METHOD__ . ' : '; $this->_logger->debug($pre . "bof and code: {$code}"); @@ -288,14 +295,15 @@ public function isCurrencyCodeSupported($code) } /** - * _mapPayFastFieldset - * Map PayFast config fields + * _mapPayfastFieldset + * Map Payfast config fields + * + * @param string $fieldName * - * @param string $fieldName * @return string|null * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - protected function _mapPayFastFieldset($fieldName) + protected function _mapPayfastFieldset($fieldName) { return "payment/{$this->_methodCode}/{$fieldName}"; } @@ -303,13 +311,14 @@ protected function _mapPayFastFieldset($fieldName) /** * Map any supported payment method into a config path by specified field name * - * @param string $fieldName + * @param string $fieldName + * * @return string|null * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _getSpecificConfigPath($fieldName) { - return $this->_mapPayFastFieldset($fieldName); + return $this->_mapPayfastFieldset($fieldName); } } diff --git a/app/code/Payfast/Payfast/Model/Config.php-org b/app/code/Payfast/Payfast/Model/Config.php-org deleted file mode 100644 index c354e6b..0000000 --- a/app/code/Payfast/Payfast/Model/Config.php-org +++ /dev/null @@ -1,269 +0,0 @@ -_logger = $logger; - parent::__construct($scopeConfig); - $this->directoryHelper = $directoryHelper; - $this->_storeManager = $storeManager; - $this->_assetRepo = $assetRepo; - - if ($params) { - $method = array_shift($params); - $this->setMethod($method); - if ($params) { - $storeId = array_shift($params); - $this->setStoreId($storeId); - } - } - } - - /** - * Check whether method available for checkout or not - * Logic based on merchant country, methods dependence - * - * @param string|null $methodCode - * @return bool - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function isMethodAvailable($methodCode = null) - { - return parent::isMethodAvailable($methodCode); - } - - - /** - * Return buyer country codes supported by PayFast - * - * @return string[] - */ - public function getSupportedBuyerCountryCodes() - { - return $this->_supportedBuyerCountryCodes; - } - - /** - * Return merchant country code, use default country if it not specified in General settings - * - * @return string - */ - public function getMerchantCountry() - { - return $this->directoryHelper->getDefaultCountry($this->_storeId); - } - - /** - * Check whether method supported for specified country or not - * Use $_methodCode and merchant country by default - * - * @param string|null $method - * @param string|null $countryCode - * @return bool - */ - public function isMethodSupportedForCountry($method = null, $countryCode = null) - { - if ($method === null) { - $method = $this->getMethodCode(); - } - - if ($countryCode === null) { - $countryCode = $this->getMerchantCountry(); - } - - return in_array($method, $this->getCountryMethods($countryCode)); - } - - /** - * Return list of allowed methods for specified country iso code - * - * @param string|null $countryCode 2-letters iso code - * @return array - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function getCountryMethods($countryCode = null) - { - $countryMethods = [ - 'other' => [ - self::METHOD_CODE, - ], - - ]; - if ($countryCode === null) { - return $countryMethods; - } - return isset($countryMethods[$countryCode]) ? $countryMethods[$countryCode] : $countryMethods['other']; - } - - /** - * Get PayFast "mark" image URL - * may be his can be place in the config xml - * - * @return string - */ - public function getPaymentMarkImageUrl() - { - return $this->_assetRepo->getUrl('Payfast_Payfast::images/logo.png'); - } - - /** - * Get "What Is PayFast" localized URL - * Supposed to be used with "mark" as popup window - * - * @return string - */ - public function getPaymentMarkWhatIsPayfast() - { - return 'PayFast Payment gateway'; - } - - /** - * Mapper from PayFast-specific payment actions to Magento payment actions - * - * @return string|null - */ - public function getPaymentAction() - { - $paymentAction = null; - $pre = __METHOD__ . ' : '; - $this->_logger->debug( $pre . 'bof' ); - - $action = $this->getValue( 'paymentAction' ); - - switch ( $action ) - { - case self::PAYMENT_ACTION_AUTH: - $paymentAction = \Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE; - break; - case self::PAYMENT_ACTION_SALE: - $paymentAction = \Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE_CAPTURE; - break; - case self::PAYMENT_ACTION_ORDER: - $paymentAction = \Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER; - break; - } - - $this->_logger->debug( $pre . 'eof : paymentAction is ' . $paymentAction ); - - return $paymentAction; - } - - /** - * Check whether specified currency code is supported - * - * @param string $code - * @return bool - */ - public function isCurrencyCodeSupported($code) - { - $supported = false; - $pre = __METHOD__ . ' : '; - - $this->_logger->debug($pre . "bof and code: {$code}" ); - - if (in_array($code, $this->_supportedCurrencyCodes)) { - $supported = true; - } - - $this->_logger->debug( $pre . "eof and supported : {$supported}" ); - - return $supported; - } - - /** - * Check whether specified locale code is supported. Fallback to en_US - * - * @param string|null $localeCode - * @return string - */ - protected function _getSupportedLocaleCode($localeCode = null) - { - if (!$localeCode || !in_array($localeCode, $this->_supportedImageLocales)) { - return 'en_US'; - } - return $localeCode; - } - - /** - * _mapPayFastFieldset - * Map PayFast config fields - * - * @param string $fieldName - * @return string|null - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function _mapPayFastFieldset($fieldName) - { - return "payment/{$this->_methodCode}/{$fieldName}"; - } - - /** - * Map any supported payment method into a config path by specified field name - * - * @param string $fieldName - * @return string|null - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - protected function _getSpecificConfigPath($fieldName) - { - return $this->_mapPayFastFieldset($fieldName); - } -} diff --git a/app/code/Payfast/Payfast/Model/Info.php b/app/code/Payfast/Payfast/Model/Info.php index 0d479d0..c6186a1 100644 --- a/app/code/Payfast/Payfast/Model/Info.php +++ b/app/code/Payfast/Payfast/Model/Info.php @@ -1,7 +1,7 @@ _storeManager = $storeManager; - $this->_urlBuilder = $urlBuilder; - $this->_checkoutSession = $checkoutSession; - $this->_exception = $exception; + $this->_storeManager = $storeManager; + $this->_urlBuilder = $urlBuilder; + $this->_checkoutSession = $checkoutSession; + $this->_exception = $exception; $this->transactionRepository = $transactionRepository; - $this->transactionBuilder = $transactionBuilder; + $this->transactionBuilder = $transactionBuilder; - $parameters = [ 'params' => [ $this->_code ] ]; + $parameters = ['params' => [$this->_code]]; $this->_config = $configFactory->create($parameters); - if (! defined('PF_DEBUG')) { + if (!defined('PF_DEBUG')) { define('PF_DEBUG', $this->_config->getValue('debug')); } } @@ -191,8 +190,8 @@ public function canUseForCurrency($currencyCode) /** * Payment action getter compatible with payment model * - * @see \Magento\Sales\Model\Payment::place() * @return string + * @see \Magento\Sales\Model\Payment::place() */ public function getConfigPaymentAction() { @@ -211,31 +210,12 @@ public function isAvailable(CartInterface $quote = null) return $this->_config->isMethodAvailable(); } - /** - * @return mixed - */ - protected function getStoreName() - { - $pre = __METHOD__ . " : "; - pflog($pre . 'bof'); - - $storeName = $this->_config->getValue( - 'general/store_information/name', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ); - - pflog($pre . 'store name is ' . $storeName); - - return $storeName; - } - /** * this where we compile data posted by the form to payfast * * @return array - * @throws \Magento\Framework\Exception\NoSuchEntityException */ - public function getStandardCheckoutFormFields() + public function getStandardCheckoutFormFields(): array { $pre = __METHOD__ . ' : '; // Variable initialization @@ -248,13 +228,16 @@ public function getStandardCheckoutFormFields() // If NOT test mode, use normal credentials if ($this->_config->getValue('server') == 'live') { - $merchantId = $this->_config->getValue('merchant_id'); + $merchantId = $this->_config->getValue('merchant_id'); $merchantKey = $this->_config->getValue('merchant_key'); - } - // If test mode, use generic sandbox credentials + } // If test mode, use generic / specific sandbox credentials else { - $merchantId = '10000100'; - $merchantKey = '46f0cd694581a'; + $merchantId = !empty($this->_config->getValue('merchant_id')) ? + $this->_config->getValue('merchant_id') : + '10000100'; + $merchantKey = !empty($this->_config->getValue('merchant_key')) ? + $this->_config->getValue('merchant_key') : + '46f0cd694581a'; } // Create description @@ -267,22 +250,22 @@ public function getStandardCheckoutFormFields() // Construct data for the form $data = [ // Merchant details - 'merchant_id' => $merchantId, - 'merchant_key' => $merchantKey, - 'return_url' => $this->getPaidSuccessUrl(), - 'cancel_url' => $this->getPaidCancelUrl(), - 'notify_url' => $this->getPaidNotifyUrl(), + 'merchant_id' => $merchantId, + 'merchant_key' => $merchantKey, + 'return_url' => $this->getPaidSuccessUrl(), + 'cancel_url' => $this->getPaidCancelUrl(), + 'notify_url' => $this->getPaidNotifyUrl(), // Buyer details - 'name_first' => $order->getData('customer_firstname'), - 'name_last' => $order->getData('customer_lastname'), + 'name_first' => $order->getData('customer_firstname'), + 'name_last' => $order->getData('customer_lastname'), 'email_address' => $order->getData('customer_email'), // Item details - 'm_payment_id' => $order->getRealOrderId(), - 'amount' => $this->getTotalAmount($order), - 'item_name' => $this->_storeManager->getStore()->getName() . ', Order #' . $order->getRealOrderId(), - //this html special characters breaks signature. + 'm_payment_id' => $order->getRealOrderId(), + 'amount' => $this->getTotalAmount($order), + 'item_name' => 'Order #' . $order->getRealOrderId(), + //this html special characters breaks signature. //'item_description' => $pfDescription, ]; @@ -295,35 +278,23 @@ public function getStandardCheckoutFormFields() } $passPhrase = $this->_config->getValue('passphrase'); - $pfOutput = substr($pfOutput, 0, -1); - - if (!empty($passPhrase) && $this->_config->getValue('server') !== 'test') { - $pfOutput = $pfOutput . "&passphrase=" . urlencode($passPhrase); + if (!empty($passPhrase)) { + $pfOutput .= 'passphrase=' . urlencode($passPhrase); + } else { + $pfOutput = rtrim($pfOutput, '&'); } pflog($pre . 'pfOutput for signature is : ' . $pfOutput); $pfSignature = md5($pfOutput); - $data['signature'] = $pfSignature; + $data['signature'] = $pfSignature; $data['user_agent'] = 'Magento ' . $this->getAppVersion(); pflog($pre . 'data is :' . print_r($data, true)); - return($data); + return ($data); } - /** - * getAppVersion - * - * @return string - */ - private function getAppVersion(): string - { - $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); - $version = $objectManager->get('Magento\Framework\App\ProductMetadataInterface')->getVersion(); - - return (preg_match('([0-9])', $version)) ? $version : '2.0.0'; - } /** * getTotalAmount */ @@ -351,24 +322,9 @@ public function getNumberFormat($number) */ public function getPaidSuccessUrl() { - return $this->_urlBuilder->getUrl('payfast/redirect/success', [ '_secure' => true ]); - } - - /** - * Get transaction with type order - * - * @param OrderPaymentInterface $payment - * - * @return false|TransactionInterface - */ - protected function getOrderTransaction($payment) - { - return $this->transactionRepository->getByTransactionType(Transaction::TYPE_ORDER, $payment->getId(), $payment->getOrder()->getId()); + return $this->_urlBuilder->getUrl('payfast/redirect/success', ['_secure' => true]); } - /* - * called dynamically by checkout's framework. - */ public function getOrderPlaceRedirectUrl() { $pre = __METHOD__ . " : "; @@ -376,12 +332,13 @@ public function getOrderPlaceRedirectUrl() return $this->_urlBuilder->getUrl('payfast/redirect'); } + /** * Checkout redirect URL getter for onepage checkout (hardcode) * - * @see \Magento\Checkout\Controller\Onepage::savePaymentAction() - * @see Quote\Payment::getCheckoutRedirectUrl() * @return string + * @see Quote\Payment::getCheckoutRedirectUrl() + * @see \Magento\Checkout\Controller\Onepage::savePaymentAction() */ public function getCheckoutRedirectUrl() { @@ -391,30 +348,34 @@ public function getCheckoutRedirectUrl() return $this->_urlBuilder->getUrl('payfast/redirect'); } - /** * getPaidCancelUrl */ public function getPaidCancelUrl() { - return $this->_urlBuilder->getUrl('payfast/redirect/cancel', [ '_secure' => true ]); + return $this->_urlBuilder->getUrl('payfast/redirect/cancel', ['_secure' => true]); } + + /* + * called dynamically by checkout's framework. + */ + /** * getPaidNotifyUrl */ public function getPaidNotifyUrl() { - return $this->_urlBuilder->getUrl('payfast/notify', [ '_secure' => true ]); + return $this->_urlBuilder->getUrl('payfast/notify', ['_secure' => true]); } /** - * getPayFastUrl + * getPayfastUrl * - * Get URL for form submission to PayFast. + * Get URL for form submission to Payfast. */ - public function getPayFastUrl() + public function getPayfastUrl() { - return('https://' . $this->getPayfastHost($this->_config->getValue('server')) . '/eng/process'); + return ('https://' . $this->getPayfastHost($this->_config->getValue('server')) . '/eng/process'); } /** @@ -424,7 +385,7 @@ public function getPayFastUrl() */ public function getPayfastHost($serverMode) { - if (!in_array($serverMode, [ 'live', 'test' ])) { + if (!in_array($serverMode, ['live', 'test'])) { $pfHost = "payfast.{$serverMode}"; } else { $pfHost = (($serverMode == 'live') ? 'www' : 'sandbox') . '.payfast.co.za'; @@ -432,4 +393,51 @@ public function getPayfastHost($serverMode) return $pfHost; } + + /** + * @return mixed + */ + protected function getStoreName() + { + $pre = __METHOD__ . " : "; + pflog($pre . 'bof'); + + $storeName = $this->_config->getValue( + 'general/store_information/name', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + + pflog($pre . 'store name is ' . $storeName); + + return $storeName; + } + + /** + * Get transaction with type order + * + * @param OrderPaymentInterface $payment + * + * @return false|TransactionInterface + */ + protected function getOrderTransaction($payment) + { + return $this->transactionRepository->getByTransactionType( + Transaction::TYPE_ORDER, + $payment->getId(), + $payment->getOrder()->getId() + ); + } + + /** + * getAppVersion + * + * @return string + */ + private function getAppVersion(): string + { + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + $version = $objectManager->get('Magento\Framework\App\ProductMetadataInterface')->getVersion(); + + return (preg_match('([0-9])', $version)) ? $version : '2.0.0'; + } } diff --git a/app/code/Payfast/Payfast/Model/PayfastConfigProvider.php b/app/code/Payfast/Payfast/Model/PayfastConfigProvider.php index d232f95..1f337e3 100644 --- a/app/code/Payfast/Payfast/Model/PayfastConfigProvider.php +++ b/app/code/Payfast/Payfast/Model/PayfastConfigProvider.php @@ -1,9 +1,10 @@ _logger = $logger; - $pre = __METHOD__ . ' : '; + $pre = __METHOD__ . ' : '; $this->_logger->debug($pre . 'bof'); - $this->localeResolver = $localeResolver; - $this->config = $configFactory->create(); + $this->localeResolver = $localeResolver; + $this->config = $configFactory->create(); $this->currentCustomer = $currentCustomer; - $this->payfastHelper = $payfastHelper; - $this->paymentHelper = $paymentHelper; + $this->payfastHelper = $payfastHelper; + $this->paymentHelper = $paymentHelper; foreach ($this->methodCodes as $code) { $this->methods[$code] = $this->paymentHelper->getMethodInstance($code); @@ -104,7 +105,7 @@ public function getConfig() $config = [ 'payment' => [ 'payfast' => [ - 'paymentAcceptanceMarkSrc' => $this->config->getPaymentMarkImageUrl(), + 'paymentAcceptanceMarkSrc' => $this->config->getPaymentMarkImageUrl(), 'paymentAcceptanceMarkHref' => $this->config->getPaymentMarkWhatIsPayfast(), ] ] @@ -112,20 +113,22 @@ public function getConfig() foreach ($this->methodCodes as $code) { if ($this->methods[$code]->isAvailable()) { - $config['payment']['payfast']['redirectUrl'][$code] = $this->getMethodRedirectUrl($code); + $config['payment']['payfast']['redirectUrl'][$code] = $this->getMethodRedirectUrl($code); $config['payment']['payfast']['billingAgreementCode'][$code] = $this->getBillingAgreementCode($code); $config['payment']['payfast']['isActive'][$code] = $this->config->isActive(); } } $this->_logger->debug($pre . 'eof', $config); + return $config; } /** * Return redirect URL for method * - * @param string $code + * @param string $code + * * @return mixed */ protected function getMethodRedirectUrl($code) @@ -137,13 +140,15 @@ protected function getMethodRedirectUrl($code) $methodUrl = $this->config->getCheckoutRedirectUrl(); $this->_logger->debug($pre . 'eof'); + return $methodUrl; } /** * Return billing agreement code for method * - * @param string $code + * @param string $code + * * @return null|string */ protected function getBillingAgreementCode($code) diff --git a/app/code/Payfast/Payfast/Model/payfast.log b/app/code/Payfast/Payfast/Model/payfast.log deleted file mode 100644 index e69de29..0000000 diff --git a/app/code/Payfast/Payfast/Model/payfast_common.inc b/app/code/Payfast/Payfast/Model/payfast_common.inc index 07e25a5..3786b76 100644 --- a/app/code/Payfast/Payfast/Model/payfast_common.inc +++ b/app/code/Payfast/Payfast/Model/payfast_common.inc @@ -2,47 +2,50 @@ /** * payfast_common.inc * - * Copyright (c) 2008 PayFast (Pty) Ltd - * You (being anyone who is not PayFast (Pty) Ltd) may download and use this plugin / code in your own website in conjunction with a registered and active PayFast account. If your PayFast account is terminated for any reason, you may not use this plugin / code or part thereof. - * Except as expressly indicated in this licence, you may not use, copy, modify or distribute this plugin / code or part thereof in any way. - * - * @author Jonathan Smit + * Copyright (c) 2023 Payfast (Pty) Ltd + * You (being anyone who is not Payfast (Pty) Ltd) may download and use this plugin / code in your own website + * in conjunction with a registered and active Payfast account. If your Payfast account is terminated for any reason, + * you may not use this plugin / code or part thereof. + * Except as expressly indicated in this licence, you may not use, copy, modify or distribute this plugin / code or + * part thereof in any way. */ //// Create user agent string // User agent constituents (for cURL) define('PF_SOFTWARE_NAME', 'Magento'); -define('PF_SOFTWARE_VER', '2.0'); -define('PF_MODULE_NAME', 'PayFast-Magento'); -define('PF_MODULE_VER', '1.1'); +define('PF_SOFTWARE_VER', '2.4.4'); +define('PF_MODULE_NAME', 'Payfast-Magento'); +define('PF_MODULE_VER', '2.4.1'); // Features // - PHP -$pfFeatures = 'PHP '. phpversion() .';'; +$pfFeatures = 'PHP ' . phpversion() . ';'; // - cURL -if(in_array('curl', get_loaded_extensions()) ) { +if (in_array('curl', get_loaded_extensions())) { define('PF_CURL', ''); - $pfVersion = curl_version(); - $pfFeatures .= ' curl '. $pfVersion['version'] .';'; -} -else { + $pfVersion = curl_version(); + $pfFeatures .= ' curl ' . $pfVersion['version'] . ';'; +} else { $pfFeatures .= ' nocurl;'; } // Create user agrent -define('PF_USER_AGENT', PF_SOFTWARE_NAME .'/'. PF_SOFTWARE_VER .' ('. trim($pfFeatures) .') '. PF_MODULE_NAME .'/'. PF_MODULE_VER); +define( + 'PF_USER_AGENT', + PF_SOFTWARE_NAME . '/' . PF_SOFTWARE_VER . ' (' . trim($pfFeatures) . ') ' . PF_MODULE_NAME . '/' . PF_MODULE_VER +); // General Defines define('PF_TIMEOUT', 15); define('PF_EPSILON', 0.01); // Messages - // Error +// Error define('PF_ERR_AMOUNT_MISMATCH', 'Amount mismatch'); define('PF_ERR_BAD_ACCESS', 'Bad access of page'); define('PF_ERR_BAD_SOURCE_IP', 'Bad source IP address'); -define('PF_ERR_CONNECT_FAILED', 'Failed to connect to PayFast'); +define('PF_ERR_CONNECT_FAILED', 'Failed to connect to Payfast'); define('PF_ERR_INVALID_SIGNATURE', 'Security signature mismatch'); define('PF_ERR_MERCHANT_ID_MISMATCH', 'Merchant ID mismatch'); define('PF_ERR_NO_SESSION', 'No saved session found for ITN transaction'); @@ -55,14 +58,14 @@ define('PF_ERR_PDT_TOKEN_MISSING', 'PDT token not present in URL'); define('PF_ERR_SESSIONID_MISMATCH', 'Session ID mismatch'); define('PF_ERR_UNKNOWN', 'Unkown error occurred'); - // General +// General define('PF_MSG_OK', 'Payment was successful'); define('PF_MSG_FAILED', 'Payment has failed'); define( 'PF_MSG_PENDING', - 'The payment is pending. Please note, you will receive another Instant'. - ' Transaction Notification when the payment status changes to'. - ' "Completed", or "Failed"' + 'The payment is pending. Please note, you will receive another Instant' . + ' Transaction Notification when the payment status changes to' . + ' "Completed", or "Failed"' ); // {{{ pfLog @@ -71,224 +74,197 @@ define( * * Log function for logging output. * - * @author Jonathan Smit * @param $msg String Message to log * @param $close Boolean Whether to close the log file or not */ -function pflog( $msg = '', $close = false ) +function pflog($msg = '', $close = false) { static $fh = 0; global $module; // Only log if debugging is enabled - if(PF_DEBUG ) { - if($close ) { + if (PF_DEBUG) { + if ($close) { fclose($fh); - } - else - { + } else { // If file doesn't exist, create it - if(!$fh ) { + if (!$fh) { $pathinfo = pathinfo(__FILE__); - $fh = fopen($pathinfo['dirname'] .'/payfast.log', 'a+'); + $fh = fopen($pathinfo['dirname'] . '/payfast.log', 'a+'); } // If file was successfully created - if($fh ) { - $line = date('Y-m-d H:i:s') .' : '. $msg ."\n"; + if ($fh) { + $line = date('Y-m-d H:i:s') . ' : ' . $msg . "\n"; fwrite($fh, $line); } } } } -// }}} -// {{{ pfGetData + /** * pfGetData - * - * @author Jonathan Smit */ function pfGetData() { // Posted variables from ITN $pfData = $_POST; + if (empty($_POST)) { + $data = file_get_contents('php://input'); + $pfData = json_decode($data, true); + } + // Strip any slashes in data - foreach( $pfData as $key => $val ) { + foreach ($pfData as $key => $val) { $pfData[$key] = stripslashes($val); } // Return "false" if no data was received - if(sizeof($pfData) == 0 ) { + if (empty($pfData)) { return []; } else { - return( $pfData ); + return ($pfData); } } -// }}} -// {{{ pfValidSignature + /** * pfValidSignature - * - * @author Jonathan Smit */ -function pfValidSignature( $pfData = null, &$pfParamString = null, $pfPassphrase = null, $serverMode=null ) +function pfValidSignature($pfData = null, &$pfParamString = null, $pfPassphrase = null) { - // Dump the submitted variables and calculate security signature - foreach( $pfData as $key => $val ) - { - if($key != 'signature' ) { - $pfParamString .= $key .'='. urlencode($val) .'&'; + foreach ($pfData as $key => $val) { + if ($key !== 'signature') { + $pfParamString .= $key . '=' . urlencode($val) . '&'; } } - // Remove the last '&' from the parameter string - $pfParamString = substr($pfParamString, 0, -1); - - if(!is_null($pfPassphrase) && $serverMode != 'test' ) { - //if server mode is live and a passphrase is set - $tempParamString = $pfParamString."&passphrase=".urlencode($pfPassphrase); - } - else - { - //if server mode is not live or a passphrase is not set - $tempParamString = $pfParamString; + if ($pfPassphrase) { + $pfParamString .= 'passphrase=' . urlencode($pfPassphrase); + } else { + $pfParamString = rtrim($pfParamString, '&'); } - $signature = md5($tempParamString); + $signature = md5($pfParamString); - $result = ( $pfData['signature'] == $signature ); + $result = hash_equals($pfData['signature'], $signature); - pflog('Signature = '. ( $result ? 'valid' : 'invalid' )); + pflog('Signature is ' . ($result ? 'valid' : 'invalid')); - return( $result ); + return ($result); } -// }}} -// {{{ pfValidData + /** * pfValidData * - * @author Jonathan Smit - * @param $pfHost String Hostname to use + * @param $pfHost String Hostname to use * @param $pfParamString String */ -function pfValidData( $pfHost = 'www.payfast.co.za', $pfParamString = '' ) +function pfValidData($pfHost = 'www.payfast.co.za', $pfParamString = '') { - pflog('Host = '. $pfHost); - pflog('Params = '. $pfParamString); + pflog('Host = ' . $pfHost); + pflog('Params = ' . $pfParamString); $response = null; // Use cURL (if available) - if(defined('PF_CURL') ) { + if (defined('PF_CURL')) { // Variable initialization - $url = 'https://'. $pfHost .'/eng/query/validate'; + $url = 'https://' . $pfHost . '/eng/query/validate'; pflog('full url is : ' . $url); // Create default cURL object $ch = curl_init(); - + // Set cURL options - Use curl_setopt for freater PHP compatibility // Base settings curl_setopt($ch, CURLOPT_USERAGENT, PF_USER_AGENT); // Set user agent curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return output as string rather than outputting it curl_setopt($ch, CURLOPT_HEADER, false); // Don't include header in output - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); + // Standard settings curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $pfParamString); curl_setopt($ch, CURLOPT_TIMEOUT, PF_TIMEOUT); - + // Execute CURL $response = curl_exec($ch); curl_close($ch); - } - // Use fsockopen - else - { + } else { // Use fsockopen // Variable initialization - $header = ''; - $res = ''; $headerDone = false; - + // Construct Header $header = "POST /eng/query/validate HTTP/1.0\r\n"; - $header .= "Host: ". $pfHost ."\r\n"; - $header .= "User-Agent: ". PF_USER_AGENT ."\r\n"; + $header .= "Host: " . $pfHost . "\r\n"; + $header .= "User-Agent: " . PF_USER_AGENT . "\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($pfParamString) . "\r\n\r\n"; - + // Connect to server - $socket = fsockopen('ssl://'. $pfHost, 443, $errno, $errstr, PF_TIMEOUT); - + $socket = fsockopen('ssl://' . $pfHost, 443, $errno, $errstr, PF_TIMEOUT); + // Send command to server fputs($socket, $header . $pfParamString); - + // Read the response from the server - while( !feof($socket) ) - { + while (!feof($socket)) { $line = fgets($socket, 1024); - + // Check if we are finished reading the header yet - if(strcmp($line, "\r\n") == 0 ) { + if (strcmp($line, "\r\n") == 0) { // read the header $headerDone = true; - } - // If header has been processed - else if($headerDone ) { + } elseif ($headerDone) { // If header has been processed // Read the main response $response .= $line; } } - } - pflog("Response:\n". print_r($response, true)); + pflog("Response:\n" . print_r($response, true)); // Interpret Response - $lines = explode("\r\n", $response); + $lines = explode("\r\n", $response); $verifyResult = trim($lines[0]); - if(strcasecmp($verifyResult, 'VALID') == 0 ) { - return( true ); + if (strcasecmp($verifyResult, 'VALID') == 0) { + return (true); } else { - return( false ); + return (false); } } -// }}} -// {{{ pfValidIP + /** * pfValidIP * - * @author Jonathan Smit - * - * @param string $sourceIP String Source IP address + * @param string $sourceIP String Source IP address * @param string $serverMode * * @return bool + * */ -function pfValidIP( $sourceIP, $serverMode = '' ) +function pfValidIP($sourceIP, $serverMode = '') { // Variable initialization $validHosts = array( 'sandbox.payfast.co.za', 'w1w.payfast.co.za', 'w2w.payfast.co.za', - ); + ); - if (!empty($serverMode) ) { + if (!empty($serverMode)) { array_push($validHosts, "www.payfast.{$serverMode}"); } $validIps = array(); - foreach( $validHosts as $pfHostname ) - { + foreach ($validHosts as $pfHostname) { $ips = gethostbynamel($pfHostname); - if($ips !== false ) { + if ($ips !== false) { $validIps = array_merge($validIps, $ips); } } @@ -296,36 +272,34 @@ function pfValidIP( $sourceIP, $serverMode = '' ) // Remove duplicates $validIps = array_unique($validIps); - pflog("Valid IPs:\n". print_r($validIps, true)); + pflog("Valid IPs:\n" . print_r($validIps, true)); - if(in_array($sourceIP, $validIps) ) { - return( true ); + if (in_array($sourceIP, $validIps)) { + return (true); } else { - return( false ); + return (false); } } -// }}} -// {{{ pfAmountsEqual + /** * pfAmountsEqual - * + * * Checks to see whether the given amounts are equal using a proper floating * point comparison with an Epsilon which ensures that insignificant decimal * places are ignored in the comparison. - * + * * eg. 100.00 is equal to 100.0001 * - * @author Jonathan Smit - * @param $amount1 Float 1st amount for comparison + * @param $amount1 Float 1st amount for comparison * @param $amount2 Float 2nd amount for comparison + * */ -function pfAmountsEqual( $amount1, $amount2 ) +function pfAmountsEqual($amount1, $amount2) { - if(abs(floatval($amount1) - floatval($amount2)) > PF_EPSILON ) { - return( false ); + if (abs(floatval($amount1) - floatval($amount2)) > PF_EPSILON) { + return (false); } else { - return( true ); + return (true); } } -// }}} -?> + diff --git a/app/code/Payfast/Payfast/Observer/SalesOrderBeforeSaveObserver.php b/app/code/Payfast/Payfast/Observer/SalesOrderBeforeSaveObserver.php index e924d44..1f13968 100644 --- a/app/code/Payfast/Payfast/Observer/SalesOrderBeforeSaveObserver.php +++ b/app/code/Payfast/Payfast/Observer/SalesOrderBeforeSaveObserver.php @@ -1,10 +1,12 @@ -_logger->debug($pre . 'bof'); /** - * @var Order $order -*/ + * @var Order $order + */ $order = $observer->getEvent()->getOrder(); - if ($order->getPayment()->getMethodInstance()->getCode() == Config::METHOD_CODE - && $order->getState() == Order::STATE_PROCESSING + if ($order->getPayment()->getMethodInstance()->getCode() == Config::METHOD_CODE + && $order->getState() == Order::STATE_PROCESSING && empty($order->getPayment()->getAdditionalInformation('pf_payment_id')) ) { $this->_logger->debug($pre . 'setting order status and preventing sending of emails.'); @@ -63,9 +66,12 @@ public function execute(Observer $observer) $this->_logger->debug('order status : ' . $order->getStatus()); $this->_logger->debug('order state : ' . $order->getState()); - $this->_logger->debug($pre . "pf_payment_id is : ( {$order->getPayment()->getAdditionalInformation('pf_payment_id')} )"); + $this->_logger->debug( + $pre . "pf_payment_id is : ( {$order->getPayment()->getAdditionalInformation('pf_payment_id')} )" + ); $this->_logger->debug($pre . 'eof'); + return $this; } } diff --git a/app/code/Payfast/Payfast/composer.json b/app/code/Payfast/Payfast/composer.json index e630d49..a31b22b 100644 --- a/app/code/Payfast/Payfast/composer.json +++ b/app/code/Payfast/Payfast/composer.json @@ -1,27 +1,25 @@ { - "name": "payfast/payfast", - "description": "Payfast Module - Tested up to Magento v2.4.5", - "license": "proprietary", - "homepage": "https://www.payfast.co.za", - "version": "2.0.7", - "minimum-stability": "dev", - "authors": - [ - { - "name": "Jonathan Smit", - "role": "Founder/Owner" - } - ], - "support": + "name": "payfast/payfast", + "description": "Payfast Module - Magento v2.4.4+", + "license": "proprietary", + "homepage": "https://payfast.io", + "version": "2.4.1", + "minimum-stability": "dev", + "authors": [ { - "email": "developers@payfast.co.za" - }, - "autoload": { - "files": [ - "registration.php" - ], - "psr-4": { - "Payfast\\Payfast\\": "" - } + "name": "App Inlet (Pty) Ltd", + "email": "info@appinlet.com" + } + ], + "support": { + "email": "support@payfast.help" + }, + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Payfast\\Payfast\\": "" } + } } diff --git a/app/code/Payfast/Payfast/etc/adminhtml/system.xml b/app/code/Payfast/Payfast/etc/adminhtml/system.xml index 7313abc..c29cef2 100644 --- a/app/code/Payfast/Payfast/etc/adminhtml/system.xml +++ b/app/code/Payfast/Payfast/etc/adminhtml/system.xml @@ -1,78 +1,106 @@ - +
- + - + Magento\Config\Model\Config\Source\Yesno - + - + Magento\Config\Model\Config\Source\Yesno Log request data to payfast.log, should be set to "No" when site is live - + Magento\Config\Model\Config\Source\Yesno when enabled this will send order confirmation email after successful payment - + Magento\Config\Model\Config\Source\Yesno when enabled this will send invoice email after successful payment - + - test or live - enter "test" to test the integration with PayFast sandbox; enter "live" when ready to perfrom live transactions. + test or live - enter "test" to test the integration with Payfast sandbox; enter "live" when + ready to perfrom live transactions. + - + - + - If passphrase set, ensure the identical passphrase is set on your PayFast account + If passphrase set, ensure the identical passphrase is set on your Payfast account - + - + Magento\Shipping\Model\Config\Source\Allmethods - + Magento\Payment\Model\Config\Source\Allspecificcountries - + Magento\Directory\Model\Config\Source\Country 1 - + - + + + Magento\Sales\Model\Config\Source\Order\Status + + + + Magento\Sales\Model\Config\Source\Order\Status + + validate-number
-
\ No newline at end of file +
diff --git a/app/code/Payfast/Payfast/etc/config.xml b/app/code/Payfast/Payfast/etc/config.xml index 3d234bb..eca83ad 100644 --- a/app/code/Payfast/Payfast/etc/config.xml +++ b/app/code/Payfast/Payfast/etc/config.xml @@ -1,12 +1,13 @@ - + diff --git a/app/code/Payfast/Payfast/etc/csp_whitelist.xml b/app/code/Payfast/Payfast/etc/csp_whitelist.xml new file mode 100644 index 0000000..ad4b16d --- /dev/null +++ b/app/code/Payfast/Payfast/etc/csp_whitelist.xml @@ -0,0 +1,12 @@ + + + + + + https://sandbox.payfast.co.za + https://www.payfast.co.za/eng/process + + + + diff --git a/app/code/Payfast/Payfast/etc/di.xml b/app/code/Payfast/Payfast/etc/di.xml index 914d115..5e02abf 100644 --- a/app/code/Payfast/Payfast/etc/di.xml +++ b/app/code/Payfast/Payfast/etc/di.xml @@ -1,12 +1,13 @@ - + @@ -33,7 +34,8 @@ - + PayfastPayfastConfigValueHandler @@ -56,7 +58,7 @@ PayfastPayfastGatewayCaptureCommand PayfastPayfastVoidGatewayCommand PayfastPayfastCancelGatewayCommand - + @@ -67,12 +69,14 @@ PayfastPayfastGatewayResponseHandlerComposite Payfast\Payfast\Gateway\Http\TransferFactory Payfast\Payfast\Gateway\Http\Client\ClientMock - Payfast\Payfast\Gateway\Validator\ResponseCodeValidator + Payfast\Payfast\Gateway\Validator\ResponseCodeValidator + - - + + Payfast\Payfast\Gateway\Request\AuthorizationRequest @@ -94,7 +98,8 @@ PayfastPayfastGatewayResponseHandlerComposite Payfast\Payfast\Gateway\Http\TransferFactory - Payfast\Payfast\Gateway\Validator\ResponseCodeValidator + Payfast\Payfast\Gateway\Validator\ResponseCodeValidator + Payfast\Payfast\Gateway\Http\Client\ClientMock @@ -111,7 +116,8 @@ Payfast\Payfast\Gateway\Request\VoidRequest Payfast\Payfast\Gateway\Response\TxnIdHandler Payfast\Payfast\Gateway\Http\TransferFactory - Payfast\Payfast\Gateway\Validator\ResponseCodeValidator + Payfast\Payfast\Gateway\Validator\ResponseCodeValidator + Payfast\Payfast\Gateway\Http\Client\ClientMock @@ -124,16 +130,18 @@ - + Payfast\Payfast\Gateway\Response\CancelDetailsHandler - Payfast\Payfast\Gateway\Validator\CancelResponseValidator + Payfast\Payfast\Gateway\Validator\CancelResponseValidator + - + diff --git a/app/code/Payfast/Payfast/etc/events.xml b/app/code/Payfast/Payfast/etc/events.xml index ed033b8..d9d35eb 100644 --- a/app/code/Payfast/Payfast/etc/events.xml +++ b/app/code/Payfast/Payfast/etc/events.xml @@ -6,8 +6,10 @@ */ --> - + - + diff --git a/app/code/Payfast/Payfast/etc/frontend/di.xml b/app/code/Payfast/Payfast/etc/frontend/di.xml index 38914c9..424d898 100644 --- a/app/code/Payfast/Payfast/etc/frontend/di.xml +++ b/app/code/Payfast/Payfast/etc/frontend/di.xml @@ -1,12 +1,13 @@ - + payfast @@ -43,7 +44,9 @@ - Payfast\Payfast\Model\PayfastConfigProvider + + Payfast\Payfast\Model\PayfastConfigProvider + diff --git a/app/code/Payfast/Payfast/etc/frontend/routes.xml b/app/code/Payfast/Payfast/etc/frontend/routes.xml index 396aacb..30ae0cd 100644 --- a/app/code/Payfast/Payfast/etc/frontend/routes.xml +++ b/app/code/Payfast/Payfast/etc/frontend/routes.xml @@ -1,15 +1,16 @@ - + - + - \ No newline at end of file + diff --git a/app/code/Payfast/Payfast/etc/frontend/sections.xml b/app/code/Payfast/Payfast/etc/frontend/sections.xml index 0113acc..8249847 100644 --- a/app/code/Payfast/Payfast/etc/frontend/sections.xml +++ b/app/code/Payfast/Payfast/etc/frontend/sections.xml @@ -1,8 +1,8 @@ diff --git a/app/code/Payfast/Payfast/etc/module.xml b/app/code/Payfast/Payfast/etc/module.xml index 3b5074a..a462854 100644 --- a/app/code/Payfast/Payfast/etc/module.xml +++ b/app/code/Payfast/Payfast/etc/module.xml @@ -1,13 +1,14 @@ - - + + diff --git a/app/code/Payfast/Payfast/etc/payment.xml b/app/code/Payfast/Payfast/etc/payment.xml index 95c7ce3..760e2d8 100644 --- a/app/code/Payfast/Payfast/etc/payment.xml +++ b/app/code/Payfast/Payfast/etc/payment.xml @@ -1,12 +1,13 @@ - + 0 diff --git a/app/code/Payfast/Payfast/registration.php b/app/code/Payfast/Payfast/registration.php index 010cbde..1fc7a1c 100644 --- a/app/code/Payfast/Payfast/registration.php +++ b/app/code/Payfast/Payfast/registration.php @@ -1,6 +1,6 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - Payfast_Payfast/js/view/payment/payfast-payments + + Payfast_Payfast/js/view/payment/payfast-payments + - true + true + + @@ -41,9 +50,8 @@ - - - - - + + + + diff --git a/app/code/Payfast/Payfast/view/frontend/layout/payfast_notify_index.xml b/app/code/Payfast/Payfast/view/frontend/layout/payfast_notify_index.xml index 3ed7fb8..59c2620 100644 --- a/app/code/Payfast/Payfast/view/frontend/layout/payfast_notify_index.xml +++ b/app/code/Payfast/Payfast/view/frontend/layout/payfast_notify_index.xml @@ -1,15 +1,17 @@ - - - - - - + + + + + + diff --git a/app/code/Payfast/Payfast/view/frontend/layout/payfast_redirect_index.xml b/app/code/Payfast/Payfast/view/frontend/layout/payfast_redirect_index.xml index 840985c..59c2620 100644 --- a/app/code/Payfast/Payfast/view/frontend/layout/payfast_redirect_index.xml +++ b/app/code/Payfast/Payfast/view/frontend/layout/payfast_redirect_index.xml @@ -1,15 +1,17 @@ - - - - + + + + diff --git a/app/code/Payfast/Payfast/view/frontend/templates/form/payfast.phtml b/app/code/Payfast/Payfast/view/frontend/templates/form/payfast.phtml index bb2ebd0..e88a0ca 100644 --- a/app/code/Payfast/Payfast/view/frontend/templates/form/payfast.phtml +++ b/app/code/Payfast/Payfast/view/frontend/templates/form/payfast.phtml @@ -1,9 +1,14 @@ - -getMethod()->getInstructions()): ?> -
escapeHtml($block->getMethodCode()) ?> instructions agreement content" id="payment_form_escapeHtml($block->getMethodCode()) ?>" style="display: none;"> - escapeHtml($instructions)) ?> + escapeHtml($instructions)) ?>
- \ No newline at end of file + diff --git a/app/code/Payfast/Payfast/view/frontend/templates/html/rk.phtml b/app/code/Payfast/Payfast/view/frontend/templates/html/rk.phtml index 6d399c4..f3c4799 100644 --- a/app/code/Payfast/Payfast/view/frontend/templates/html/rk.phtml +++ b/app/code/Payfast/Payfast/view/frontend/templates/html/rk.phtml @@ -1,11 +1,16 @@ -
-
- getPostData() as $key=>$value): ?> - - + + getPostData() as $key => $value): ?> + +
diff --git a/app/code/Payfast/Payfast/view/frontend/templates/redirect.phtml b/app/code/Payfast/Payfast/view/frontend/templates/redirect.phtml index 45c6605..c8923a1 100644 --- a/app/code/Payfast/Payfast/view/frontend/templates/redirect.phtml +++ b/app/code/Payfast/Payfast/view/frontend/templates/redirect.phtml @@ -1,15 +1,24 @@ - -

escapeHtml($this->getMessage()); ?>

+

escapeHtml($this->getMessage()); ?>

-
- getFormData() as $item => $value): ?> - - + getFormData() as $item => $value): ?> + +
-getSubmitForm(); ?> +getSubmitForm(); ?> diff --git a/app/code/Payfast/Payfast/view/frontend/web/css/payfast_checkout.css b/app/code/Payfast/Payfast/view/frontend/web/css/payfast_checkout.css new file mode 100755 index 0000000..8d72ef5 --- /dev/null +++ b/app/code/Payfast/Payfast/view/frontend/web/css/payfast_checkout.css @@ -0,0 +1,3 @@ +img.payment-icon { + max-width: 30%; +} diff --git a/app/code/Payfast/Payfast/view/frontend/web/images/logo.png b/app/code/Payfast/Payfast/view/frontend/web/images/logo.png deleted file mode 100644 index a1c64b7..0000000 Binary files a/app/code/Payfast/Payfast/view/frontend/web/images/logo.png and /dev/null differ diff --git a/app/code/Payfast/Payfast/view/frontend/web/images/logo.svg b/app/code/Payfast/Payfast/view/frontend/web/images/logo.svg new file mode 100644 index 0000000..8ba1a09 --- /dev/null +++ b/app/code/Payfast/Payfast/view/frontend/web/images/logo.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/method-renderer/payfast-method.js b/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/method-renderer/payfast-method.js index 8400c05..6de9d82 100644 --- a/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/method-renderer/payfast-method.js +++ b/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/method-renderer/payfast-method.js @@ -1,71 +1,71 @@ /** - * Copyright (c) 2008 PayFast (Pty) Ltd - * You (being anyone who is not PayFast (Pty) Ltd) may download and use this plugin / code in your own website in conjunction with a registered and active PayFast account. If your PayFast account is terminated for any reason, you may not use this plugin / code or part thereof. + * Copyright (c) 2023 Payfast (Pty) Ltd + * You (being anyone who is not Payfast (Pty) Ltd) may download and use this plugin / code in your own website in conjunction with a registered and active Payfast account. If your Payfast account is terminated for any reason, you may not use this plugin / code or part thereof. * Except as expressly indicated in this licence, you may not use, copy, modify or distribute this plugin / code or part thereof in any way. */ define( - [ - 'jquery', - 'Magento_Checkout/js/view/payment/default', - 'Magento_Checkout/js/action/place-order', - 'Magento_Checkout/js/action/select-payment-method', - 'Magento_Customer/js/model/customer', - 'Magento_Checkout/js/checkout-data', - 'Magento_Checkout/js/model/payment/additional-validators', - 'mage/url', - 'Magento_Checkout/js/model/quote', - 'Magento_Ui/js/view/messages' - ], - function ($, - Component, - placeOrderAction, - selectPaymentMethodAction, - customer, - checkoutData, - additionalValidators, - url, - quote, - ) { - 'use strict'; + [ + 'jquery', + 'Magento_Checkout/js/view/payment/default', + 'Magento_Checkout/js/action/place-order', + 'Magento_Checkout/js/action/select-payment-method', + 'Magento_Customer/js/model/customer', + 'Magento_Checkout/js/checkout-data', + 'Magento_Checkout/js/model/payment/additional-validators', + 'mage/url', + 'Magento_Checkout/js/model/quote', + 'Magento_Ui/js/view/messages' + ], + function ($, + Component, + placeOrderAction, + selectPaymentMethodAction, + customer, + checkoutData, + additionalValidators, + url, + quote, + ) { + 'use strict' - return Component.extend( - { - defaults: { - template: 'Payfast_Payfast/payment/payfast' - }, - redirectAfterPlaceOrder: false, + return Component.extend( + { + defaults: { + template: 'Payfast_Payfast/payment/payfast' + }, + redirectAfterPlaceOrder: false, - getCode: function () { - return 'payfast'; - }, - /** - * Get value of instruction field. - * - * @returns {String} - */ - getInstructions: function () { - return window.checkoutConfig.payment.instructions[this.item.method]; - }, - isAvailable: function () { - return quote.totals().grand_total <= 0; - }, + getCode: function () { + return 'payfast' + }, + /** + * Get value of instruction field. + * + * @returns {String} + */ + getInstructions: function () { + return window.checkoutConfig.payment.instructions[this.item.method] + }, + isAvailable: function () { + return quote.totals().grand_total <= 0 + }, - afterPlaceOrder: function () { - window.location.replace(url.build(window.checkoutConfig.payment.payfast.redirectUrl.payfast)); - }, - /** - * Returns payment acceptance mark link path - */ - getPaymentAcceptanceMarkHref: function () { - return window.checkoutConfig.payment.payfast.paymentAcceptanceMarkHref; - }, - /** - * Returns payment acceptance mark image path - */ - getPaymentAcceptanceMarkSrc: function () { - return window.checkoutConfig.payment.payfast.paymentAcceptanceMarkSrc; - }, - } - ); - } -); \ No newline at end of file + afterPlaceOrder: function () { + window.location.replace(url.build(window.checkoutConfig.payment.payfast.redirectUrl.payfast)) + }, + /** + * Returns payment acceptance mark link path + */ + getPaymentAcceptanceMarkHref: function () { + return window.checkoutConfig.payment.payfast.paymentAcceptanceMarkHref + }, + /** + * Returns payment acceptance mark image path + */ + getPaymentAcceptanceMarkSrc: function () { + return window.checkoutConfig.payment.payfast.paymentAcceptanceMarkSrc + }, + } + ) + } +) diff --git a/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/payfast-payments.js b/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/payfast-payments.js index fce9fcb..6bf873b 100644 --- a/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/payfast-payments.js +++ b/app/code/Payfast/Payfast/view/frontend/web/js/view/payment/payfast-payments.js @@ -1,27 +1,27 @@ /*browser:true*/ /*global define*/ -/*Copyright (c) 2008 PayFast (Pty) Ltd -You (being anyone who is not PayFast (Pty) Ltd) may download and use this plugin / code in your own website in conjunction with a registered and active PayFast account. If your PayFast account is terminated for any reason, you may not use this plugin / code or part thereof. +/*Copyright (c) 2023 Payfast (Pty) Ltd +You (being anyone who is not Payfast (Pty) Ltd) may download and use this plugin / code in your own website in conjunction with a registered and active Payfast account. If your Payfast account is terminated for any reason, you may not use this plugin / code or part thereof. Except as expressly indicated in this licence, you may not use, copy, modify or distribute this plugin / code or part thereof in any way.*/ define( - [ - 'uiComponent', - 'Magento_Checkout/js/model/payment/renderer-list' - ], - function (Component, - rendererList - ) { - 'use strict'; + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/renderer-list' + ], + function (Component, + rendererList + ) { + 'use strict' - rendererList.push( - { - type: 'payfast', - component: 'Payfast_Payfast/js/view/payment/method-renderer/payfast-method' - } - ); - /** - * Add view logic here if needed - */ - return Component.extend({}); - } -); \ No newline at end of file + rendererList.push( + { + type: 'payfast', + component: 'Payfast_Payfast/js/view/payment/method-renderer/payfast-method' + } + ) + /** + * Add view logic here if needed + */ + return Component.extend({}) + } +) diff --git a/app/code/Payfast/Payfast/view/frontend/web/template/payment/payfast.html b/app/code/Payfast/Payfast/view/frontend/web/template/payment/payfast.html index 3239687..dcf467f 100644 --- a/app/code/Payfast/Payfast/view/frontend/web/template/payment/payfast.html +++ b/app/code/Payfast/Payfast/view/frontend/web/template/payment/payfast.html @@ -1,23 +1,25 @@ -
- -
- +
@@ -33,14 +35,14 @@