<?php
/*
  $Id: buysafe.php,v 1.14 2007/03/14 05:58:35 hpdl Exp $

  osCommerce, Open Source E-Commerce Solutions
  http://www.oscommerce.com

  Copyright (c) 2003 osCommerce

  Released under the GNU General Public License
*/

  class buysafe
  {
    var $title, $debug_info;

    function buysafe()
    {
      $this->code = 'buysafe';
      $this->title = MODULE_BUYSAFE_BUYSAFE_TITLE;
      $this->description = MODULE_BUYSAFE_BUYSAFE_DESCRIPTION;
      $this->enabled = ((MODULE_BUYSAFE_BUYSAFE_STATUS == 'True') ? true : false);
    }

    function check()
    {
      if (!isset($this->_check))
      {
        $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_BUYSAFE_BUYSAFE_STATUS'");
        $this->_check = tep_db_num_rows($check_query);
      }
      return $this->_check;
    }

    function call_api($method, $params = array(), $order = '')
    {
// {{
      global $currency;
      if (tep_not_null($currency) && $currency != 'USD') return false;
      $check_stop_api_calls = tep_db_fetch_array(tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_BUYSAFE_BUYSAFE_STOP_API_CALLS_TIME' and now() <= (configuration_value + interval 1 second)"));
      if (tep_not_null($check_stop_api_calls['configuration_value'])) return false;
// }}
      switch ($method)
      {
      case 'AddUpdateShoppingCart':
      case 'SetShoppingCartCheckout':
        require_once(DIR_WS_CLASSES . 'nusoap.php');
        $soapclient = new soapclient(MODULE_BUYSAFE_BUYSAFE_API_URL, false, false, false, false, false, 5, 5);
        if ($err = $soapclient->getError())
        {
          return array('faultstring' => '<b>Constructor error</b> ' . $err);
        }
        if ($method == 'AddUpdateShoppingCart') $object_reference = 'ShoppingCartAddUpdateRQ';
        if ($method == 'SetShoppingCartCheckout') $object_reference = 'ShoppingCartCheckoutRQ';
        $body = '
<' . $object_reference . ' xmlns="http://ws.buysafe.com">
  <ShoppingCartId>' . $this->str_encode($params['buysafe_cart_id'] ? $params['buysafe_cart_id'] : MODULE_BUYSAFE_BUYSAFE_CART_PREFIX . '-' . tep_session_id() . tep_count_customer_orders()) . '</ShoppingCartId>
  <PreviouslyCanceledCartID>' . $this->str_encode($params['buysafe_previous_cart_id'] ? $params['buysafe_previous_cart_id'] : '') . '</PreviouslyCanceledCartID>
  <OrderNumber>' . $this->str_encode($params['orders_id'] ? $params['orders_id'] : 'Not_yet_known') . '</OrderNumber>
  <ClientIP>' . $this->str_encode($params['buysafe_client_ip'] ? $params['buysafe_client_ip'] : getenv('REMOTE_ADDR')) . '</ClientIP>
  <SessionId>' . $this->str_encode($params['buysafe_session_id'] ? $params['buysafe_session_id'] : tep_session_id()) . '</SessionId>'
 . $this->get_buyer_info($order) . '
  <WantsBond>
    <HasBoolean>true</HasBoolean>
    <Value>' . $this->str_encode($params['WantsBond']) . '</Value>
  </WantsBond>'
 . $this->get_cart_items($order) . '
</' . $object_reference . '>';
        $result = $soapclient->call($method, $body, 'http://ws.buysafe.com', 'http://ws.buysafe.com/' . $method, $this->get_headers(), null, 'rpc', 'literal');
        $this->make_debug_info($soapclient, $method, $result);
        if ($soapclient->fault)
        {
          return $result;
        }
        else
        {
          if ($err = $soapclient->getError())
          {
            return array('faultstring' => '<b>Error</b> ' . $err);
          }
          else
          {
            return $result;
          }
        }
        break;
      case 'SetShoppingCartCancelOrder':
        require_once(DIR_WS_CLASSES . 'nusoap.php');
        $soapclient = new soapclient(MODULE_BUYSAFE_BUYSAFE_API_URL, false);
        if ($err = $soapclient->getError())
        {
          return array('faultstring' => '<b>Constructor error</b> ' . $err);
        }
        $body = '
<SetShoppingCartCancelOrderRQ xmlns="http://ws.buysafe.com">
  <IPAddress>' . $this->str_encode($params['buysafe_client_ip']) . '</IPAddress>
  <DateProcessed>
    <DateTimeValue>' . $this->str_encode($params['date_purchased'] ? str_replace(' ', 'T', $params['date_purchased']) : '0001-01-01T00:00:00') . '</DateTimeValue>
    <HasDateTime>' . ($params['date_purchased'] ? 'true' : 'false') . '</HasDateTime>
  </DateProcessed>
  <PaymentProcessed>false</PaymentProcessed>
  <ShoppingCartId>' . $this->str_encode($params['buysafe_cart_id']) . '</ShoppingCartId>
  <SessionId>' . $this->str_encode($params['buysafe_session_id']) . '</SessionId>
</SetShoppingCartCancelOrderRQ>';
        $result = $soapclient->call($method, $body, 'http://ws.buysafe.com', 'http://ws.buysafe.com/' . $method, $this->get_headers(), null, 'rpc', 'literal');
        $this->make_debug_info($soapclient, $method, $result);
        if ($soapclient->fault)
        {
          return $result;
        }
        else
        {
          if ($err = $soapclient->getError())
          {
            return array('faultstring' => '<b>Error</b> ' . $err);
          }
          else
          {
            return $result;
          }
        }
        break;
      case 'GetbuySAFEDateTime':
        require_once(DIR_WS_CLASSES . 'nusoap.php');
        $soapclient = new soapclient(MODULE_BUYSAFE_BUYSAFE_API_URL, false);
        if ($err = $soapclient->getError())
        {
          return array('faultstring' => '<b>Constructor error</b> ' . $err);
        }
        $body = '';
        $result = $soapclient->call($method, $body, 'http://ws.buysafe.com', 'http://ws.buysafe.com/' . $method, $this->get_headers($params['private_token']), null, 'rpc', 'literal');
        $this->make_debug_info($soapclient, $method, $result);
        if ($soapclient->fault)
        {
          return $result;
        }
        else
        {
          if ($err = $soapclient->getError())
          {
            return array('faultstring' => '<b>Error</b> ' . $err);
          }
          else
          {
            return $result;
          }
        }
        break;
      default:
        return array('faultstring' => 'Wrong API Method!');
      }
    }

    function draw_payment_page()
    {
      global $cart, $buysafe_result, $currencies, $WantsBond;

      if (is_array($buysafe_result) && $buysafe_result['IsBuySafeEnabled'] == 'true')
      {
?>
      <tr>
        <td><?php echo tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td>
      </tr>
      <tr>
        <td><table border="0" width="100%" cellspacing="0" cellpadding="2">
          <tr>
            <td class="main"><b><?php echo $buysafe_result['CartHeaderDisplayText']; ?></b></td>
          </tr>
        </table></td>
      </tr>
<script src="<?php echo MODULE_BUYSAFE_BUYSAFE_ROLLOVER_URL; ?>" type="text/javascript" language="javascript" charset="utf-8"></script>
<script language="JavaScript" type="text/javascript">
<!--
function buySAFEOnClick()
{
  if (document.checkout_payment.WantsBond.value == 'false')
  {
    document.checkout_payment.WantsBond.value = 'true';
  }
  else
  {
    document.checkout_payment.WantsBond.value = 'false';
  }
  document.checkout_payment.action = '<?php echo tep_href_link(FILENAME_CHECKOUT_PAYMENT, tep_get_all_get_params(), 'SSL'); ?>';
  document.checkout_payment.submit();
}
//-->
</script>
      <tr>
        <td><?php echo tep_draw_hidden_field('WantsBond', ($WantsBond ? $WantsBond : 'false')); ?><table border="0" width="100%" cellspacing="1" cellpadding="2" class="infoBox">
          <tr class="infoBoxContents">
            <td><table width="100%" cellspacing="2" cellpadding="2" border="0">
              <tr>
                <td width="55%" class="main" valign="top"><?php echo $buysafe_result['CartInstructionsDisplayText']; ?></td>
                <td width="45%" align="right" rowspan="2"><table cellspacing="0" cellpadding="2" border="0">
                  <tr>
                    <td class="main" align="right"><b><?php echo SUB_TITLE_CART_TOTAL; ?></b></td>
                    <td class="main" align="right"><b><?php echo $currencies->format($cart->show_total()); ?></b></td>
                  </tr>
                  <tr>
                    <td class="main" align="right"><b><?php echo $buysafe_result['BondingSignal']; ?></b></td>
                    <td class="main" align="right"><b><?php echo $buysafe_result['BondCostDisplayText']; ?></b></td>
                  </tr>
                  <tr>
                    <td class="main" align="right"><b><?php echo SUB_TITLE_TOTAL; ?></b></td>
                    <td class="main" align="right"><b><?php echo ($buysafe_result['BondCostDisplayText'] ? $currencies->format($cart->show_total() + $buysafe_result['TotalBondCost']) : $currencies->format($cart->show_total())); ?></b></td>
                  </tr>
                </table></td>
              </tr>
              <tr>
                <td class="main"><a href="<?php echo $buysafe_result['CartDetailsUrl']; ?>" target="_blank" style="text-decoration:underline"><?php echo $buysafe_result['CartDetailsDisplayText']; ?></a></td>
              </tr>
            </table></td>
          </tr>
        </table></td>
      </tr>
<?php
      } // // end if (is_array($buysafe_result))
    }

    function keys()
    {
      return array('MODULE_BUYSAFE_BUYSAFE_STATUS', 'MODULE_BUYSAFE_BUYSAFE_SEAL_TYPE', 'MODULE_BUYSAFE_BUYSAFE_CART_PREFIX', 'MODULE_BUYSAFE_BUYSAFE_SEAL_AUTHENTICATION_DATA', 'MODULE_BUYSAFE_BUYSAFE_STORE_AUTHENTICATION_DATA', 'MODULE_BUYSAFE_BUYSAFE_PLATFORM', 'MODULE_BUYSAFE_BUYSAFE_TOK', 'MODULE_BUYSAFE_BUYSAFE_API_URL', 'MODULE_BUYSAFE_BUYSAFE_ROLLOVER_URL', 'MODULE_BUYSAFE_BUYSAFE_STOP_API_CALLS_TIME');
    }

    function hidden_keys()
    {
      return array('MODULE_BUYSAFE_BUYSAFE_CART_PREFIX', 'MODULE_BUYSAFE_BUYSAFE_PLATFORM', 'MODULE_BUYSAFE_BUYSAFE_TOK', 'MODULE_BUYSAFE_BUYSAFE_API_URL', 'MODULE_BUYSAFE_BUYSAFE_ROLLOVER_URL', 'MODULE_BUYSAFE_BUYSAFE_STOP_API_CALLS_TIME');
    }

    function install()
    {
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable buySAFE Module', 'MODULE_BUYSAFE_BUYSAFE_STATUS', 'True', 'Select true to enable buySAFE.', '6', '1', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('buySAFE Seal Size', 'MODULE_BUYSAFE_BUYSAFE_SEAL_TYPE', 'Large', 'Select buySAFE Seal Size here.', '6', '2', 'tep_cfg_select_option(array(\'Large\', \'Medium\', \'Small\'), ', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Cart Prefix', 'MODULE_BUYSAFE_BUYSAFE_CART_PREFIX', '" . substr(preg_replace("([^a-z0-9]+)i", '', STORE_NAME), 0, 8) . "', 'Cart prefix field used to create CartID.', '6', '3', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Seal Authentication Data', 'MODULE_BUYSAFE_BUYSAFE_SEAL_AUTHENTICATION_DATA', '-- none --', 'Authenticate store: <a href=\"http://techsupport.buysafe.com/index.php?_m=knowledgebase&_a=viewarticle&kbarticleid=90\" target=\"_blank\" style=\"text-decoration:underline\">click here</a> for instructions.<br>', '6', '4', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Store Authentication Data', 'MODULE_BUYSAFE_BUYSAFE_STORE_AUTHENTICATION_DATA', '-- none --', '', '6', '5', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('buySAFE Platform', 'MODULE_BUYSAFE_BUYSAFE_PLATFORM', 'oscommerce', 'The platform as provided by buySAFE.', '6', '6', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('buySAFE Token', 'MODULE_BUYSAFE_BUYSAFE_TOK', 'AFA71B86-7222-498A-95E9-79CA27B4F426', 'The buySAFE Token as provided by buySAFE.', '6', '7', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Checkout API URL', 'MODULE_BUYSAFE_BUYSAFE_API_URL', 'https://api.buysafe.com/buysafews/checkoutapi.dll', 'The post URL for the Checkout API.', '6', '8', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Rollover JS URL', 'MODULE_BUYSAFE_BUYSAFE_ROLLOVER_URL', 'https://seal.buysafe.com/private/rollover/rollover.js', 'The code to process the rollover is provided by buySAFE.', '6', '9', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Stop API Calls Time', 'MODULE_BUYSAFE_BUYSAFE_STOP_API_CALLS_TIME', '', 'Stop API calls to this datetime.', '6', '10', now())");

      // Install ot_buysafe module
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort Order', 'MODULE_ORDER_TOTAL_BUYSAFE_SORT_ORDER', '4', 'Sort order of display.', '6', '2', now())");
      tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . (int)(MODULE_ORDER_TOTAL_TOTAL_SORT_ORDER - 1 > 0 ? MODULE_ORDER_TOTAL_TOTAL_SORT_ORDER - 1 : 0) . "' where configuration_key = 'MODULE_ORDER_TOTAL_BUYSAFE_SORT_ORDER'");
      define('MODULE_ORDER_TOTAL_BUYSAFE_SORT_ORDER', (int)(MODULE_ORDER_TOTAL_TOTAL_SORT_ORDER - 1 > 0 ? MODULE_ORDER_TOTAL_TOTAL_SORT_ORDER - 1 : 0));
      $this->update_installed_ot_modules();
    }

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

      // Remove ot_buysafe module
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_ORDER_TOTAL_BUYSAFE_SORT_ORDER'");
      $this->update_installed_ot_modules();
    }

    function update_installed_ot_modules()
    {
      global $PHP_SELF;
      $module_directory = DIR_FS_CATALOG_MODULES . 'order_total/';
      $module_key = 'MODULE_ORDER_TOTAL_INSTALLED';
      $file_extension = substr($PHP_SELF, strrpos($PHP_SELF, '.'));
      $directory_array = array();
      if ($dir = @dir($module_directory)) {
        while ($file = $dir->read()) {
          if (!is_dir($module_directory . $file)) {
            if (substr($file, strrpos($file, '.')) == $file_extension) {
              $directory_array[] = $file;
            }
          }
        }
        sort($directory_array);
        $dir->close();
      }
      $installed_modules = array();
      for ($i=0, $n=sizeof($directory_array); $i<$n; $i++) {
        $file = $directory_array[$i];
        include($module_directory . $file);
        $class = substr($file, 0, strrpos($file, '.'));
        if (tep_class_exists($class)) {
          $module = new $class;
          if ($module->check() > 0) {
            if ($module->sort_order > 0) {
              $installed_modules[$module->sort_order] = $file;
            } else {
              $installed_modules[] = $file;
            }
          }
        }
      }
      ksort($installed_modules);
      $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = '" . $module_key . "'");
      if (tep_db_num_rows($check_query)) {
        $check = tep_db_fetch_array($check_query);
        if ($check['configuration_value'] != implode(';', $installed_modules)) {
          tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . implode(';', $installed_modules) . "', last_modified = now() where configuration_key = '" . $module_key . "'");
        }
      } else {
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Installed Modules', '" . $module_key . "', '" . implode(';', $installed_modules) . "', 'This is automatically updated. No need to edit.', '6', '0', now())");
      }
    }

    function get_headers($private_token = '')
    {
      return '
<MerchantServiceProviderCredentials xmlns="http://ws.buysafe.com">
  <Us'.'erN'.'ame>' . $this->str_encode(MODULE_BUYSAFE_BUYSAFE_PLATFORM) . '</Us'.'erN'.'ame>
  <Pa'.'ssw'.'ord>' . $this->str_encode(MODULE_BUYSAFE_BUYSAFE_TOK) . '</Pa'.'ssw'.'ord>
</MerchantServiceProviderCredentials>
<BuySafeUserCredentials xmlns="http://ws.buysafe.com">
  <AuthenticationTokens>
    <string>' . $this->str_encode($private_token ? $private_token : MODULE_BUYSAFE_BUYSAFE_STORE_AUTHENTICATION_DATA) . '</string>
  </AuthenticationTokens>
</BuySafeUserCredentials>
<BuySafeWSHeader xmlns="http://ws.buysafe.com">
  <Version>600</Version>
</BuySafeWSHeader>';
    }

    function get_buyer_info($order = '')
    {
      global $customer_id, $sendto, $billto;

      if ($order)
      {
        $arr = explode(' ', $order->customer['name']);
        $firstname = $arr[0]; $lastname = '';
        for ($i = 1; $i < count($arr); $i++) {
          $lastname .= $arr[$i] . ' ';
        }
        $billing = tep_db_fetch_array(tep_db_query("select countries_iso_code_2 from " . TABLE_COUNTRIES . " where countries_name = '" . tep_db_input($order->billing['country']) . "'"));
        $delivery = tep_db_fetch_array(tep_db_query("select countries_iso_code_2 from " . TABLE_COUNTRIES . " where countries_name = '" . tep_db_input($order->delivery['country']) . "'"));
        return '
  <BuyerInfo>
    <FirstName>' . $this->str_encode($firstname) . '</FirstName>
    <LastName>' . $this->str_encode(trim($lastname)) . '</LastName>
    <Email>' . $this->str_encode($order->customer['email_address']) . '</Email>
    <BuyerType>Repeat</BuyerType>
    <BillingAddress>
      <PostalCode>' . $this->str_encode($order->billing['postcode']) . '</PostalCode>
      <CountryCode>' . $this->str_encode($this->validate_country_code($billing['countries_iso_code_2'])) . '</CountryCode>
    </BillingAddress>
    <ShippingAddress>
      <PostalCode>' . $this->str_encode($order->delivery['postcode']) . '</PostalCode>
      <CountryCode>' . $this->str_encode($this->validate_country_code($delivery['countries_iso_code_2'])) . '</CountryCode>
    </ShippingAddress>
  </BuyerInfo>';
      }

      if (tep_session_is_registered('customer_id'))
      {
        $customer_address = tep_db_fetch_array(tep_db_query("select c.customers_firstname, c.customers_lastname, c.customers_telephone, c.customers_email_address, ab.entry_company, ab.entry_street_address, ab.entry_suburb, ab.entry_postcode, ab.entry_city, ab.entry_zone_id, z.zone_name, co.countries_id, co.countries_name, co.countries_iso_code_2, co.countries_iso_code_3, co.address_format_id, ab.entry_state from " . TABLE_CUSTOMERS . " c, " . TABLE_ADDRESS_BOOK . " ab left join " . TABLE_ZONES . " z on (ab.entry_zone_id = z.zone_id) left join " . TABLE_COUNTRIES . " co on (ab.entry_country_id = co.countries_id) where c.customers_id = '" . (int)$customer_id . "' and ab.customers_id = '" . (int)$customer_id . "' and c.customers_default_address_id = ab.address_book_id"));
        if (tep_session_is_registered('billto') && $billto != '')
        {
          $billing_address = tep_db_fetch_array(tep_db_query("select ab.entry_postcode, ab.entry_state, ab.entry_zone_id, ab.entry_state, z.zone_name, co.countries_id, co.countries_name, co.countries_iso_code_2, co.countries_iso_code_3, co.address_format_id from " . TABLE_ADDRESS_BOOK . " ab left join " . TABLE_ZONES . " z on (ab.entry_zone_id = z.zone_id) left join " . TABLE_COUNTRIES . " co on (ab.entry_country_id = co.countries_id) where customers_id = '" . (int)$customer_id . "' and address_book_id = '" . (int)$billto . "'"));
        }
        if (tep_session_is_registered('sendto') && $sendto != '')
        {
          $shipping_address = tep_db_fetch_array(tep_db_query("select ab.entry_postcode, ab.entry_state, ab.entry_zone_id, ab.entry_state, z.zone_name, co.countries_id, co.countries_name, co.countries_iso_code_2, co.countries_iso_code_3, co.address_format_id from " . TABLE_ADDRESS_BOOK . " ab left join " . TABLE_ZONES . " z on (ab.entry_zone_id = z.zone_id) left join " . TABLE_COUNTRIES . " co on (ab.entry_country_id = co.countries_id) where customers_id = '" . (int)$customer_id . "' and address_book_id = '" . (int)$sendto . "'"));
        }
        return '
  <BuyerInfo>
    <FirstName>' . $this->str_encode($customer_address['customers_firstname']) . '</FirstName>
    <LastName>' . $this->str_encode($customer_address['customers_lastname']) . '</LastName>
    <Email>' . $this->str_encode($customer_address['customers_email_address']) . '</Email>
    <BuyerType>Registered</BuyerType>
    <BillingAddress>
      <PostalCode>' . $this->str_encode($billing_address['entry_postcode'] ? $billing_address['entry_postcode'] : $customer_address['entry_postcode']) . '</PostalCode>
      <CountryCode>' . $this->str_encode($this->validate_country_code($billing_address['countries_iso_code_2'] ? $billing_address['countries_iso_code_2'] : $customer_address['countries_iso_code_2'])) . '</CountryCode>
    </BillingAddress>
    <ShippingAddress>
      <PostalCode>' . $this->str_encode($shipping_address['entry_postcode'] ? $shipping_address['entry_postcode'] : $customer_address['entry_postcode']) . '</PostalCode>
      <CountryCode>' . $this->str_encode($this->validate_country_code($shipping_address['countries_iso_code_2'] ? $shipping_address['countries_iso_code_2'] : $customer_address['countries_iso_code_2'])) . '</CountryCode>
    </ShippingAddress>
  </BuyerInfo>';
      }
      else return '
  <BuyerInfo>
    <BuyerType>Unknown</BuyerType>
  </BuyerInfo>';
    }

    function get_cart_items($order = '')
    {
      global $cart, $currencies, $currency, $languages_id;

      if ($order)
      {
        $items_string = ''; $i = 0;
        foreach ($order->products as $product)
        {
          $attributes_string = ''; $i++;
          if ($product['attributes'])
          {
            reset($product['attributes']);
            foreach ($product['attributes'] as $attribute)
            {
              $attributes_string .= $attribute['option'] . ': ' . $attribute['value'] . ' (' . $attribute['prefix'] . $currencies->format($attribute['price']) . ');';
            }
          }
// {{
          $check_unique = tep_db_fetch_array(tep_db_query("select count(*) as total from " . TABLE_PRODUCTS . " where products_model = '" . tep_db_input($product['model']) . "' group by products_model"));
// }}
          $items_string .= '
    <ShoppingCartItem>
      <UserToken>' . $this->str_encode(MODULE_BUYSAFE_BUYSAFE_STORE_AUTHENTICATION_DATA) . '</UserToken>
      <MarketplaceItemCode>' . $this->str_encode((tep_not_null($product['model']) && $check_unique['total'] == 1) ? $product['model'] : $product['name']) . '-' . $i . '</MarketplaceItemCode>
      <StockKeepingUnit>' . $this->str_encode($product['model']) . '</StockKeepingUnit>
      <Title>' . $this->str_encode($product['name']) . '</Title>
      <Attributes>' . $this->str_encode($attributes_string) . '</Attributes>
      <isRestricted>false</isRestricted>
      <QuantityPurchased>' . $this->str_encode($product['qty']) . '</QuantityPurchased>
      <PriceInfo>
        <FinalPrice>
          <CurrencyCode>' . $this->str_encode($order->info['currency']) . '</CurrencyCode>
          <Value>' . number_format(tep_round($product['final_price'], 2), 2, '.', '') . '</Value>
        </FinalPrice>
      </PriceInfo>
      <URLInfo>
        <ViewItem>' . tep_catalog_href_link('product_info.php', 'products_id=' . $product['id'], 'NONSSL') . '</ViewItem>
      </URLInfo>
    </ShoppingCartItem>';
        }

        return '
  <Items>'
 . $items_string . '
  </Items>';
      }

      if ($cart->count_contents() > 0)
      {
        $items_string = '';
        $products = $cart->get_products();
        for ($i=0, $n=sizeof($products); $i<$n; $i++)
        {
          $attributes_string = '';
          if ($products[$i]['attributes'])
          {
            reset($products[$i]['attributes']);
            while (list($option, $value) = each($products[$i]['attributes']))
            {
              $attributes_query = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa where pa.products_id = '" . (int)$products[$i]['id'] . "' and pa.options_id = '" . (int)$option . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . (int)$value . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . (int)$languages_id . "' and poval.language_id = '" . (int)$languages_id . "'");
              $attributes = tep_db_fetch_array($attributes_query);
              $attributes_string .= $attributes['products_options_name'] . ': ' . $attributes['products_options_values_name'] . ' (' . $attributes['price_prefix'] . $currencies->format($attributes['options_values_price']) . ');';
            }
          }
// {{
          $check_unique = tep_db_fetch_array(tep_db_query("select count(*) as total from " . TABLE_PRODUCTS . " where products_model = '" . tep_db_input($products[$i]['model']) . "' group by products_model"));
// }}
          $items_string .= '
    <ShoppingCartItem>
      <UserToken>' . $this->str_encode(MODULE_BUYSAFE_BUYSAFE_STORE_AUTHENTICATION_DATA) . '</UserToken>
      <MarketplaceItemCode>' . $this->str_encode((tep_not_null($products[$i]['model']) && $check_unique['total'] == 1) ? $products[$i]['model'] : $products[$i]['name']) . '-' . ($i + 1) . '</MarketplaceItemCode>
      <StockKeepingUnit>' . $this->str_encode($products[$i]['model']) . '</StockKeepingUnit>
      <Title>' . $this->str_encode($products[$i]['name']) . '</Title>
      <Attributes>' . $this->str_encode($attributes_string) . '</Attributes>
      <isRestricted>false</isRestricted>
      <QuantityPurchased>' . $this->str_encode($products[$i]['quantity']) . '</QuantityPurchased>
      <PriceInfo>
        <FinalPrice>
          <CurrencyCode>' . $this->str_encode($currency) . '</CurrencyCode>
          <Value>' . number_format(tep_round($products[$i]['price'] + $cart->attributes_price($products[$i]['id']), 2), 2, '.', '') . '</Value>
        </FinalPrice>
      </PriceInfo>
      <URLInfo>
        <ViewItem>' . tep_href_link(FILENAME_PRODUCT_INFO, 'products_id=' . $products[$i]['id'], 'NONSSL', false) . '</ViewItem>
      </URLInfo>
    </ShoppingCartItem>';
        }

        return '
  <Items>'
 . $items_string . '
  </Items>';
      } else return '';
    }

    function str_encode($value)
    {
      return utf8_encode(htmlspecialchars($value)); // if charset ISO-8859-1 only, use utf8_encode() function
      //return iconv((CHARSET, 'UTF-8', htmlspecialchars($value)); // if not, use iconv() function
    }

    function validate_country_code($country_code)
    {
      if (in_array($country_code, array('US', 'AX', 'CA', 'DZ', 'AS', 'AD', 'AO', 'AI', 'AQ', 'AG', 'AR', 'AM', 'AW', 'AU', 'AT', 'AZ', 'BS', 'BH', 'BD', 'BB', 'BY', 'BE', 'BZ', 'BJ', 'BM', 'BT', 'BO', 'BA', 'BW', 'BV', 'BR', 'IO', 'BN', 'BG', 'BF', 'BI', 'KH', 'CM', 'AL', 'CV', 'KY', 'CF', 'TD', 'CL', 'CN', 'CX', 'CC', 'CO', 'KM', 'CG', 'CD', 'CK', 'CR', 'CI', 'HR', 'CU', 'CY', 'CZ', 'DK', 'DJ', 'DM', 'DO', 'EC', 'EG', 'SV', 'GQ', 'ER', 'EE', 'ET', 'FK', 'FO', 'FJ', 'FI', 'FR', 'GF', 'PF', 'TF', 'GA', 'GM', 'GE', 'DE', 'GH', 'GI', 'GR', 'GL', 'GD', 'GP', 'GT', 'GG', 'GN', 'GW', 'GY', 'HT', 'HM', 'VA', 'HN', 'HK', 'HU', 'IS', 'IN', 'ID', 'IR', 'IQ', 'IE', 'IL', 'IT', 'JM', 'JP', 'JO', 'KZ', 'KE', 'KI', 'KP', 'KR', 'KW', 'KG', 'LA', 'LV', 'LB', 'LS', 'LR', 'LY', 'LI', 'LT', 'LU', 'MO', 'MK', 'MG', 'MW', 'MY', 'MV', 'ML', 'MT', 'MH', 'MQ', 'MR', 'MU', 'YT', 'MX', 'FM', 'MD', 'MC', 'MN', 'MS', 'MA', 'MZ', 'MM', 'NA', 'NR', 'NP', 'NL', 'AN', 'NC', 'NZ', 'NI', 'NE', 'NG', 'NU', 'NF', 'MP', 'NO', 'OM', 'PK', 'PW', 'PS', 'PA', 'PG', 'PY', 'PE', 'PH', 'PN', 'PL', 'PT', 'PR', 'QA', 'RE', 'RO', 'RU', 'RW', 'SH', 'KN', 'LC', 'PM', 'VC', 'WS', 'SM', 'ST', 'SA', 'SN', 'RS', 'SC', 'SL', 'SG', 'SK', 'SI', 'SB', 'SO', 'ZA', 'GS', 'ES', 'LK', 'SD', 'SR', 'SJ', 'SZ', 'SE', 'CH', 'SY', 'TW', 'TJ', 'TZ', 'TH', 'TL', 'TG', 'TK', 'TO', 'TT', 'TN', 'TR', 'TM', 'TC', 'TV', 'UG', 'UA', 'AE', 'GB', 'AF', 'UM', 'UY', 'UZ', 'VU', 'VE', 'VN', 'VG', 'VI', 'WF', 'EH', 'YE', 'ZM', 'OT')))
      {
        return $country_code;
      }
      else
      {
        return 'OT';
      }
    }

    function make_debug_info($soapclient, $method, $result)
    {
      $headers = $soapclient->getHeaders();
      $headers_array = $this->decodeXML($headers);
      $TransactionId = $headers_array[TransactionId] ? $headers_array[TransactionId] : $result[detail][TransactionStatus][TransactionId];
      $isSuccessful = $headers_array[isSuccessful] ? $headers_array[isSuccessful] : $result[detail][TransactionStatus][isSuccessful];
      $this->debug_info = <<<TEXT_DEBUG_LABEL
<!-- buySAFE Debug Info
    Request
        Action: $method
    Result
        TransactionId: $TransactionId
        isSuccessful: $isSuccessful
        isFatal: $result[isFatal]
        IsBuySafeEnabled: $result[IsBuySafeEnabled]
        TotalBondCost: $result[TotalBondCost]
-->
TEXT_DEBUG_LABEL;
//echo '<h2>Request</h2><pre>' . htmlspecialchars($soapclient->request, ENT_QUOTES) . '</pre>';
//echo '<h2>Response</h2><pre>' . htmlspecialchars($soapclient->response, ENT_QUOTES) . '</pre>';
    }

    function get_debug_info()
    {
      return $this->debug_info;
    }

    function decodeXML($xmlstg)
    {
      preg_match_all ("(<([a-z0-9]+)>([^<>]*?)</[a-z0-9]+>)i", $xmlstg, $out, PREG_SET_ORDER);
      $n = 0;
      while (isset($out[$n]))
      {
        $retarr[$out[$n][1]] = strip_tags($out[$n][2]);
        $n++; 
      }
      return $retarr;
    }
  }
?>
