id = "richwrap"; $this->name = "Richwrap"; } public function calculate($ship_method, $ship_date, $address, $weight, $total_shipment_weight) { //ship method is only fedex ground for now /** * Address: array * id * quantity * ship_name * ship_address_1 * ship_address_2 * ship_city * ship_state * ship_postal */ if ($address['ship_address_1'] == 'Address 1') $address['ship_address_1'] = ''; if ($address['ship_address_2'] == 'Address 2') $address['ship_address_2'] = ''; if ($address['ship_city'] == 'City') $address['ship_city'] = ''; if ($address['ship_state'] == 'State') $address['ship_state'] = ''; if ($address['ship_postal'] == 'Zip') $address['ship_postal'] = ''; //perform basic checking of the address before moving forward if ( strlen($address['ship_name']) > 2 && strlen($address['ship_address_1']) > 5 && strlen($address['ship_city']) > 1 && strlen($address['ship_state']) > 1 && strlen($address['ship_postal']) >= 5 ) { //looks somewhat valid, further checking $options = array( 'address_1' => $address['ship_address_1'], 'address_2' => $address['ship_address_2'], 'city' => $address['ship_city'], 'state' => $address['ship_state'], 'postal' => $address['ship_postal'] ); $result = self::get_cache($this->id . '_address', $options); if (!$result) { $result = self::verify_address($options); self::update_cache($this->id . '_address', $options, $result); } $clean_address = self::get_address($result); if ($clean_address) { $total_weight = $weight; $options = array($clean_address, $total_weight); $result = self::get_cache($this->id . '_shipping', $options); if (!$result) { $result = fedex::get_result($clean_address, $total_weight); self::update_cache($this->id . '_shipping', $options, $result); } $rates = fedex::get_rates($result); if (isset($rates['FEDEX_GROUND']) || isset($rates['GROUND_HOME_DELIVERY'])) { if (isset($rates['FEDEX_GROUND'])) $rate = floatval($rates['FEDEX_GROUND']); else $rate = floatval($rates['GROUND_HOME_DELIVERY']); $overweight = floatval(store_options::get('Shipping - Costs', 'Overweight Limit (lbs)', '200')); $residential_padding = floatval(store_options::get('Shipping - Costs', 'Residential Padding (Percent)', '12.5')) / 100; $residential_overweight_padding = floatval(store_options::get('Shipping - Costs', 'Residential Overweight Padding (Percent)', '20')) / 100; $commercial_padding = floatval(store_options::get('Shipping - Costs', 'Commercial Padding (Percent)', '20')) / 100; $commercial_overweight_padding = floatval(store_options::get('Shipping - Costs', 'Commercial Overweight Padding (Percent)', '20')) / 100; if ($total_shipment_weight < $overweight) { if ($clean_address['type'] == 'R') $rate += $rate * $residential_padding; else $rate += $rate * $commercial_padding; } else { if ($clean_address['type'] == 'R') $rate += $rate * $residential_overweight_padding; else $rate += $rate * $commercial_overweight_padding; } return number_format($rate,2); } } } return false; } public function get_address($result) { $address = false; try { $flat_xml = self::flatten_xml($result); if (isset($flat_xml['Response|ReturnCode'])) { $return_code = $flat_xml['Response|ReturnCode']; if ($return_code == '31' || $return_code == '32') { $address = isset($flat_xml['Response|AddrLine1']) ? $flat_xml['Response|AddrLine1'] : ''; $address2 = isset($flat_xml['Response|AddrLine2']) ? $flat_xml['Response|AddrLine2'] : ''; $city = isset($flat_xml['Response|City']) ? $flat_xml['Response|City'] : ''; $state = isset($flat_xml['Response|State']) ? $flat_xml['Response|State'] : ''; $zip = isset($flat_xml['Response|ZIP5']) ? $flat_xml['Response|ZIP5'] : ''; $rdi = isset($flat_xml['Response|RDI']) ? $flat_xml['Response|RDI'] : ''; $address = array( 'address' => $address, 'address2' => $address2, 'city' => $city, 'state' => $state, 'zip' => $zip, 'type' => $rdi ); } } } catch (Exception $e) { } return $address; } function verify_address($options) { $addr0 = ""; $addr1 = urlencode(($options['address_2'] != '') ? $options['address_1'] : ''); $addr2 = urlencode(($options['address_2'] != '') ? $options['address_2'] : $options['address_1']); $addr3 = urlencode($options['city'] . ', ' .$options['state'] . ' ' . $options['postal']); $licensecode = store_options::get('Shipping', 'Address Verification - License Code', 'djh43uxjn4'); $url = "http://www.nrgsoft.com/webservices/address_validation.lasso?AddrLine3=$addr0&AddrLine2=$addr1&AddrLine1=$addr2&AddrLineLast=$addr3&licensecode=$licensecode"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch,CURLOPT_TIMEOUT,60); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0); $response=curl_exec($ch); curl_close($ch); return $response ; } private function flatten_xml($content) { $xml_start = strpos($content, 'xml($xml_content)) { $values = array(); $parents = array(); while ($xml->read()) { if ($xml->nodeType == XMLReader::ELEMENT) { array_push($parents, $xml->name); } elseif ($xml->nodeType == XMLReader::END_ELEMENT) { array_pop($parents); } elseif ($xml->nodeType == XMLReader::TEXT) { $key = join('|', $parents); $values[$key] = $xml->value; } } $xml->close(); return $values; } else { $xml->close(); return false; } } } class fedex { public static function get_rates($xml) { $xmlresult = self::xml2array($xml); $error = ""; if (isset($xmlresult['v8:RateReply']['v8:HighestSeverity']['value'])) $error = $xmlresult['v8:RateReply']['v8:HighestSeverity']['value']; //if ($error != 'SUCCESS' && $error != 'WARNING') { // return false; //} $rates = array(); for ($i=0;$i $totalcharges ) { $totalcharges = $gndtotalcharges ; } $rates[$servicecode] = $totalcharges; } } return $rates; } private static function xml2array($contents, $get_attributes=1, $priority = 'attribute', $array_force=array()) { if(!$contents) return array(); if(!function_exists('xml_parser_create')) { //print "'xml_parser_create()' function not found!"; return array(); } //Get the XML parser of PHP - PHP must have this module for the parser to work $parser = xml_parser_create(''); xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss 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... //Initializations $xml_array = array(); $parents = array(); $opened_tags = array(); $arr = array(); $current = &$xml_array; //Refference //Go through the tags. $repeated_tag_index = array();//Multiple tags with same name will be turned into an array foreach($xml_values as $data) { unset($attributes,$value);//Remove existing values, or there will be trouble //This command will extract these variables into the foreach scope // tag(string), type(string), level(int), attributes(array). extract($data);//We could use the array by itself, but this cooler. $result = array(); $attributes_data = array(); if(isset($value)) { if($priority == 'tag') $result = $value; else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode } //Set the attributes too. 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' } } //See tag status and do the needed. if($type == "open") {//The starting of the tag '' $parent[$level-1] = &$current; if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag if (in_array($tag,$array_force)) $current[$tag][0] = $result; else $current[$tag] = $result; if($attributes_data) $current[$tag. '_attr'] = $attributes_data; $repeated_tag_index[$tag.'_'.$level] = 1; if (in_array($tag,$array_force)) $current = &$current[$tag][0]; else $current = &$current[$tag]; } else { //There was another element with the same tag name if(isset($current[$tag][0])) {//If there is a 0th element it is already an array $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result; $repeated_tag_index[$tag.'_'.$level]++; } else {//This section will make the value an array if multiple tags with the same name appear together $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array $repeated_tag_index[$tag.'_'.$level] = 2; if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well $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") { //Tags that ends in 1 line '' //See if the key is already taken. if(!isset($current[$tag])) { //New Key $current[$tag] = $result; $repeated_tag_index[$tag.'_'.$level] = 1; if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data; } else { //If taken, put all things inside a list(array) if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array... // ...push the new element into that array. $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 { //If it is not an array... $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value $repeated_tag_index[$tag.'_'.$level] = 1; if($priority == 'tag' and $get_attributes) { if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well $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') { //End of tag '' $current = &$parent[$level-1]; } } return($xml_array); } public static function get_result($address, $weight) { /* $address: array address address2 city state zip */ $origin_name = store_options::get('Shipping', 'Origin Name', 'RICHWRAP'); $origin_address = store_options::get('Shipping', 'Origin Address', '401 East North Street'); $origin_city = store_options::get('Shipping', 'Origin City', 'ELBURN'); $origin_state = store_options::get('Shipping', 'Origin State', 'IL'); $origin_postal = store_options::get('Shipping', 'Origin Postal', '60119'); $origin_country = store_options::get('Shipping', 'Origin Country', 'US'); $fedex_key = store_options::get('Shipping', 'Fedex Key', 'vGFSl41KS0y0cPkA'); $fedex_password = store_options::get('Shipping', 'Fedex Password', '9PWsF0AMtbSN9IrILssy2wRiR'); $fedex_account = store_options::get('Shipping', 'Fedex Account', '510087682'); $fedex_meter = store_options::get('Shipping', 'Fedex Meter', '100034316'); $fedex_hubid = store_options::get('Shipping', 'Fedex Hub Id', '5303'); $fedex_server = store_options::get('Shipping', 'Fedex Server (DEV or LIVE)', 'DEV'); if ($fedex_server != 'LIVE') $fedex_server = 'DEV'; $result = self::quoteFedEx( $origin_name, $origin_address, $origin_city, $origin_state, $origin_postal, $origin_country, $fedex_key, $fedex_password, $fedex_account, $fedex_meter, $fedex_hubid, $fedex_server, $address['address'], $address['city'], $address['state'], $address['zip'], 'US', $address['type'] == 'R', $weight ); return $result; } private static function quoteFedEx ( $origin_name, $origin_address, $origin_city, $origin_state, $origin_postal, $origin_country, $fedex_key, $fedex_password, $fedex_account, $fedex_meter, $fedex_hubid, $fedex_server, $delivery_address, $delivery_city, $delivery_state, $delivery_zip, $delivery_country, $delivery_residential, $shipping_weight) { $delivery_zip = substr($delivery_zip, 0, 5); $today = date ('Y-m-d'); $Request = " $fedex_key $fedex_password $fedex_account $fedex_meter NRG crs 8 0 0 true {$today}T10:19:26-05:00 REGULAR_PICKUP YOUR_PACKAGING $origin_name $origin_address $origin_city $origin_state $origin_postal $origin_country $delivery_address $delivery_city $delivery_state $delivery_zip $delivery_country" ; if ($delivery_residential) { $Request .= "true\n"; } $Request .=" SENDER $fedex_account US PARCEL_SELECT USPS_DELIVERY_CONFIRMATION $fedex_hubid ACCOUNT 1 INDIVIDUAL_PACKAGES 1 LB $shipping_weight "; if ( $fedex_server == 'DEV' ) { // dev server $url = "https://gatewaybeta.fedex.com/xml"; } else { // production server $url = "https://gateway.fedex.com/xml"; } // execute request $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_TIMEOUT,60); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0); curl_setopt($ch, CURLOPT_POSTFIELDS, $Request); $response = curl_exec($ch); curl_close($ch); return $response; } } ?>