1,'code' => 'FEDEX_GROUND', 'name' => 'FedEx Ground', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172') , 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>2,'code' => 'FEDEX_2_DAY', 'name' => 'FedEx 2 Day', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172'), 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>3,'code' => 'FEDEX_EXPRESS_SAVER', 'name' => 'FedEx Express Saver Time Pickup', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172'), 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>4,'code' => 'FIRST_OVERNIGHT', 'name' => 'FedEx First Overnight', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172'), 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>5,'code' => 'GROUND_HOME_DELIVERY', 'name' => 'FedEx Ground (Home Delivery)', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172'), 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>6,'code' => 'PRIORITY_OVERNIGHT', 'name' => 'FedEx Priority Overnight', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172'), 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>7,'code' => 'SMART_POST', 'name' => 'FedEx Smart Post', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172'), 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>8,'code' => 'STANDARD_OVERNIGHT', 'name' => 'FedEx Standard Overnight', 'countries' => 'USA, PUERTO RICO', 'zones' => array('country_United_States_of_America_223','country_Puerto_Rico_172'), 'destinations' => array('country_United_States_of_America_223','country_Puerto_Rico_172')), array('key'=>9,'code' => 'INTERNATIONAL_GROUND', 'name' => 'FedEx International Ground'), array('key'=>10,'code' => 'INTERNATIONAL_ECONOMY', 'name' => 'FedEx International Economy'), array('key'=>11,'code' => 'INTERNATIONAL_ECONOMY_DISTRIBUTION', 'name' => 'FedEx International Economy Distribution'), array('key'=>12,'code' => 'INTERNATIONAL_FIRST', 'name' => 'FedEx International First'), array('key'=>13,'code' => 'INTERNATIONAL_PRIORITY', 'name' => 'FedEx International Priority'), array('key'=>14,'code' => 'INTERNATIONAL_PRIORITY_DISTRIBUTION', 'name' => 'FedEx International Priority Distribution'), array('key'=>15,'code' => 'EUROPE_FIRST_INTERNATIONAL_PRIORITY', 'name' => 'FedEx Europe First') ); var $convertUnit=array( 'kg' => 'KGS', 'lb' => 'LBS', 'cm' => 'CM', 'in' => 'IN', 'kg2' => 'kg', 'lb2' => 'lb', 'cm2' => 'cm', 'in2' => 'in', ); public $nbpackage = 0; function shippingMethods(&$main){ $methods = array(); if(!empty($main->shipping_params->methodsList)){ $main->shipping_params->methods=unserialize($main->shipping_params->methodsList); } if(!empty($main->shipping_params->methods)){ foreach($main->shipping_params->methods as $method){ $selected = null; foreach($this->fedex_methods as $fedex){ if($fedex['code']==$method) { $selected = $fedex; break; } } if($selected){ $methods[$main->shipping_id . '-' . $selected['key']] = $selected['name']; } } } return $methods; } function onShippingDisplay(&$order,&$dbrates,&$usable_rates,&$messages){ if(!hikashop_loadUser()) return false; $local_usable_rates = array(); $local_messages = array(); $ret = parent::onShippingDisplay($order, $dbrates, $local_usable_rates, $local_messages); if($ret === false) return false; $currentShippingZone = null; $currentCurrencyId = null; $currencyClass=hikashop_get('class.currency'); foreach($local_usable_rates as $k => $rate){ if(empty($rate->shipping_params->methodsList)) { $messages['no_shipping_methods_configured'] = 'No shipping methods configured in the FedEx shipping plugin options'; continue; } $rate->shipping_params->methods = unserialize($rate->shipping_params->methodsList); if($order->weight <= 0 || ($order->volume <= 0 && @$rate->shipping_params->use_dimensions == 1)) continue; $this->freight = false; $this->classicMethod = false; $heavyProduct = false; $weightTotal = 0; if(!empty($rate->shipping_params->methods)) { foreach($rate->shipping_params->methods as $method) { if($method=='TDCB' || $method=='TDA' || $method=='TDO' || $method=='308' || $method=='309' || $method=='310') $this->freight = true; else $this->classicMethod = true; } } $data = null; if(empty($order->shipping_address)) { $messages['no_shipping_methods_configured'] = 'No shipping address is configured.'; return true; } $this->shipping_currency_id=$currency= hikashop_getCurrency(); $db = JFactory::getDBO(); $query='SELECT currency_code FROM '.hikashop_table('currency').' WHERE currency_id IN ('.$this->shipping_currency_id.')'; $db->setQuery($query); $this->shipping_currency_code = $db->loadResult(); $cart = hikashop_get('class.cart'); $null = null; $cart->loadAddress($null,$order->shipping_address->address_id,'object', 'shipping'); $currency = hikashop_get('class.currency'); $receivedMethods=$this->_getRates($rate, $order, $heavyProduct, $null); if(empty($receivedMethods)) { $messages['no_rates'] = JText::_('NO_SHIPPING_METHOD_FOUND'); continue; } $i = 0; $local_usable_rates = array(); foreach($receivedMethods as $method) { $usableMethods[] = $method; $local_usable_rates[$i]=(!HIKASHOP_PHP5) ? $rate : clone($rate); $local_usable_rates[$i]->shipping_price += round($method['value'], 2); $selected_method = ''; $name = ''; foreach($this->fedex_methods as $fedex_method) { if($fedex_method['code'] == $method['code'] && ($method['old_currency_code'] == 'CAD' || !isset($fedex_method['double']))) { $name = $fedex_method['name']; $selected_method = $fedex_method['key']; break; } } $local_usable_rates[$i]->shipping_name=$name; if(!empty($selected_method)) $local_usable_rates[$i]->shipping_id .= '-' . $selected_method; $sep = ''; if(@$rate->shipping_params->show_eta) { if(@$rate->shipping_params->show_eta_delay) { //if not fedex ground method if($method['delivery_delay']!=-1 && $method['day']>0){ $local_usable_rates[$i]->shipping_description.=$sep.JText::sprintf( 'ESTIMATED_TIME_AFTER_SEND', $method['delivery_delay']); }else{ $local_usable_rates[$i]->shipping_description.=$sep.JText::_( 'NO_ESTIMATED_TIME_AFTER_SEND'); } } else { //if not fedex ground method if($method['delivery_day']!=-1 && $method['day']>0){ $local_usable_rates[$i]->shipping_description.=$sep.JText::sprintf( 'ESTIMATED_TIME_AFTER_SEND', $method['delivery_day']); }else{ $local_usable_rates[$i]->shipping_description.=$sep.JText::_( 'NO_ESTIMATED_TIME_AFTER_SEND'); } } $sep = '
'; if($method['delivery_time']!=-1 && $method['day']>0){ if(@$rate->shipping_params->show_eta_format == '12') $local_usable_rates[$i]->shipping_description.=$sep.JText::sprintf( 'DELIVERY_HOUR', date('h:i:s a', strtotime($method['delivery_time']))); else $local_usable_rates[$i]->shipping_description.=$sep.JText::sprintf( 'DELIVERY_HOUR', $method['delivery_time']); }else{ $local_usable_rates[$i]->shipping_description.=$sep.JText::_( 'NO_DELIVERY_HOUR'); } } if(@$rate->shipping_params->show_notes && !empty($method['notes'])) { foreach($method['notes'] as $note){ if($note->Code != '820' && $note->Code != '819' && !empty($note->LocalizedMessage) ) { $local_usable_rates[$i]->shipping_description.=$sep.implode('
', $note->LocalizedMessage); $sep = '
'; } } } if($rate->shipping_params->group_package && $this->nbpackage>0) $local_usable_rates[$i]->shipping_description.='
'.JText::sprintf('X_PACKAGES', $this->nbpackage); $i++; } foreach($local_usable_rates as $i => $finalRate){ if(isset($finalRate->shipping_price_orig) || isset($finalRate->shipping_currency_id_orig)){ if($finalRate->shipping_currency_id_orig == $finalRate->shipping_currency_id) $finalRate->shipping_price_orig = $finalRate->shipping_price; else $finalRate->shipping_price_orig = $currencyClass->convertUniquePrice($finalRate->shipping_price, $finalRate->shipping_currency_id, $finalRate->shipping_currency_id_orig); } $usable_rates[$finalRate->shipping_id]=$finalRate; } } // BOF: gpraceman added to sort rates from least to most expensive $usable_rates = $this->array_sort($usable_rates, 'shipping_price', 'fedex', SORT_ASC); // EOF: gpraceman added to sort rates from least to most expensive } function getShippingDefaultValues(&$element){ $element->shipping_name='FedEx'; $element->shipping_description=''; $element->group_package=0; $element->debug=0; $element->shipping_images='fedex'; $element->shipping_params->post_code=''; $element->shipping_currency_id = $this->main_currency; $element->shipping_params->pickup_type='01'; $element->shipping_params->destination_type='auto'; } function onShippingConfiguration(&$element){ $config =& hikashop_config(); $this->main_currency = $config->get('main_currency', 1); $currencyClass = hikashop_get('class.currency'); $currency = hikashop_get('class.currency'); $this->currencyCode = $currency->get($this->main_currency)->currency_code; $this->currencySymbol = $currency->get($this->main_currency)->currency_symbol; $this->fedex = JRequest::getCmd('name','fedex'); $this->categoryType = hikashop_get('type.categorysub'); $this->categoryType->type = 'tax'; $this->categoryType->field = 'category_id'; parent::onShippingConfiguration($element); $elements = array($element); $key = key($elements); if(empty($elements[$key]->shipping_params->lang_file_override)){ jimport('joomla.filesystem.file'); jimport('joomla.filesystem.folder'); $folder = JLanguage::getLanguagePath(JPATH_ROOT).DS.'overrides'; $path = $folder.DS.'en-GB.override.ini'; $content_override=''; if(JFile::exists($path)){ $content_override=JFile::read($path); } $content_override .= ' FEDEX_METER_ID="Meter #"'.' FEDEX_ACCOUNT_NUMBER="Account #"'.' FEDEX_API_KEY="API Key"'.' FEDEX_API_PASSWORD="API Password"'.' FEDEX_SHOW_ETA="Show ETA?"'.' FEDEX_SHOW_ETA_FORMAT="ETA Format"'.' PACKAGING_TYPE="Packaging Type"'.' BOX_DIMENSIONS="Box Dimensions"'.' ORIGINATION_POSTCODE="Ship From Postcode"'.' SENDER_COMPANY="Sender Company"'.' SENDER_PHONE="Sender Phone"'.' SENDER_ADDRESS="Sender Address"'.' SENDER_CITY="Sender City"'.' SENDER_STATE="Sender State"'.' SENDER_POSTCODE="Sender Zip"'; if(!JFolder::exists($folder)){ JFolder::create($folder); } if(JFolder::exists($folder)){ $path = $folder.DS.'en-GB.override.ini'; $result = JFile::write($path, $content_override); if(!$result){ hikashop_display(JText::sprintf('FAIL_SAVE',$path),'error'); }else { $elements[$key]->shipping_params->lang_file_override = 1; } } } $js=" function checkAllBox(id, type){ var toCheck = document.getElementById(id).getElementsByTagName('input'); for (i = 0 ; i < toCheck.length ; i++) { if (toCheck[i].type == 'checkbox') { if(type == 'check'){ toCheck[i].checked = true; }else{ toCheck[i].checked = false; } } } }"; if(!HIKASHOP_PHP5) { $doc =& JFactory::getDocument(); } else { $doc = JFactory::getDocument(); } $doc->addScriptDeclaration( "\n" ); } function onShippingConfigurationSave(&$element){ $app = JFactory::getApplication(); $methods=array(); if(empty($element->shipping_params->account_number) || empty($element->shipping_params->origination_postcode) || empty($element->shipping_params->meter_id) || empty($element->shipping_params->api_key) || empty($element->shipping_params->api_password) || empty($element->shipping_params->sender_company) || empty($element->shipping_params->sender_phone) || empty($element->shipping_params->sender_address) || empty($element->shipping_params->sender_city) || empty($element->shipping_params->sender_state) || empty($element->shipping_params->sender_country) || empty($element->shipping_params->sender_postcode) ){ $app->enqueueMessage(JText::sprintf('ENTER_INFO', 'FedEx', JText::_('SENDER_INFORMATIONS').' ('. JText::_( 'FEDEX_ORIGINATION_POSTCODE' ).', '.JText::_( 'FEDEX_ACCOUNT_NUMBER' ).', '.JText::_( 'FEDEX_METER_ID' ).', '.JText::_( 'FEDEX_API_KEY' ).', '.JText::_( 'HIKA_PASSWORD' ).', '.JText::_( 'COMPANY' ).', '.JText::_( 'TELEPHONE' ).', '.JText::_( 'ADDRESS' ).', '.JText::_( 'CITY' ).', '.JText::_( 'COUNTRY' ).', '.JText::_( 'POST_CODE' ).')')); } if(isset($_REQUEST['data']['shipping_methods'])){ foreach($_REQUEST['data']['shipping_methods'] as $method){ foreach($this->fedex_methods as $fedexMethod){ $name=strtolower($fedexMethod['name']); $name=str_replace(' ','_', $name); if($name==$method['name']){ $obj = new stdClass(); $methods[strip_tags($method['name'])]=strip_tags($fedexMethod['code']); } } } } else { $app->enqueueMessage(JText::sprintf('CHOOSE_SHIPPING_SERVICE')); } $element->shipping_params->methodsList = serialize($methods); return true; } // add all rates for each package together. apply any rate discounts. // returns an array of merged rates // TODO: move all fees, discounts, etc. calculations to class.Package function _getRates(&$rate, &$order, $heavyProduct, $null){ $db = JFactory::getDBO(); $total_price = 0; // order total foreach($order->products as $k=>$v){ foreach($v->prices as $price){ $total_price = $total_price + $price->price_value; } } $data['fedex_account_number']=@$rate->shipping_params->account_number; $data['fedex_meter_number']=@$rate->shipping_params->meter_id; $data['fedex_api_key']=@$rate->shipping_params->api_key; $data['fedex_api_password']=@$rate->shipping_params->api_password; $data['show_eta']=@$rate->shipping_params->show_eta; $data['show_eta_format']=@$rate->shipping_params->show_eta_format; $data['packaging_type']=@$rate->shipping_params->packaging_type; $data['include_price']=@$rate->shipping_params->include_price; $data['currency_code']= $this->shipping_currency_code; $data['weight_approximation']=@$rate->shipping_params->weight_approximation; $data['use_dimensions']=@$rate->shipping_params->use_dimensions; $data['dim_approximation_l']=@$rate->shipping_params->dim_approximation_l; $data['dim_approximation_w']=@$rate->shipping_params->dim_approximation_w; $data['dim_approximation_h']=@$rate->shipping_params->dim_approximation_h; $data['methods']=@$rate->shipping_params->methods; $data['destZip']=@$null->shipping_address->address_post_code; $data['destCountry']=@$null->shipping_address->address_country->zone_code_2; $data['zip']=@$rate->shipping_params->origination_postcode; $data['total_insured']=@$total_price; $data['sender_company']=@$rate->shipping_params->sender_company; $data['sender_phone']=@$rate->shipping_params->sender_phone; $data['sender_address']=@$rate->shipping_params->sender_address; $data['sender_city']=@$rate->shipping_params->sender_city; $state_zone = ''; $state_zone=@$rate->shipping_params->sender_state; $query="SELECT zone_id, zone_code_2, zone_code_3 FROM ".hikashop_table('zone')." WHERE zone_namekey IN (".$db->Quote($state_zone).")"; $db->setQuery($query); $state = $db->loadObject(); $data['sender_state'] = ''; if(isset($state->zone_code_2) && strlen($state->zone_code_2) == 2) $data['sender_state'] = $state->zone_code_2; elseif(strlen($state->zone_code_3) == 2) $data['sender_state']=$state->zone_code_3; $data['sender_postcode']=$rate->shipping_params->sender_postcode; $data['recipient']=$null->shipping_address; $czone_code = ''; $czone_code=@$rate->shipping_params->sender_country; $query="SELECT zone_id, zone_code_2 FROM ".hikashop_table('zone')." WHERE zone_namekey IN (".$db->Quote($czone_code).")"; $db->setQuery($query); $czone = $db->loadObject(); $data['country'] = $czone->zone_code_2; $data['XMLpackage']=''; /*$data['destType']=''; if(@$rate->shipping_params->destination_type=='res'){ $data['destType']=''; } if(@$rate->shipping_params->destination_type=='auto' && !isset($order->shipping_address->address_company)){ $data['destType']=''; }*/ // BOF: gpraceman added to use address_type field to determine if shipping to a residential address $data['residential'] = false; if(@$rate->shipping_params->destination_type=='res'){ $data['residential'] = true; } if(@$rate->shipping_params->destination_type=='auto' && ($order->shipping_address->address_type=='res')){ $data['residential'] = true; } // EOF: gpraceman added to use address_type field to determine if shipping to a residential address $data['pickup_type']=@$rate->shipping_params->pickup_type; $this->nbpackage = 0; if(!$rate->shipping_params->group_package || $rate->shipping_params->group_package == 0){ $data['weight']=0; $data['height']=0; $data['length']=0; $data['width']=0; $data['price']=0; foreach($order->products as $product){ if($product->product_parent_id==0){ if(isset($product->variants)){ foreach($product->variants as $variant){ //Convert the unit of measurement if it's not the good one $caracs=parent::_convertCharacteristics($variant, $data); $data['weight_unit']=$caracs['weight_unit']; $data['dimension_unit']=$caracs['dimension_unit']; $data['weight']+=round($caracs['weight'],2)*$variant->cart_product_quantity; if($caracs['height'] != '' && $caracs['height'] != '0.00' && $caracs['height'] != 0){ $data['height']+=round($caracs['height'],2)*$variant->cart_product_quantity; $data['length']+=round($caracs['length'],2)*$variant->cart_product_quantity; $data['width']+=round($caracs['width'],2)*$variant->cart_product_quantity; } $data['price']+=$variant->prices[0]->price_value_with_tax*$variant->cart_product_quantity; } } else{ //Convert the unit of measurement if it's not the good one $caracs=parent::_convertCharacteristics($product, $data); $data['weight_unit']=$caracs['weight_unit']; $data['dimension_unit']=$caracs['dimension_unit']; $data['weight']+=round($caracs['weight'],2)*$product->cart_product_quantity; if($caracs['height'] != '' && $caracs['height'] != '0.00' && $caracs['height'] != 0){ $data['height']+=round($caracs['height'],2)*$product->cart_product_quantity; $data['length']+=round($caracs['length'],2)*$product->cart_product_quantity; $data['width']+=round($caracs['width'],2)*$product->cart_product_quantity; } $data['price']+=$product->prices[0]->price_value_with_tax*$product->cart_product_quantity; } } } if(($this->freight==true && $this->classicMethod==false) || ($heavyProduct==true && $this->freight==true)) $data['XMLpackage'].=$this->_createPackage($data, $product, $rate, $order ); else $data['XMLpackage'].=$this->_createPackage($data, $product, $rate, $order, true ); $usableMethods=$this->_FEDEXrequestMethods($data,$rate); return $usableMethods; } else{ $data['weight']=0; $data['height']=0; $data['length']=0; $data['width']=0; $data['price']=0; $current_package = array(); $limitation = array( 'length' => 150, 'weight' => 119, 'dimension' => 300 ); if(!empty($rate->shipping_params->methods)) { foreach($rate->shipping_params->methods as $k => $v) { $l_lenght = 0; $l_weight = 0; $l_dimension = 0; switch($v) { case 'FEDEX_GROUND': $l_length = 150; $l_weight =108; $l_dimension=165; break; case 'FEDEX_EXPRESS_SAVER': $l_length = 150; $l_weight =119; $l_dimension=130; break; } if($l_length > 0 && $limitation['length'] > $l_length) { $limitation['length'] = $l_length; } if($l_weight > 0 && $limitation['weight'] > $l_weight) { $limitation['weight'] = $l_weight; } if($l_dimension > 0 && $limitation['dimension'] > $l_dimension) { $limitation['dimension'] = $l_dimension; } } } foreach($order->products as $product){ if($product->product_parent_id==0){ if(isset($product->variants)){ foreach($product->variants as $variant){ for($i=0;$i<$variant->cart_product_quantity;$i++){ //Convert the unit of measurement if it's not the good one $caracs=parent::_convertCharacteristics($variant, $data); //Group package algorithm : $current_package = parent::groupPackages($data, $caracs); if($data['weight']+round($caracs['weight'],2)>$limitation['weight'] || $current_package['dim']>$limitation['dimension'] || $data['width']>$limitation['length']){ $data['XMLpackage'].=$this->_createPackage($data, $product, $rate, $order, true ); //size and weight are reset to the last package we didn't include $data['weight']=round($caracs['weight'],2); $data['height']=$current_package['y']; $data['length']=$current_package['z']; $data['width']=$current_package['x']; $data['price']=$variant->prices[0]->price_value_with_tax; } else{ $data['weight']+=round($caracs['weight'],2); $data['height']=max($data['height'],$current_package['y']); $data['length']=max($data['length'],$current_package['z']); $data['width']+=$current_package['x']; $data['price']+=$variant->prices[0]->price_value_with_tax; } } } } else{ //if the package is too big with the last product, we create a package without this one for($i=0;$i<$product->cart_product_quantity;$i++){ //Convert the unit of measurement if it's not the good one $caracs=parent::_convertCharacteristics($product, $data); //Group package algorithm : $current_package = parent::groupPackages($data, $caracs); if($data['weight']+round($caracs['weight'],2)>$limitation['weight'] || $current_package['dim']>$limitation['dimension'] || $data['width']>$limitation['length']){ $this->nbpackage++; $data['XMLpackage'].=$this->_createPackage($data, $product, $rate, $order, true ); //size and weight are reset to the last package we didn't include $data['weight']=round($caracs['weight'],2); $data['height']=$current_package['y']; $data['length']=$current_package['z']; $data['width']=$current_package['x']; $data['price']=$product->prices[0]->price_value_with_tax; } else{ $data['weight']+=round($caracs['weight'],2); $data['height']=max($data['height'],$current_package['y']); $data['length']=max($data['length'],$current_package['z']); $data['width']+=$current_package['x']; $data['price']+=$product->prices[0]->price_value_with_tax; } } } } } if (($data['weight']+$data['height']+$data['length']+$data['width'])>0){ $this->nbpackage++; $data['XMLpackage'].=$this->_createPackage($data, $product, $rate, $order, true); } $usableMethods=$this->_FEDEXrequestMethods($data,$rate); } if(empty($usableMethods)){ return false; } $currencies=array(); foreach($usableMethods as $method){ $currencies[$method['currency_code']]='"'.$method['currency_code'].'"'; } $db = JFactory::getDBO(); $query='SELECT currency_code, currency_id FROM '.hikashop_table('currency').' WHERE currency_code IN ('.implode(',',$currencies).')'; $db->setQuery($query); $currencyList = $db->loadObjectList(); $currencyList=reset($currencyList); foreach($usableMethods as $i => $method){ $usableMethods[$i]['currency_id']=$currencyList->currency_id; } $usableMethods = parent::_currencyConversion($usableMethods, $order); //print_r($usableMethods); exit; return $usableMethods; } function _createPackage(&$data, &$product, &$rate, &$order, $includeDimension=false){ if(empty($data['weight'])){ //Convert the unit of measurement if it's not the good one $caracs=parent::_convertCharacteristics($product, $data); $data['weight_unit']=$caracs['weight_unit']; $data['dimension_unit']=$caracs['dimension_unit']; $data['weight']=round($caracs['weight'],2); if($caracs['height'] != '' && $caracs['height'] != '0.00' && $caracs['height'] != 0){ $data['height']=round($caracs['height'],2); $data['length']=round($caracs['length'],2); $data['width']=round($caracs['width'],2); } } if($data['weight_unit'] == 'KGS') $data['weight_unit'] = 'KG'; if($data['weight_unit'] == 'LBS') $data['weight_unit'] = 'LB'; $currencyClass=hikashop_get('class.currency'); $config =& hikashop_config(); $this->main_currency = $config->get('main_currency',1); $currency = hikashop_getCurrency(); if(isset($data['price'])){ $price=$data['price']; } else{ $price=$product->prices[0]->price_value; } if(@$this->shipping_currency_id!=@$data['currency'] && !empty($data['currency'])){ $price=$currencyClass->convertUniquePrice($price, $this->shipping_currency_id,@$data['currency']); } if(!empty($rate->shipping_params->weight_approximation)){ $data['weight']=$data['weight']+$data['weight']*$rate->shipping_params->weight_approximation/100; } if(@$data['weight']<1){ $data['weight']=1; } if(!empty($rate->shipping_params->dim_approximation_h) && @$rate->shipping_params->use_dimensions == 1){ $data['height']=$data['height']+$data['height']*$rate->shipping_params->dim_approximation_h/100; } if(!empty($rate->shipping_params->dim_approximation_l) && @$rate->shipping_params->use_dimensions == 1){ $data['length']=$data['length']+$data['length']*$rate->shipping_params->dim_approximation_l/100; } if(!empty($rate->shipping_params->dim_approximation_w) && @$rate->shipping_params->use_dimensions == 1){ $data['width']=$data['width']+$data['width']*$rate->shipping_params->dim_approximation_w/100; } $options=''; $dimension=''; if(@$rate->shipping_params->include_price){ $options=' '.$data['currency_code'].' '.$price.' '; } if($includeDimension){ if($data['height'] != '' && $data['height'] != 0 && $data['height'] != '0.00'){ $dimension=' '.$data['dimension_unit'].' '.$data['length'].' '.$data['width'].' '.$data['height'].' '; } } static $id = 0; $xml=' 02 Shop '.$dimension.' '.$data['weight_unit'].' '.$data['weight'].' '.$options.' '; $id++; return $xml; } function _FEDEXrequestMethods($data,$rate){ global $fedex_methods; $path_to_wsdl = dirname(__FILE__).DS.'fedex_rate.wsdl'; ini_set("soap.wsdl_cache_enabled","0"); if(!class_exists('SoapClient')){ $app = JFactory::getApplication(); $app->enqueueMessage('The FEDEX shipping plugin needs the SOAP library installed but it seems that it is not available on your server. Please contact your web hosting to set it up.','error'); return false; } $client = new SoapClient($path_to_wsdl, array('exceptions' => false)); $shipment= array(); foreach($data['methods'] as $k=>$v){ // BOF: gpraceman added to skip ground delivery type not applicable to address type if ($v == 'FEDEX_GROUND' && $data['residential'] || $v == 'GROUND_HOME_DELIVERY' && !$data['residential']) { continue; } // EOF: gpraceman added to skip ground delivery type not applicable to address type $request['WebAuthenticationDetail'] = array( 'UserCredential' =>array( 'Key' => $data['fedex_api_key'], 'Password' => $data['fedex_api_password'] ) ); $request['ClientDetail'] = array( 'AccountNumber' => $data['fedex_account_number'], 'MeterNumber' => $data['fedex_meter_number'] ); $request['TransactionDetail'] = array('CustomerTransactionId' => ' *** Rate Request v10 using PHP ***'); $request['Version'] = array( 'ServiceId' => 'crs', 'Major' => '10', 'Intermediate' => '0', 'Minor' => '0' ); $request['ReturnTransitAndCommit'] = true; $request['RequestedShipment']['DropoffType'] = 'REGULAR_PICKUP'; // valid values REGULAR_PICKUP, REQUEST_COURIER, ... $request['RequestedShipment']['ShipTimestamp'] = date('c'); $request['RequestedShipment']['ServiceType'] = $v; // valid values STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND, ... $request['RequestedShipment']['PackagingType'] = $data['packaging_type']; // valid values FEDEX_BOX, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING, ... $request['RequestedShipment']['TotalInsuredValue']=array('Ammount'=>$data['total_insured'],'Currency'=>'USD'); $request['RequestedPackageDetailType'] = 'PACKAGE_SUMMARY'; $shipper = array( 'Contact' => array( 'PersonName' => $data['sender_company'], 'CompanyName' => $data['sender_company'], 'PhoneNumber' => $data['sender_phone']), 'Address' => array( 'StreetLines' => array($data['sender_address']), 'City' => $data['sender_city'], 'StateOrProvinceCode' => $data['sender_state'], 'PostalCode' => $data['sender_postcode'], 'CountryCode' => $data['country']) ); $recipient_StateOrProvinceCode = ''; if(isset($data['recipient']->address_state->zone_code_2) && strlen($data['recipient']->address_state->zone_code_2) == 2) $recipient_StateOrProvinceCode = $data['recipient']->address_state->zone_code_2; elseif(strlen($data['recipient']->address_state->zone_code_3) == 2) $recipient_StateOrProvinceCode = $data['recipient']->address_state->zone_code_3; $recipient = array( 'Contact' => array( 'PersonName' => $data['recipient']->address_title." ".$data['recipient']->address_firstname." ".$data['recipient']->address_lastname, 'CompanyName' => $data['recipient']->address_company, 'PhoneNumber' => $data['recipient']->address_telephone ), 'Address' => array( 'StreetLines' => array($data['recipient']->address_street), 'City' => $data['recipient']->address_city, 'StateOrProvinceCode' => $recipient_StateOrProvinceCode, 'PostalCode' => $data['recipient']->address_post_code, 'CountryCode' => $data['recipient']->address_country->zone_code_2, //'Residential' => true) 'Residential' => $data['residential']) // gpraceman modified ); /* gpraceman removed since being set above if(@$rate->shipping_params->destination_type=='res'){ $recipient['Address']['Residential'] = true; } if(@$rate->shipping_params->destination_type=='com' || (@$rate->shipping_params->destination_type=='auto' && $v == 'FEDEX_GROUND')){ $recipient['Address']['Residential'] = false; }*/ $shippingChargesPayment = array( 'PaymentType' => 'SENDER', // valid values RECIPIENT, SENDER and THIRD_PARTY 'Payor' => array( 'AccountNumber' => $data['fedex_account_number'], 'CountryCode' => $data['country']) ); $pkg_values = $this->xml2array(''.$data['XMLpackage'].''); $pkg_values = $pkg_values['root']; $pkg_count = count($pkg_values); $request['RequestedShipment']['Shipper'] = $shipper; $request['RequestedShipment']['Recipient'] = $recipient; $request['RequestedShipment']['ShippingChargesPayment'] = $shippingChargesPayment; $request['RequestedShipment']['RateRequestTypes'] = 'ACCOUNT'; if(empty($rate->shipping_params->rate_types) || $rate->shipping_params->rate_types != 'ACCOUNT'){ $request['RequestedShipment']['RateRequestTypes'] = 'LIST'; } $request['RequestedShipment']['PackageCount'] = $pkg_count; $request['RequestedShipment']['RequestedPackageLineItems'] = $this->addPackageLineItem($pkg_values); if(@$rate->shipping_params->debug){ echo "
Request $v :
"; echo '
' . var_export($request, true) . '
'; } // echo( '
'.var_export($request, true).'
' ); // try { $response = $client->getRates($request); // } // catch(SoapFault $e) { } // echo( '
'.var_export($response, true).'
' ); if(isset($response->HighestSeverity) && $response->HighestSeverity == "ERROR") { static $notif = false; if(!$notif && isset($response->Notifications->Message) && $response->Notifications->Message == 'Authentication Failed') { $app = JFactory::getApplication(); $app->enqueueMessage('FEDEX Authentication Failed'); $notif = true; } if(!$notif && !empty($response->Notifications->Message) && $response->Notifications->Message != 'Service is not allowed') { $app = JFactory::getApplication(); $app->enqueueMessage('The FedEx request failed with the message : ' . $response->Notifications->Message); } } if(@$rate->shipping_params->debug){ echo "
Response $v :
"; echo '
' . var_export($response, true) . '
'; } // NOTE and WARNING = SUCCESS + warning/note message if(!empty($response->HighestSeverity) && ($response->HighestSeverity == "SUCCESS" || $response->HighestSeverity == "NOTE" || $response->HighestSeverity == "WARNING")) { $code = ''; $notes = array(); if($response->HighestSeverity == "NOTE" || $response->HighestSeverity == "WARNING") { $notes = $response->Notifications; } foreach($this->fedex_methods as $k=>$v) { if($v['code'] == $response->RateReplyDetails->ServiceType){ $code = $v['code']; } } $delayType = hikashop_get('type.delay'); if(!empty($response->RateReplyDetails->DeliveryTimestamp)) $timestamp = strtotime($response->RateReplyDetails->DeliveryTimestamp); else { $timestamp = 0; $response->RateReplyDetails->DeliveryTimestamp=0; } $totalNetPrice = 0; $discountAmount = 0; if(is_array($response->RateReplyDetails->RatedShipmentDetails)){ $totalNetPrice = $response->RateReplyDetails->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Amount; if($request['RequestedShipment']['RateRequestTypes'] != 'ACCOUNT'){ $discountAmount = $response->RateReplyDetails->RatedShipmentDetails[0]->ShipmentRateDetail->TotalFreightDiscounts->Amount; } $shipment[] = array( 'value'=>$totalNetPrice + $discountAmount, 'code'=>$code, 'delivery_timestamp' => $timestamp, 'day'=>$response->RateReplyDetails->DeliveryTimestamp, 'delivery_day' => date("m/d/Y", $timestamp), 'delivery_delay' => parent::displayDelaySECtoDAY($timestamp - strtotime('now'),2), 'delivery_time' => date("H:i:s", $timestamp), 'currency_code'=>$response->RateReplyDetails->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Currency, 'old_currency_code' => $response->RateReplyDetails->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Currency, 'notes' => $notes ); } else if(is_object($response->RateReplyDetails->RatedShipmentDetails)){ $totalNetPrice = $response->RateReplyDetails->RatedShipmentDetails->ShipmentRateDetail->TotalNetCharge->Amount; if($request['RequestedShipment']['RateRequestTypes'] != 'ACCOUNT'){ $discountAmount = $response->RateReplyDetails->RatedShipmentDetails->ShipmentRateDetail->TotalFreightDiscounts->Amount; } $shipment[] = array( 'value'=>$totalNetPrice + $discountAmount, 'code'=>$code, 'delivery_timestamp' => $timestamp, 'day'=>$response->RateReplyDetails->DeliveryTimestamp, 'delivery_day' => date("m/d/Y", $timestamp), 'delivery_delay' => parent::displayDelaySECtoDAY($timestamp - strtotime('now'),2), 'delivery_time' => date("H:i:s", $timestamp), 'currency_code'=>$response->RateReplyDetails->RatedShipmentDetails->ShipmentRateDetail->TotalNetCharge->Currency, 'old_currency_code' => $response->RateReplyDetails->RatedShipmentDetails->ShipmentRateDetail->TotalNetCharge->Currency, 'notes' => $notes ); } } else if(!empty($response->HighestSeverity) && ($response->HighestSeverity == "ERROR")) { static $errorsDisplayed = array(); //TODO add error_code+message $acceptedCodes = array(836); if(!empty($response->Notifications)) { foreach($response->Notifications as $notif) { if(!is_object($notif)) continue; $errorCode = $notif->Code; if(!in_array($errorCode, $acceptedCodes)) { if(!isset($errorsDisplayed[$errorCode])) { $app = JFactory::getApplication(); $app->enqueueMessage($notif->Message); } $errorsDisplayed[$errorCode] = true; } } } } } return $shipment; } function printSuccess($client, $response) { echo '

Transaction Successful

'; echo "\n"; printRequestResponse($client); } function printRequestResponse($client){ echo '

Request

' . "\n"; echo '
' . htmlspecialchars($client->__getLastRequest()). '
'; echo "\n"; echo '

Response

'. "\n"; echo '
' . htmlspecialchars($client->__getLastResponse()). '
'; echo "\n"; } /** * Print SOAP Fault */ function printFault($exception, $client) { echo '

Fault

' . "
\n"; echo "Code:{$exception->faultcode}
\n"; echo "String:{$exception->faultstring}
\n"; writeToLog($client); } /** * SOAP request/response logging to a file */ function writeToLog($client){ if (!$logfile = fopen(TRANSACTIONS_LOG_FILE, "a")) { error_func("Cannot open " . TRANSACTIONS_LOG_FILE . " file.\n", 0); exit(1); } fwrite($logfile, sprintf("\r%s:- %s",date("D M j G:i:s T Y"), $client->__getLastRequest(). "\n\n" . $client->__getLastResponse())); } /** * This section provides a convenient place to setup many commonly used variables * needed for the php sample code to function. */ function getProperty($var){ if($var == 'check') Return true; if($var == 'shipaccount') Return 'XXX'; if($var == 'billaccount') Return 'XXX'; if($var == 'dutyaccount') Return 'XXX'; if($var == 'accounttovalidate') Return 'XXX'; if($var == 'meter') Return 'XXX'; if($var == 'key') Return 'XXX'; if($var == 'password') Return ''; if($var == 'shippingChargesPayment') Return 'SENDER'; if($var == 'internationalPaymentType') Return 'SENDER'; if($var == 'readydate') Return '2010-05-31T08:44:07'; if($var == 'readytime') Return '12:00:00-05:00'; if($var == 'closetime') Return '20:00:00-05:00'; if($var == 'closedate') Return date("Y-m-d"); if($var == 'pickupdate') Return date("Y-m-d", mktime(8, 0, 0, date("m") , date("d")+1, date("Y"))); if($var == 'pickuptimestamp') Return mktime(8, 0, 0, date("m") , date("d")+1, date("Y")); if($var == 'pickuplocationid') Return 'XXX'; if($var == 'pickupconfirmationnumber') Return '00'; if($var == 'dispatchdate') Return date("Y-m-d", mktime(8, 0, 0, date("m") , date("d")+1, date("Y"))); if($var == 'dispatchtimestamp') Return mktime(8, 0, 0, date("m") , date("d")+1, date("Y")); if($var == 'dispatchlocationid') Return 'XXX'; if($var == 'dispatchconfirmationnumber') Return '00'; if($var == 'shiptimestamp') Return mktime(10, 0, 0, date("m"), date("d")+1, date("Y")); if($var == 'tag_readytimestamp') Return mktime(10, 0, 0, date("m"), date("d")+1, date("Y")); if($var == 'tag_latesttimestamp') Return mktime(15, 0, 0, date("m"), date("d")+1, date("Y")); if($var == 'trackingnumber') Return 'XXX'; if($var == 'trackaccount') Return 'XXX'; if($var == 'shipdate') Return '2010-06-06'; if($var == 'account') Return 'XXX'; if($var == 'phonenumber') Return '1234567890'; if($var == 'closedate') Return '2010-05-30'; if($var == 'expirationdate') Return '2011-06-15'; if($var == 'hubid') Return '5531'; if($var == 'begindate') Return '2011-05-20'; if($var == 'enddate') Return '2011-05-31'; if($var == 'address1') Return array('StreetLines' => array('10 Fed Ex Pkwy'), 'City' => 'Memphis', 'StateOrProvinceCode' => 'TN', 'PostalCode' => '38115', 'CountryCode' => 'US'); if($var == 'address2') Return array('StreetLines' => array('13450 Farmcrest Ct'), 'City' => 'Herndon', 'StateOrProvinceCode' => 'VA', 'PostalCode' => '20171', 'CountryCode' => 'US'); if($var == 'locatoraddress') Return array(array('StreetLines'=>'240 Central Park S'), 'City'=>'Austin', 'StateOrProvinceCode'=>'TX', 'PostalCode'=>'78701', 'CountryCode'=>'US'); if($var == 'recipientcontact') Return array('ContactId' => 'arnet', 'PersonName' => 'Recipient Contact', 'PhoneNumber' => '1234567890'); if($var == 'freightaccount') Return 'XXX'; if($var == 'freightbilling') Return array( 'Contact'=>array( 'ContactId' => 'freight1', 'PersonName' => 'Big Shipper', 'Title' => 'Manager', 'CompanyName' => 'Freight Shipper Co', 'PhoneNumber' => '1234567890' ), 'Address'=>array( 'StreetLines'=>array('1202 Chalet Ln', 'Do Not Delete - Test Account'), 'City' =>'Harrison', 'StateOrProvinceCode' => 'AR', 'PostalCode' => '72601-6353', 'CountryCode' => 'US' ) ); } function setEndpoint($var){ if($var == 'changeEndpoint') Return false; if($var == 'endpoint') Return ''; } function printNotifications($notes){ foreach($notes as $noteKey => $note){ if(is_string($note)){ echo $noteKey . ': ' . $note . Newline; } else{ printNotifications($note); } } echo Newline; } function printError($client, $response){ echo '

Error returned in processing transaction

'; echo "\n"; printNotifications($response->Notifications); printRequestResponse($client, $response); } function addPackageLineItem($pkg_values){ $packageLineItem[] = array(); $ct = count($pkg_values); $x = 1; foreach($pkg_values as $pkg) { if($pkg['PackageWeight']['UnitOfMeasurement']['Code'] == "LBS"){ $uom = "LB"; } else { $uom = $pkg["PackageWeight"]["UnitOfMeasurement"]['Code']; } if(is_array($pkg['Dimensions'])){ $dimensions = array("Dimensions"=>array( 'Length' => $pkg['Dimensions']['Length'], 'Width' => $pkg['Dimensions']['Width'], 'Height' => $pkg['Dimensions']['Height'], 'Units' => $pkg['Dimensions']['UnitOfMeasurement']['Code']) ); } $packageLineItem = array( 'SequenceNumber'=>$x, 'GroupPackageCount'=>$ct, 'Weight' => array( 'Value' => $pkg['PackageWeight']['Weight'], 'Units' => $uom ), $dimensions ); $x++; } return $packageLineItem; } function xml2array($contents, $get_attributes = 1, $priority = 'tag') { //$contents = ""; if (!function_exists('xml_parser_create')) { return array (); } $parser = xml_parser_create(''); xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); xml_parse_into_struct($parser, trim($contents), $xml_values); xml_parser_free($parser); if (!$xml_values) return; //Hmm... $xml_array = array (); $parents = array (); $opened_tags = array (); $arr = array (); $current = & $xml_array; $repeated_tag_index = array (); foreach ($xml_values as $data) { unset ($attributes, $value); extract($data); $result = array (); $attributes_data = array (); if (isset ($value)) { if ($priority == 'tag') $result = $value; else $result['value'] = $value; } if (isset ($attributes) and $get_attributes) { foreach ($attributes as $attr => $val) { if ($priority == 'tag') $attributes_data[$attr] = $val; else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' } } if ($type == "open") { $parent[$level -1] = & $current; if (!is_array($current) or (!in_array($tag, array_keys($current)))) { $current[$tag] = $result; if ($attributes_data) $current[$tag . '_attr'] = $attributes_data; $repeated_tag_index[$tag . '_' . $level] = 1; $current = & $current[$tag]; } else { if (isset ($current[$tag][0])) { $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; $repeated_tag_index[$tag . '_' . $level]++; } else { $current[$tag] = array ( $current[$tag], $result ); $repeated_tag_index[$tag . '_' . $level] = 2; if (isset ($current[$tag . '_attr'])) { $current[$tag]['0_attr'] = $current[$tag . '_attr']; unset ($current[$tag . '_attr']); } } $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1; $current = & $current[$tag][$last_item_index]; } } elseif ($type == "complete") { if (!isset ($current[$tag])) { $current[$tag] = $result; $repeated_tag_index[$tag . '_' . $level] = 1; if ($priority == 'tag' and $attributes_data) $current[$tag . '_attr'] = $attributes_data; } else { if (isset ($current[$tag][0]) and is_array($current[$tag])) { $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; if ($priority == 'tag' and $get_attributes and $attributes_data) { $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; } $repeated_tag_index[$tag . '_' . $level]++; } else { $current[$tag] = array ( $current[$tag], $result ); $repeated_tag_index[$tag . '_' . $level] = 1; if ($priority == 'tag' and $get_attributes) { if (isset ($current[$tag . '_attr'])) { $current[$tag]['0_attr'] = $current[$tag . '_attr']; unset ($current[$tag . '_attr']); } if ($attributes_data) { $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; } } $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken } } } elseif ($type == 'close') { $current = & $parent[$level -1]; } } return ($xml_array); } function array_sort($array, $on, $type, $order = SORT_ASC) { if (empty($array)) return array(); $new_array = array(); $sortable_array = array(); foreach ($array as $key => $value) { if($value->shipping_type == $type) $sortable_array[$key] = $value->shipping_price; } switch ($order) { case SORT_ASC: asort($sortable_array); break; case SORT_DESC: arsort($sortable_array); break; } foreach ($sortable_array as $k => $v) { $new_array[$k] = $array[$k]; } return $new_array; } }