5.x-1.x branch
Shipping quote module that interfaces with www.ups.com to get rates for small package shipments.
Coded by Lyle Mantooth
| Name | Description |
|---|---|
| theme_uc_ups_confirm_shipment | Display final shipment information for review. |
| theme_uc_ups_label_image | Display the shipping label for printing. |
| uc_ups_access_request | Return XML access request to be prepended to all requests to the UPS webservice. |
| uc_ups_admin_settings | UPS Online Tool settings. |
| uc_ups_admin_settings_validate | Validation handler for uc_ups_admin_settings. |
| uc_ups_configuration | Implementation of hook_configuration(). |
| uc_ups_confirm_shipment | Last chance for user to review shipment. |
| uc_ups_confirm_shipment_submit | Submit handler for uc_ups_confirm_shipment(). |
| uc_ups_form_alter | Implementation of hook_form_alter(). |
| uc_ups_fulfill_order | Shipment creation callback. |
| uc_ups_fulfill_order_submit | Submit handler for uc_ups_fulfill_order(). |
| uc_ups_fulfill_order_validate | Validation handler for uc_ups_fulfill_order(). |
| uc_ups_markup | Modify the rate received from UPS before displaying to the customer. |
| uc_ups_menu | Implementation of hook_menu(). |
| uc_ups_nodeapi | Implementation of hook_nodeapi(). |
| uc_ups_product_alter_validate | Validation handler for UPS product fields. |
| uc_ups_quote | Callback for retrieving a UPS shipping quote. |
| uc_ups_request_pickup | Construct an XML label and pickup request. |
| uc_ups_shipment_request | Construct an XML shippment request. |
| uc_ups_shipping_method | Implementation of Übercart's hook_shipping_method(). |
| uc_ups_shipping_quote | Construct an XML quote request. |
| uc_ups_shipping_type | Implementation of Übercart's hook_shipping_type(). |
| uc_ups_store_status | Implementation of Übercart's hook_store_status(). |
| uc_ups_void_shipment | |
| uc_ups_void_shipment_request | |
| _uc_ups_new_package | |
| _uc_ups_pkg_types | Convenience function to get UPS codes for their package types. |
| _uc_ups_service_list | Convenience function to get UPS codes for their services. |
- <?php
-
- /**
- * @file
- * Shipping quote module that interfaces with www.ups.com to get rates for small
- * package shipments.
- *
- * Coded by Lyle Mantooth
- */
-
- /******************************************************************************
- * Drupal Hooks *
- ******************************************************************************/
-
- /**
- * Implementation of hook_menu().
- */
- function uc_ups_menu($may_cache) {
- $items = array();
-
- if ($may_cache) {
- $items[] = array('path' => 'admin/store/settings/quotes/methods/ups',
- 'access' => user_access('configure quotes'),
- 'title' => t('UPS'),
- 'callback' => 'drupal_get_form',
- 'callback arguments' => 'uc_ups_admin_settings',
- 'type' => MENU_LOCAL_TASK,
- );
- }
- else {
- $items[] = array('path' => 'admin/store/orders/'. arg(3) .'/shipments/ups',
- 'access' => user_access('fulfill orders'),
- 'title' => t('UPS shipment'),
- 'callback' => 'drupal_get_form',
- 'callback arguments' => array('uc_ups_confirm_shipment', arg(3)),
- 'type' => MENU_CALLBACK,
- );
- $items[] = array('path' => 'admin/store/orders/'. arg(3) .'/shipments/labels/ups',
- 'access' => user_access('fulfill orders'),
- 'callback' => 'theme',
- 'callback arguments' => array('uc_ups_label_image'),
- 'type' => MENU_CALLBACK,
- );
- drupal_add_css(drupal_get_path('module', 'uc_ups') .'/uc_ups.css');
- }
-
- return $items;
- }
-
- /**
- * Implementation of hook_form_alter().
- *
- * Add package type to products.
- *
- * @see uc_product_form
- * @see uc_ups_product_alte_validate
- */
- function uc_ups_form_alter($form_id, &$form) {
- $node = $form['#node'];
- if (is_object($node) && $form_id == $node->type .'_node_form' && isset($form['base']['dimensions']) && in_array($node->type, module_invoke_all('product_types'))) {
- $enabled = variable_get('uc_quote_enabled', array());
- $weight = variable_get('uc_quote_method_weight', array('ups' => 0));
- $ups = array('#type' => 'fieldset',
- '#title' => t('UPS product description'),
- '#collapsible' => true,
- '#collapsed' => ($enabled['ups'] == false || uc_product_get_shipping_type($node) != 'small_package'),
- '#weight' => $weight['ups'],
- '#tree' => true,
- );
- $ups['pkg_type'] = array('#type' => 'select',
- '#title' => t('Package type'),
- '#options' => _uc_ups_pkg_types(),
- '#default_value' => $node->ups['pkg_type'] ? $node->ups['pkg_type'] : '02',
- );
- $form['shipping']['ups'] = $ups;
- if ($enabled['ups']) {
- $form['#validate']['uc_ups_product_alter_validate'] = array();
- }
- }
- }
-
- /**
- * Validation handler for UPS product fields.
- */
- function uc_ups_product_alter_validate($form_id, $form_values) {
- $enabled = variable_get('uc_quote_enabled', array());
- if ($form_values['shippable'] && ($form_values['shipping_type'] == 'small_package' || (empty($form_values['shipping_type']) && variable_get('uc_store_shipping_type', 'small_package') == 'small_package'))) {
- if ($form_values['ups']['pkg_type'] == '02' && (empty($form_values['length']) || empty($form_values['width']) || empty($form_values['height']))) {
- form_set_error('base][dimensions', t('Dimensions are required for custom packaging.'));
- }
- }
- }
-
- /**
- * Implementation of hook_nodeapi().
- */
- function uc_ups_nodeapi(&$node, $op) {
- if (in_array($node->type, module_invoke_all('product_types'))) {
- switch ($op) {
- case 'insert':
- case 'update':
- if (isset($node->ups)) {
- $ups_values = $node->ups;
- if (!$node->revision) {
- db_query("DELETE FROM {uc_ups_products} WHERE vid = %d", $node->vid);
- }
- db_query("INSERT INTO {uc_ups_products} (vid, nid, pkg_type) VALUES (%d, %d, '%s')",
- $node->vid, $node->nid, $ups_values['pkg_type']);
- }
- break;
- case 'load':
- if (uc_product_get_shipping_type($node) == 'small_package') {
- return array('ups' => db_fetch_array(db_query("SELECT * FROM {uc_ups_products} WHERE vid = %d", $node->vid)));
- }
- break;
- case 'delete':
- db_query("DELETE FROM {uc_ups_products} WHERE nid = %d", $node->nid);
- break;
- case 'delete revision':
- db_query("DELETE FROM {uc_ups_products} WHERE vid = %d", $node->vid);
- break;
- }
- }
- }
-
- /******************************************************************************
- * Workflow-ng Hooks *
- ******************************************************************************/
-
- /**
- * Implementation of hook_configuration().
- *
- * Connect the UPS quote action and event.
- */
- function uc_ups_configuration() {
- $enabled = variable_get('uc_quote_enabled', array());
- $configurations = array(
- 'uc_ups_get_quote' => array(
- '#label' => t('Shipping quote from UPS'),
- '#event' => 'get_quote_from_ups',
- '#module' => 'uc_ups',
- '#active' => $enabled['ups'],
- ),
- );
-
- $action = workflow_ng_use_action('uc_quote_action_get_quote', array(
- '#label' => t('Fetch a shipping quote'),
- ));
- $configurations['uc_ups_get_quote'] = workflow_ng_configure($configurations['uc_ups_get_quote'], $action);
-
- return $configurations;
- }
-
- /******************************************************************************
- * Übercart Hooks *
- ******************************************************************************/
-
- /**
- * Implementation of Übercart's hook_shipping_type().
- */
- function uc_ups_shipping_type() {
- $weight = variable_get('uc_quote_type_weight', array('small_package' => 0));
-
- $types = array();
- $types['small_package'] = array(
- 'id' => 'small_package',
- 'title' => t('Small packages'),
- 'weight' => $weight['small_package'],
- );
-
- return $types;
- }
-
- /**
- * Implementation of Übercart's hook_shipping_method().
- */
- function uc_ups_shipping_method() {
- $methods = array();
-
- $enabled = variable_get('uc_quote_enabled', array());
- $weight = variable_get('uc_quote_method_weight', array('ups' => 0));
- $methods['ups'] = array(
- 'id' => 'ups',
- 'module' => 'uc_ups',
- 'title' => t('UPS'),
- 'enabled' => $enabled['ups'],
- 'quote' => array(
- 'type' => 'small_package',
- 'callback' => 'uc_ups_quote',
- 'accessorials' => _uc_ups_service_list(),
- ),
- 'ship' => array(
- 'type' => 'small_package',
- 'callback' => 'uc_ups_fulfill_order',
- 'pkg_types' => _uc_ups_pkg_types(),
- ),
- 'cancel' => 'uc_ups_void_shipment',
- 'weight' => $weight['ups'],
- );
-
- return $methods;
- }
-
- /**
- * Implementation of Übercart's hook_store_status().
- *
- * Let the administrator know that the UPS account information has not been
- * filled out.
- */
- function uc_ups_store_status() {
- $messages = array();
- $access = variable_get('uc_ups_access_license', '') != '';
- $account = variable_get('uc_ups_shipper_number', '') != '';
- $user = variable_get('uc_ups_user_id', '') != '';
- $password = variable_get('uc_ups_password', '') != '';
- if ($access && $account && $user && $password) {
- $messages[] = array('status' => 'ok', 'title' => t('UPS Online Tools'),
- 'desc' => t('Information needed to access UPS Online Tools has been entered.'),
- );
- }
- else {
- $messages[] = array('status' => 'error', 'title' => t('UPS Online Tools'),
- 'desc' => t('More information is needed to access UPS Online Tools. Please enter it <a href="!url">here</a>.', array('!url' => url('admin/store/settings/quotes/methods/ups'))),
- );
- }
-
- return $messages;
- }
-
- /******************************************************************************
- * Menu Callbacks *
- ******************************************************************************/
-
- /**
- * UPS Online Tool settings.
- *
- * Record UPS account information neccessary to use the service. Allow testing
- * or production mode. Configure which UPS services are quoted to customers.
- *
- * @ingroup forms
- * @see uc_admin_settings_validate
- */
- function uc_ups_admin_settings() {
- $form = array();
-
- $form['uc_ups_access_license'] = array('#type' => 'textfield',
- '#title' => t('UPS OnLine Tools XML Access Key'),
- '#default_value' => variable_get('uc_ups_access_license', ''),
- '#required' => true,
- );
- $form['uc_ups_shipper_number'] = array('#type' => 'textfield',
- '#title' => t('UPS Shipper #'),
- '#description' => t('The 6-character string identifying your UPS account as a shipper.'),
- '#default_value' => variable_get('uc_ups_shipper_number', ''),
- '#required' => true,
- );
- $form['uc_ups_user_id'] = array('#type' => 'textfield',
- '#title' => t('UPS.com user ID'),
- '#default_value' => variable_get('uc_ups_user_id', ''),
- '#required' => true,
- );
- $form['uc_ups_password'] = array('#type' => 'password',
- '#title' => t('Password'),
- '#default_value' => variable_get('uc_ups_password', ''),
- );
- $form['uc_ups_connection_address'] = array('#type' => 'select',
- '#title' => t('Mode'),
- '#description' => t('Quotes and shipments requested in Testing mode will not be picked up or charged to your account.'),
- '#options' => array('https://wwwcie.ups.com/ups.app/xml/' => t('Testing'),
- 'https://www.ups.com/ups.app/xml/' => t('Production'),
- ),
- '#default_value' => variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/'),
- );
- $form['uc_ups_services'] = array('#type' => 'checkboxes',
- '#title' => t('UPS services'),
- '#default_value' => variable_get('uc_ups_services', _uc_ups_service_list()),
- '#options' => _uc_ups_service_list(),
- '#description' => t('Select the UPS services that are available to customers.'),
- );
- $form['uc_ups_pickup_type'] = array('#type' => 'select',
- '#title' => t('Pickup type'),
- '#options' => array(
- '01' => 'Daily Pickup',
- '03' => 'Customer Counter',
- '06' => 'One Time Pickup',
- '07' => 'On Call Air',
- '11' => 'Suggested Retail Rates',
- '19' => 'Letter Center',
- '20' => 'Air Service Center',
- ),
- '#default_value' => variable_get('uc_ups_pickup_type', '01'),
- );
- $form['uc_ups_classification'] = array('#type' => 'select',
- '#title' => t('UPS Customer classification'),
- '#options' => array(
- '01' => t('Wholesale'),
- '03' => t('Occasional'),
- '04' => t('Retail'),
- ),
- '#default_value' => variable_get('uc_ups_classification', '04'),
- '#description' => t('The kind of customer you are to UPS. For daily pickups the default is wholesale; for customer counter pickups the default is retail; for other pickups the default is occasional.'),
- );
- $form['uc_ups_negotiated_rates'] = array('#type' => 'radios',
- '#title' => t('Negotiated rates'),
- '#default_value' => variable_get('uc_ups_negotiated_rates', 0),
- '#options' => array(1 => t('Yes'), 0 => t('No')),
- '#description' => t('Is your UPS account receiving negotiated rates on shipments?'),
- );
- $form['uc_ups_residential_quotes'] = array('#type' => 'radios',
- '#title' => t('Assume UPS shipping quotes will be delivered to'),
- '#default_value' => variable_get('uc_ups_residential_quotes', 0),
- '#options' => array(
- 0 => t('Business locations'),
- 1 => t('Residential locations (extra fees)'),
- ),
- );
- $form['uc_ups_markup_type'] = array('#type' => 'select',
- '#title' => t('Markup type'),
- '#default_value' => variable_get('uc_ups_markup_type', 'percentage'),
- '#options' => array(
- 'percentage' => t('Percentage (%)'),
- 'multiplier' => t('Multiplier (×)'),
- 'currency' => t('Addition (!currency)', array('!currency' => variable_get('uc_currency_sign', '$'))),
- ),
- );
- $form['uc_ups_markup'] = array('#type' => 'textfield',
- '#title' => t('Shipping rate markup'),
- '#default_value' => variable_get('uc_ups_markup', '0'),
- '#description' => t('Markup shipping rate quote by currency amount, percentage, or multiplier.'),
- );
- $form['uc_ups_all_in_one'] = array('#type' => 'radios',
- '#title' => t('Product packages'),
- '#default_value' => variable_get('uc_ups_all_in_one', 1),
- '#options' => array(
- 0 => t('Each in its own package'),
- 1 => t('All in one'),
- ),
- '#description' => t('Indicate whether each product is quoted as shipping separately or all in one package.'),
- );
- $form['uc_ups_unit_system'] = array('#type' => 'select',
- '#title' => t('System of measurement'),
- '#default_value' => variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in')),
- '#options' => array(
- 'in' => t('British'),
- 'cm' => t('Metric'),
- ),
- '#description' => t('Choose the standard system of measurement for your country.'),
- );
- $form['uc_ups_insurance'] = array(
- '#type' => 'checkbox',
- '#title' => t('Package insurance'),
- '#default_value' => variable_get('uc_ups_insurance', TRUE),
- '#description' => t('When enabled, products are insured for their full value.'),
- );
-
- return system_settings_form($form);
- }
-
- /**
- * Validation handler for uc_ups_admin_settings.
- *
- * Require password only if it hasn't been set.
- */
- function uc_ups_admin_settings_validate($form_id, $form_values, $form) {
- $old_password = variable_get('uc_ups_password', '');
- if (!$form_values['uc_ups_password']) {
- if ($old_password) {
- form_set_value($form['uc_ups_password'], $old_password);
- }
- else {
- form_set_error('uc_ups_password', t('Password field is required.'));
- }
- }
- }
-
- /******************************************************************************
- * Module Functions *
- ******************************************************************************/
-
- /**
- * Return XML access request to be prepended to all requests to the UPS webservice.
- */
- function uc_ups_access_request() {
- $access = variable_get('uc_ups_access_license', '');
- $user = variable_get('uc_ups_user_id', '');
- $password = variable_get('uc_ups_password', '');
- return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
- <AccessRequest xml:lang=\"en-US\">
- <AccessLicenseNumber>$access</AccessLicenseNumber>
- <UserId>$user</UserId>
- <Password>$password</Password>
- </AccessRequest>
- ";
- }
-
- /**
- * Construct an XML quote request.
- *
- * @param $packages
- * Array of packages received from the cart.
- * @param $origin
- * Delivery origin address information.
- * @param $destination
- * Delivery destination address information.
- * @param $ups_service
- * UPS service code (refers to UPS Ground, Next-Day Air, etc.).
- * @return
- * RatingServiceSelectionRequest XML document to send to UPS
- */
- function uc_ups_shipping_quote($packages, $origin, $destination, $ups_service) {
- $store['name'] = variable_get('uc_store_name', NULL);
- $store['owner'] = variable_get('uc_store_owner', NULL);
- $store['email'] = variable_get('uc_store_email', NULL);
- $store['email_from'] = variable_get('uc_store_email', NULL);
- $store['phone'] = variable_get('uc_store_phone', NULL);
- $store['fax'] = variable_get('uc_store_fax', NULL);
- $store['street1'] = variable_get('uc_store_street1', NULL);
- $store['street2'] = variable_get('uc_store_street2', NULL);
- $store['city'] = variable_get('uc_store_city', NULL);
- $store['zone'] = variable_get('uc_store_zone', NULL);
- $store['postal_code'] = variable_get('uc_store_postal_code', NULL);
- $store['country'] = variable_get('uc_store_country', 840);
-
- $account = variable_get('uc_ups_shipper_number', '');
- $ua = explode(' ', $_SERVER['HTTP_USER_AGENT']);
- $user_agent = $ua[0];
-
- $services = _uc_ups_service_list();
- $service = array('code' => $ups_service, 'description' => $services[$ups_service]);
-
- $pkg_types = _uc_ups_pkg_types();
-
- $shipper_zone = uc_get_zone_code($store['zone']);
- $shipper_country = uc_get_country_data(array('country_id' => $store['country']));
- $shipper_country = $shipper_country[0]['country_iso_code_2'];
- $shipper_zip = $store['postal_code'];
- $shipto_zone = uc_get_zone_code($destination->zone);
- $shipto_country = uc_get_country_data(array('country_id' => $destination->country));
- $shipto_country = $shipto_country[0]['country_iso_code_2'];
- $shipto_zip = $destination->postal_code;
- $shipfrom_zone = uc_get_zone_code($origin->zone);
- $shipfrom_country = uc_get_country_data(array('country_id' => $origin->country));
- $shipfrom_country = $shipfrom_country[0]['country_iso_code_2'];
- $shipfrom_zip = $origin->postal_code;
-
- $ups_units = variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in'));
- switch ($ups_units) {
- case 'in':
- $units = 'LBS';
- $unit_name = 'Pounds';
- break;
- case 'cm':
- $units = 'KGS';
- $unit_name = 'Kilograms';
- break;
- }
-
- $shipment_weight = 0;
- $package_schema = '';
- foreach ($packages as $package) {
- $qty = $package->qty;
- for ($i = 0; $i < $qty; $i++) {
- $package_type = array('code' => $package->pkg_type, 'description' => $pkg_types[$package->pkg_type]);
- $package_schema .= "<Package>";
- $package_schema .= "<PackagingType>";
- $package_schema .= "<Code>". $package_type['code'] ."</Code>";
- //$package_schema .= "<Description>". $package_type['description'] ."</Description>";
- $package_schema .= "</PackagingType>";
- if ($package->pkg_type == '02' && $package->length && $package->width && $package->height) {
- if ($package->length < $package->width) {
- list($package->length, $package->width) = array($package->width, $package->length);
- }
- $package_schema .= "<Dimensions>";
- $package_schema .= "<UnitOfMeasurement>";
- $conversion = uc_weight_conversion($package->length_units, variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in')));
- $package_schema .= "<Code>". strtoupper(variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in'))) ."</Code>";
- $package_schema .= "</UnitOfMeasurement>";
- $package_schema .= "<Length>". number_format($package->length * $conversion, 2, '.', '') ."</Length>";
- $package_schema .= "<Width>". number_format($package->width * $conversion, 2, '.', '') ."</Width>";
- $package_schema .= "<Height>". number_format($package->height * $conversion, 2, '.', '') ."</Height>";
- $package_schema .= "</Dimensions>";
- }
- $size = $package->length * $conversion + 2 * $conversion * ($package->width + $package->height);
- switch ($ups_units) {
- case 'in':
- $conversion = uc_weight_conversion($package->weight_units, 'lb');
- break;
- case 'cm':
- $conversion = uc_weight_conversion($package->weight_units, 'kg');
- break;
- }
- $weight = max(1, $package->weight * $conversion);
- $shipment_weight += $weight;
- $package_schema .= "<PackageWeight>";
- $package_schema .= "<UnitOfMeasurement>";
- $package_schema .= "<Code>$units</Code>";
- $package_schema .= "<Description>$unit_name</Description>";
- $package_schema .= "</UnitOfMeasurement>";
- $package_schema .= "<Weight>". number_format($weight, 1, '.', '') ."</Weight>";
- $package_schema .= "</PackageWeight>";
- if ($size > 130 && $size <= 165) {
- $package_schema .= "<LargePackageIndicator/>";
- }
- if (variable_get('uc_ups_insurance', TRUE)) {
- $package_schema .= "<PackageServiceOptions>";
- $package_schema .= "<InsuredValue>";
- $package_schema .= "<CurrencyCode>". variable_get('uc_currency_code', 'USD') ."</CurrencyCode>";
- $package_schema .= "<MonetaryValue>". $package->price ."</MonetaryValue>";
- $package_schema .= "</InsuredValue>";
- $package_schema .= "</PackageServiceOptions>";
- }
- $package_schema .= "</Package>";
- }
- }
-
- $schema = uc_ups_access_request() ."
- <?xml version=\"1.0\" encoding=\"UTF-8\"?>
- <RatingServiceSelectionRequest xml:lang=\"en-US\">
- <Request>
- <TransactionReference>
- <CustomerContext>Complex Rate Request</CustomerContext>
- <XpciVersion>1.0001</XpciVersion>
- </TransactionReference>
- <RequestAction>Rate</RequestAction>
- <RequestOption>rate</RequestOption>
- </Request>
- <PickupType>
- <Code>". variable_get('uc_ups_pickup_type', '01') ."</Code>
- </PickupType>
- <CustomerClassification>
- <Code>". variable_get('uc_ups_classification', '04') ."</Code>
- </CustomerClassification>
- <Shipment>
- <Shipper>
- <ShipperNumber>". variable_get('uc_ups_shipper_number', '') ."</ShipperNumber>
- <Address>
- <City>". $store['city'] ."</City>
- <StateProvinceCode>$shipper_zone</StateProvinceCode>
- <PostalCode>$shipper_zip</PostalCode>
- <CountryCode>$shipper_country</CountryCode>
- </Address>
- </Shipper>
- <ShipTo>
- <Address>
- <StateProvinceCode>$shipto_zone</StateProvinceCode>
- <PostalCode>$shipto_zip</PostalCode>
- <CountryCode>$shipto_country</CountryCode>
- ";
- if (variable_get('uc_ups_residential_quotes', 0)) {
- $schema .= "<ResidentialAddressIndicator/>
- ";
- }
- $schema .= "</Address>
- </ShipTo>
- <ShipFrom>
- <Address>
- <StateProvinceCode>$shipfrom_zone</StateProvinceCode>
- <PostalCode>$shipfrom_zip</PostalCode>
- <CountryCode>$shipfrom_country</CountryCode>
- </Address>
- </ShipFrom>
- <ShipmentWeight>
- <UnitOfMeasurement>
- <Code>$units</Code>
- <Description>$unit_name</Description>
- </UnitOfMeasurement>
- <Weight>". number_format($shipment_weight, 1, '.', '') ."</Weight>
- </ShipmentWeight>
- <Service>
- <Code>{$service[code]}</Code>
- <Description>{$service[description]}</Description>
- </Service>
- ";
- $schema .= $package_schema;
- if (variable_get('uc_ups_negotiated_rates', false)) {
- $schema .= "<RateInformation>
- <NegotiatedRatesIndicator/>
- </RateInformation>";
- }
- $schema .= "</Shipment>
- </RatingServiceSelectionRequest>";
-
- return $schema;
- }
-
- /**
- * Construct an XML shippment request.
- *
- * @param $packages
- * Array of packages received from the cart.
- * @param $origin
- * Delivery origin address information.
- * @param $destination
- * Delivery destination address information.
- * @param $ups_service
- * UPS service code (refers to UPS Ground, Next-Day Air, etc.).
- * @return
- * ShipConfirm XML document to send to UPS
- */
- function uc_ups_shipment_request($packages, $origin, $destination, $ups_service) {
- $store['name'] = variable_get('uc_store_name', NULL);
- $store['owner'] = variable_get('uc_store_owner', NULL);
- $store['email'] = variable_get('uc_store_email', NULL);
- $store['email_from'] = variable_get('uc_store_email', NULL);
- $store['phone'] = variable_get('uc_store_phone', NULL);
- $store['fax'] = variable_get('uc_store_fax', NULL);
- $store['street1'] = variable_get('uc_store_street1', NULL);
- $store['street2'] = variable_get('uc_store_street2', NULL);
- $store['city'] = variable_get('uc_store_city', NULL);
- $store['zone'] = variable_get('uc_store_zone', NULL);
- $store['postal_code'] = variable_get('uc_store_postal_code', NULL);
- $store['country'] = variable_get('uc_store_country', 840);
-
- $account = variable_get('uc_ups_shipper_number', '');
- $ua = explode(' ', $_SERVER['HTTP_USER_AGENT']);
- $user_agent = $ua[0];
-
- $services = _uc_ups_service_list();
- $service = array('code' => $ups_service, 'description' => $services[$ups_service]);
-
- $pkg_types = _uc_ups_pkg_types();
-
- $shipper_zone = uc_get_zone_code($store['zone']);
- $shipper_country = uc_get_country_data(array('country_id' => $store['country']));
- $shipper_country = $shipper_country[0]['country_iso_code_2'];
- $shipper_zip = $store['postal_code'];
- $shipto_zone = uc_get_zone_code($destination->zone);
- $shipto_country = uc_get_country_data(array('country_id' => $destination->country));
- $shipto_country = $shipto_country[0]['country_iso_code_2'];
- $shipto_zip = $destination->postal_code;
- $shipfrom_zone = uc_get_zone_code($origin->zone);
- $shipfrom_country = uc_get_country_data(array('country_id' => $origin->country));
- $shipfrom_country = $shipfrom_country[0]['country_iso_code_2'];
- $shipfrom_zip = $origin->postal_code;
-
- $ups_units = variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in'));
-
- $package_schema = '';
- foreach ($packages as $package) {
- $qty = $package->qty;
- for ($i = 0; $i < $qty; $i++) {
- $package_type = array('code' => $package->pkg_type, 'description' => $pkg_types[$package->pkg_type]);
- $package_schema .= "<Package>";
- $package_schema .= "<PackagingType>";
- $package_schema .= "<Code>". $package_type['code'] ."</Code>";
- $package_schema .= "</PackagingType>";
- if ($package->pkg_type == '02' && $package->length && $package->width && $package->height) {
- if ($package->length < $package->width) {
- list($package->length, $package->width) = array($package->width, $package->length);
- }
- $package_schema .= "<Dimensions>";
- $package_schema .= "<UnitOfMeasurement>";
- $conversion = constant(strtoupper($package->length_units) .'_TO_'. strtoupper(variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in'))));
- $package_schema .= "<Code>". strtoupper(variable_get('uc_ups_unit_system', variable_get('uc_length_unit', 'in'))) ."</Code>";
- $package_schema .= "</UnitOfMeasurement>";
- $package_schema .= "<Length>". (floor($package->length * $conversion) + 1) ."</Length>";
- $package_schema .= "<Width>". (floor($package->width * $conversion) + 1) ."</Width>";
- $package_schema .= "<Height>". (floor($package->height * $conversion) + 1) ."</Height>";
- $package_schema .= "</Dimensions>";
- }
- $size = $package->length * $conversion + 2 * $conversion * ($package->width + $package->height);
- switch ($ups_units) {
- case 'in':
- $conversion = uc_weight_conversion($package->weight_units, 'lb');
- break;
- case 'cm':
- $conversion = uc_weight_conversion($package->weight_units, 'kg');
- break;
- }
- $weight = $package->weight * $conversion;
- $package_schema .= "<PackageWeight>";
- $package_schema .= "<UnitOfMeasurement>";
- $package_schema .= "<Code>$units</Code>";
- $package_schema .= "<Description>$unit_name</Description>";
- $package_schema .= "</UnitOfMeasurement>";
- $package_schema .= "<Weight>". number_format($weight, 1, '.', '') ."</Weight>";
- $package_schema .= "</PackageWeight>";
- if ($size > 130 && $size <= 165) {
- $package_schema .= "<LargePackageIndicator/>";
- }
- $package_schema .= "<PackageServiceOptions>";
- $package_schema .= "<InsuredValue>";
- $package_schema .= "<CurrencyCode>". variable_get('uc_currency_code', 'USD') ."</CurrencyCode>";
- $package_schema .= "<MonetaryValue>". number_format($package->price, 2, '.', '') ."</MonetaryValue>";
- $package_schema .= "</InsuredValue>";
- $package_schema .= "</PackageServiceOptions>";
- $package_schema .= "</Package>";
- }
- }
-
- $schema = uc_ups_access_request() ."
- <?xml version=\"1.0\" encoding=\"UTF-8\"?>
- <ShipmentConfirmRequest xml:lang=\"en-US\">
- <Request>
- <TransactionReference>
- <CustomerContext>Complex Rate Request</CustomerContext>
- <XpciVersion>1.0001</XpciVersion>
- </TransactionReference>
- <RequestAction>ShipConfirm</RequestAction>
- <RequestOption>validate</RequestOption>
- </Request>
- <Shipment>";
- $schema .= "<Shipper>";
- $schema .= "<Name>". $store['name'] ."</Name>";
- $schema .= "<ShipperNumber>". variable_get('uc_ups_shipper_number', '') ."</ShipperNumber>";
- if ($store['phone']) {
- $schema .= "<PhoneNumber>". $store['phone'] ."</PhoneNumber>";
- }
- if ($store['fax']) {
- $schema .= "<FaxNumber>". $store['fax'] ."</FaxNumber>";
- }
- if ($store['email']) {
- $schema .= "<EMailAddress>". $store['email'] ."</EMailAddress>";
- }
- $schema .= "<Address>";
- $schema .= "<AddressLine1>". $store['street1'] ."</AddressLine1>";
- if ($store['street2']) {
- $schema .= "<AddressLine2>". $store['street2'] ."</AddressLine2>";
- }
- $schema .= "<City>". $store['city'] ."</City>";
- $schema .= "<StateProvinceCode>$shipper_zone</StateProvinceCode>";
- $schema .= "<PostalCode>$shipper_zip</PostalCode>";
- $schema .= "<CountryCode>$shipper_country</CountryCode>";
- $schema .= "</Address>";
- $schema .= "</Shipper>";
- $schema .= "<ShipTo>";
- $schema .= "<CompanyName>". $destination->company ."</CompanyName>";
- $schema .= "<AttentionName>". $destination->first_name .' '. $destination->last_name ."</AttentionName>";
- $schema .= "<PhoneNumber>". $destination->phone ."</PhoneNumber>";
- $schema .= "<EMailAddress>". $destination->email ."</EMailAddress>";
- $schema .= "<Address>";
- $schema .= "<AddressLine1>". $destination->street1 ."</AddressLine1>";
- if ($destination->street2) {
- $schema .= "<AddressLine2>". $destination->street2 ."</AddressLine2>";
- }
- $schema .= "<City>". $destination->city ."</City>";
- $schema .= "<StateProvinceCode>$shipto_zone</StateProvinceCode>";
- $schema .= "<PostalCode>$shipto_zip</PostalCode>";
- $schema .= "<CountryCode>$shipto_country</CountryCode>";
- if ($destination->residence) {
- $schema .= "<ResidentialAddressIndicator/>";
- }
- $schema .= "</Address>";
- $schema .= "</ShipTo>";
- $schema .= "<ShipFrom>";
- $schema .= "<CompanyName>". $origin->company ."</CompanyName>";
- $schema .= "<AttentionName>". $origin->first_name .' '. $origin->last_name ."</AttentionName>";
- $schema .= "<PhoneNumber>". $origin->phone ."</PhoneNumber>";
- $schema .= "<EMailAddress>". $origin->email ."</EMailAddress>";
- $schema .= "<Address>";
- $schema .= "<AddressLine1>". $origin->street1 ."</AddressLine1>";
- if ($origin->street2) {
- $schema .= "<AddressLine2>". $origin->street2 ."</AddressLine2>";
- }
- $schema .= "<City>". $origin->city ."</City>";
- $schema .= "<StateProvinceCode>$shipfrom_zone</StateProvinceCode>";
- $schema .= "<PostalCode>$shipfrom_zip</PostalCode>";
- $schema .= "<CountryCode>$shipfrom_country</CountryCode>";
- $schema .= "</Address>";
- $schema .= "</ShipFrom>";
- $schema .= "<PaymentInformation>";
- $schema .= "<Prepaid>";
- $schema .= "<BillShipper>";
- $schema .= "<AccountNumber>$account</AccountNumber>";
- $schema .= "</BillShipper>";
- $schema .= "</Prepaid>";
- $schema .= "</PaymentInformation>";
- if (variable_get('uc_ups_negotiated_rates', false)) {
- $schema .= "<RateInformation>
- <NegotiatedRatesIndicator/>
- </RateInformation>";
- }
- $schema .= "<Service>";
- $schema .= "<Code>{$service[code]}</Code>";
- $schema .= "<Description>{$service[description]}</Description>";
- $schema .= "</Service>";
- $schema .= $package_schema;
- $schema .= "</Shipment>";
- $schema .= "<LabelSpecification>";
- $schema .= "<LabelPrintMethod>";
- $schema .= "<Code>GIF</Code>";
- $schema .= "</LabelPrintMethod>";
- $schema .= "<LabelImageFormat>";
- $schema .= "<Code>GIF</Code>";
- $schema .= "</LabelImageFormat>";
- $schema .= "</LabelSpecification>";
- $schema .= "</ShipmentConfirmRequest>";
-
- return $schema;
- }
-
- /**
- * Callback for retrieving a UPS shipping quote.
- *
- * Request a quote for each enabled UPS Service. Therefore, the quote will
- * take longer to display to the user for each option the customer has available.
- *
- * @param $products
- * Array of cart contents.
- * @param $details
- * Order details other than product information.
- * @return
- * JSON object containing rate, error, and debugging information.
- */
- function uc_ups_quote($products, $details) {
- include_once(drupal_get_path('module', 'uc_store') .'/includes/simplexml.php');
- $quotes = array();
-
- $method = uc_ups_shipping_method();
-
- $addresses = array((array)variable_get('uc_quote_store_default_address', new stdClass()));
- $key = 0;
- $last_key = 0;
- $packages = array();
- if (variable_get('uc_ups_all_in_one', true) && count($products) > 1) {
- foreach ($products as $product) {
- if ($product->nid) {
- // Packages are grouped by the address from which they will be
- // shipped. We will keep track of the different addresses in an array
- // and use their keys for the array of packages.
-
- $address = (array)uc_quote_get_default_shipping_address($product->nid);
- $key = array_search($address, $addresses);
- if ($key === false) {
- // This is a new address. Increment the address counter $last_key
- // instead of using [] so that it can be used in $packages and
- // $addresses.
- $addresses[++$last_key] = $address;
- $key = $last_key;
- }
- }
-
- // Add this product to the last package from the found address or start
- // a new package.
- if (isset($packages[$key]) && count($packages[$key])) {
- $package = array_pop($packages[$key]);
- }
- else {
- $package = _uc_ups_new_package();
- }
-
- $weight = $product->weight * $product->qty * uc_weight_conversion($product->weight_units, 'lb');
-
- $package->weight += $weight;
- $package->price += $product->price * $product->qty;
-
- $conversion = uc_weight_conversion($product->length_units, 'in');
- $package->length = max($product->length * $conversion, $package->length);
- $package->width = max($product->width * $conversion, $package->width);
- $package->height = max($product->height * $conversion, $package->height);
-
- $packages[$key][] = $package;
- }
- foreach ($packages as $addr_key => $shipment) {
- foreach ($shipment as $key => $package) {
- if (!$package->weight) {
- unset($packages[$addr_key][$key]);
- continue;
- }
- elseif ($package->weight > 150) {
- // UPS has a weight limit on packages of 150 lbs. Pretend the
- // products can be divided into enough packages.
- $qty = floor($package->weight / 150) + 1;
- $package->qty = $qty;
- $package->weight /= $qty;
- $package->price /= $qty;
- }
- }
- }
- }
- else {
- foreach ($products as $product) {
- $key = 0;
- if ($product->nid) {
- $address = (array)uc_quote_get_default_shipping_address($product->nid);
- $key = array_search($address, $addresses);
- if ($key === false) {
- $addresses[++$last_key] = $address;
- $key = $last_key;
- }
- }
- if (!$product->pkg_qty) {
- $product->pkg_qty = 1;
- }
- $num_of_pkgs = (int)($product->qty / $product->pkg_qty);
- if ($num_of_pkgs) {
- $package = drupal_clone($product);
- $package->description = $product->model;
- $package->weight = $product->weight * $product->pkg_qty;
- $package->price = $product->price * $product->pkg_qty;
- $package->qty = $num_of_pkgs;
- $package->pkg_type = $product->ups ? $product->ups['pkg_type'] : '02';
- if ($package->weight) {
- $packages[$key][] = $package;
- }
- }
- $remaining_qty = $product->qty % $product->pkg_qty;
- if ($remaining_qty) {
- $package = drupal_clone($product);
- $package->description = $product->model;
- $package->weight = $product->weight * $remaining_qty;
- $package->price = $product->price * $remaining_qty;
- $package->qty = 1;
- $package->pkg_type = $product->ups ? $product->ups['pkg_type'] : '02';
- if ($package->weight) {
- $packages[$key][] = $package;
- }
- }
- }
- }
- if (!count($packages)) {
- return array();
- }
-
- $dest = (object)$details;
-
- foreach ($packages as $key => $ship_packages) {
- $orig = (object)$addresses[$key];
- $orig->email = variable_get('uc_store_email', '');
- foreach (array_keys(array_filter(variable_get('uc_ups_services', array()))) as $ups_service) {
- $request = uc_ups_shipping_quote($ship_packages, $orig, $dest, $ups_service);
- $resp = drupal_http_request(variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/') .'Rate', array(), 'POST', $request);
- if (user_access('configure quotes') && variable_get('uc_quote_display_debug', false)) {
- $quotes[$ups_service]['debug'] .= /* '<pre>'. print_r($ship_packages, true) .'</pre>' . */ htmlentities($request) .' <br /><br /> '. htmlentities($resp->data);
- }
- $response = new JSimpleXML();
- $response->loadString($resp->data);
- if (isset($response->document->response[0]->error)) {
- foreach ($response->document->response[0]->error as $error) {
- if (user_access('configure quotes') && variable_get('uc_quote_display_debug', false)) {
- $quotes[$ups_service]['error'][] = $error->errorseverity[0]->data() .' '. $error->errorcode[0]->data() .': '. $error->errordescription[0]->data();
- }
- if ($error->errorseverity[0]->data() == 'HardError') {
- // All or nothing quote. If some products can't be shipped by
- // a certain service, no quote is given for that service. If
- // that means no quotes are given at all, they'd better call in.
- unset($quotes[$ups_service]['rate']);
- }
- }
- }
- // if NegotiatedRates exist, quote based on those, otherwise, use TotalCharges
- if (isset($response->document->ratedshipment)) {
- $charge = $response->document->ratedshipment[0]->totalcharges[0];
- if (isset($response->document->ratedshipment[0]->negotiatedrates)) {
- $charge = $response->document->ratedshipment[0]->negotiatedrates[0]->netsummarycharges[0]->grandtotal[0];
- }
- if (!isset($charge->currencycode) || $charge->currencycode[0]->data() == variable_get('uc_currency_code', "USD")) {
- $rate = uc_ups_markup($charge->monetaryvalue[0]->data());
- $quotes[$ups_service]['rate'] += $rate;
- }
- }
- }
- }
- uasort($quotes, 'uc_quote_price_sort');
- foreach ($quotes as $key => $quote) {
- if (isset($quote['rate'])) {
- $quotes[$key]['format'] = uc_currency_format($quote['rate']);
- $quotes[$key]['option_label'] = '<img class="ups_logo" src="'. base_path() . drupal_get_path('module', 'uc_ups') .'/uc_ups_logo.gif" /> '. $method['ups']['quote']['accessorials'][$key] . t(' Rate');
- }
- }
-
- /**
- * Ugly hack to work around PHP bug, details here:
- * http://bugs.php.net/bug.php?id=23220
- * We strip out errors that look something like:
- * warning: fread() [function.fread]: SSL fatal protocol error in...
- * Copied from http://drupal.org/node/70915 and then improved by Lyle.
- */
- $messages = drupal_set_message();
- $errors = $messages['error'];
- $total = count($errors);
- for ($i = 0; $i <= $total; $i++) {
- if (strpos($errors[$i], 'SSL: fatal protocol error in')) {
- unset($_SESSION['messages']['error'][$i]);
- }
- }
- if (empty($_SESSION['messages']['error'])) {
- unset($_SESSION['messages']['error']);
- }
- db_query("DELETE FROM {watchdog} WHERE type = 'php' AND message LIKE '%%SSL: fatal protocol error%%'");
- // End of ugly hack.
-
- return $quotes;
- }
-
- /**
- * Shipment creation callback.
- *
- * Confirm shipment data before requesting a shipping label.
- *
- * @param $order_id
- * The order id for the shipment.
- * @param $package_ids
- * Array of package ids to shipped.
- * @ingroup forms
- * @see uc_ups_fulfill_order_submit
- */
- function uc_ups_fulfill_order($order_id, $package_ids) {
- $form = array();
- $pkg_types = _uc_ups_pkg_types();
- if ($order = uc_order_load($order_id)) {
- $form['order_id'] = array('#type' => 'value', '#value' => $order_id);
- $packages = array();
- $addresses = array();
- $form['packages'] = array('#tree' => true);
- foreach ($package_ids as $id) {
- $package = uc_shipping_package_load($id);
- if ($package) {
- foreach ($package->addresses as $address) {
- if (!in_array($address, $addresses)) {
- $addresses[] = $address;
- }
- }
- // Create list of products and get a representative product for default values
- $product_list = array();
- $declared_value = 0;
- foreach ($package->products as $product) {
- $product_list[] = $product->qty .' x '. $product->model;
- $declared_value += $product->qty * $product->price;
- }
- $ups_data = db_fetch_array(db_query("SELECT pkg_type FROM {uc_ups_products} WHERE nid = %d", $product->nid));
- $product->ups = $ups_data;
- $pkg_form = array('#type' => 'fieldset',
- '#title' => t('Package !id', array('!id' => $id)),
- );
- $pkg_form['products'] = array('#value' => theme('item_list', $product_list));
- $pkg_form['package_id'] = array('#type' => 'hidden', '#value' => $id);
- $pkg_form['pkg_type'] = array('#type' => 'select',
- '#title' => t('Package type'),
- '#options' => $pkg_types,
- '#default_value' => $product->ups['pkg_type'],
- '#required' => true,
- );
- $pkg_form['declared_value'] = array('#type' => 'textfield',
- '#title' => t('Declared value'),
- '#default_value' => $declared_value,
- '#required' => true,
- );
- $pkg_type['dimensions'] = array('#type' => 'fieldset',
- '#title' => t('Dimensions'),
- '#description' => t('Physical dimensions of the package.'),
- '#theme' => 'uc_ups_dimensions',
- );
- $pkg_form['dimensions']['units'] = array('#type' => 'select',
- '#title' => t('Units of measurement'),
- '#options' => array(
- 'in' => t('Inches'),
- 'ft' => t('Feet'),
- 'cm' => t('Centimeters'),
- 'mm' => t('Millimeters'),
- ),
- '#default_value' => $product->length_units ? $product->length_units : variable_get('uc_length_unit', 'in'),
- );
- $pkg_form['dimensions']['length'] = array('#type' => 'textfield',
- '#title' => t('Length'),
- '#default_value' => $product->length,
- );
- $pkg_form['dimensions']['width'] = array('#type' => 'textfield',
- '#title' => t('Width'),
- '#default_value' => $product->width,
- );
- $pkg_form['dimensions']['height'] = array('#type' => 'textfield',
- '#title' => t('Height'),
- '#default_value' => $product->height,
- );
- $form['packages'][$id] = $pkg_form;
- }
- }
-
- $form = array_merge($form, uc_shipping_address_form($addresses, $order));
-
- foreach (array('delivery_email', 'delivery_last_name', 'delivery_company', 'delivery_street1', 'delivery_city', 'delivery_zone', 'delivery_country', 'delivery_postal_code') as $field) {
- $form['destination'][$field]['#required'] = true;
- }
-
- $ups_services = _uc_ups_service_list();
- $services = array_filter(variable_get('uc_ups_services', array()));
- foreach ($services as $ups_id => $service) {
- $services[$ups_id] = $ups_services[$ups_id];
- }
- if (count($services)) {
- $form['service'] = array('#type' => 'select',
- '#title' => t('UPS service'),
- '#options' => $services,
- );
- }
- $today = getdate();
- $form['ship_date'] = array('#type' => 'date',
- '#title' => t('Ship date'),
- '#default_value' => array('year' => $today['year'], 'month' => $today['mon'], 'day' => $today['mday']),
- );
- $form['expected_delivery'] = array('#type' => 'date',
- '#title' => t('Expected delivery'),
- '#default_value' => array('year' => $today['year'], 'month' => $today['mon'], 'day' => $today['mday']),
- );
- $form['submit'] = array('#type' => 'submit', '#value' => t('Review shipment'));
- }
- else {
- drupal_set_message(t("What? That's not an order id. You can't create a shipment without an order."));
- drupal_goto('admin/store/orders');
- }
- return $form;
- }
-
- /**
- * Validation handler for uc_ups_fulfill_order().
- *
- * Pass final information into shipment object.
- *
- * @see uc_ups_confirm_shipment
- */
- function uc_ups_fulfill_order_validate($form_id, $form_values) {
- include_once(drupal_get_path('module', 'uc_store') .'/includes/simplexml.php');
- $origin = new stdClass();
- $destination = new stdClass();
- $packages = array();
- foreach ($form_values as $key => $value) {
- if (substr($key, 0, 7) == 'pickup_') {
- $field = substr($key, 7);
- $origin->$field = $value;
- }
- else if (substr($key, 0, 9) == 'delivery_') {
- $field = substr($key, 9);
- $destination->$field = $value;
- }
- }
- $_SESSION['ups'] = array();
- $_SESSION['ups']['origin'] = $origin;
- $_SESSION['ups']['destination'] = $destination;
- foreach ($form_values['packages'] as $id => $pkg_form) {
- $package = uc_shipping_package_load($id);
- $package->pkg_type = $pkg_form['pkg_type'];
- $package->value = $pkg_form['declared_value'];
- $package->length = $pkg_form['dimensions']['length'];
- $package->width = $pkg_form['dimensions']['width'];
- $package->height = $pkg_form['dimensions']['height'];
- $package->length_units = $pkg_form['dimensions']['units'];
- $package->qty = 1;
- $_SESSION['ups']['packages'][$id] = $package;
- }
- $_SESSION['ups']['service'] = $form_values['service'];
- $_SESSION['ups']['ship_date'] = $form_values['ship_date'];
- $_SESSION['ups']['expected_delivery'] = $form_values['expected_delivery'];
- $_SESSION['ups']['order_id'] = $form_values['order_id'];
-
- $request = uc_ups_shipment_request($_SESSION['ups']['packages'], $origin, $destination, $form_values['service']);
- //print htmlentities($request);
- $response_obj = drupal_http_request(variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/') .'ShipConfirm', array(), 'POST', $request);
- $response = new JSimpleXML();
- $response->loadString($response_obj->data);
- //drupal_set_message('<pre>'. htmlentities($response->document->asXML()) .'</pre>');
- if (is_array($response->document->response[0]->error)) {
- $error = $response->document->response[0]->error[0];
- $error_msg = $error->errorseverity[0]->data() .' Error '. $error->errorcode[0]->data() .': '. $error->errordescription[0]->data();
- drupal_set_message($error_msg, 'error');
- //drupal_set_message('<pre>'. print_r($_SESSION['ups']['packages'], true) .'</pre>' . htmlentities($request) .' <br /><br /> '. htmlentities($response->data));
- if ($error->errorseverity[0]->data() == 'Hard') {
- return null;
- }
- }
- $charge = new stdClass();
- // if NegotiatedRates exist, quote based on those, otherwise, use TotalCharges
- if (is_array($response->document->shipmentcharges)) {
- $charge = $response->document->shipmentcharges[0]->totalcharges[0];
- $_SESSION['ups']['rate']['type'] = t('Total Charges');
- if (is_array($response->document->shipmentcharges[0]->negotiatedrates)) {
- $charge = $response->document->shipmentcharges[0]->negotiatedrates[0]->netsummarycharges[0]->grandtotal[0];
- $_SESSION['ups']['rate']['type'] = t('Negotiated Rates');
- }
- }
- $_SESSION['ups']['rate']['currency'] = $charge->currencycode[0]->data();
- $_SESSION['ups']['rate']['amount'] = $charge->monetaryvalue[0]->data();
- $_SESSION['ups']['digest'] = $response->document->shipmentdigest[0]->data();
- }
-
- /**
- * Submit handler for uc_ups_fulfill_order().
- *
- * Pass final information into shipment object.
- *
- * @see uc_ups_confirm_shipment
- */
- function uc_ups_fulfill_order_submit($form_id, $form_values) {
- return 'admin/store/orders/'. $form_values['order_id'] .'/shipments/ups';
- }
-
- /**
- * Last chance for user to review shipment.
- *
- * @ingroup forms
- * @see theme_uc_ups_confirm_shipment
- * @see uc_ups_confirm_shipment_submit
- */
- function uc_ups_confirm_shipment($order_id) {
- $form = array();
- $form['digest'] = array('#type' => 'hidden', '#value' => $_SESSION['ups']['digest']);
- $form['submit'] = array('#type' => 'submit', '#value' => t('Request Pickup'));
- return $form;
- }
-
- /**
- * Display final shipment information for review.
- */
- function theme_uc_ups_confirm_shipment($form) {
- $output = '';
-
- $output .= '<div class="shipping_address"><b>'. t('Ship from:') .'</b><br />';
- $output .= uc_address_format(
- check_plain($_SESSION['ups']['origin']->first_name),
- check_plain($_SESSION['ups']['origin']->last_name),
- check_plain($_SESSION['ups']['origin']->company),
- check_plain($_SESSION['ups']['origin']->street1),
- check_plain($_SESSION['ups']['origin']->street2),
- check_plain($_SESSION['ups']['origin']->city),
- check_plain($_SESSION['ups']['origin']->zone),
- check_plain($_SESSION['ups']['origin']->postal_code),
- check_plain($_SESSION['ups']['origin']->country)
- );
- $output .= '<br />'. check_plain($_SESSION['ups']['origin']->email);
- $output .= '</div>';
-
- $output .= '<div class="shipping_address"><b>'. t('Ship to:') .'</b><br />';
- $output .= uc_address_format(
- check_plain($_SESSION['ups']['destination']->first_name),
- check_plain($_SESSION['ups']['destination']->last_name),
- check_plain($_SESSION['ups']['destination']->company),
- check_plain($_SESSION['ups']['destination']->street1),
- check_plain($_SESSION['ups']['destination']->street2),
- check_plain($_SESSION['ups']['destination']->city),
- check_plain($_SESSION['ups']['destination']->zone),
- check_plain($_SESSION['ups']['destination']->postal_code),
- check_plain($_SESSION['ups']['destination']->country)
- );
- $output .= '<br />'. check_plain($_SESSION['ups']['destination']->email);
- $output .= '</div>';
- $output .= '<div class="shipment_data">';
- $method = uc_ups_shipping_method();
- $output .= '<b>'. $method['ups']['quote']['accessorials'][$_SESSION['ups']['service']] .'</b><br />';
- $output .= '<i>'. check_plain($_SESSION['ups']['rate']['type']) .'</i>: '. uc_currency_format($_SESSION['ups']['rate']['amount']) .' ('. check_plain($_SESSION['ups']['rate']['currency']) .')<br />';
- $ship_date = $_SESSION['ups']['ship_date'];
- $output .= 'Ship date: '. format_date(gmmktime(12, 0, 0, $ship_date['month'], $ship_date['day'], $ship_date['year']), 'custom', variable_get('uc_date_format_default', 'm/d/Y'));
- $exp_delivery = $_SESSION['ups']['expected_delivery'];
- $output .= '<br />Expected delivery: '. format_date(gmmktime(12, 0, 0, $exp_delivery['month'], $exp_delivery['day'], $exp_delivery['year']), 'custom', variable_get('uc_date_format_default', 'm/d/Y'));
- $output .= "</div>\n<br style=\"clear: both;\" />";
- $output .= drupal_render($form);
- return $output;
- }
-
- /**
- * Submit handler for uc_ups_confirm_shipment().
- *
- * Generate label and schedule pickup of the shipment.
- */
- function uc_ups_confirm_shipment_submit($form_id, $form_values) {
- include_once(drupal_get_path('module', 'uc_store') .'/includes/simplexml.php');
- // Request pickup using parameters in form.
- $order_id = $_SESSION['ups']['order_id'];
- $packages = array_keys($_SESSION['ups']['packages']);
- $request = uc_ups_request_pickup($form_values['digest'], $order_id, $packages);
- $result = drupal_http_request(variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/') .'ShipAccept', array(), 'POST', $request);
- $response = new JSimpleXML();
- $response->loadString($result->data);
- $code = $response->document->response[0]->responsestatuscode[0]->data();
- if ($code == 0) { // failed request
- $error = $response->document->response[0]->error[0];
- $error_severity = $error->errorseverity[0]->data();
- $error_code = $error->errorcode[0]->data();
- $error_description = $error->errordescription[0]->data();
- drupal_set_message(t('(@severity error @code) @description', array('@severity' => $error_severity, '@code' => $error_code, '@description' => $error_description)), 'error');
- if ($error_severity == 'HardError') {
- return 'admin/store/orders/'. $order_id .'/shipments/ups/'. implode('/', $packages);
- }
- }
-
- $shipment = new stdClass();
- $shipment->order_id = $order_id;
- $shipment->origin = drupal_clone($_SESSION['ups']['origin']);
- $shipment->destination = drupal_clone($_SESSION['ups']['destination']);
- $shipment->packages = $_SESSION['ups']['packages'];
- $shipment->shipping_method = 'ups';
- $shipment->accessorials = $_SESSION['ups']['service'];
- $shipment->carrier = t('UPS');
- // if NegotiatedRates exist, quote based on those, otherwise, use TotalCharges
- if (is_array($response->document->shipmentresults[0]->shipmentcharges)) {
- $charge = $response->document->shipmentresults[0]->shipmentcharges[0]->totalcharges[0];
- if (is_array($response->document->shipmentresults[0]->negotiatedrates)) {
- $charge = $response->document->shipmentresults[0]->negotiatedrates[0]->netsummarycharges[0]->grandtotal[0];
- }
- }
- $cost = $charge->monetaryvalue[0]->data();
- $shipment->cost = $cost;
- $shipment->tracking_number = $response->document->shipmentresults[0]->shipmentidentificationnumber[0]->data();
- $ship_date = $_SESSION['ups']['ship_date'];
- $shipment->ship_date = gmmktime(12, 0, 0, $ship_date['month'], $ship_date['day'], $ship_date['year']);
- $exp_delivery = $_SESSION['ups']['expected_delivery'];
- $shipment->expected_delivery = gmmktime(12, 0, 0, $exp_delivery['month'], $exp_delivery['day'], $exp_delivery['year']);
-
- foreach ($response->document->shipmentresults[0]->packageresults as $package_results) {
- $package =& current($shipment->packages);
- $package->tracking_number = $package_results->trackingnumber[0]->data();
- $label_image = $package_results->labelimage[0]->graphicimage[0]->data();
- if (file_check_directory(file_create_path('ups_labels'), FILE_CREATE_DIRECTORY)) {
- $label_path = file_create_path('ups_labels') .'/label'. $package->tracking_number .'.gif';
- if ($label_file = fopen($label_path, 'wb')) {
- fwrite($label_file, base64_decode($label_image));
- fclose($label_file);
- $package->label_image = $label_path;
- }
- else {
- drupal_set_message(t('Could not open a file to save the label image.'), 'error');
- }
- }
- else {
- drupal_set_message(t('Could not find or create the directory "ups_labels" in the file system path.'), 'error');
- }
- unset($package);
- next($shipment->packages);
- }
-
- uc_shipping_shipment_save($shipment);
-
- unset($_SESSION['ups']);
- return 'admin/store/orders/'. $order_id .'/shipments';
- }
-
- /**
- * Construct an XML label and pickup request.
- *
- * @param $digest
- * Base-64 encoded shipment request.
- * @param $order_id
- * The order id of the shipment.
- * @param $packages
- * An array of package ids to be shipped.
- * @return
- * ShipmentAcceptRequest XML document to send to UPS.
- */
- function uc_ups_request_pickup($digest, $order_id = 0, $packages = array()) {
- $packages = (array)$packages;
-
- $schema = uc_ups_access_request();
- $schema .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
- <ShipmentAcceptRequest>
- <Request>
- <RequestAction>ShipAccept</RequestAction>";
- if ($order_id || count($packages)) {
- $schema .= "\n<TransactionReference>
- <CustomerContext>";
- if ($order_id) {
- $schema .= "<OrderId>". $order_id ."</OrderId>\n";
- }
- foreach ($packages as $pkg_id) {
- $schema .= "<PackageId>". $pkg_id ."</PackageId>\n";
- }
- $schema .= "</CustomerContext>\n</TransactionReference>\n";
- }
- $schema .= " </Request>
- <ShipmentDigest>". $digest ."</ShipmentDigest>
- </ShipmentAcceptRequest>";
-
- //drupal_set_message('<pre>'. htmlentities($schema) .'</pre>');
- return $schema;
- }
-
- /**
- * Display the shipping label for printing.
- *
- * Each argument is a component of the file path to the image.
- *
- * @ingroup themeable
- */
- function theme_uc_ups_label_image() {
- $args = func_get_args();
- $image_path = implode('/', $args);
- print '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
- <html><head><title>
- View/Print Label</title></head><style>
- .small_text {font-size: 80%;}
- .large_text {font-size: 115%;}
- </style>
- <body bgcolor="#FFFFFF">
- <table border="0" cellpadding="0" cellspacing="0" width="600"><tr>
- <td height="410" align="left" valign="top">
- <b class="large_text">View/Print Label</b>
- <br />
- <ol class="small_text"> <li><b>Print the label:</b>
- Select Print from the File menu in this browser window to print the label below.<br /><br /><li><b>
- Fold the printed label at the dotted line.</b>
- Place the label in a UPS Shipping Pouch. If you do not have a pouch, affix the folded label using clear plastic shipping tape over the entire label.<br /><br /><li><b>GETTING YOUR SHIPMENT TO UPS<br />
- Customers without a Daily Pickup</b><ul><li>Ground, 3 Day Select, and Standard to Canada shipments must be dropped off at an authorized UPS location, or handed to a UPS driver. Pickup service is not available for these services. To find the nearest drop-off location, select the Drop-off icon from the UPS tool bar.<li>
- Air shipments (including Worldwide Express and Expedited) can be picked up or dropped off. To schedule a pickup, or to find a drop-off location, select the Pickup or Drop-off icon from the UPS tool bar. </ul> <br />
- <b>Customers with a Daily Pickup</b><ul><li>
- Your driver will pickup your shipment(s) as usual. </ul>
- </ol></td></tr></table><table border="0" cellpadding="0" cellspacing="0" width="600">
- <tr>
- <td class="small_text" align="left" valign="top">
-
- FOLD HERE</td>
- </tr>
- <tr>
- <td align="left" valign="top"><hr />
- </td>
- </tr>
- </table>
-
- <table>
- <tr>
- <td height="10">
- </td>
- </tr>
- </table>
-
- <table border="0" cellpadding="0" cellspacing="0" width="650" ><tr>
- <td align="left" valign="top">
- <img src="'. base_path() . $image_path .'" height="392" width="672">
- </td>
- </tr></table>
- </body>
- </html>';
-
- exit();
- }
-
- function uc_ups_void_shipment_request($shipment_number, $tracking_numbers = array()) {
- $schema = uc_ups_access_request();
- $schema .= '<?xml version="1.0"?>';
- $schema .= '<VoidShipmentRequest>';
- $schema .= '<Request>';
- $schema .= '<RequestAction>Void</RequestAction>';
- $schema .= '<TransactionReference>';
- $schema .= '<CustomerContext>';
- $schema .= t('Void shipment @ship_number and tracking numbers @track_list', array('@ship_number' => $shipment_number, '@track_list' => implode(', ', $tracking_numbers)));
- $schema .= '</CustomerContext>';
- $schema .= '<XpciVersion>1.0</XpciVersion>';
- $schema .= '</TransactionReference>';
- $schema .= '</Request>';
- $schema .= '<ExpandedVoidShipment>';
- $schema .= '<ShipmentIdentificationNumber>'. $shipment_number .'</ShipmentIdentificationNumber>';
- foreach ($tracking_numbers as $number) {
- $schema .= '<TrackingNumber>'. $number .'</TrackingNumber>';
- }
- $schema .= '</ExpandedVoidShipment>';
- $schema .= '</VoidShipmentRequest>';
- return $schema;
- }
-
- function uc_ups_void_shipment($shipment_number, $tracking_numbers = array()) {
- include_once(drupal_get_path('module', 'uc_store') .'/includes/simplexml.php');
- $success = false;
- $request = uc_ups_void_shipment_request($shipment_number, $tracking_numbers);
- $resp = drupal_http_request(variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/') .'Void', array(), 'POST', $request);
- $response = new JSimpleXML();
- $response->loadString($resp->data);
- if (is_array($response->document->response)) {
- if (is_array($response->document->response[0]->responsestatuscode)) {
- $success = $response->document->response[0]->responsestatuscode[0]->data();
- }
- if (is_array($response->document->response[0]->error)) {
- foreach ($response->document->response[0]->error as $error) {
- drupal_set_message($error->errorseverity[0]->data() .' '. $error->errorcode[0]->data() .': '. $error->errordescription[0]->data(), 'error');
- }
- }
- }
- if (is_array($response->document->status)) {
- if (is_array($response->document->status[0]->statustype)) {
- $success = $response->document->status[0]->statustype[0]->code[0]->data();
- }
- }
- return (bool)$success;
- }
-
- /**
- * Modify the rate received from UPS before displaying to the customer.
- */
- function uc_ups_markup($rate) {
- $markup = variable_get('uc_ups_markup', '0');
- $type = variable_get('uc_ups_markup_type', 'percentage');
- if (is_numeric(trim($markup))) {
- switch ($type) {
- case 'percentage':
- return $rate + $rate * floatval(trim($markup)) / 100;
- case 'multiplier':
- return $rate * floatval(trim($markup));
- case 'currency':
- return $rate + floatval(trim($markup));
- }
- }
- else {
- return $rate;
- }
- }
-
- /**
- * Convenience function to get UPS codes for their services.
- */
- function _uc_ups_service_list() {
- return array(
- '03' => t('UPS Ground'),
- '11' => t('UPS Standard'),
- '01' => t('UPS Next Day Air'),
- '13' => t('UPS Next Day Air Saver'),
- '14' => t('UPS Next Day Early A.M.'),
- '02' => t('UPS 2nd Day Air'),
- '59' => t('UPS 2nd Day Air A.M.'),
- '12' => t('UPS 3-Day Select'),
- );
- }
-
- /**
- * Convenience function to get UPS codes for their package types.
- */
- function _uc_ups_pkg_types() {
- return array(
- '01' => t('UPS Letter'),
- '02' => t('Customer Supplied Package'),
- '03' => t('Tube'),
- '04' => t('PAK'),
- '21' => t('UPS Express Box'),
- '24' => t('UPS 25KG Box'),
- '25' => t('UPS 10KG Box'),
- '30' => t('Pallet'),
- );
- }
-
- function _uc_ups_new_package() {
- $package = new stdClass();
-
- $package->weight = 0;
- $package->price = 0;
-
- $package->length = 0;
- $package->width = 0;
- $package->height = 0;
-
- $package->length_units = 'in';
- $package->weight_units = 'lb';
- $package->qty = 1;
- $package->pkg_type = '02';
-
- return $package;
- }
-