From 7c8846b76a8dd9506ddd0a7f99bc479387be6d02 Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 8 Dec 2019 10:50:04 -0500 Subject: [PATCH 1/2] v1.3.0 handling of taxes removal of duplicate values wrong return fee removed firstname/lastname which could be incorrect code cleanup --- en-GB.plg_payperdownloadplus_paystackpay.ini | 8 +- paystackpay.php | 462 ++++++++++--------- paystackpay.xml | 2 +- tmpl/default.php | 6 +- 4 files changed, 262 insertions(+), 216 deletions(-) diff --git a/en-GB.plg_payperdownloadplus_paystackpay.ini b/en-GB.plg_payperdownloadplus_paystackpay.ini index 4e1037f..fd2fbb8 100755 --- a/en-GB.plg_payperdownloadplus_paystackpay.ini +++ b/en-GB.plg_payperdownloadplus_paystackpay.ini @@ -23,4 +23,10 @@ COM_PAYSTACKPAY_EXTRACHARGE_VALUEDESC="The value of the extra charges" ; front -PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_PAYWITHPAYSTACK="Pay with PayStack" \ No newline at end of file +PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_PAYWITHPAYSTACK="Pay with PayStack" + +PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_ADDITIONALFEEWILLAPPLY="A payment charge of %s %s will apply" + +PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_MISSINGPUBLICKEY="Missing public key for PayStackPay" +PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_MISSINGSECRETKEY="Missing secret key for PayStackPay" +PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_USERMUSTBELOGGEDIN="User must be logged in" diff --git a/paystackpay.php b/paystackpay.php index 4364322..d0d3370 100755 --- a/paystackpay.php +++ b/paystackpay.php @@ -44,9 +44,10 @@ function log_transaction_success($trx_ref){ } } - class plgPayperDownloadPlusPaystackPay extends JPlugin { + protected static $tax_percentage; + public function __construct(&$subject, $config = array()) { parent::__construct($subject, $config); @@ -54,159 +55,168 @@ public function __construct(&$subject, $config = array()) $this->loadLanguage(); } - public function onRenderPaymentForm($user, $license, $resource, - $returnUrl, $thankyouUrl) + public function onRenderPaymentForm($user, $license, $resource, $returnUrl, $thankyouUrl) { - $siteUrl = JUri::base(); $package_price = array(); - $theuser = JFactory::getUser(); $pmntinfo = $this->getPaystackPaymentInfo(); $public_key = $pmntinfo->public_key; - $user_id = 0; - if($user) - { - $user_id = $user->id; $customer_email = $user->email; - $thename = explode(" ",$user->name); $firstname = $thename[0]; - // if(count($thename) > 1){$lastname = $thename[1];} - } - else{ - $user_id = $theuser->id; $customer_email = $theuser->email; - $thename = explode(" ",$theuser->name); $firstname = $thename[0]; - } - if($public_key && $customer_email) + if (empty($public_key)) { + echo JText::_('PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_MISSINGPUBLICKEY'); + return; + } + + $secret_key = $pmntinfo->secret_key; + + if (empty($secret_key)) { + echo JText::_('PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_MISSINGSECRETKEY'); + return; + } + + if (!isset($user)) { + echo JText::_('PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY_USERMUSTBELOGGEDIN'); + return; + } + + $user_id = $user->id; + $customer_email = $user->email; +// $thename = explode(" ",$user->name); +// $firstname = $thename[0]; // that's a leap of faith +// if (count($thename) > 1) { +// $lastname = $thename[1]; +// } + + if($license || $resource) { $item_id = 0; $name = ""; $damount = 0; $currency = ""; $description = ""; - $type = ""; $task = ""; $download_id = 0; $amount = 0; - if($license || $resource) + $type = ""; $task = ""; $download_id = ''; $amount = 0; + + if($resource) { - if($resource) - { - $damount = $resource->resource_price; - $currency = $resource->resource_price_currency; //$currency = $pmntinfo->currency; - $item_id = $resource->resource_license_id; - $name = $resource->resource_name; - $download_id = $resource->download_id; - if($resource->alternate_resource_description) - $description = $resource->alternate_resource_description; - else - $description = $resource->resource_description; - $task = "confirmres"; - $type = "resource"; - } + $damount = $resource->resource_price; + $currency = $resource->resource_price_currency; + $item_id = $resource->resource_license_id; + $name = $resource->resource_name; + $download_id = $resource->download_id; + if($resource->alternate_resource_description) + $description = $resource->alternate_resource_description; else - { - $damount = $license->price; - $currency = $license->currency_code; //$currency = $pmntinfo->currency; - $item_id = $license->license_id; - $name = $license->license_name; - $description = $license->description; - $task = "confirm"; - $type = "license"; - } - $package_price = $this->calcFinalAmount($damount, $pmntinfo->ps_extra, $pmntinfo->ps_extratype, $pmntinfo->ps_extraval); - $amount = $package_price[0] * 100; - $amount = (int)$amount; - $returnBase64Coded = base64_encode($returnUrl); - - $callbackurl = JURI::root() . 'index.php?option=com_payperdownload&gateway=paystack&task=' . $task; - $callbackurl .= '&item_id=' . htmlentities($item_id); - $callbackurl .= '&item_type=' . $type; - $callbackurl .= '&user_id=' . htmlentities($user_id); - $callbackurl .= '&amount=' . htmlentities($damount); - $callbackurl .= '¤cy=' . htmlentities($currency); - $callbackurl .= '&r=' . htmlentities($returnBase64Coded); - - if ($thankyouUrl) { - $returnParams = ''; - if ($type == 'license') { - if (strstr($thankyouUrl, "?") === false) { - $returnParams = '?lid=' . (int)$license->license_id; - } else { - $returnParams = '&lid=' . (int)$license->license_id; - } - } - $callbackurl .= '&redirect=' . htmlentities(base64_encode($thankyouUrl . $returnParams)); - } + $description = $resource->resource_description; + $task = "confirmres"; + $type = "resource"; + } + else + { + $damount = $license->price; + $currency = $license->currency_code; + $item_id = $license->license_id; + $name = $license->license_name; + $description = $license->description; + $task = "confirm"; + $type = "license"; + } - if ($download_id) { - $callbackurl .= '&download_id=' . (int)$download_id; - } + $tax = 0; + $tax_percentage = $this->_getTaxPercentage(); + if ($tax_percentage > 0) { + $tax = round($damount * $tax_percentage / 100, 2); + $damount = $damount + $tax; + } - $the_reference = 'ppdp'.floor(mt_rand()*10 + 1);//''+Math.floor((Math.random() * 1000000000) + 1); - //put the reference in a session - $session = JFactory::getSession(); - $session->set('session_transaction_id',$the_reference); //dump($the_reference,"the created reference"); - - //construct the variable containing the form - - JFactory::getDocument()->addScript('https://js.paystack.co/v1/inline.js'); - - if (count($thename) > 1) { - $lastname = $thename[1]; - } - - $js_declaration = <<< JS - function payWithPaystack() { - var handler = PaystackPop.setup({ - key: "$public_key", - email: "$customer_email", - amount: "$amount", - ref: "$the_reference", - currency: "$currency", - firstname: "$firstname", - lastname: "$lastname", - metadata: { - "ecommerce_platform":"Joomla 3", - "payment_plugin": "Paystackpay for PayPerDownload", - "author": "Daydah", - custom_fields: [ - { - display_name: "Plugin", - variable_name: "plugin", - value: "Paystackpay for PayPerDownload" - } - ] - }, - callback: function(response){ - document.getElementById("paystack-payment_form").submit(); - }, - onClose: function(){ - /* cancelling by the buyer */ - } - }); - handler.openIframe(); - } - - window.addEventListener('load', function() { - document.querySelector('#paystack-pay-btn').addEventListener('click', function () { - payWithPaystack(); - }); - }, false); + // apply the tax before or after the additonnal fee ? + + $package_price = $this->calcFinalAmount($damount, $pmntinfo->ps_extra, $pmntinfo->ps_extratype, $pmntinfo->ps_extraval); + $amount = $package_price[0] * 100; + $amount = (int)$amount; + + $callbackurl = JURI::root() . 'index.php?option=com_payperdownload&gateway=paystack&task=' . $task; + + $the_reference = 'ppdp'.floor(mt_rand()*10 + 1);//''+Math.floor((Math.random() * 1000000000) + 1); + //put the reference in a session + $session = JFactory::getSession(); + $session->set('session_transaction_id',$the_reference); //dump($the_reference,"the created reference"); + + //construct the variable containing the form + + JFactory::getDocument()->addScript('https://js.paystack.co/v1/inline.js'); + + $js_declaration = <<< JS + function payWithPaystack() { + var handler = PaystackPop.setup({ + key: "$public_key", + email: "$customer_email", + amount: "$amount", + ref: "$the_reference", + currency: "$currency", + metadata: { + "ecommerce_platform":"Joomla 3", + "payment_plugin": "Paystackpay for PayPerDownload", + "author": "Daydah", + custom_fields: [ + { + display_name: "Plugin", + variable_name: "plugin", + value: "Paystackpay for PayPerDownload" + } + ] + }, + callback: function(response){ + document.getElementById("paystack-payment_form").submit(); + }, + onClose: function(){ + /* cancelling by the buyer */ + } + }); + handler.openIframe(); + } + + window.addEventListener('load', function() { + document.querySelector('#paystack-pay-btn').addEventListener('click', function () { + payWithPaystack(); + }); + }, false); JS; - JFactory::getDocument()->addScriptDeclaration($js_declaration); - - //$tosend ='
'.$redirectHeading.'
'; - echo '
'; - - echo $this->_loadTemplate('default.php'); - - //add the hidden form fields too - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - - if($download_id) - { - echo ''; + + echo ''; + + $variables = array('additional_fee' => $package_price[1], 'currency' => $currency); + echo $this->_loadTemplate('default.php', $variables); + + //add the hidden form fields too + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + if ($type == 'resource') { + echo ''; + } + + if ($thankyouUrl) { + $returnParams = ''; + if ($type == 'license') { + if (strstr($thankyouUrl, "?") === false) { + $returnParams = '?lid=' . (int)$license->license_id; + } else { + $returnParams = '&lid=' . (int)$license->license_id; + } + } + echo ''; + } + + //echo ''; + + if ($download_id) { + echo 'getString("item_type"); @@ -229,19 +239,24 @@ public function onPaymentReceived($gateway, &$dealt, &$payed, $download_id = $jinput->getInt("download_id"); $license_id = 0; $resource_id = 0; - $tax = 0; - if($item_type == "resource") - {$resource_id = $item_id;} - else - {$license_id = $item_id;} - $session = JFactory::getSession(); + $tax = $jinput->getFloat('tax', 0); + $fee = 0; // $jinput->getFloat('the-fee', 0); + + if ($item_type == 'resource') { + $resource_id = $item_id; + } else { + $license_id = $item_id; + } + + $session = JFactory::getSession(); $thetransactionid = $session->get('session_transaction_id'); - $pmntinfo1 = $this->getPaystackPaymentInfo(); + $pmntinfo = $this->getPaystackPaymentInfo(); - $secret_key = $pmntinfo1->secret_key; - $public_key = $pmntinfo1->public_key; - if($secret_key && $thetransactionid) + $secret_key = $pmntinfo->secret_key; + $public_key = $pmntinfo->public_key; + + if($thetransactionid) { try { @@ -272,21 +287,22 @@ public function onPaymentReceived($gateway, &$dealt, &$payed, // Update order status - From pending to complete - $amount = $amount;// / 100.0; + $payed = true; $transactionId = $sentreference; - $fee = $jinput->getInt('the-fee'); + + $fee = $transData->fees / 100.0; + $status = "COMPLETED"; $validate_response = "VERIFIED"; $response = json_encode($transData); $payerEmail = $transData->customer->email; - if(!$payerEmail){ $payerEmail = $theuser->email;} } else if (property_exists($transData, 'error') || (property_exists($transData, 'status') && $transData->status === 'failed')) - { - $status = "FAILED"; - $response = $transData->gateway_response; - } + { + $status = "FAILED"; + $response = $transData->gateway_response; + } if($download_id) { @@ -343,7 +359,7 @@ public function calcFinalAmount($initialval, $extra1, $extratype, $extraval) if($extratype == 0){ //then the type is a percentage //calculate percentage value - $dextra = ($extraval * $initialval)/100; + $dextra = round(($extraval * $initialval)/100, 2); $finvalue = $initialval + $dextra; } else{//then the type is a fixed amount @@ -358,50 +374,50 @@ public function calcFinalAmount($initialval, $extra1, $extratype, $extraval) /* * @param string $secret_key is either the demo or live secret key from your dashboard. $transactionid is the transaction reference code sent to the API previously */ - - public function verifyPaystackTransaction($transactionid, $secret_key) - { - $transactionStatus = new stdClass(); - $transactionStatus->error = ""; - // try a file_get verification - $opts = array( - 'http' => array( - 'method' => "GET", - 'header' => "Authorization: Bearer " . $secret_key - ) - ); - - $context = stream_context_create($opts); - $url = "https://api.paystack.co/transaction/verify/" . $transactionid; - $response = file_get_contents($url, false, $context); - - // if file_get didn't work, try curl - if (!$response) { - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, "https://api.paystack.co/transaction/verify/" . $transactionid); - curl_setopt($ch, CURLOPT_HTTPHEADER, array( - 'Authorization: Bearer ' . $secret_key - )); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_HEADER, false); - - // Make sure CURL_SSLVERSION_TLSv1_2 is defined as 6 - // cURL must be able to use TLSv1.2 to connect - // to Paystack servers - if (!defined('CURL_SSLVERSION_TLSv1_2')) { - define('CURL_SSLVERSION_TLSv1_2', 6); - } - curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); - // exec the cURL - $response = curl_exec($ch); - // should be 0 - if (curl_errno($ch)) { - // curl ended with an error - $transactionStatus->error = "cURL said:" . curl_error($ch); - } - //close connection - curl_close($ch); + public function verifyPaystackTransaction($transactionid, $secret_key) + { + $transactionStatus = new stdClass(); + $transactionStatus->error = ""; + + // try a file_get verification + $opts = array( + 'http' => array( + 'method' => "GET", + 'header' => "Authorization: Bearer " . $secret_key + ) + ); + + $context = stream_context_create($opts); + $url = "https://api.paystack.co/transaction/verify/" . $transactionid; + $response = file_get_contents($url, false, $context); + + // if file_get didn't work, try curl + if (!$response) { + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, "https://api.paystack.co/transaction/verify/" . $transactionid); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Authorization: Bearer ' . $secret_key + )); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, false); + + // Make sure CURL_SSLVERSION_TLSv1_2 is defined as 6 + // cURL must be able to use TLSv1.2 to connect + // to Paystack servers + if (!defined('CURL_SSLVERSION_TLSv1_2')) { + define('CURL_SSLVERSION_TLSv1_2', 6); + } + curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + // exec the cURL + $response = curl_exec($ch); + // should be 0 + if (curl_errno($ch)) { + // curl ended with an error + $transactionStatus->error = "cURL said:" . curl_error($ch); + } + //close connection + curl_close($ch); } if ($response) @@ -431,14 +447,14 @@ public function getPaystackPaymentInfo() switch($pddpinfo->pmode) { case 0: //its in test mode - $pddpinfo->secret_key = $this->params->get('ppdp_test_secret_key'); - $pddpinfo->public_key = $this->params->get('ppdp_test_public_key'); break; + $pddpinfo->secret_key = trim($this->params->get('ppdp_test_secret_key')); + $pddpinfo->public_key = trim($this->params->get('ppdp_test_public_key')); break; case 1://its live - $pddpinfo->secret_key = $this->params->get('ppdp_live_secret_key'); - $pddpinfo->public_key = $this->params->get('ppdp_live_public_key'); break; + $pddpinfo->secret_key = trim($this->params->get('ppdp_live_secret_key')); + $pddpinfo->public_key = trim($this->params->get('ppdp_live_public_key')); break; default: //its in test mode - $pddpinfo->secret_key = $this->params->get('ppdp_test_secret_key'); - $pddpinfo->public_key = $this->params->get('ppdp_test_public_key'); break; + $pddpinfo->secret_key = trim($this->params->get('ppdp_test_secret_key')); + $pddpinfo->public_key = trim($this->params->get('ppdp_test_public_key')); break; } //$pddpinfo->notify_email = $this->params->get('notify_email', ''); @@ -450,7 +466,29 @@ public function getPaystackPaymentInfo() return $pddpinfo; } - private function _loadTemplate($file = null, $variables = array()) + protected function _getTaxPercentage() + { + if (!isset(self::$tax_percentage)) { + + $db = JFactory::getDBO(); + + $db->setQuery('SELECT tax_rate FROM #__payperdownloadplus_config'); + + self::$tax_percentage = 0; + try { + $tax_percentage = $db->loadResult(); + if (!is_null($tax_percentage)) { + self::$tax_percentage = $tax_percentage; + } + } catch (RuntimeException $e) { + self::$tax_percentage = 0; + } + } + + return self::$tax_percentage; + } + + protected function _loadTemplate($file = null, $variables = array()) { $template = JFactory::getApplication()->getTemplate(); $overridePath = JPATH_THEMES.'/'.$template.'/html/plg_payperdownloadplus_paystackpay'; diff --git a/paystackpay.xml b/paystackpay.xml index ae58959..f1b2459 100755 --- a/paystackpay.xml +++ b/paystackpay.xml @@ -1,7 +1,7 @@ PLG_PAYPERDOWNLOADPLUS_PAYSTACKPAY - 1.2.1 + 1.3.0 Aug 2019 Daydah Adeniyi www.jibitech.com diff --git a/tmpl/default.php b/tmpl/default.php index 69b4adc..edfd995 100644 --- a/tmpl/default.php +++ b/tmpl/default.php @@ -9,8 +9,10 @@ // no direct access defined('_JEXEC') or die; - ?> \ No newline at end of file + + 0) : ?> + + \ No newline at end of file From b4be65d2377d6bb0276e4c189aecd2bc35353ee1 Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 8 Dec 2019 11:12:44 -0500 Subject: [PATCH 2/2] wrong amount sent to request --- paystackpay.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paystackpay.php b/paystackpay.php index d0d3370..f51e20c 100755 --- a/paystackpay.php +++ b/paystackpay.php @@ -188,7 +188,7 @@ function payWithPaystack() { echo ''; echo ''; echo ''; - echo ''; + echo ''; // damount + possible reversal fee before x100 echo ''; echo '';