ash_ups

Author : Greg Gullett and Instinct.co.uk SVN : UPS Trunk : Version : 1.1.0 : December 21, 2010.

Defined (1)

The class is defined in the following location(s).

/wpsc-shipping/ups_20.php  
  1. class ash_ups { 
  2. public $internal_name; 
  3. public $name; 
  4. public $service_url = ''; 
  5. public $Services = array(); 
  6. public $singular_shipping = false; 
  7. public $shipment; 
  8. public $is_external = true; 
  9. public $requires_curl = true; 
  10. public $requires_weight = true; 
  11. public $needs_zipcode = true; 
  12.  
  13. public $drop_types = array(); 
  14. public $cust_types = array(); 
  15.  
  16. function ash_ups () { 
  17. $this->internal_name = 'ups'; 
  18. $this->name = _x( 'UPS', 'Shipping Module', 'wpsc' ); 
  19. $this->is_external = true; 
  20. $this->requires_curl = true; 
  21. $this->requires_weight = true; 
  22. $this->needs_zipcode = true; 
  23. $this->_setServiceURL(); 
  24. $this->_includeUPSData(); 
  25. return true; 
  26.  
  27. function __autoload ( $name ) { 
  28. include_once( '../wpsc-includes/shipping.helper.php' ); 
  29.  
  30. function getId () { 
  31. // return $this->usps_id; 
  32.  
  33. function setId ( $id ) { 
  34. // $usps_id = $id; 
  35. // return true; 
  36.  
  37. private function _setServiceURL () { 
  38. global $wpdb; 
  39. $wpsc_ups_settings = get_option( 'wpsc_ups_settings' ); 
  40. $wpsc_ups_environment = ( array_key_exists( 'upsenvironment', (array) $wpsc_ups_settings ) ) ? $wpsc_ups_settings['upsenvironment'] : '0'; //(1) testing, else (0) production. 
  41.  
  42. if ( '1' == $wpsc_ups_environment ) { 
  43. $this->service_url = 'https://wwwcie.ups.com/ups.app/xml/Rate'; 
  44. } else { 
  45. $this->service_url = 'https://www.ups.com/ups.app/xml/Rate'; 
  46.  
  47. function getName () { 
  48. return $this->name; 
  49.  
  50. function getInternalName () { 
  51. return $this->internal_name; 
  52.  
  53. private function _includeUPSData () { 
  54. $this->drop_types = array( 
  55. '01' => __( 'Daily Pickup', 'wpsc' ),  
  56. '03' => __( 'Customer Counter', 'wpsc' ),  
  57. '06' => __( 'One Time Pickup', 'wpsc' ),  
  58. '07' => __( 'On Call Air', 'wpsc' ),  
  59. '19' => __( 'Letter Center', 'wpsc' ),  
  60. '20' => __( 'Air Service Center', 'wpsc' ),  
  61. '11' => __( 'Suggested Retail Rates (Advanced Config)', 'wpsc' ),  
  62. ); 
  63.  
  64. $this->cust_types = array( 
  65. '01' => __( 'Daily Pickup, with UPS Account', 'wpsc' ),  
  66. '03' => __( 'No Daily Pickup, with No or Other Account', 'wpsc' ),  
  67. '04' => __( 'Retail Outlet (Only US origin shipments)', 'wpsc' ) 
  68. ); 
  69.  
  70. $this->Services = array( 
  71. '14' => __( 'Next Day Air Early AM', 'wpsc' ),  
  72. '01' => __( 'Next Day Air', 'wpsc' ),  
  73. '13' => __( 'Next Day Air Saver', 'wpsc' ),  
  74. '59' => __( '2nd Day Air AM', 'wpsc' ),  
  75. '02' => __( '2nd Day Air', 'wpsc' ),  
  76. '12' => __( '3 Day Select', 'wpsc' ),  
  77. '03' => __( 'Ground', 'wpsc' ),  
  78. '11' => __( 'Standard', 'wpsc' ),  
  79. '07' => __( 'Worldwide Express', 'wpsc' ),  
  80. '54' => __( 'Worldwide Express Plus', 'wpsc' ),  
  81. '08' => __( 'Worldwide Expedited', 'wpsc' ),  
  82. '65' => __( 'Saver', 'wpsc' ),  
  83. '82' => __( 'UPS Today Standard', 'wpsc' ),  
  84. '83' => __( 'UPS Today Dedicated Courier', 'wpsc' ),  
  85. '84' => __( 'UPS Today Intercity', 'wpsc' ),  
  86. '85' => __( 'UPS Today Express', 'wpsc' ),  
  87. '86' => __( 'UPS Today Express Saver', 'wpsc' ) 
  88. ); 
  89.  
  90. function getForm () { 
  91. if ( ! isset( $this->Services ) ) { 
  92. $this->_includeUPSData(); 
  93. //__('Your Packaging', 'wpsc'); <-- use to translate 
  94. $wpsc_ups_settings = get_option( 'wpsc_ups_settings' ); 
  95. $wpsc_ups_services = get_option( 'wpsc_ups_services' ); 
  96. // Defined on page 41 in UPS API documentation RSS_Tool_06_10_09.pdf 
  97. /**$packaging_options['00'] = __('**UNKNOWN**', 'wpsc');*/ 
  98. $packaging_options['01'] = __( 'UPS Letter', 'wpsc' ); 
  99. $packaging_options['02'] = __( 'Your Packaging', 'wpsc' ); 
  100. $packaging_options['03'] = __( 'UPS Tube', 'wpsc' ); 
  101. $packaging_options['04'] = __( 'UPS Pak', 'wpsc' ); 
  102. $packaging_options['21'] = __( 'UPS Express Box', 'wpsc' ); 
  103. $packaging_options['2a'] = __( 'UPS Express Box - Small', 'wpsc' ); 
  104. $packaging_options['2b'] = __( 'UPS Express Box - Medium', 'wpsc' ); 
  105. $packaging_options['2c'] = __( 'UPS Express Box - Large', 'wpsc' ); 
  106.  
  107. ob_start(); 
  108. ?> 
  109. <tr><td><table class='form-table'> 
  110. <tr> 
  111. <td><?php _e( 'Destination Type', 'wpsc' ); ?></td> 
  112. <td> 
  113. <label> 
  114. <input type='radio' <?php checked( '2' != $wpsc_ups_settings['49_residential'] ); ?> value='1' name='wpsc_ups_settings[49_residential]' /> 
  115. <?php _e( 'Residential Address', 'wpsc' ); ?> 
  116. </label><br /> 
  117. <label><input type='radio' <?php checked( '2' == $wpsc_ups_settings['49_residential'] ); ?>value='2' name='wpsc_ups_settings[49_residential]' /> 
  118. <?php _e( 'Commercial Address', 'wpsc' )?> 
  119. </label> 
  120. </td> 
  121. </tr> 
  122.  
  123. <?php 
  124. $sel2_drop = ''; 
  125. if ( empty( $wpsc_ups_settings['DropoffType'] ) ) { 
  126. $sel2_drop = '01'; 
  127. } else { 
  128. $sel2_drop = $wpsc_ups_settings['DropoffType']; 
  129. ?> 
  130. <tr> 
  131. <td><?php _e( 'Dropoff Type', 'wpsc' ); ?></td> 
  132. <td> 
  133. <script type="text/javascript"> 
  134. function checkDropValue () { 
  135. var val = jQuery("#drop_type option:selected").val(); 
  136. if (val == "11") { 
  137. jQuery("#cust_type").removeAttr("disabled"); 
  138. } else { 
  139. jQuery("#cust_type").attr("disabled", true); 
  140. </script> 
  141. <select id='drop_type' name='wpsc_ups_settings[DropoffType]' onChange='checkDropValue()' > 
  142. <?php foreach ( array_keys( (array) $this->drop_types ) as $dkey ): ?> 
  143. <option value="<?php esc_attr_e( $dkey ); ?>" <?php selected( $dkey, $sel2_drop ); ?> > 
  144. <?php echo( $this->drop_types[$dkey] ); ?> 
  145. </option> 
  146. <?php endforeach; ?> 
  147. </select> 
  148. </td> 
  149. </tr> 
  150.  
  151. <?php 
  152. $sel3_drop = ''; 
  153. if ( empty( $wpsc_ups_settings['CustomerType'] ) ) { 
  154. $sel3_drop = '01'; 
  155. } else { 
  156. $sel3_drop = $wpsc_ups_settings['CustomerType']; 
  157. ?> 
  158. <tr> 
  159. <td><?php _e( 'Customer Type', 'wpsc' ); ?></td> 
  160. <td> 
  161. <select id='cust_type' name='wpsc_ups_settings[CustomerType]' <?php disabled( $wpsc_ups_settings['DropoffType'] != '11' ); ?> > 
  162. <?php foreach( array_keys( $this->cust_types ) as $dkey ): ?> 
  163. <option value="<?php esc_attr_e( $dkey ); ?>" <?php selected( $sel3_drop == $dkey ); ?> > 
  164. <?php echo( $this->cust_types[$dkey] ); ?> 
  165. </option> 
  166. <?php endforeach; ?> 
  167. </select> 
  168. </td> 
  169. </tr> 
  170.  
  171. <tr> 
  172. <td><?php _e( 'Packaging', 'wpsc' ); ?></td> 
  173. <td> 
  174. <select name='wpsc_ups_settings[48_container]'> 
  175. <?php foreach ( $packaging_options as $key => $name ): ?> 
  176. <option value='<?php esc_attr_e( $key ); ?>' <?php selected( $key == $wpsc_ups_settings['48_container'] );?>> 
  177. <?php esc_html_e( $name ); ?> 
  178. </option> 
  179. <?php endforeach; ?> 
  180. </select> 
  181. </td> 
  182. </tr> 
  183.  
  184. <tr> 
  185. <td><?php _e( 'Shipping Settings', 'wpsc' ); ?></td> 
  186. <td> 
  187. <input type="checkbox" id="ups_env_test" name="wpsc_ups_settings[upsenvironment]" value="1" <?php checked( 1, isset( $wpsc_ups_settings['upsenvironment'] ) && (bool) $wpsc_ups_settings['upsenvironment'] ); ?> /> 
  188. <label for="ups_env_test" ><?php _e( 'Use Testing Environment', 'wpsc' ); ?></label> 
  189. <br /> 
  190. <input type="checkbox" id="ups_negotiated_rates" name="wpsc_ups_settings[ups_negotiated_rates]" value="1" <?php checked( 1, isset( $wpsc_ups_settings['ups_negotiated_rates'] ) && (bool) $wpsc_ups_settings['ups_negotiated_rates'] ); ?> /> 
  191. <label for="ups_negotiated_rates" ><?php _e( 'Show UPS negotiated rates', 'wpsc' ); ?> *</label> 
  192. <br /> 
  193. <input type="checkbox" id="ups_insured_shipment" name="wpsc_ups_settings[insured_shipment]" value="1" <?php checked( 1, isset( $wpsc_ups_settings['insured_shipment'] ) && (bool) $wpsc_ups_settings['insured_shipment'] ); ?> /> 
  194. <label for="ups_insured_shipment" ><?php _e( 'Insure shipment against cart total', 'wpsc' ); ?> *</label> 
  195. <br /> 
  196. <input type="checkbox" id="ups_singular_shipping" name="wpsc_ups_settings[singular_shipping]" value="1" <?php checked( 1, isset( $wpsc_ups_settings['singular_shipping'] ) && (bool) $wpsc_ups_settings['singular_shipping'] ); ?> /> 
  197. <label for="ups_singular_shipping" ><?php _e( 'Singular Shipping', 'wpsc' ); ?> *</label> 
  198. <p class='description'><?php _e( 'Rate each quantity of items in a cart as its own package using dimensions on product', 'wpsc' ); ?></p> 
  199. <input type="checkbox" id="ups_intl_rate" name="wpsc_ups_settings[intl_rate]" value="1" <?php checked( 1, isset( $wpsc_ups_settings['intl_rate'] ) && (bool) $wpsc_ups_settings['intl_rate'] ); ?> /> 
  200. <label for="ups_intl_rate" ><?php _e( 'Disable International Shipping', 'wpsc' ); ?></label> 
  201. <p class='description'><?php _e( 'No shipping rates will be displayed if the shipment destination country is different than your base country/region.', 'wpsc' ); ?></p> 
  202. </td> 
  203. </tr> 
  204.  
  205. <?php 
  206. ksort( $this->Services ); 
  207. $first = false; 
  208. ?> 
  209. <tr> 
  210. <td><?php _e( 'UPS Preferred Services', 'wpsc' ); ?></td> 
  211. <td> 
  212. <div class="ui-widget-content multiple-select"> 
  213. <?php foreach( array_keys( $this->Services ) as $service ): ?> 
  214. <input type="checkbox" id="wps_ups_srv_<?php esc_attr_e( $service ); ?>" name="wpsc_ups_services[]" value="<?php esc_attr_e( $service ); ?>" <?php checked( is_array( $wpsc_ups_services ) && ( array_search( $service, $wpsc_ups_services ) !== false ) ); ?> /> 
  215. <label for="wps_ups_srv_<?php esc_attr_e( $service); ?>"><?php esc_html_e( $this->Services[$service] ); ?></label><br /> 
  216. <?php endforeach; ?> 
  217. </div> 
  218. <p class='description'><?php _e( 'Note: All services used if no services selected', 'wpsc' ); ?></p> 
  219. </td> 
  220. </tr> 
  221.  
  222. <tr> 
  223. <td colspan='2'><strong><?php _e( 'My UPS', 'wpsc' ); ?></strong></td> 
  224. </tr> 
  225. <tr> 
  226. <td><?php _e( 'Account Number', 'wpsc' ); ?> *</td> 
  227. <td> 
  228. <input type="text" name='wpsc_ups_settings[upsaccount]' value="<?php esc_attr_e( $wpsc_ups_settings['upsaccount'] ); ?>" /> 
  229. </td> 
  230. </tr> 
  231. <tr> 
  232. <td><?php _e( 'Username', 'wpsc' ); ?></td> 
  233. <td> 
  234. <input type="text" name='wpsc_ups_settings[upsusername]' value="<?php esc_attr_e( base64_decode( $wpsc_ups_settings['upsusername'] ) ); ?>" /> 
  235. </td> 
  236. </tr> 
  237. <tr> 
  238. <td><?php _e( 'Password', 'wpsc' ); ?></td> 
  239. <td> 
  240. <input type="password" name='wpsc_ups_settings[upspassword]' value="<?php esc_attr_e( base64_decode( $wpsc_ups_settings['upspassword'] ) ); ?>" /> 
  241. </td> 
  242. </tr> 
  243. <tr> 
  244. <td><?php _e( 'UPS XML API Key', 'wpsc' ); ?></td> 
  245. <td> 
  246. <input type="text" name='wpsc_ups_settings[upsid]' value="<?php esc_attr_e( base64_decode( $wpsc_ups_settings['upsid'] ) ); ?>" /> 
  247. <p class='description'><?php printf( __( "Don't have an API login/ID? <a href='%s' target='_blank'>Sign up for My UPS</a>", 'wpsc' ), esc_url( "https://www.ups.com/upsdeveloperkit?loc=en_US" ) ); ?></p> 
  248. </td> 
  249. </tr> 
  250. <tr> 
  251. <td colspan='2'> 
  252. <p class='description'><?php _e( '* For Negotiated rates, you must enter a UPS account number and select "Show UPS negotiated rates" ', 'wpsc' ); ?></p> 
  253. <p class='description'><?php printf( __( "For more help configuring UPS, please <a href='%s'>read our documentation</a>", 'wpsc' ), esc_url( 'http://docs.wpecommerce.org/wiki/documentation/shipping/ups' ) ); ?></p> 
  254. </td> 
  255. </tr> 
  256. </table></td></tr> 
  257. <?php 
  258. // End new Code 
  259. return ob_get_clean(); 
  260.  
  261. function submit_form() { 
  262. /** This function is called when the user hit "submit" in the 
  263. * UPS settings area under Shipping to update the setttings. 
  264. */ 
  265. if (isset( $_POST['wpsc_ups_settings'] ) && !empty( $_POST['wpsc_ups_settings'] ) ) { 
  266. if ( isset( $_POST['wpsc_ups_services'] ) ) { 
  267. $wpsc_ups_services = $_POST['wpsc_ups_services']; 
  268. update_option('wpsc_ups_services', $wpsc_ups_services); 
  269. $temp = stripslashes_deep( $_POST['wpsc_ups_settings'] ); 
  270. // base64_encode the information so it isnt stored as plaintext. 
  271. // base64 is by no means secure but without knowing if the server 
  272. // has mcrypt installed what can you do really? 
  273. $temp['upsusername'] = base64_encode( $temp['upsusername'] ); 
  274. $temp['upspassword'] = base64_encode( $temp['upspassword'] ); 
  275. $temp['upsid'] = base64_encode( $temp['upsid'] ); 
  276.  
  277. update_option('wpsc_ups_settings', $temp); 
  278. return true; 
  279.  
  280. function array2xml( $data ) { 
  281. $xml = ""; 
  282. if ( is_array( $data ) ) { 
  283. foreach( $data as $key => $value ) { 
  284. $xml .= "<" . trim( $key ) . ">"; 
  285. $xml .= $this->array2xml($value); 
  286. $xml .= "</" . trim( $key ) . ">"; 
  287. } else if ( is_bool( $data ) ) { 
  288. if ( $data ) { 
  289. $xml = "true\n"; 
  290. } else { 
  291. $xml = "false\n"; 
  292. } else { 
  293. $xml = trim( $data ) . "\n"; 
  294. return $xml; 
  295.  
  296. private function _is_large( &$pack, $package ) { 
  297. $maximum = 165; // in inches 
  298. $large_floor = 130; // in inches 
  299. $calc_total=(round($package->length)+(2*round($package->width))+(2*round($package->height))); //see http://www.ups.com/content/us/en/resources/prepare/oversize.html. 
  300. if ( $calc_total > $maximum || round( $package->length ) > 108 ) { //see http://www.ups.com/content/us/en/resources/prepare/oversize.html. 
  301. throw new Exception( "Package dimensions exceed non-freight limits" ); 
  302. } elseif ( $calc_total > $large_floor ) { 
  303. $pack["LargePackageIndicator"] = ""; 
  304.  
  305. private function _insured_value( &$pack, $package, $args ) { 
  306. $monetary_value = $package->value; 
  307. if ( $package->insurance === TRUE ) { 
  308. if ( $package->insured_amount ) { 
  309. $monetary_value = $package->insured_amount; 
  310. $pack["PackageServiceOptions"]["InsuredValue"] = array( 
  311. "CurrencyCode" => $args["currency"],  
  312. "MonetaryValue" => $package->insured_amount 
  313. ); 
  314.  
  315. private function _declared_value( &$pack, $package, $args ) { 
  316. $pack["PackageServiceOptions"]["DeclaredValue"] = array( 
  317. "CurrencyCode" => $args["currency"],  
  318. "MonetaryValue" => $package->value //Per package value, not total value 
  319. ); 
  320.  
  321. private function _build_shipment( &$Shipment, $args ) { 
  322.  
  323. $cart_shipment = apply_filters( 'wpsc_the_shipment', $this->shipment, $args ); //Filter to allow reprocessing shipment packages. 
  324.  
  325. foreach ( $cart_shipment->packages as $package ) { 
  326. $pack = array( 
  327. "PackagingType" => array( 
  328. "Code" => "02" 
  329. ),  
  330. "Dimensions" => array( 
  331. "UnitOfMeasurement" => array( 
  332. "Code" => "IN" 
  333. ),  
  334. "Length" => $package->length,  
  335. "Width" => $package->width,  
  336. "Height" => $package->height 
  337. ),  
  338. "PackageWeight"=>array( 
  339. "UnitOfMeasurement"=>array( 
  340. "Code" => "LBS" 
  341. ),  
  342. "Weight" => $package->weight 
  343. ); // End Package 
  344. // handle if the package is "large" or not (UPS standard) 
  345. $this->_is_large($pack, $package); 
  346. $this->_insured_value($pack, $package, $args); 
  347. $this->_declared_value($pack, $package, $args); 
  348. $Shipment .= $this->array2xml(array("Package"=>$pack)); 
  349. } // End for each package in shipment 
  350.  
  351. private function _buildRateRequest( $args ) { 
  352. // Vars is an array 
  353. // $RateRequest, $RatePackage, $RateCustomPackage, $RateRequestEnd 
  354. // Are defined in ups_data.php that is included below if not 
  355. // done so by instantiating class ... shouldnt ever need to 
  356. // Always start of with this, it includes the auth block 
  357. $REQUEST = "<?xml version=\"1.0\"?>\n 
  358. <AccessRequest xml:lang=\"en-US\">\n"; 
  359.  
  360. $access = array( 
  361. "AccessLicenseNumber" => base64_decode( $args['api_id'] ), // UPS API ID# 
  362. "UserId" => base64_decode( $args['username'] ), // UPS API Username 
  363. "Password" => base64_decode( $args['password'] ) // UPS API Password 
  364. ); 
  365.  
  366. $REQUEST .= $this->array2xml( $access ); 
  367. $REQUEST .= "</AccessRequest>\n"; 
  368. $REQUEST .= "<RatingServiceSelectionRequest xml:lang=\"en-US\">\n"; 
  369.  
  370. // By Default we will shop. Shop when you do not have a service type 
  371. // and you want to get a set of services and rates back! 
  372. $RequestType = "Shop"; 
  373. // If service type is set we cannot shop so instead we Rate! 
  374. if ( isset( $args["service"] ) ) { 
  375. $RequestType = "Rate"; 
  376.  
  377. $RatingServiceRequest = array( 
  378. "Request" => array( 
  379. "TransactionReference" => array( 
  380. "CustomerContext" => "Rate Request",  
  381. "XpciVersion" => "1.0001" 
  382. ),  
  383. "RequestAction" => "Rate",  
  384. "RequestOption" => $RequestType 
  385. ); 
  386.  
  387. // Set the dropoff code 
  388. $dropCode = ( array_key_exists( 'DropoffType', $args ) ) ? $args['DropoffType'] : '01'; 
  389. $PickupType = array( 
  390. "PickupType" => array( 
  391. "Code" => $dropCode 
  392. ); 
  393.  
  394. $REQUEST .= $this->array2xml( $PickupType ); 
  395.  
  396. if ( $dropCode == "11" && $args['shipr_ccode'] == "US" ) { 
  397. // Set the request code 
  398. $CustCode = ( array_key_exists( 'CustomerType', $args ) ) ? $args['CustomerType'] : '01'; 
  399. $CustomerType = array( 
  400. "CustomerClassification" => array( 
  401. "Code"=>$CustCode 
  402. ); 
  403. $REQUEST .= $this->array2xml( $CustomerType ); 
  404.  
  405. // Set up Shipment Node 
  406. $Shipment = ""; 
  407.  
  408. // Shipper Address (billing) 
  409. $Shipper = array( 
  410. "Address" => array( 
  411. "StateProvinceCode" => $args['shipr_state'],  
  412. "PostalCode" => $args['shipr_pcode'], // The shipper Postal Code 
  413. "CountryCode" => $args['shipr_ccode'] 
  414. ); 
  415.  
  416. // Negotiated Rates 
  417. if ( array_key_exists( 'negotiated_rates', $args ) ) { 
  418. if ( $args['negotiated_rates'] == '1' && ! empty( $args['account_number'] ) ) { 
  419. $Shipper["ShipperNumber"] = $args['account_number']; 
  420.  
  421. // If the city is configured use it 
  422. if ( array_key_exists( 'shipr_city', $args ) ) { 
  423. if ( ! empty( $args['shipr_city'] ) ) { 
  424. $Shipper["Address"]["City"] = $args["shipr_city"]; 
  425.  
  426. $Shipment .= $this->array2xml( array("Shipper" => $Shipper ) ); 
  427.  
  428. // The physical address the shipment is from (normally the same as billing) 
  429. $ShipFrom = array( 
  430. "Address" => array( 
  431. "StateProvinceCode" => $args['shipf_state'],  
  432. "PostalCode" => $args['shipf_pcode'], // The shipper Postal Code 
  433. "CountryCode" => $args['shipf_ccode'] 
  434. )); 
  435.  
  436. // If the city is configured use it 
  437. if ( array_key_exists( 'shipf_city', $args ) ) { 
  438. if ( ! empty( $args['shipf_city'] ) ) { 
  439. $ShipFrom["Address"]["City"] = $args["shipf_city"]; 
  440.  
  441. $Shipment .= $this->array2xml( array( "ShipFrom" => $ShipFrom ) ); 
  442.  
  443. $ShipTo = array( 
  444. "Address" => array( 
  445. "StateProvinceCode" => $args['dest_state'], // The Destination State 
  446. "PostalCode" => $args['dest_pcode'], // The Destination Postal Code 
  447. "CountryCode" => $args['dest_ccode'], // The Destination Country 
  448. //"ResidentialAddress"=>"1" 
  449. ); 
  450.  
  451. if ( $args['residential'] == '1' ) { //ResidentialAddressIndicator orig - Indicator 
  452. $ShipTo["Address"]["ResidentialAddressIndicator"] = "1"; 
  453.  
  454. $Shipment .= $this->array2xml( array( "ShipTo" => $ShipTo ) ); 
  455.  
  456. // If there is a specific service being requested then 
  457. // we want to pass the service into the XML 
  458. if ( isset( $args["service"] ) ) { 
  459. $Shipment .= $this->array2xml( array( "Service" => array( "Code" => $args['service'] ) ) ); 
  460.  
  461. // Include this only if you want negotiated rates 
  462. if ( array_key_exists( 'negotiated_rates', $args ) ) { 
  463. if ( $args['negotiated_rates'] == "1" ) { 
  464. $Shipment .= $this->array2xml( array( "RateInformation" => array( "NegotiatedRatesIndicator" => "" ) ) ); 
  465.  
  466. if ( (boolean) $args["singular_shipping"] ) { 
  467. $this->_build_shipment( $Shipment, $args ); 
  468. } else { 
  469. $package = array( 
  470. "Package" => array( 
  471. "PackagingType" => array( 
  472. "Code" => $args['packaging'] 
  473. ),  
  474. "PackageWeight" => array( 
  475. "UnitOfMeasurement" => array( 
  476. "Code" => $args['units'] 
  477. ),  
  478. "Weight" => $args["weight"] 
  479. ); 
  480. if ( (boolean) $args["insured_shipment"] ) { 
  481. $package["PackageServiceOptions"] = array( 
  482. "InsuredValue"=> array( 
  483. "CurrencyCode" => $args["currency"],  
  484. "MonetaryValue" => $args["cart_total"] 
  485. ); 
  486.  
  487. $Shipment .= $this->array2xml( $package ); 
  488.  
  489. // Set the structure for the Shipment Node 
  490. $RatingServiceRequest["Shipment"] = $Shipment; 
  491.  
  492. $REQUEST .= $this->array2xml( $RatingServiceRequest ); 
  493. $REQUEST .= "</RatingServiceSelectionRequest>"; 
  494.  
  495. // Return the final XML document as a string to be used by _makeRateRequest 
  496. return $REQUEST; 
  497.  
  498. private function _makeRateRequest( $message ) { 
  499. // Make the XML request to the server and retrieve the response 
  500. $ch = curl_init(); 
  501.  
  502. curl_setopt( $ch, CURLOPT_URL, $this->service_url ); 
  503. curl_setopt( $ch, CURLOPT_POST, 1 ); 
  504. curl_setopt( $ch, CURLOPT_POSTFIELDS, $message ); 
  505. curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1); 
  506.  
  507. $data = curl_exec( $ch ); 
  508. curl_close( $ch ); 
  509. return $data; 
  510.  
  511. public function futureDate( $interval ) { 
  512. //Wed Apr 7 
  513. date_default_timezone_set( 'America/Los_Angeles' ); 
  514. $timestamp = date( 'c' ); 
  515. $hour = date( "G" ); 
  516. if ( (int) $hour >= 3 ) { 
  517. $interval += 1; 
  518.  
  519. $date = date( "Y-m-d" ); 
  520. $interval = " +$interval day"; 
  521. $final = date( "D M j", strtotime( date( "Y-m-d", strtotime( $date ) ) . $interval ) ); 
  522. $test = explode(" ", $final); 
  523.  
  524. if ( $test[0] == "Sat" ) { 
  525. return $this->futureDate( $interval + 2 ); 
  526. } else if ( $test[0] == "Sun" ) { 
  527. return $this->futureDate( $interval + 1 ); 
  528. return $final; 
  529.  
  530. private function _parseQuote( $raw ) { 
  531. global $wpdb; 
  532.  
  533. $config = get_option( 'wpsc_ups_settings', array() ); 
  534. $debug = ( array_key_exists( 'upsenvironment', $config) ) ? $config['upsenvironment'] : ""; 
  535.  
  536. $rate_table = array(); 
  537. $wpsc_ups_services = get_option( "wpsc_ups_services" ); 
  538. // Initialize a DOM using the XML passed in! 
  539. $objDOM = new DOMDocument(); 
  540. if ( $raw != '' ) { 
  541. $objDOM->loadXML( $raw ); 
  542.  
  543. // Get the <ResponseStatusCode> from the UPS XML 
  544. $getStatusNode = $objDOM->getElementsByTagName( "ResponseStatusCode" ); 
  545. // Get the value of the error code, 1 == No Error, 0 == Error !!! 
  546. $statusCode = $getStatusNode->item( 0 )->nodeValue; 
  547.  
  548. if ( $statusCode == "0" ) { 
  549. // Usually I dont leave debug stuff in but this is handy stuff!! 
  550. // it will print out the error message returned by UPS! 
  551. if ( $debug == "1" ) { 
  552. $getErrorDescNode = $objDOM->getElementsByTagName( "ErrorDescription" ); 
  553. $ErrorDesc = $getErrorDescNode->item( 0 )->nodeValue; 
  554. echo "<br />Error : " . $ErrorDesc . "<br />"; 
  555. return false; 
  556. } else { 
  557. $RateBlocks = $objDOM->getElementsByTagName( 'RatedShipment' ); 
  558. foreach ( $RateBlocks as $rate_block ) { 
  559. // Get the <Service> Node from the XML chunk 
  560. $getServiceNode = $rate_block->getElementsByTagName( 'Service' ); 
  561. $serviceNode = $getServiceNode->item( 0 ); 
  562.  
  563. // Get the <Code> Node from the <Service> chunk 
  564. $getServiceCodeNode = $serviceNode->getElementsByTagName( 'Code' ); 
  565. // Get the value from <Code> 
  566. $serviceCode = $getServiceCodeNode->item( 0 )->nodeValue; 
  567. $go = true; 
  568. $price = ''; 
  569. $time = ''; 
  570.  
  571. //if (array_key_exists('ups_negotiated_rates', $config)) { 
  572. $getNegotiatedRateNode = $rate_block->getElementsByTagName( 'NegotiatedRates' ); 
  573. if ( $getNegotiatedRateNode ) { 
  574. $negotiatedRateNode = $getNegotiatedRateNode->item( 0 ); 
  575. if ( $negotiatedRateNode ) { 
  576. $getNetSummaryNode = $negotiatedRateNode->getElementsByTagName( 'NetSummaryCharges' ); 
  577. $netSummaryNode = $getNetSummaryNode->item( 0 ); 
  578.  
  579. $getGrandTotalNode = $netSummaryNode->getElementsByTagName( 'GrandTotal' ); 
  580. $grandTotalNode = $getGrandTotalNode->item( 0 ); 
  581.  
  582. $getMonetaryNode = $grandTotalNode->getElementsByTagName( 'MonetaryValue' ); 
  583. $monetaryNode = $getMonetaryNode->item( 0 )->nodeValue; 
  584. if ( ! empty( $monetaryNode ) ) { 
  585. $go = false; 
  586. $price = $monetaryNode; 
  587.  
  588. // Get the <TotalCharges> Node from the XML chunk 
  589. $getChargeNodes = $rate_block->getElementsByTagName( 'TotalCharges' ); 
  590. $chargeNode = $getChargeNodes->item( 0 ); 
  591.  
  592. // Get the <CurrencyCode> from the <TotalCharge> chunk 
  593. $getCurrNode = $chargeNode->getElementsByTagName( 'CurrencyCode' ); 
  594.  
  595. // Get the value of <CurrencyCode> 
  596. $currCode = $getCurrNode->item( 0 )->nodeValue; 
  597.  
  598. if ( $go == true ) { 
  599. // Get the <MonetaryValue> from the <TotalCharge> chunk 
  600. $getMonetaryNode = $chargeNode->getElementsByTagName( 'MonetaryValue' ); 
  601. // Get the value of <MonetaryValue> 
  602. $price = $getMonetaryNode->item( 0 )->nodeValue; 
  603. // If there are any services specified in the admin area 
  604. // this will check that list and pass on adding any services that 
  605. // are not explicitly defined. 
  606. if ( ! empty( $wpsc_ups_services ) ) { 
  607. if ( is_array( $wpsc_ups_services ) ) { 
  608. if ( array_search( $serviceCode, (array) $wpsc_ups_services ) === false ) { 
  609. continue; 
  610. } else if ( $wpsc_ups_services != $serviceCode ) { 
  611. continue; 
  612. if ( array_key_exists( $serviceCode, (array) $this->Services ) ) { 
  613. $rate_table[ $this->Services[ $serviceCode ] ] = array( $currCode, $price ); 
  614. } // End foreach rated shipment block 
  615. // Reverse sort the rate selection so it is cheapest first! 
  616. if ( ! empty( $rate_table ) ) { 
  617. asort( $rate_table ); 
  618. return $rate_table; 
  619.  
  620. private function _formatTable( $services, $currency = false ) { 
  621. /** The checkout template expects the array to be in a certain 
  622. * format. This function will iterate through the provided 
  623. * services array and format it for use. During the loop 
  624. * we take advantage of the loop and translate the currency 
  625. * if necessary based off of what UPS tells us they are giving us 
  626. * for currency and what is set for the main currency in the settings 
  627. * area 
  628. */ 
  629. $converter = null; 
  630. if ( $currency ) { 
  631. $converter = new CURRENCYCONVERTER(); 
  632. $finalTable = array(); 
  633. foreach ( array_keys( $services ) as $service ) { 
  634. if ( $currency != false && $currency != $services[ $service ][0] ) { 
  635. $temp = $services[ $service ][1]; 
  636. $services[ $service ][1] = $converter->convert( 
  637. $services[ $service ][1],  
  638. $currency,  
  639. $services[ $service ][0] 
  640. ); 
  641. $finalTable[ $service ] = $services[ $service ][1]; 
  642. return $finalTable; 
  643.  
  644. function getQuote() { 
  645. global $wpdb, $wpec_ash, $wpsc_cart, $wpec_ash_tools; 
  646. // Arguments array for various functions to use 
  647. $args = array(); 
  648.  
  649. $args['dest_ccode'] = wpsc_get_customer_meta( 'shippingcountry' ); 
  650.  
  651. // Get the ups settings from the ups account info page (Shipping tab) 
  652. $wpsc_ups_settings = get_option( 'wpsc_ups_settings', array() ); 
  653.  
  654. //Disable International Shipping. Default: Enabled, as it currently is. 
  655. $args['intl_rate'] = isset( $wpsc_ups_settings['intl_rate'] ) && ! empty( $wpsc_ups_settings['intl_rate'] ) ? FALSE : TRUE; 
  656. if ( ! $args['intl_rate'] && $args['dest_ccode'] != get_option( 'base_country' ) ) { 
  657. return array(); 
  658.  
  659. // Destination zip code 
  660. $args['dest_pcode'] = (string) wpsc_get_customer_meta( 'shippingpostcode' ); 
  661.  
  662. if ( ! is_object( $wpec_ash_tools ) ) { 
  663. $wpec_ash_tools = new ASHTools(); 
  664.  
  665. if ( empty( $args['dest_pcode'] ) && $wpec_ash_tools->needs_post_code( $args['dest_ccode'] ) ) { 
  666. // We cannot get a quote without a zip code so might as well return! 
  667. return array(); 
  668.  
  669. // Get the total weight from the shopping cart 
  670. $args['weight'] = wpsc_cart_weight_total(); 
  671. if ( empty( $args['weight'] ) ) { 
  672. return array(); 
  673.  
  674. $args['dest_state'] = ''; 
  675.  
  676. $wpsc_country = new WPSC_Country( wpsc_get_customer_meta( 'shippingcountry' ) ); 
  677.  
  678. if ( $wpsc_country->has_regions() ) { 
  679. $wpsc_region = $wpsc_country->get_region( wpsc_get_customer_meta( 'shippingregion' ) ); 
  680. if ( is_a( $wpsc_region, 'WPSC_Region' ) ) { 
  681. $args['dest_state'] = $wpsc_region->get_code(); 
  682.  
  683. if ( empty ( $args['dest_state'] ) ) { 
  684. $args['dest_state'] = wpsc_get_customer_meta( 'shippingstate' ); 
  685.  
  686. if ( ! is_object( $wpec_ash ) ) { 
  687. $wpec_ash = new ASH(); 
  688.  
  689. $shipping_cache_check['state'] = $args['dest_state']; //The destination is needed for cached shipment check. 
  690. $shipping_cache_check['country'] = $args['dest_ccode']; 
  691. $shipping_cache_check['zipcode'] = $args['dest_pcode']; 
  692.  
  693. $this->shipment = $wpec_ash->get_shipment(); 
  694. $this->shipment->set_destination( $this->internal_name, $shipping_cache_check ); //Set this shipment's destination. 
  695. $this->shipment->rates_expire = date( 'Y-m-d' ); 
  696. $args['shipper'] = $this->internal_name; 
  697.  
  698. $args['singular_shipping'] = ( array_key_exists( 'singular_shipping', $wpsc_ups_settings ) ) ? $wpsc_ups_settings['singular_shipping'] : '0'; 
  699. if ( $args['weight'] > 150 && ! (boolean) $args['singular_shipping'] ) { // This is where shipping breaks out of UPS if weight is higher than 150 LBS 
  700. $over_weight_txt = apply_filters( 
  701. 'wpsc_shipment_over_weight',  
  702. __( 'Your order exceeds the standard shipping weight limit. Please contact us to quote other shipping alternatives.', 'wpsc' ),  
  703. $args 
  704. ); 
  705. $shipping_quotes[$over_weight_txt] = 0; // yes, a constant. 
  706. $wpec_ash->cache_results( $this->internal_name, array( $shipping_quotes ), $this->shipment ); //Update shipment cache. 
  707. return array( $shipping_quotes ); 
  708.  
  709. $cache = $wpec_ash->check_cache( $this->internal_name, $this->shipment ); //And now, we're ready to check cache. 
  710.  
  711. // We do not want to spam UPS (and slow down our process) if we already 
  712. // have a shipping quote! 
  713. if ( count( $cache['rate_table'] ) >= 1 ) { 
  714. return $cache['rate_table']; 
  715.  
  716. // Final rate table 
  717. $rate_table = array(); 
  718.  
  719. // API Auth settings // 
  720. $args['username'] = ( array_key_exists( 'upsaccount', $wpsc_ups_settings ) ) ? $wpsc_ups_settings['upsusername'] : ''; 
  721. $args['password'] = ( array_key_exists( 'upspassword', $wpsc_ups_settings ) ) ? $wpsc_ups_settings['upspassword'] : ''; 
  722. $args['api_id'] = ( array_key_exists( 'upsid', $wpsc_ups_settings ) ) ? $wpsc_ups_settings['upsid'] : ''; 
  723. $args['account_number'] = ( array_key_exists( 'upsaccount', $wpsc_ups_settings ) ) ? $wpsc_ups_settings['upsaccount'] : ''; 
  724. $args['negotiated_rates'] = ( array_key_exists( 'ups_negotiated_rates', $wpsc_ups_settings ) ) ? $wpsc_ups_settings['ups_negotiated_rates'] : ''; 
  725. $args['residential'] = $wpsc_ups_settings['49_residential']; 
  726. $args['insured_shipment'] = ( array_key_exists( 'insured_shipment', $wpsc_ups_settings ) ) ? $wpsc_ups_settings['insured_shipment'] : '0'; 
  727. // What kind of pickup service do you use ? 
  728. $args['DropoffType'] = $wpsc_ups_settings['DropoffType']; 
  729. $args['packaging'] = $wpsc_ups_settings['48_container']; 
  730. // Preferred Currency to display 
  731. $currency_data = WPSC_Countries::get_currency_code( get_option( 'currency_type' ) ); 
  732. if ( ! empty( $currency_data ) ) { 
  733. $args['currency'] = $currency_data; 
  734. } else { 
  735. $args['currency'] = 'USD'; 
  736. // Shipping billing / account address 
  737. $region = new WPSC_Region( get_option( 'base_country' ), get_option( 'base_region' ) ); 
  738.  
  739. $args['shipr_state'] = $region->get_code(); 
  740. $args['shipr_city'] = get_option( 'base_city' ); 
  741. $args['shipr_ccode'] = get_option( 'base_country' ); 
  742. $args['shipr_pcode'] = get_option( 'base_zipcode' ); 
  743.  
  744. // Physical Shipping address being shipped from 
  745. $args['shipf_state'] = $args['shipr_state']; 
  746. $args['shipf_city'] = $args['shipr_city']; 
  747. $args['shipf_ccode'] = $args['shipr_ccode']; 
  748. $args['shipf_pcode'] = $args['shipr_pcode']; 
  749. $args['units'] = 'LBS'; 
  750.  
  751. $args['cart_total'] = $wpsc_cart->calculate_subtotal( true ); 
  752. $args = apply_filters( 'wpsc_shipment_data', $args, $this->shipment ); 
  753. if ( isset( $args['stop'] ) ) { //Do not get rates. 
  754. return array(); 
  755. // Build the XML request 
  756. $request = $this->_buildRateRequest( $args ); 
  757. // Now that we have the message to send ... Send it! 
  758. $raw_quote = $this->_makeRateRequest( $request ); 
  759. // Now we have the UPS response .. unfortunately its not ready 
  760. // to be viewed by normal humans ... 
  761. $quotes = $this->_parseQuote( $raw_quote ); 
  762. // If we actually have rates back from UPS we can use em! 
  763. if ( $quotes != false ) { 
  764. $rate_table = apply_filters( 'wpsc_rates_table', $this->_formatTable( $quotes, $args['currency'] ), $args, $this->shipment ); 
  765. } else { 
  766. if ( isset( $wpsc_ups_settings['upsenvironment'] ) ) { 
  767. echo '<strong>:: GetQuote ::DEBUG OUTPUT::</strong><br />'; 
  768. echo 'Arguments sent to UPS'; 
  769. print_r( $args ); 
  770. echo '<hr />'; 
  771. print $request; 
  772. echo '<hr />'; 
  773. echo 'Response from UPS'; 
  774. echo $raw_quote; 
  775. echo '</strong>:: GetQuote ::End DEBUG OUTPUT::'; 
  776.  
  777. $wpec_ash->cache_results( 
  778. $this->internal_name,  
  779. $rate_table,  
  780. $this->shipment 
  781. ); 
  782.  
  783. // return the final formatted array ! 
  784. return $rate_table; 
  785.  
  786. // Empty Function, this exists just b/c it is prototyped elsewhere 
  787. function get_item_shipping() {