Hello,

I am running Zen Cart 1.3.8p3 (PHP 5.2.12) and am working at porting the osCommerce iTransact credit card module (v1.2) for use with my Zen Cart installation.

With that in mind, I downloaded the original osCommerce iTransact module from here http://www.itransact.com/redicart/itransact-osc-1.2.zip and followed the instructions (to the best of my limited abilities) for porting osCommerce modules to Zen Cart found here

http://www.zen-cart.com/wiki/index.p...dules_from_osC

and have managed to get the module to successfully post transactions so that my credit card is charged and iTransact sends me a nice success message saying that all is well.

However, the passback/return functionality appears to be broken because once the transaction is completed on the iTransact web interface the user is returned to Zen Cart and greeted with the following error message:

"Whoops! Sorry, but you are not allowed to perform the action requested. You are still logged in to your account and may continue shopping. Please choose a destination from a menu."

This error comes from Zen Cart and appears to fire due to a "time out" of some sort, but I could be wrong. The "time out" assumption is based on the name of the file in the Zen Cart framework containing the error message (time_out.php

Line #11), but I have no idea which function called the error.

Also, no record of the completed transaction can be found in the Admin interface on Zen Cart, which means that Zen Cart never got a response back from iTransact (at least not in readable form) to tell it about the transaction.

So, being a C# guy used to the rich glories of debugging in Visual Studio and not having a clue what I'm doing in PHP beyond the basics--and being new to debugging in Eclipse, I'm rather lost at the moment. I want to setup remote debugging on my server so I can set breakpoints and see what data is being returned, if any at all, but am throwing out this Hail Mary post before I hassle with SSH and installing debugging tools on my remote server and all that fun stuff.

Can some PHP/Zen Cart God out there please have a look at my ported osCommerce code listed below and spot the glowing flaw in my effort and tell me what I'm doing wrong? I sure hope so because my nerves are shot (not being able to debug effectively is driving me crazy).

Any feedback at all would be most appreciated.

Thanks and very cordially,

Wulf

The code posted below is my modified code:

Code:
<?php
/*
  osCommerce, Open Source E-Commerce Solutions
  http://www.oscommerce.com

  Copyright (c) 2003 osCommerce

  iTransact, Inc. (Credit Card) Module v1.2
  Copyright (c) 2003 React, Ltd.
  http://react.co.nz

  Modified for Zen Cart by Wulfmaer

  Released under the GNU General Public License
*/

  class itransact {
    var $code, $title, $description, $enabled;

// class constructor
    function itransact() {
      global $order;

      $this->code = 'itransact';
      $this->title = MODULE_PAYMENT_ITRANSACT_TEXT_TITLE;
      $this->description = MODULE_PAYMENT_ITRANSACT_TEXT_DESCRIPTION;
      $this->enabled = ((MODULE_PAYMENT_ITRANSACT_STATUS == 'True') ? true : false);
      $this->sort_order = MODULE_PAYMENT_ITRANSACT_SORT_ORDER;

      if ((int)MODULE_PAYMENT_ITRANSACT_ORDER_STATUS_ID > 0) {
        $this->order_status = MODULE_PAYMENT_ITRANSACT_ORDER_STATUS_ID;
      }

      if (is_object($order)) $this->update_status();

      if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
        $this->form_action_url = 'https://secure.paymentclearing.com/cgi-bin/rc/ord.cgi';
      } else {
        $this->form_action_url = 'https://secure.paymentclearing.com/cgi-bin/mas/split.cgi';
      }
    }

// class methods
    function update_status() {
      global $order;
      global $db;

      if ( ($this->enabled == true) && ((int)MODULE_PAYMENT_ITRANSACT_ZONE > 0) ) {
        $check_flag = false;
        $check_query = $db->Execute("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . MODULE_PAYMENT_ITRANSACT_ZONE . "' and zone_country_id = '" . $order->billing['country']['id'] . "' order by zone_id");
        while ($check = $db->Execute($check_query)) {
          if ($check['zone_id'] < 1) {
            $check_flag = true;
            break;
          } elseif ($check['zone_id'] == $order->billing['zone_id']) {
            $check_flag = true;
            break;
          }
        }

        if ($check_flag == false) {
          $this->enabled = false;
        }
      }
    }

    function javascript_validation() {
      if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
        $js = '  if (payment_value == "' . $this->code . '") {' . "\n" .
              '    var cc_number = document.checkout_payment.itransact_cc_number.value;' . "\n" .
              '    if (cc_number == "" || cc_number.length < ' . CC_NUMBER_MIN_LENGTH . ') {' . "\n" .
              '      error_message = error_message + "' . MODULE_PAYMENT_ITRANSACT_TEXT_JS_CC_NUMBER . '";' . "\n" .
              '      error = 1;' . "\n" .
              '    }' . "\n" .
              '  }' . "\n";
        }
      return $js;
    }

    function selection() {
      global $order;

      for ($i=1; $i<13; $i++) {
        $expires_month[] = array('id' => sprintf('%02d', $i), 'text' => strftime('%B',mktime(0,0,0,$i,1,2000)));
      }

      $today = getdate(); 
      for ($i=$today['year']; $i < $today['year']+10; $i++) {
        $expires_year[] = array('id' => strftime('%y',mktime(0,0,0,1,1,$i)), 'text' => strftime('%Y',mktime(0,0,0,1,1,$i)));
      }
      if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
        $selection = array('id' => $this->code,
                           'module' => $this->title,
                           'fields' => array(array('title' => MODULE_PAYMENT_ITRANSACT_TEXT_CREDIT_CARD_NUMBER,
                                                   'field' => zen_draw_input_field('itransact_cc_number')),
                                             array('title' => MODULE_PAYMENT_ITRANSACT_TEXT_CREDIT_CARD_EXPIRES,
                                                   'field' => zen_draw_pull_down_menu('itransact_cc_expires_month', $expires_month) . '&nbsp;' . zen_draw_pull_down_menu('itransact_cc_expires_year', $expires_year))));
        if (MODULE_PAYMENT_ITRANSACT_CVV == 'True') {
          array_push($selection['fields'], array('title' => MODULE_PAYMENT_ITRANSACT_TEXT_CREDIT_CARD_CVV,
                                                 'field' => zen_draw_input_field('itransact_cc_cvv', '', 'size="4" maxlength="3"') . '&nbsp;<small>' . MODULE_PAYMENT_ITRANSACT_TEXT_CREDIT_CARD_CVV_LOCATION . '</small>'));
        }
      } else {
        $selection = array('id' => $this->code,
                           'module' => $this->title);
      }

      return $selection;
    }

    function pre_confirmation_check() {
      global $_POST;

      if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
        include(DIR_WS_CLASSES . 'cc_validation.php');

        $cc_validation = new cc_validation();
        $result = $cc_validation->validate($_POST['itransact_cc_number'], $_POST['itransact_cc_expires_month'], $_POST['itransact_cc_expires_year']);
        $error = '';
        switch ($result) {
          case -1:
            $error = sprintf(TEXT_CCVAL_ERROR_UNKNOWN_CARD, substr($cc_validation->cc_number, 0, 4));
            break;
          case -2:
          case -3:
          case -4:
            $error = TEXT_CCVAL_ERROR_INVALID_DATE;
            break;
          case false:
            $error = TEXT_CCVAL_ERROR_INVALID_NUMBER;
            break;
        }

        if ( ($result == false) || ($result < 1) ) {
          $payment_error_return = 'payment_error=' . $this->code . '&error=' . urlencode($error) . '&itransact_cc_expires_month=' . $_POST['itransact_cc_expires_month'] . '&itransact_cc_expires_year=' . $_POST

['itransact_cc_expires_year'] . '&itransact_cc_cvv=' . urlencode($_POST['itransact_cc_cvv']);

          zen_redirect(zen_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false));
        }

        $this->cc_card_type = $cc_validation->cc_type;
        $this->cc_card_number = $cc_validation->cc_number;
        $this->cc_expiry_month = $cc_validation->cc_expiry_month;
        $this->cc_expiry_year = $cc_validation->cc_expiry_year;
      }
    }

    function confirmation() {
      global $_POST;

      if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
        $confirmation = array('title' => $this->title . ': ' . $this->cc_card_type,
                              'fields' => array(array('title' => MODULE_PAYMENT_ITRANSACT_TEXT_CREDIT_CARD_NUMBER,
                                                      'field' => substr($this->cc_card_number, 0, 4) . str_repeat('X', (strlen($this->cc_card_number) - 8)) . substr($this->cc_card_number, -4)),
                                                array('title' => MODULE_PAYMENT_ITRANSACT_TEXT_CREDIT_CARD_EXPIRES,
                                                      'field' => strftime('%B, %Y', mktime(0,0,0,$_POST['itransact_cc_expires_month'], 1, '20' . $_POST['itransact_cc_expires_year'])))));
        if (zen_not_null($_POST['itransact_cc_cvv'])) {
          array_push($confirmation['fields'], array('title' => MODULE_PAYMENT_ITRANSACT_TEXT_CREDIT_CARD_CVV,
                                                    'field' => $_POST['itransact_cc_cvv']));
        }
      }

      return $confirmation;
    }

    function process_button() {
      //global $HTTP_SERVER_VARS, $order, $customer_id, $_POST;
      global $order, $customer_id, $_POST;

      $process_button_string = zen_draw_hidden_field('vendor_id', MODULE_PAYMENT_ITRANSACT_VENDOR_ID) .
                               zen_draw_hidden_field('home_page', zen_href_link(FILENAME_ACCOUNT_HISTORY, '', 'SSL'));

      if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
        $process_button_string .= zen_draw_hidden_field('ret_addr', zen_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL', false));
      } else {
        $process_button_string .= zen_draw_hidden_field('osc-ret_addr', zen_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL', false)) .
                                  zen_draw_hidden_field('passback', 'osc-ret_addr') .
                                  zen_draw_hidden_field('osc-decl_addr', zen_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode(MODULE_PAYMENT_ITRANSACT_TEXT_DECLINED_MESSAGE), 'SSL', true, false)) .
                                  zen_draw_hidden_field('passback', 'osc-decl_addr') .
                                  zen_draw_hidden_field('osc-succ_addr', zen_href_link(FILENAME_CHECKOUT_SUCCESS, '', 'SSL')) .
                                  zen_draw_hidden_field('passback', 'osc-succ_addr') .
                                  zen_draw_hidden_field('osc-err_addr', zen_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode(MODULE_PAYMENT_ITRANSACT_TEXT_ERROR_MESSAGE), 'SSL', true, false)) .
                                  zen_draw_hidden_field('passback', 'osc-err_addr') .
                                  zen_draw_hidden_field('ret_addr', 'https://secure.paymentclearing.com/osc/ret/');
      }

      $process_button_string .= zen_draw_hidden_field('1_desc', STORE_NAME . ' Order Total') .
                                zen_draw_hidden_field('1_cost', number_format($order->info['total'], 2, '.', '')) .
                                zen_draw_hidden_field('1_qty', '1'); // *_anything showaddr

      if (MODULE_PAYMENT_ITRANSACT_CVV == 'True') {
        if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
          $process_button_string .= zen_draw_hidden_field('cvv2_number', $_POST['itransact_cc_cvv']);
        } else {
          $process_button_string .= zen_draw_hidden_field('showcvv', '1');
        }
      }

      $process_button_string .= zen_draw_hidden_field('mername', STORE_NAME) .
                                zen_draw_hidden_field('acceptcards', '1') .
                                zen_draw_hidden_field('acceptchecks', '0') .
                                zen_draw_hidden_field('accepteft', '0') .
                                zen_draw_hidden_field('altaddr', '0') .
                                zen_draw_hidden_field('nonum', '1') .
                                // preauth
                                zen_draw_hidden_field('ret_mode', 'post') .
                                zen_draw_hidden_field('post_back_on_error', '1') . // check_num check_memo
                                zen_draw_hidden_field('passback', zen_session_name()) . // lookup email_text
                                zen_draw_hidden_field('first_name', $order->billing['firstname']) .
                                zen_draw_hidden_field('last_name', $order->billing['lastname']) .
                                zen_draw_hidden_field('address', $order->billing['street_address']) .
                                zen_draw_hidden_field('city', $order->billing['city']) .
                                zen_draw_hidden_field('state', $order->billing['state']) .
                                zen_draw_hidden_field('zip', $order->billing['postcode']) .
                                zen_draw_hidden_field('country', $order->billing['country']['title']) .
                                zen_draw_hidden_field('phone', $order->customer['telephone']) .
                                zen_draw_hidden_field('email', $order->customer['email_address']);

      if (strstr(MODULE_PAYMENT_ITRANSACT_FORMAT, 'Standard')) {
        $process_button_string .= zen_draw_hidden_field('ccnum', $this->cc_card_number) .
                                  zen_draw_hidden_field('ccmo', strftime('%B',mktime(0,0,0,$this->cc_expiry_month,1,2000))) .
                                  zen_draw_hidden_field('ccyr', $this->cc_expiry_year); // aba account
      }

      $process_button_string .= zen_draw_hidden_field('sfname', $order->delivery['firstname']) .
                                zen_draw_hidden_field('slname', $order->delivery['lastname']) .
                                zen_draw_hidden_field('saddr', $order->delivery['street_address']) .
                                zen_draw_hidden_field('scity', $order->delivery['city']) .
                                zen_draw_hidden_field('sstate', $order->delivery['state']) .
                                zen_draw_hidden_field('szip', $order->delivery['postcode']) .
                                zen_draw_hidden_field('sctry', $order->delivery['country']['title']);

      $process_button_string .= zen_draw_hidden_field(zen_session_name(), zen_session_id());

      return $process_button_string;
    }

    function before_process() {
      //global $HTTP_SERVER_VARS, $_POST;
      global $_POST;

      if (in_array($_SERVER['REMOTE_ADDR'], gethostbynamel("osc-ret.itransact.com"))) {
        if (isset($_POST['die'])) {
          zen_redirect(zen_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode(MODULE_PAYMENT_ITRANSACT_TEXT_ERROR_MESSAGE), 'SSL', true, false));
        } else if (isset($_POST['err'])) {
          zen_redirect(zen_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode(MODULE_PAYMENT_ITRANSACT_TEXT_DECLINED_MESSAGE), 'SSL', true, false));
        } else if (isset($_POST['signature'])) {
          return;
        } else {
          zen_redirect(zen_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode(MODULE_PAYMENT_ITRANSACT_TEXT_ERROR_MESSAGE), 'SSL', true, false));
        }
      } else {
        zen_redirect(zen_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode(MODULE_PAYMENT_ITRANSACT_TEXT_ERROR_MESSAGE), 'SSL', true, false));
      }
    }

    function after_process() {
      return false;
    }

    function get_error() {
      global $_GET;

      $error = array('title' => MODULE_PAYMENT_ITRANSACT_TEXT_ERROR,
                     'error' => stripslashes(urldecode($_GET['error'])));

      return $error;
    }

    function check() {
    global $db;
      if (!isset($this->_check)) {
        $check_query = $db->Execute("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_PAYMENT_ITRANSACT_STATUS'");
        $this->_check = $check_query->RecordCount();
      }
      return $this->_check;
    }

    function install() {
    global $db;
      $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable iTransact, 

inc. (<i>Credit Card</I>) Module', 'MODULE_PAYMENT_ITRANSACT_STATUS', 'True', 'Do you want to accept iTransact, inc. (<i>Credit Card</i>) payments?', '6', '0', 'zen_cfg_select_option(array(\'True\', \'False\'), ', now())");
      $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Vendor ID', 

'MODULE_PAYMENT_ITRANSACT_VENDOR_ID', '12345', 'The vendor ID used for the iTransact, inc. service', '6', '0', now())");
      $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Order Form 

Format', 'MODULE_PAYMENT_ITRANSACT_FORMAT', 'Split', 'The order form format used for transactions', '6', '0', 'zen_cfg_select_option(array(\'Split\',\'Standard (Requires a SSL certificate)\'), ', now())");
      $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Allow CVV?', 

'MODULE_PAYMENT_ITRANSACT_CVV', 'False', 'Allow customers to enter the CVV number from their credit card?', '6', '0', 'zen_cfg_select_option(array(\'True\', \'False\'), ', now())");
      $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort order of display.', 

'MODULE_PAYMENT_ITRANSACT_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '0', now())");
      $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values 

('Payment Zone', 'MODULE_PAYMENT_ITRANSACT_ZONE', '0', 'If a zone is selected, only enable this payment method for that zone.', '6', '2', 'zen_get_zone_class_title', 'zen_cfg_pull_down_zone_classes(', now())");
      $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set 

Order Status', 'MODULE_PAYMENT_ITRANSACT_ORDER_STATUS_ID', '0', 'Set the status of orders made with this payment module to this value', '6', '0', 'zen_cfg_pull_down_order_statuses(', 'zen_get_order_status_name', now())");
    }

    function remove() {
    global $db;
      $db->Execute("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')");
    }

    function keys() {
      return array('MODULE_PAYMENT_ITRANSACT_STATUS', 'MODULE_PAYMENT_ITRANSACT_VENDOR_ID', 'MODULE_PAYMENT_ITRANSACT_FORMAT', 'MODULE_PAYMENT_ITRANSACT_CVV', 'MODULE_PAYMENT_ITRANSACT_ZONE', 'MODULE_PAYMENT_ITRANSACT_ORDER_STATUS_ID', 

'MODULE_PAYMENT_ITRANSACT_SORT_ORDER');
    }
  }
?>