Jump to content


  • Content count

  • Joined

  • Last visited

  • Days Won


Reputation Activity

  1. Like
    katapofatico reacted to raiwa in Store Mode BS   
    I use it like it is set during installation: 755. Other addons and the core admin protection also write to .htaccess and need this setting, so I think it should be ok.
  2. Like
    katapofatico got a reaction from raiwa in Store Mode BS   
    Installing the content module, on URL ...admin/modules.php?set=header_tags&module=ht_store_mode
    Notice: Use of undefined constant MODULE_HEADER_TAGS_STORE_MODE_MESSAGE_ - assumed 'MODULE_HEADER_TAGS_STORE_MODE_MESSAGE_' in .../includes/modules/header_tags/ht_store_mode.php on line 201
    $KeysArray[] = MODULE_HEADER_TAGS_STORE_MODE_MESSAGE_ . $key; Fixed:
  3. Like
    katapofatico reacted to kymation in Spam addon   
    There is definitely spam in the Addons section. I found two that were pure commercial advertising and another that was malicious code. I reported all of them, and nothing was ever done. You should probably just ignore this one.
  4. Like
    katapofatico reacted to kymation in [Addon} Theme Switcher   
    Instructions for creating and downloading themes are in the Theme Switcher manual, included in the download. The "design it on your store" feature is no longer supported by Themeroller. Unfortunately I can't edit that description to remove the obsolete part.
  5. Like
    katapofatico reacted to Eskil in Payment module development how-to   
    This is a lengthy post. This post is meant for anyone who wants to create/implement their custom payment module. The contents of this post hopefully answers many question anyone has. It is the result of my own acquired understanding of how osCommerce payment modules work. I appreciate any comments if you find this post useful. Please reply to this post if you identify any mistakes in my post or want to elaborate on the topic.
    I originally replied to a post on how to create a module and received some PMs asking me to elaborate on this.
    In this post I will include that same overview with extended explanations and sample code. This post does not attempt to explain how to write a module, as there are many considerations one needs to take and each payment gateway is different. I will outline the standard functions in a module that are required and when and how they are called/used. I assume we are using a gateway which requires a http-post redirect.
    First, a simple overview of the standard/required payment module functions (the standard PayPal module or cc module are good references as they implement standard functions and have minimal code):

    Function name
    Calling script
    class constructor
    Sets initial member variables and module status (enabled/disabled).
    Define the form_action_url variable which is your gateway url (that will recieve the POST data).
    Include any static variables you may require in your code here.
    Here you can implement using payment zones (refer to standard PayPal module as reference).
    Called by module's class constructor, checkout_confirmation.php, checkout_process.php
    Here you may define client side javascript that will verify any input fields you use in the payment method selection page. Refer to standard cc module as reference (cc.php).
    Called by checkout_payment.php
    This function outputs the payment method title/text and if required, the input fields.
    Called by checkout_payment.php
    Use this function implement any checks of any conditions after payment method has been selected. You most probably don't need to implement anything here.
    Called by checkout_confirmation.php before any page output.
    Implement any checks or processing on the order information before proceeding to payment confirmation. You most probably don't need to implement anything here.
    Called by checkout_confirmation.php
    Outputs the html form hidden elements sent as POST data to the payment gateway.
    Called by checkout_confirmation.php
    This is where you will implement any payment verification. This function can be quite complicated to implement. I will elaborate in this later in this post.
    Called by checkout_process.php before order is finalised
    Here you may implement any post proessing of the payment/order after the order has been finalised. At this point you now have a reference to the created osCommerce order id and you would typically update any custom database tables you may have for your module. You most probably don't need to implement anything here.
    Called by checkout_process.php after order is finalised
    For more advanced error handling. When your module logic returns any errors you will redirect to checkout_payment.php with some error information. When implemented corretly, this function can be used to genereate the proper error texts for particular errors. The redirect must be formatted like this:

    tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error=' . $this->code.'&error='.urlencode('some error'), 'NONSSL', true, false));
    I will examplify this in my sample code later in this post (the standard PayPal module does not implement this method).
    Called by checkout_payment.php
    Standard functionlity for osCommerce to see if the module is installed.
    This is where you define module's configurations (displayed in admin).
    Standard functionality to uninstall the module.
    This array must include all the configuration setting keys defined in your install() function.
    A good payment gateway (and payment module) should allow for payment verification. Without any form of payment verification your module is open for url-hacking. This is a very simple consept where a malicious user simply pastes the success url of the e-commerce system (in this case checkout_process.php) and the order is completed assuming the payment has been completed. You can try this by installing the standard PayPal module, completing the order as far as not confirming the order. Then paste in the full url for checkout_process.php for your server.
    I will with the following sample code show how to implement payment verification. There are probably numerous ways this may be done. I assume a simple scenario where the payment information is verified by the gateway by re-submitting the data first recieved from the gateway. The information is first checked by the payment module (simple verification) and then re-submitted back the gateway for verification (advanced verification). A result code is passed back to the module. This communication is passed on an underlying layer using secure sockets (SSL) and is invisible to the user (no re-directs). My sample uses cURL to enable underlying connections over SSL.
    Note: The module's internal check of the payment data requires to compare the payment amount passed from the gateway with the order amount. To achieve this the $order_totals object must be instantiated from within the module and requires a little hack/work around to be able to complete the order processing: the rest of the code in checkout_process.php from the point where the module's before_process() function is called, must be executed from within this module function. This is related to the chicken&egg problem described here . I have made notes in the sample code where this occurs. (I discovered this problem when tax was added to shipping. The payment amounts would differ.)
    Listing 1: usage of before_process() to verify a payment.

    function before_process() { global $HTTP_POST_VARS, $cart, $order, $currency, $currencies, $customer_id; // return error if key values are missing if(!isset($HTTP_POST_VARS['PaymentID']) || !isset($HTTP_POST_VARS['OrderID']) || !isset($HTTP_POST_VARS['Amount']) ) tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode('No payment information found.'), 'NONSSL', true, false)); $in_paymentID = ''; $in_amount = ''; $in_orderID = ''; $in_currency = ''; // read returned data from gateway $in_paymentID = urldecode($HTTP_POST_VARS['PaymentID']); $in_amount = urldecode($HTTP_POST_VARS['Amount']); $in_orderID = urldecode($HTTP_POST_VARS['OrderID']); $in_currency = urldecode($HTTP_POST_VARS['Currency']); // add PaymentID as comment to order $order->info['comments'] .= "\nPaymentID: ". $in_paymentID; /* From checkout_process.php: create $order_totals object, otherwise $order object will have incorrect data * This is why the rest of checkout_process.php must be included in this function. (see end of function def) * The $order_totalts object needs to be instantiated here and cannot be instantiated twice! */ require(DIR_WS_CLASSES . 'order_total.php'); $order_total_modules = new order_total; $order_totals = $order_total_modules->process(); // Check that values are untampered (simple verification). // Note: get_orderno is an added custom function to generate an orderid as an osc order has no id until it has been completely processed.... if( ($in_amount != number_format($order->info['total'] * $currencies->get_value($currency), $currencies->get_decimal_places($currency), '.', '')) || ($in_orderID != $this->get_orderno($customer_id)) || ($in_currency != $currency) ) ){ tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode('Data has been tampered! Payment aborted.'), 'NONSSL', true, false)); } /* Verify transaction with gateway. * The actual verification is defined in a separate function (validate_payment()). * This code assumes using cURL for posting data over SSL. */ $this->validate_payment( $HTTP_POST_VARS ); // Processing continues here if there is no error /* Here we continue the processing that otherwise is done by checkout_process.php. * Include everything in checkout_process starting from line #57 * Alternatively extract that code into an include file (i.e include('module_checkout_process.inc.php'); ) */ include('sample_module_checkout_process.inc.php'); }
    Lising 2: The payment validation method

    /* Payment verification * Note that this processing is an example only. All gateways are different. * This function shows how to post data back to the gateway. * * The recieved payment data are posted back to the gateway to verify that they are correct. * Gateway verifies amount, currency, transaction_id and order_id. * Gateway returns 0 for success. * * Also make note of how the errors are handled. * The error information can include your own codes that later are interpreted by the module's get_error() function. */ function validate_payment( $request ){ $postfields = null; foreach($request as $key=>$value){ if($key && $value){ $postfields.=$key."=".urlencode($value)."&"; } } curl_setopt($ch, CURLOPT_URL, 'https://insert.gateway.verification.url.here'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); curl_setopt($ch, CURLOPT_HEADER, 0); // ignore http headers curl_setopt($ch, CURLOPT_TIMEOUT, 10); //returns error 28 curl_setopt($ch, CURLOPT_FAILONERROR, 1); //returns error 22 on HTTP error (http statuscode >= 300) curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // Post data back to gateway $result = curl_exec($ch); // check for error if (curl_errno($ch) != CURLE_OK) { $result['errno'] = curl_errno($ch); $result['errstr'] = curl_error($ch); } curl_close ($ch); // process verification result // if result is array then a CURL error has occurred if(is_array($result) && isset($result['errno'])){ $errornumber = $result['errno']; $errortext = $result['errstr']; $this->luup_debug('Curl or socket error: ', $errornumber . ' ' . $errortext); switch($errornumber){ case CURLE_HTTP_RETURNED_ERROR: // HTTP error tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error=' . $this->code.'&error='.urlencode($errortext), 'NONSSL', true, false)); break; case CURLE_OPERATION_TIMEOUTED: tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error=' . $this->code.'&error='.urlencode('TIMEOUT'), 'NONSSL', true, false)); break; case 0: // connection failure tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error=' . $this->code.'&error='.urlencode('CONNECT_FAIL'), 'NONSSL', true, false)); break; default: // curl/socket error tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error=' . $this->code.'&error='.urlencode($errornumber.': '.$errortext), 'NONSSL', true, false)); break; } } else{ // is the payment verified? if($result != '0'){ // payment is not ok tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error='.$this->code.'&error='.urlencode($result), 'NONSSL', true, false)); } // payment is ok return true; }
    Listing 3: Formatting errors

    // displays/formats error function get_error() { global $HTTP_GET_VARS, $language; // ensure we have all texts defined require_once(DIR_WS_LANGUAGES . $language . '/modules/payment/'.$this->code.'.php'); $error = ''; $error_text['title'] = MODULE_PAYMENT_SAMPLE_TEXT_ERROR_TITLE; if(isset($HTTP_GET_VARS['error'])) $error = urldecode($HTTP_GET_VARS['error']); // otherwise default error is displayed switch($error){ case 'TIMEOUT': $error_text['error'] = MODULE_PAYMENT_SAMPLE_TEXT_ERROR_TIMEOUT; break; case 'CONNECT_FAIL': $error_text['error'] = MODULE_PAYMENT_LUUP_SAMPLE_ERROR_CONNECT_FAIL; break; /* include additional handling for gateway specific errors here */ default: //other error $error_text['error'] = MODULE_PAYMENT_SAMPLE_TEXT_ERROR_UNKNOWN ." ($error)"; break; } return $error_text; }
    Developing a payment module may be a complicated and time-consuming task. I hope this post helps you to understand how the payment process works and how the payment module's functions are used - and in the end makes it easier for you to write your own custom payment module. :thumbsup:
  6. Like
    katapofatico reacted to Tsimi in Discount Code BS   
    Here is a BETA package that contains a couple of code improvements provided by @@katapofatico and the new discount on shipping feature provided by @@raiwa and @@greasemonkey. I need some guys to test this before it can be cleaned and uploaded as new update to the addons area.
    *Please do not use this in a live store yet, this package is not final and contains a lot uncleaned code.
  7. Like
    katapofatico got a reaction from Tsimi in Discount Code BS   
    @@Tsimi More improvements, this time in order to avoid code changes:
    A ) Instead of write on admin/template_top.php, you can add these lines on admin/discount_codes.php, before applies_to_onclick() definition:
    $(document).ready(function() {     if (<?php echo ((basename($PHP_SELF) == 'discount_codes.php' && isset($action) && $action == 'new') ? 'true' : 'false')?>) {         onload();     } }); B ) Instead of modify checkout_payment.php, you can use a header_tag module that inject HTML and javascript. I have the module files but... I can't attach to this post! Anybody can show me how?
    C) Instead of modify 11 lines on checkout_process.php and 7 on application_top, you can use hook callings and write only 1 or 2 lines.
  8. Like
    katapofatico got a reaction from Tsimi in Discount Code BS   
    @@Tsimi I have uploaded my header tag module here: http://addons.oscommerce.com/info/9470
  9. Like
    katapofatico reacted to kymation in [Addon] Modular Product Page (Bootstrap)   
    So the Limit 1 would make the query faster by stopping after it finds the first match. That would be worth doing for cases where that table is very large. Good point!
    The latest version does not call tep_get_products_special_price(), it does the database call directly. This is probably a good place to add a Limit 1 as well. I could probably improve this slightly by using a temporary variable. I also suspect that the improvement would be impossible to detect on a modern server. Oh well, best practices and all that.
    Thanks for the suggestions.
  10. Like
    katapofatico reacted to 14steve14 in [Addon] Modular Product Page (Bootstrap)   
    You are one of only a few coders that have finally embraced the whole concept of the bootstrap version and are trying to reduce core code changes, and make the whole system modular. Congratulations, the work you are doing must be helping to move the BS version of oscommerce forward. Thank you for the great work.
    I have added both the modular product and index pages to my test store and they seem to work very well. Hopefully others will produce even more modules and ideas to enhance what is already available.
  11. Like
    katapofatico reacted to kymation in [Addon] Modular Navigation Bar (Bootstrap)   
    I've uploaded a new version of the base Modular Navigation Bar Addon. Thanks to @@katapofatico for spotting one of my typos. I think I've fixed everything now, but please post here if you find any more. As always, bug reports are welcome.
  12. Like
    katapofatico got a reaction from Tsimi in Horizontal Categories Menu BS   
    I've founded that it's better to declare $result before the if: in other case, if the if results false, the final sentence return $result; throws again a PHP Notice:  Undefined variable.
    function _buildHoz($parent_id, $level = 0) { $result = ''; // this line added if (isset($this->_data[$parent_id])) {
  13. Like
    katapofatico reacted to m2a221 in How to create payment module   
  14. Like
    katapofatico reacted to kieran_mullen in Something module writers need to do..   
    While I appreciate all the hard work people do to create modules for OScommerce, there are a couple of things I find are greatly lacking.
    1)Every add on should have a dedicated support thread automatically created and linked in the project details. (People of course are free to create ther own)
    2)There needs to be an email/rss update notification when something the oadd on gets changed or added
    3)Every add module which is its own option that can be selected within the control panel shoudl display the current version. That way once you get your notifcation email you know how old your install is.