You are here

commerce_fedex.module in Commerce FedEx 7

Defines the FedEx shipping method and services for Drupal Commerce.

File

commerce_fedex.module
View source
<?php

/**
 * @file
 * Defines the FedEx shipping method and services for Drupal Commerce.
 */

/**
 * Implements hook_menu().
 */
function commerce_fedex_menu() {
  $items = array();
  $items['admin/commerce/config/shipping/methods/fedex/edit'] = array(
    'title' => 'Edit',
    'description' => 'Adjust FedEx shipping settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'commerce_fedex_settings_form',
    ),
    'access arguments' => array(
      'administer shipping',
    ),
    'file' => 'includes/commerce_fedex.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'context' => MENU_CONTEXT_INLINE,
    'weight' => 0,
  );
  return $items;
}

/**
 * Implements hook_commerce_shipping_method_info().
 */
function commerce_fedex_commerce_shipping_method_info() {
  $shipping_methods = array();
  $shipping_methods['fedex'] = array(
    'title' => t('FedEx'),
    'description' => t('Quote rates from FedEx'),
  );
  return $shipping_methods;
}

/**
 * Implements hook_commerce_shipping_service_info().
 */
function commerce_fedex_commerce_shipping_service_info() {
  $shipping_services = array();
  $available_services = commerce_fedex_shipping_service_types();
  $selected_services = variable_get('commerce_fedex_services', array());
  foreach ($selected_services as $id => $val) {
    if (!empty($val)) {
      $service = $available_services[$id];
      $shipping_services[drupal_strtolower($id)] = array(
        'title' => $service,
        'description' => $service,
        'display_title' => $service,
        'shipping_method' => 'fedex',
        'price_component' => 'shipping',
        'callbacks' => array(
          'rate' => 'commerce_fedex_service_rate_order',
        ),
      );
    }
  }
  return $shipping_services;
}

/**
 * Implements hook_commerce_shipping_service_rate_options_alter().
 */
function commerce_fedex_commerce_shipping_service_rate_options_alter(&$options, $order) {

  // If the display FedEx logo next to FedEx services is enabled in settings,
  // loop through the shipping options and add the FedEx logo to FedEx services.
  if (variable_get('commerce_fedex_show_logo', FALSE)) {
    $image = drupal_get_path('module', 'commerce_fedex') . '/images/fedex-logo.png';
    if (file_exists($image)) {
      foreach ($options as $key => &$option) {
        if (in_array(drupal_strtoupper($key), array_keys(commerce_fedex_shipping_service_types()))) {
          $option = theme('image', array(
            'path' => $image,
            'width' => '32px',
          )) . ' ' . $option;
        }
      }
    }
  }
}

/**
 * Returns an array of shipping method rates obtained from FedEx servers.
 *
 * @param array $shipping_service
 *   The shipping service that is being requested by commerce shipping.
 * @param object $order
 *   The commerce order object for the order that we're requesting rates for.
 *
 * @return array
 *   The rate values for the requested shipping service.
 */
function commerce_fedex_service_rate_order($shipping_service, $order) {

  // First attempt to recover cached shipping rates for the current order.
  $rates = commerce_shipping_rates_cache_get('fedex', $order, 0);

  // The request for each FedEx service is the same because they're collected
  // all at once. If the first request failed, then they will all fail. If the
  // rates variable is not an array then continue with the request.
  if (!is_array($rates)) {

    // Include the file that handles SOAP requests.
    module_load_include('inc', 'commerce_fedex', 'includes/commerce_fedex_soap_client');

    // Create the rate request to submit to FedEx for collecting shipping rates.
    $request = commerce_fedex_create_rate_request($order);
    if (!empty($request)) {

      // Submit the soap request and gather available FedEx shipping rates.
      $response = commerce_fedex_submit_soap_request($request, 'getRates');

      // Make sure the response was successful and contains rate reply details.
      if (!empty($response) && !empty($response->RateReplyDetails)) {

        // Set the variables are regex to determine which rates should be used.
        $rate_option = strtoupper(variable_get('commerce_fedex_rate_service_type', 'list'));
        $rate_match = '/^PAYOR_' . $rate_option . '/';

        // If only one rate reply comes back, then RateReplyDetails won't be an array.
        // However, we expect one. Stick the rate reply into an array to make the code
        // below happy.
        if (!is_array($response->RateReplyDetails)) {
          $response->RateReplyDetails = array(
            $response->RateReplyDetails,
          );
        }

        // Loop through the rate details object from FedEx.
        foreach ($response->RateReplyDetails as $rate) {

          // Set amount and currency code to NULL.
          $amount = NULL;
          $currency_code = NULL;

          // When requesting ACCOUNT rates, GROUND_HOME_DELIVERY will return an
          // object instead an array of objects.
          if (is_object($rate->RatedShipmentDetails)) {
            if (preg_match($rate_match, $rate->RatedShipmentDetails->ShipmentRateDetail->RateType)) {
              $amount = $rate->RatedShipmentDetails->ShipmentRateDetail->TotalNetCharge->Amount;
              $currency_code = $rate->RatedShipmentDetails->ShipmentRateDetail->TotalNetCharge->Currency;
            }
          }
          else {

            // Loop through the array of rate option objects.
            foreach ($rate->RatedShipmentDetails as $shipment_details) {
              if (preg_match($rate_match, $shipment_details->ShipmentRateDetail->RateType)) {
                $amount = $shipment_details->ShipmentRateDetail->TotalNetCharge->Amount;
                $currency_code = $shipment_details->ShipmentRateDetail->TotalNetCharge->Currency;
              }
            }
          }
          if (!empty($amount) && !empty($currency_code)) {
            $name = check_plain($rate->ServiceType);

            // Create the shipping service array to return to commerce_shipping.
            $rates[strtolower($name)] = array(
              'amount' => commerce_currency_decimal_to_amount($amount, $currency_code),
              'currency_code' => $currency_code,
              'data' => array(),
            );
          }
        }
      }
      if (!empty($rates)) {

        // Cache the calculated rates for subsequent requests.
        commerce_shipping_rates_cache_set('fedex', $order, $rates);
      }
      else {

        // If request fails, cache an empty array to prevent multiple failed
        // requests since all additional requests will fail as well.
        commerce_shipping_rates_cache_set('fedex', $order, array());
      }
    }
  }

  // Return the rate for the requested service or FALSE if not found.
  return isset($rates[$shipping_service['name']]) ? $rates[$shipping_service['name']] : FALSE;
}

/**
 * Returns an array representing the available shipping services from FedEx that
 * this module offers.
 *
 * @return array
 *   The keyed values of available shipping services.
 */
function commerce_fedex_shipping_service_types() {
  return array(
    'FEDEX_GROUND' => t('FedEx Ground'),
    'FEDEX_2_DAY' => t('FedEx 2 Day'),
    'FEDEX_2_DAY_AM' => t('FedEx 2 Day AM'),
    'FEDEX_EXPRESS_SAVER' => t('FedEx Express Saver'),
    'FIRST_OVERNIGHT' => t('FedEx First Overnight'),
    'GROUND_HOME_DELIVERY' => t('FedEx Ground Home Delivery'),
    'INTERNATIONAL_ECONOMY' => t('FedEx International Economy'),
    'INTERNATIONAL_FIRST' => t('FedEx International First'),
    'INTERNATIONAL_PRIORITY' => t('FedEx International Priority'),
    'PRIORITY_OVERNIGHT' => t('FedEx Priority Overnight'),
    'SMART_POST' => t('FedEx Smart Post'),
    'STANDARD_OVERNIGHT' => t('FedEx Standard Overnight'),
  );
}

/**
 * Returns an array of available FedEx package types.
 *
 * @return array
 *   The keyed values of available shipping package types.
 */
function commerce_fedex_package_types() {
  return array(
    'FEDEX_BOX' => t('FedEx Box'),
    'FEDEX_TUBE' => t('FedEx Tube'),
    'FEDEX_PAK' => t('FedEx Pak'),
    'FEDEX_ENVELOPE' => t('FedEx Envelope'),
    'YOUR_PACKAGING' => t('Customer Supplied Packaging'),
  );
}

/**
 * Returns an array of Drupal variables that are set by this module.
 *
 * @return array
 *   The variables that are set by this module.
 */
function commerce_fedex_settings_fields() {
  return array(
    'commerce_fedex_key',
    'commerce_fedex_password',
    'commerce_fedex_account_number',
    'commerce_fedex_meter_number',
    'commerce_fedex_key_testing',
    'commerce_fedex_password_testing',
    'commerce_fedex_account_number_testing',
    'commerce_fedex_meter_number_testing',
    'commerce_fedex_request_mode',
    'commerce_fedex_shipper_name',
    'commerce_fedex_company_name',
    'commerce_fedex_address_line_1',
    'commerce_fedex_address_line_2',
    'commerce_fedex_city',
    'commerce_fedex_state',
    'commerce_fedex_postal_code',
    'commerce_fedex_country_code',
    'commerce_fedex_services',
    'commerce_fedex_show_logo',
    'commerce_fedex_default_package_type',
    'commerce_fedex_default_package_size_length',
    'commerce_fedex_default_package_size_width',
    'commerce_fedex_default_package_size_height',
    'commerce_fedex_shipto_residential',
    'commerce_fedex_rate_service_type',
    'commerce_fedex_log',
    'commerce_fedex_dropoff',
    'commerce_fedex_insurance',
    'commerce_fedex_smartpost_indicia_type',
    'commerce_fedex_smartpost_hub_id',
  );
}

/**
 * Returns a list of SmartPost indicia types.
 *
 * @return array
 *   List of SmartPost indicia types.
 */
function commerce_fedex_smartpost_indicia_types() {
  return array(
    'MEDIA_MAIL' => t('Media Mail'),
    'PARCEL_SELECT' => t('Parcel Select'),
    'PRESORTED_BOUND_PRINTED_MATTER' => t('Presorted Bound Printed Matter'),
    'PRESORTED_STANDARD' => t('Presorted Standard'),
    'PARCEL_RETURN' => t('Parcel Return'),
  );
}

/**
 * Returns a list of SmartPost Hub IDs.
 *
 * @return array
 *   They keyed list of SmartPost Hub IDs provided by FedEx.
 */
function commerce_fedex_smartpost_hub_ids() {
  return array(
    '5185' => 'ALPA Allentown',
    '5303' => 'ATGA Atlanta',
    '5281' => 'CHNC Charlotte',
    '5602' => 'CIIL Chicago',
    '5929' => 'COCA Chino',
    '5751' => 'DLTX Dallas',
    '5802' => 'DNCO Denver',
    '5481' => 'DTMI Detroit',
    '5087' => 'EDNJ Edison',
    '5431' => 'GCOH Grove City',
    '5771' => 'HOTX Houston',
    '5465' => 'ININ Indianapolis',
    '5648' => 'KCKS Kansas City',
    '5902' => 'LACA Los Angeles',
    '5254' => 'MAWV Martinsburg',
    '5379' => 'METN Memphis',
    '5552' => 'MPMN Minneapolis',
    '5531' => 'NBWI New Berlin',
    '5110' => 'NENY Newburgh',
    '5015' => 'NOMA Northborough',
    '5327' => 'ORFL Orlando',
    '5194' => 'PHPA Philadelphia',
    '5854' => 'PHAZ Phoenix',
    '5150' => 'PTPA Pittsburgh',
    '5958' => 'SACA Sacramento',
    '5843' => 'SCUT Salt Lake City',
    '5983' => 'SEWA Seattle',
    '5631' => 'STMO St. Louis',
  );
}

/**
 * Returns an array of FedEx codes for dropoff and pickup.
 *
 * @return array
 *   The keyed values of available dropoff types.
 */
function commerce_fedex_dropoff_types() {
  return array(
    'BUSINESS_SERVICE_CENTER' => t('Dropoff at FedEx Business Service Center'),
    'DROP_BOX' => t('Dropoff at FedEx Drop Box'),
    'REGULAR_PICKUP' => t('Regularly scheduled Pickup from your location'),
    'REQUEST_COURIER' => t('One-time Pickup request'),
    'STATION' => t('Dropoff at FedEx Staffed Location'),
  );
}

/**
 * Returns an array of Countries serviced by FedEx.
 *
 * @return array
 *   The keyed values of countries that FedEx services.
 */
function commerce_fedex_serviced_countries() {
  return array(
    'AF' => 'Afghanistan',
    'AL' => 'Albania',
    'DZ' => 'Algeria',
    'AS' => 'American Samoa',
    'AD' => 'Andorra',
    'AO' => 'Angola',
    'AI' => 'Anguilla',
    'AG' => 'Antigua/Barbuda',
    'AR' => 'Argentina',
    'AM' => 'Armenia',
    'AW' => 'Aruba',
    'AU' => 'Australia',
    'AT' => 'Austria',
    'AZ' => 'Azerbaijan',
    'BS' => 'Bahamas',
    'BH' => 'Bahrain',
    'BD' => 'Bangladesh',
    'BB' => 'Barbados',
    'BY' => 'Belarus',
    'BE' => 'Belgium',
    'BZ' => 'Belize',
    'BJ' => 'Benin',
    'BM' => 'Bermuda',
    'BT' => 'Bhutan',
    'BO' => 'Bolivia',
    'BA' => 'Bosnia-Herzegovina',
    'BW' => 'Botswana',
    'BR' => 'Brazil',
    'VG' => 'British Virgin Islands',
    'BN' => 'Brunei',
    'BG' => 'Bulgaria',
    'BF' => 'Burkina Faso',
    'BI' => 'Burundi',
    'KH' => 'Cambodia',
    'CM' => 'Cameroon',
    'CA' => 'Canada',
    'CV' => 'Cape Verde',
    'KY' => 'Cayman Islands',
    'TD' => 'Chad',
    'CL' => 'Chile',
    'CN' => 'China',
    'CO' => 'Colombia',
    'CG' => 'Congo Brazzaville',
    'CD' => 'Congo Democratic Rep. of',
    'CK' => 'Cook Islands',
    'CR' => 'Costa Rica',
    'HR' => 'Croatia',
    'CY' => 'Cyprus',
    'CZ' => 'Czech Republic',
    'DK' => 'Denmark',
    'DJ' => 'Djibouti',
    'DM' => 'Dominica',
    'DO' => 'Dominican Republic',
    'TL' => 'East Timor',
    'EC' => 'Ecuador',
    'EG' => 'Egypt',
    'SV' => 'El Salvador',
    'GQ' => 'Equatorial Guinea',
    'ER' => 'Eritrea',
    'EE' => 'Estonia',
    'ET' => 'Ethiopia',
    'FO' => 'Faeroe Islands',
    'FJ' => 'Fiji',
    'FI' => 'Finland',
    'FR' => 'France',
    'GF' => 'French Guiana',
    'PF' => 'French Polynesia',
    'GA' => 'Gabon',
    'GM' => 'Gambia',
    'GE' => 'Georgia',
    'DE' => 'Germany',
    'GH' => 'Ghana',
    'GI' => 'Gibraltar',
    'GR' => 'Greece',
    'GL' => 'Greenland',
    'GD' => 'Grenada',
    'GP' => 'Guadeloupe',
    'GU' => 'Guam',
    'GT' => 'Guatemala',
    'GN' => 'Guinea',
    'GY' => 'Guyana',
    'HT' => 'Haiti',
    'HN' => 'Honduras',
    'HK' => 'Hong Kong',
    'HU' => 'Hungary',
    'IS' => 'Iceland',
    'IN' => 'India',
    'ID' => 'Indonesia',
    'IQ' => 'Iraq',
    'IE' => 'Ireland',
    'IL' => 'Israel',
    'IT' => 'Italy',
    'CI' => 'Ivory Coast',
    'JM' => 'Jamaica',
    'JP' => 'Japan',
    'JO' => 'Jordan',
    'KZ' => 'Kazakhstan',
    'KE' => 'Kenya',
    'KW' => 'Kuwait',
    'KG' => 'Kyrgyzstan',
    'LA' => 'Laos',
    'LV' => 'Latvia',
    'LB' => 'Lebanon',
    'LS' => 'Lesotho',
    'LR' => 'Liberia',
    'LY' => 'Libya',
    'LI' => 'Liechtenstein',
    'LT' => 'Lithuania',
    'LU' => 'Luxembourg',
    'MO' => 'Macau',
    'MK' => 'Macedonia',
    'MG' => 'Madagascar',
    'MW' => 'Malawi',
    'MY' => 'Malaysia',
    'MV' => 'Maldives',
    'ML' => 'Mali',
    'MT' => 'Malta',
    'MH' => 'Marshall Islands',
    'MQ' => 'Martinique',
    'MR' => 'Mauritania',
    'MU' => 'Mauritius',
    'MX' => 'Mexico',
    'FM' => 'Micronesia',
    'MD' => 'Moldova',
    'MC' => 'Monaco',
    'MN' => 'Mongolia',
    'ME' => 'Montenegro',
    'MS' => 'Montserrat',
    'MA' => 'Morocco',
    'MZ' => 'Mozambique',
    'NA' => 'Namibia',
    'NP' => 'Nepal',
    'NL' => 'Netherlands',
    'AN' => 'Netherlands Antilles',
    'NC' => 'New Caledonia',
    'NZ' => 'New Zealand',
    'NI' => 'Nicaragua',
    'NE' => 'Niger',
    'NG' => 'Nigeria',
    'NO' => 'Norway',
    'OM' => 'Oman',
    'PK' => 'Pakistan',
    'PW' => 'Palau',
    'PS' => 'Palestine Autonomous',
    'PA' => 'Panama',
    'PG' => 'Papua New Guinea',
    'PY' => 'Paraguay',
    'PE' => 'Peru',
    'PH' => 'Philippines',
    'PL' => 'Poland',
    'PT' => 'Portugal',
    'PR' => 'Puerto Rico',
    'QA' => 'Qatar',
    'RE' => 'Reunion',
    'RO' => 'Romania',
    'RU' => 'Russian Federation',
    'RW' => 'Rwanda',
    'MP' => 'Saipan',
    'WS' => 'Samoa',
    'SA' => 'Saudi Arabia',
    'SN' => 'Senegal',
    'RS' => 'Serbia',
    'SC' => 'Seychelles',
    'SG' => 'Singapore',
    'SK' => 'Slovak Republic',
    'SI' => 'Slovenia',
    'ZA' => 'South Africa',
    'KR' => 'South Korea',
    'ES' => 'Spain',
    'LK' => 'Sri Lanka',
    'KN' => 'St. Kitts/Nevis',
    'LC' => 'St. Lucia',
    'VC' => 'St. Vincent',
    'SR' => 'Suriname',
    'SZ' => 'Swaziland',
    'SE' => 'Sweden',
    'CH' => 'Switzerland',
    'SY' => 'Syria',
    'TW' => 'Taiwan',
    'TZ' => 'Tanzania',
    'TH' => 'Thailand',
    'TG' => 'Togo',
    'TO' => 'Tonga',
    'TT' => 'Trinidad/Tobago',
    'TN' => 'Tunisia',
    'TR' => 'Turkey',
    'TM' => 'Turkmenistan',
    'TC' => 'Turks & Caicos Islands',
    'VI' => 'U.S. Virgin Islands',
    'UG' => 'Uganda',
    'UA' => 'Ukraine',
    'AE' => 'United Arab Emirates',
    'GB' => 'United Kingdom',
    'US' => 'United States',
    'UY' => 'Uruguay',
    'UZ' => 'Uzbekistan',
    'VU' => 'Vanuatu',
    'VE' => 'Venezuela',
    'VN' => 'Vietnam',
    'WF' => 'Wallis & Futuna',
    'YE' => 'Yemen',
    'ZM' => 'Zambia',
    'ZW' => 'Zimbabwe',
  );
}

Functions

Namesort descending Description
commerce_fedex_commerce_shipping_method_info Implements hook_commerce_shipping_method_info().
commerce_fedex_commerce_shipping_service_info Implements hook_commerce_shipping_service_info().
commerce_fedex_commerce_shipping_service_rate_options_alter Implements hook_commerce_shipping_service_rate_options_alter().
commerce_fedex_dropoff_types Returns an array of FedEx codes for dropoff and pickup.
commerce_fedex_menu Implements hook_menu().
commerce_fedex_package_types Returns an array of available FedEx package types.
commerce_fedex_serviced_countries Returns an array of Countries serviced by FedEx.
commerce_fedex_service_rate_order Returns an array of shipping method rates obtained from FedEx servers.
commerce_fedex_settings_fields Returns an array of Drupal variables that are set by this module.
commerce_fedex_shipping_service_types Returns an array representing the available shipping services from FedEx that this module offers.
commerce_fedex_smartpost_hub_ids Returns a list of SmartPost Hub IDs.
commerce_fedex_smartpost_indicia_types Returns a list of SmartPost indicia types.