You are here

function uc_fedex_shipment_request in FedEx Shipping 7.2

Same name and namespace in other branches
  1. 6.2 uc_fedex.ship.inc \uc_fedex_shipment_request()

Constructs and executes a SOAP ShipService request.

Parameters

$packages: Array of packages received from the cart.

$origin: Delivery origin address information.

$destination: Delivery destination address information.

$fedex_service: FedEx service code (refers to FedEx Ground, Standard Overnight, etc.).

Return value

Response object from SOAP request.

2 calls to uc_fedex_shipment_request()
uc_fedex_confirm_shipment_submit in ./uc_fedex.ship.inc
Generates shipping labels.
uc_fedex_fulfill_order_validate in ./uc_fedex.ship.inc
Passes final information into shipment object.

File

./uc_fedex.ship.inc, line 33
FedEx Web Services Rate / Available Services Quote.

Code

function uc_fedex_shipment_request($packages, $origin, $destination, $fedex_service) {

  // Assemble information about origin.
  $country = uc_get_country_data(array(
    'country_id' => $origin->country,
  ));
  $origin->country_iso_code_2 = $country[0]['country_iso_code_2'];

  // Assemble information about destination.
  $country = uc_get_country_data(array(
    'country_id' => $destination->country,
  ));
  $destination->country_iso_code_2 = $country[0]['country_iso_code_2'];

  // Set up SOAP call.
  // Allow tracing so details of request can be retrieved for error logging.
  $client = new SoapClient(drupal_get_path('module', 'uc_fedex') . '/wsdl-' . variable_get('uc_fedex_server_role', 'testing') . '/ShipService_v7.wsdl', array(
    'trace' => 1,
  ));

  // FedEx user key and password filled in by user on admin form.
  $request['WebAuthenticationDetail'] = array(
    'UserCredential' => array(
      'Key' => variable_get('uc_fedex_user_credential_key', 0),
      'Password' => variable_get('uc_fedex_user_credential_password', 0),
    ),
  );

  // FedEx account and meter number filled in by user on admin form.
  $request['ClientDetail'] = array(
    'AccountNumber' => variable_get('uc_fedex_account_number', 0),
    'MeterNumber' => variable_get('uc_fedex_meter_number', 0),
  );

  // Optional parameter, contains anything.
  $request['TransactionDetail'] = array(
    'CustomerTransactionId' => '*** Shipping Request v7 from Ubercart ***',
  );

  // Shipping Request v7.0.0.
  $request['Version'] = array(
    'ServiceId' => 'ship',
    'Major' => '7',
    'Intermediate' => '0',
    'Minor' => '0',
  );

  // Timestamp.
  $request['RequestedShipment']['ShipTimestamp'] = date('c');

  // Drupal 6.x version of format_date() doesn't support 'c', so until
  // then we use date() directly.  date() doesn't take care of site
  // timezone, though.

  //$request['RequestedShipment']['ShipTimestamp'] = format_date(time(), 'custom', 'c');

  // Set Pickup/Dropoff type.
  $request['RequestedShipment']['DropoffType'] = variable_get('uc_fedex_dropoff_type', 'REGULAR_PICKUP');

  // Set Packaging type.
  // First element of the packages array is used because all packages
  // in a multi-package shipment must have the same packaging type.
  $request['RequestedShipment']['PackagingType'] = reset($packages)->pkg_type;

  // Set Service.
  $request['RequestedShipment']['ServiceType'] = $fedex_service;
  $street_lines = array();
  $street_lines[] = $origin->street1;
  if (!empty($origin->street2)) {
    $street_lines[] = $origin->street2;
  }

  // Get address.
  $request['RequestedShipment']['Shipper'] = array(
    'Contact' => array(
      'CompanyName' => $origin->company,
      'PhoneNumber' => $origin->phone,
    ),
    'Address' => array(
      'StreetLines' => $street_lines,
      'City' => $origin->city,
      'StateOrProvinceCode' => uc_get_zone_code($origin->zone),
      'PostalCode' => $origin->postal_code,
      'CountryCode' => $origin->country_iso_code_2,
    ),
  );
  $street_lines = array();
  $street_lines[] = $destination->street1;
  if (!empty($destination->street2)) {
    $street_lines[] = $destination->street2;
  }

  // Grab details of package destination.
  $request['RequestedShipment']['Recipient'] = array(
    'Contact' => array(
      'PersonName' => $destination->first_name . ' ' . $destination->last_name,
      'CompanyName' => $destination->company,
      'PhoneNumber' => $destination->phone,
    ),
    'Address' => array(
      'StreetLines' => $street_lines,
      'City' => $destination->city,
      'StateOrProvinceCode' => uc_get_zone_code($destination->zone),
      'PostalCode' => $destination->postal_code,
      'CountryCode' => $destination->country_iso_code_2,
      'Residential' => $destination->residential,
    ),
  );

  // CompanyName needs to be unset if empty.
  if (empty($destination->company)) {
    unset($request['RequestedShipment']['Recipient']['Contact']['CompanyName']);
  }

  // Label specifications.
  $request['RequestedShipment']['LabelSpecification'] = array(
    'LabelFormatType' => 'COMMON2D',
    'ImageType' => variable_get('uc_fedex_label_image_format', 'PDF'),
    'LabelStockType' => variable_get('uc_fedex_label_stock', 'PAPER_7X4.75'),
    'LabelPrintingOrientation' => variable_get('uc_fedex_label_orientation', 'TOP_EDGE_OF_TEXT_FIRST'),
  );

  // Bill shipping to?
  $request['RequestedShipment']['ShippingChargesPayment'] = array(
    'PaymentType' => 'SENDER',
    'Payor' => array(
      'AccountNumber' => variable_get('uc_fedex_account_number', 0),
      'CountryCode' => $origin->country_iso_code_2,
    ),
  );

  // Note that ACCOUNT rates *require* a valid account number
  // and return accurate answers only on the production server.
  $request['RequestedShipment']['RateRequestTypes'] = strtoupper(variable_get('uc_fedex_quote_type', 'list'));
  $request['RequestedShipment']['PackageDetail'] = 'INDIVIDUAL_PACKAGES';
  $request['RequestedShipment']['PackageCount'] = count($packages);

  // Fill in Package details.
  $request['RequestedShipment']['RequestedPackageLineItems'] = array();

  // Determine weight and length units to send to FedEx.
  $weight_units = strtoupper(variable_get('uc_weight_unit', 'LB'));
  $weight_conversion_factor = 1;
  if ($weight_units != 'LB' && $weight_units != 'KG') {
    $weight_conversion_factor = uc_weight_conversion($weight_units, 'LB');
    $weight_units = 'LB';
  }
  $length_units = strtoupper(variable_get('uc_length_unit', 'IN'));
  $length_conversion_factor = 1;
  if ($length_units != 'IN' && $length_units != 'CM') {
    $length_conversion_factor = uc_length_conversion($length_units, 'IN');
    $length_units = 'IN';
  }

  // Iterate over $packages to account for multi-package shipments.
  $sequence = 0;
  $package_properties = array();
  foreach ($packages as $package) {
    $sequence++;
    $package_properties[$sequence] = array(
      'SequenceNumber' => $sequence,
      'CustomerReferences' => array(
        '0' => array(
          'CustomerReferenceType' => 'INVOICE_NUMBER',
          // Gag - shouldn't be getting $order_id out of _SESSION.
          'Value' => $_SESSION['fedex']['order_id'],
        ),
        '1' => array(
          'CustomerReferenceType' => 'CUSTOMER_REFERENCE',
          'Value' => $_SESSION['fedex']['reference'],
        ),
      ),
      // Weights must be rounded up to nearest integer value.
      'Weight' => array(
        'Value' => ceil($package->weight * $weight_conversion_factor),
        'Units' => $weight_units,
      ),
      // Lengths must be rounded up to nearest integer value.
      'Dimensions' => array(
        'Length' => ceil($package->length * $length_conversion_factor),
        'Width' => ceil($package->width * $length_conversion_factor),
        'Height' => ceil($package->height * $length_conversion_factor),
        'Units' => $length_units,
      ),
    );

    // Only need Package Dimensions if using our own packaging.
    if ($request['RequestedShipment']['PackagingType'] != 'YOUR_PACKAGING') {
      unset($package_properties[$sequence]['Dimensions']);
    }

    // Add Insurance if requested.
    if (variable_get('uc_fedex_insurance', FALSE)) {
      $package_properties[$sequence]['InsuredValue'] = array(
        'Amount' => $package->value,
        'Currency' => 'USD',
      );
    }

    // Multi-package shipments need to reference master tracking number.
    if ($sequence > 1) {
      $request['RequestedShipment']['MasterTrackingId'] = $master_tracking_id;
    }

    // Fill in SOAP request with $package_properties.
    $request['RequestedShipment']['RequestedPackageLineItems'][0] = $package_properties[$sequence];

    //
    // For Multi-Package shipments, need to send one SOAP request
    // *per package* to the FedEx server.
    //
    try {
      $response[$sequence] = $client
        ->processShipment($request);
      if ($response[$sequence]->HighestSeverity != 'FAILURE' && $response[$sequence]->HighestSeverity != 'ERROR') {
        print_request_response($client);

        // Save master tracking # to use for remaining package in shipment.
        if ($sequence == 1 && count($packages) > 1) {
          $master_tracking_id = $response[$sequence]->CompletedShipmentDetail->MasterTrackingId;
        }
      }
      else {
        drupal_set_message(t('Error in processing FedEx Shipping Request.'), 'error');
        foreach ($response[$sequence]->Notifications as $notification) {
          if (is_array($response[$sequence]->Notifications)) {
            drupal_set_message($notification->Severity . ': ' . $notification->Message, 'error');
          }
          else {
            drupal_set_message($notification, 'error');
          }
        }
      }
    } catch (SoapFault $exception) {
      drupal_set_message('<h2>Fault</h2><br /><b>Code:</b>' . $exception->faultcode . '<br /><b>String:</b>' . $exception->faultstring . '<br />', 'error');
    }
  }
  return $response;
}