From e4bef1e06170a9dfa8353459c38746558ce1fceb Mon Sep 17 00:00:00 2001 From: wpawel Date: Mon, 13 Sep 2021 16:24:35 +0200 Subject: [PATCH] v1.1.0 - important: added new addresses to whitelist for notifications! - security change: added a new version of the API in the context of calculating the checksum ('chk') - an additional setting has been added in the configuration: whether the server uses a proxy. The setting determines how the ip address of notifications received from dotpay will be checked. Disable the options only if you have a problem with receiving notifications. - small changes --- dotpay.css | 4 +- dotpay.php | 335 +++++++++--------- dotpay.xml | 16 +- fields/dotpaylogo.php | 7 +- language/en-GB/en-GB.plg_vmpayment_dotpay.ini | 14 +- language/pl-PL/pl-PL.plg_vmpayment_dotpay.ini | 13 +- 6 files changed, 212 insertions(+), 177 deletions(-) diff --git a/dotpay.css b/dotpay.css index 1d1c0a9..7f56d22 100644 --- a/dotpay.css +++ b/dotpay.css @@ -1,8 +1,8 @@ /** * @package Dotpay Payment Plugin module for VirtueMart v3 for Joomla! 3.4 * @version $1.0.1: dotpay.css 2015-08-24 - * @author Dotpay SA < tech@dotpay.pl > - * @copyright (C) 2015 - Dotpay SA + * @author PayPro S.A. < tech@dotpay.pl > + * @copyright (C) 2021 - PayPro S.A. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html **/ diff --git a/dotpay.php b/dotpay.php index 8af7dc1..66badf2 100644 --- a/dotpay.php +++ b/dotpay.php @@ -1,9 +1,9 @@ - * @copyright (C) 2021 - Dotpay sp. z o.o. + * @package Dotpay Payment Plugin module for VirtueMart v3 for Joomla! >= 3.4 + * @version $1.1.0: dotpay.php 2021-09-13 + * @author PayPro S.A.. < tech@dotpay.pl > + * @copyright (C) 2021 - PayPro S.A. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html **/ @@ -18,13 +18,26 @@ class plgVmPaymentDotpay extends vmPSPlugin { /** Version information */ - const DP_RELDATE = '2021-03-26'; - const DOTPAY_MODULE_VERSION = '1.0.6'; + const DP_RELDATE = '2021-09-13'; + const DOTPAY_MODULE_VERSION = '1.1.0'; /** Dotpay IP allowed */ - const DOTPAY_IP = '195.150.9.37'; + //const DOTPAY_IP = '195.150.9.37'; + + const DOTPAY_IP_WHITE_LIST = array( + '195.150.9.37', + '91.216.191.181', + '91.216.191.182', + '91.216.191.183', + '91.216.191.184', + '91.216.191.185', + '5.252.202.255', + ); + + + const DP_SUPPORT_IP = '77.79.195.34'; @@ -120,10 +133,11 @@ public function renderPluginName($payment_plugin) return ' ' . + '" alt="' . $name . '" />'. parent::renderPluginName($payment_plugin); } - + + /** * Zwraca dane do formularza ktory przesyla je pozniej do dotpay @@ -540,9 +554,33 @@ public function plgVmOnPaymentNotification() { exit('plugin error'); } + + $dotpay_office = false; + $proxy_desc =''; + + if( (int)$this->getDPConf('dotpay_nonproxy') == 1) { + $clientIp = $_SERVER['REMOTE_ADDR']; + $proxy_desc = 'FALSE'; + }else{ + $clientIp = $this->getClientIp(); + $proxy_desc = 'TRUE'; + } + + + + // diagnostic only for customer service dotpay : - if(($_SERVER["REMOTE_ADDR"] == self::DP_SUPPORT_IP || $this->getClientIp() == self::DP_SUPPORT_IP) && strtoupper($_SERVER['REQUEST_METHOD']) == 'GET') { + + if( ($clientIp == self::DP_SUPPORT_IP) && (strtoupper($_SERVER['REQUEST_METHOD']) == 'GET')) + { + $dotpay_office = true; + }else{ + $dotpay_office = false; + } + + + if($dotpay_office == true) { @@ -556,7 +594,10 @@ public function plgVmOnPaymentNotification() { "
* Dotpay module ver: ".self::DOTPAY_MODULE_VERSION.", release date: ".self::DP_RELDATE. "
   - ID: ". $paymentMethod->dotpay_id. - "
   - Test mode: ".(bool)$this->getDPConf('fake_real'). + "
   - Test mode: ".(int)$this->getDPConf('fake_real'). + "
Server does not use a proxy: ".(int)$this->getDPConf('dotpay_nonproxy'). + "
REMOTE ADDRESS: ".$_SERVER['REMOTE_ADDR']. + "
   - Automatyczne przekierowanie: ".$this->getDPConf('autoredirect'). "
   - Opłata dodatkowa wyboru płatności (stała): ".$this->getDPConf('cost_per_transaction'). "
   - Opłata dodatkowa zależna od wartości zamówienia (procent od zamówienia): ".$this->getDPConf('cost_percent_total') @@ -566,11 +607,13 @@ public function plgVmOnPaymentNotification() { // ---- . - - if(!$this->isIpValidated($paymentMethod)){ - exit('Virtuemart - untrusted ip: '.$_SERVER["REMOTE_ADDR"].' ('.$this->getClientIp().')' ); + if (!$this->isAllowedIp($clientIp, self::DOTPAY_IP_WHITE_LIST)) + { + die("Virtuemart - ERROR (REMOTE ADDRESS: ".$this->getClientIp(true)."/".$_SERVER["REMOTE_ADDR"].", PROXY:".$proxy_desc.")"); } + + if (strtoupper($_SERVER['REQUEST_METHOD']) != 'POST') { exit("Virtuemart - ERROR (METHOD <> POST)"); } @@ -975,69 +1018,29 @@ private function isSingnatureValidated($post, $paymentMethod,$debug=false) } - } - - - private function isSingnatureValidated2($post, $paymentMethod) - { - $string = $paymentMethod->dotpay_pin . - $post->get('id', '', 'STRING') . - $post->get('operation_number', '', 'STRING') . - $post->get('operation_type', '', 'STRING') . - $post->get('operation_status', '', 'STRING') . - $post->get('operation_amount', '', 'STRING') . - $post->get('operation_currency', '', 'STRING') . - $post->get('operation_withdrawal_amount', '', 'STRING') . - $post->get('operation_commission_amount', '', 'STRING') . - $post->get('is_completed', '', 'STRING') . - $post->get('operation_original_amount', '', 'STRING') . - $post->get('operation_original_currency', '', 'STRING') . - $post->get('operation_datetime', '', 'STRING') . - $post->get('operation_related_number', '', 'STRING') . - $post->get('control', '', 'STRING') . - $post->get('description', '', 'STRING') . - $post->get('email', '', 'STRING') . - $post->get('p_info', '', 'STRING') . - $post->get('p_email', '', 'STRING') . - $post->get('credit_card_issuer_identification_number', '', 'STRING') . - $post->get('credit_card_masked_number', '', 'STRING') . - $post->get('credit_card_expiration_year', '', 'STRING') . - $post->get('credit_card_expiration_month', '', 'STRING') . - $post->get('credit_card_brand_codename', '', 'STRING') . - $post->get('credit_card_brand_code', '', 'STRING') . - $post->get('credit_card_unique_identifier', '', 'STRING') . - $post->get('credit_card_id', '', 'STRING') . - $post->get('channel', '', 'STRING') . - $post->get('channel_country', '', 'STRING') . - $post->get('geoip_country', '', 'STRING') . - $post->get('payer_bank_account_name', '', 'STRING') . - $post->get('payer_bank_account', '', 'STRING') . - $post->get('payer_transfer_title', '', 'STRING') . - $post->get('blik_voucher_pin', '', 'STRING') . - $post->get('blik_voucher_amount', '', 'STRING') . - $post->get('blik_voucher_amount_used', '', 'STRING') ; - - - if($post->get('signature') == hash('sha256', $string)){ - return true; - } } + /** - * Sprawdza czy ip jest z dotpaya - * - * @param $paymentMethod - * @return bool + * Returns if the given ip is on the given whitelist. + * + * @param string $ip The ip to check. + * @param array $whitelist The ip whitelist. An array of strings. + * + * @return bool */ - private function isIpValidated($paymentMethod) + public function isAllowedIp($ip, array $whitelist) { - if($_SERVER['REMOTE_ADDR'] == self::DOTPAY_IP || $this->getClientIp() == self::DOTPAY_IP ){ + $ip = (string)$ip; + if (in_array($ip, $whitelist, true)) { return true; } return false; } + + /** * zapisuje order na podstawie danych z arraya * @@ -1304,35 +1307,61 @@ private function geShoptHost() private function getInputsForm($orderData) { if (null !== $this->getPhoneDP($orderData['phone_2']) ) { - $phone = $this->getPhoneDP($orderData['phone_2']); + $phone = (string) $this->getPhoneDP($orderData['phone_2']); } else { - $phone = $this->getPhoneDP($orderData['phone_1']); + $phone = (string) $this->getPhoneDP($orderData['phone_1']); } $data = array( - 'id' => $orderData['dotpay_id'], - 'amount' => $orderData['amount'], - 'currency' => $orderData['currency'], - 'control' => $orderData['dotpay_control'].'|domain:'.$this->geShoptHost().'|VirtueMart:v'.vmVersion::$RELEASE.'|Dotpay module v:'.self::DOTPAY_MODULE_VERSION, - 'description' => $orderData['description'], - 'lang' => $orderData['lang'], + 'id' => (string) $orderData['dotpay_id'], + 'amount' => (string) $orderData['amount'], + 'currency' => (string)$orderData['currency'], + 'control' => (string) $orderData['dotpay_control'].'|domain:'.$this->geShoptHost().'|VirtueMart:v'.vmVersion::$RELEASE.'|Dotpay module v:'.self::DOTPAY_MODULE_VERSION, + 'description' => (string)$orderData['description'], + 'lang' => (string) $orderData['lang'], 'type' => '0', - 'url' => $orderData['url'], - 'urlc' => $orderData['urlc'], - 'firstname' => $this->getFirstnameDP($orderData['first_name']), - 'lastname' => $this->getLastnameDP($orderData['last_name']), - 'email' => $orderData['email'], - 'city' => $this->getCityDP($orderData['city']), - 'street' => $this->getStreetDP($orderData['address_1']), - 'street_n1' => $this->getStreet2DP($orderData['address_2']), - 'postcode' => $this->getPostcodeDP($orderData['postcode'],$orderData['lang']), - 'phone' => $phone, - 'country' => $this->getCountryDP($orderData['country']), - 'api_version' => 'dev' + 'url' => (string) $orderData['url'], + 'urlc' => (string) $orderData['urlc'], + 'firstname' => (string) $this->getFirstnameDP($orderData['first_name']), + 'lastname' => (string) $this->getLastnameDP($orderData['last_name']), + 'email' => (string) $orderData['email'], + 'api_version' => 'next', + 'ignore_last_payment_channel' => '1' + ); - + + if( null != trim($phone)) + { + $data["phone"] = (string) $phone; + } + if( null != trim($this->getCountryDP($orderData['country']))) + { + $data["country"] = (string)$this->getCountryDP($orderData['country']); + } + if( null != trim($this->getPostcodeDP($orderData['postcode'],$orderData['lang']))) + { + $data["postcode"] = (string) $this->getPostcodeDP($orderData['postcode'],$orderData['lang']); + } + + if( null != trim($this->getStreet2DP($orderData['address_2']))) + { + $data["street_n1"] = (string)$this->getStreet2DP($orderData['address_2']); + } + + if( null != trim($this->getStreetDP($orderData['address_1']))) + { + $data["street"] = (string) $this->getStreetDP($orderData['address_1']); + } + + if( null != trim($this->getCityDP($orderData['city']))) + { + $data["city"] = (string) $this->getCityDP($orderData['city']); + } + + return $data; + } @@ -1366,6 +1395,14 @@ private function getDPConf($what){ return false; } } + else if($what == 'dotpay_nonproxy') { + preg_match('/\|dotpay_nonproxy="(\d+)"\|/', $params, $get_param1); + if (isset($get_param1[1])){ + return trim($get_param1[1]); + }else{ + return false; + } + } else if($what == 'cost_per_transaction') { preg_match('/\|cost_per_transaction="([\d\.]+)"\|/', $params, $get_param1); if (isset($get_param1[1])){ @@ -1405,59 +1442,48 @@ private function getDPConf($what){ return false; } - /** * Generate CHK for seller and payment data * @param type $DotpayPin Dotpay seller PIN * @param array $orderData parameters of payment * @return string */ - protected function generateCHK($orderData) { - - $getinputForm = $this->getInputsForm($orderData); - - $DotpayPin = $this->getDPConf('dotpay_pin'); - - $ChkParametersChain = - $DotpayPin. - (isset($getinputForm['api_version']) ? $getinputForm['api_version'] : null). - (isset($getinputForm['lang']) ? $getinputForm['lang'] : null). - (isset($getinputForm['id']) ? $getinputForm['id'] : null). - (isset($getinputForm['amount']) ? $getinputForm['amount'] : null). - (isset($getinputForm['currency']) ? $getinputForm['currency'] : null). - (isset($getinputForm['description']) ? $getinputForm['description'] : null). - (isset($getinputForm['control']) ? $getinputForm['control'] : null). - (isset($getinputForm['channel']) ? $getinputForm['channel'] : null). - (isset($getinputForm['ch_lock']) ? $getinputForm['ch_lock'] : null). - (isset($getinputForm['channel_groups']) ? $getinputForm['channel_groups'] : null). - (isset($getinputForm['url']) ? $getinputForm['url'] : null). - (isset($getinputForm['type']) ? $getinputForm['type'] : null). - (isset($getinputForm['buttontext']) ? $getinputForm['buttontext'] : null). - (isset($getinputForm['urlc']) ? $getinputForm['urlc'] : null). - (isset($getinputForm['firstname']) ? $getinputForm['firstname'] : null). - (isset($getinputForm['lastname']) ? $getinputForm['lastname'] : null). - (isset($getinputForm['email']) ? $getinputForm['email'] : null). - (isset($getinputForm['street']) ? $getinputForm['street'] : null). - (isset($getinputForm['street_n1']) ? $getinputForm['street_n1'] : null). - (isset($getinputForm['street_n2']) ? $getinputForm['street_n2'] : null). - (isset($getinputForm['state']) ? $getinputForm['state'] : null). - (isset($getinputForm['addr3']) ? $getinputForm['addr3'] : null). - (isset($getinputForm['city']) ? $getinputForm['city'] : null). - (isset($getinputForm['postcode']) ? $getinputForm['postcode'] : null). - (isset($getinputForm['phone']) ? $getinputForm['phone'] : null). - (isset($getinputForm['country']) ? $getinputForm['country'] : null). - (isset($getinputForm['p_info']) ? $getinputForm['p_info'] : null). - (isset($getinputForm['p_email']) ? $getinputForm['p_email'] : null). - (isset($getinputForm['bylaw']) ? $getinputForm['bylaw'] : null). - (isset($getinputForm['personal_data']) ? $getinputForm['personal_data'] : null). - (isset($getinputForm['blik_code']) ? $getinputForm['blik_code'] : null). - (isset($getinputForm['ignore_last_payment_channel']) ? $getinputForm['ignore_last_payment_channel'] : null); - - - return hash('sha256',$ChkParametersChain); - + + + ## function: counts the checksum from the defined array of all parameters + + public static function generateCHK($ParametersArray, $DotpayPin) + { + + if(isset($ParametersArray['chk'])) + { + unset($ParametersArray['chk']); + } + + //sorting the parameter list + ksort($ParametersArray); + + // Display the semicolon separated list + $paramList = implode(';', array_keys($ParametersArray)); + + //adding the parameter 'paramList' with sorted list of parameters to the array + $ParametersArray['paramsList'] = $paramList; + + //re-sorting the parameter list + ksort($ParametersArray); + + //json encoding + $json = json_encode($ParametersArray, JSON_UNESCAPED_SLASHES); + + + return hash_hmac('sha256', $json, $DotpayPin, false); + + } + + + /** * Na podstawie przygotowanego arraya beda renderowane inputy do formularza * @@ -1467,36 +1493,16 @@ protected function generateCHK($orderData) { private function getHtmlInputs($orderData) { - $getinputForm = $this->getInputsForm($orderData); - $chk = $this->generateCHK($orderData); + $data = $this->getInputsForm($orderData); + $pin = trim($this->getDPConf('dotpay_pin')); - $data = array( - 'id' => $orderData['dotpay_id'], - 'amount' => $getinputForm['amount'], - 'currency' => $getinputForm['currency'], - 'control' => $getinputForm['control'], - 'description' => $getinputForm['description'], - 'lang' => $getinputForm['lang'], - 'type' => 0, - 'url' => $getinputForm['url'], - 'urlc' => $getinputForm['urlc'], - 'firstname' => $getinputForm['firstname'], - 'lastname' => $getinputForm['lastname'], - 'email' => $getinputForm['email'], - 'city' => $getinputForm['city'], - 'street' => $getinputForm['street'], - 'street_n1' => $getinputForm['street_n1'], - 'postcode' => $getinputForm['postcode'], - 'phone' => $getinputForm['phone'], - 'country' => $getinputForm['country'], - 'api_version' => 'dev' - ); + $chk = $this->generateCHK($data, $pin); $html = ''; foreach($data as $key => $value){ $html .= ''; } - if(null !== $this->getDPConf('dotpay_pin')){ + if(null !== $pin){ $html .= ''; } @@ -1515,15 +1521,24 @@ private function getHtmlFormEnd() $src = JURI::root().'plugins/vmpayment/dotpay/'.'dp_logo_alpha_110_47.png'; - $html = "
".vmText::_('PLG_DOTPAY_REDIRECT_IMG_CLICK')."

".vmText::_('PLG_DOTPAY_REDIRECT_IMG_WAIT')."

"; + $html = "
".vmText::_('PLG_DOTPAY_REDIRECT_IMG_CLICK')."
"; + if((int)$this->getDPConf('autoredirect') != 1) { + $html .= "

".vmText::_('PLG_DOTPAY_REDIRECT_IMG_CLICK_DESCR')."

"; + }else{ + $html .= "

".vmText::_('PLG_DOTPAY_REDIRECT_IMG_WAIT')."

"; + } + $html .='


'; $html .=''; $html .=''; + if((int)$this->getDPConf('autoredirect') == 1) { + $html .= "

".vmText::_('PLG_DOTPAY_REDIRECT_IMG_WAIT')."

"; + $html .= ''; + } - $html .= ''; return $html; } diff --git a/dotpay.xml b/dotpay.xml index 776335d..223e3d2 100644 --- a/dotpay.xml +++ b/dotpay.xml @@ -15,13 +15,13 @@ language VM Payment - Dotpay - 26.03.2021 - Dotpay sp. z o.o. - Copyright (C) 2021 Dotpay sp. z o.o. . All rights reserved. + 13.09.2021 + PayPro S.A.. + Copyright (C) 2021 PayPro S.A.. . All rights reserved. GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html tech@dotpay.pl http://www.dotpay.pl - 1.0.6 + 1.1.0 PLG_DOTPAY_CONF_DESCRIPTION @@ -34,11 +34,15 @@ - - + + + + + + diff --git a/fields/dotpaylogo.php b/fields/dotpaylogo.php index 25bcba5..c27f878 100644 --- a/fields/dotpaylogo.php +++ b/fields/dotpaylogo.php @@ -2,8 +2,8 @@ /** * @package Dotpay Payment Plugin module for VirtueMart v3 for Joomla! 3.4 * @version $1.2: dotpaylogo.php 2021-03-26 - * @author Dotpay sp. z o.o. < tech@dotpay.pl > - * @copyright (C) 2021 - Dotpay sp. z o.o. + * @author PayPro S.A.. < tech@dotpay.pl > + * @copyright (C) 2021 - PayPro S.A.. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html **/ @@ -22,7 +22,8 @@ class JFormFieldDotpayLogo extends JFormField { function getInput() { $src = JURI::root() . "plugins/vmpayment/dotpay/"."dp_logo_alpha_175_50.png"; $register_link_dotpay = ''; - return " $register_link_dotpay + + return " $register_link_dotpay