diff --git a/shipping/uc_ups/README.certification.txt b/shipping/uc_ups/README.certification.txt
new file mode 100644
index 0000000..710ce3b
--- /dev/null
+++ b/shipping/uc_ups/README.certification.txt
@@ -0,0 +1,33 @@
+UPS requires that users certify their application against a series of test
+responses before access to the production servers is granted. The uc_ups module
+has a 'certification mode' that can assist you in generating the files required
+to pass UPS' certification process.
+
+To begin, enable certification mode by browsing to "Administer > Store
+Administration > Configuration > Shipping quote settings > Quote methods > UPS"
+and selecting the checkbox titled "Certification mode". As well, be sure that
+the active mode under the "Credentials" section is set to "Testing".
+
+Next, download the latest copy of the XML developer guide documentation. It will
+include the procedure required to gain production access. Login to the UPS
+Developer Kit website here:
+https://www.ups.com/upsdeveloperkit/downloadresource?loc=en_US
+
+Once logged in, select and download the Shipping API. The documentation pack
+should contain a document named 'Shipping Package XML Developers Guide' inside
+the 'Developers Guide' folder with a section on how to certify your account for
+production access.
+
+Note that you do not need to manually capture and store the XML requests, label
+images or HTML pages as noted in the UPS documentation. Putting the module in
+certification mode will store all of these files for you automatically. As you
+create UPS shipments from any Ubercart order, these files will created under the
+sites/default/files/ups_certification folder of your website. After having
+shipped and voided the shipments as specified by UPS, simply send the resulting
+files in an archive to the UPS certification team.
+
+After completing certification, remember to delete the ups_certification folder
+and to disable certification mode so that the uc_ups does not continue to log
+information about all your shipments. While the filenames of the generated files
+would be difficult to guess, keep in mind that they are public when stored in
+the site/default/files folder.
diff --git a/shipping/uc_ups/uc_ups.admin.inc b/shipping/uc_ups/uc_ups.admin.inc
index 8edcfa1..75bd1a1 100644
--- a/shipping/uc_ups/uc_ups.admin.inc
+++ b/shipping/uc_ups/uc_ups.admin.inc
@@ -221,6 +221,13 @@ function uc_ups_admin_settings() {
     '#description'   => t('Controls how long labels are stored on the server before being automatically deleted. Cron must be enabled for automatic deletion. Default is never delete the labels, keep them forever.'),
   );
 
+  $form['uc_ups_cert_mode'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Certification mode'),
+    '#default_value' => variable_get('uc_ups_cert_mode', FALSE),
+    '#description' => t('When enabled, the UPS module will produce the necessary files for certification by UPS. Not for production use!.'),
+  );
+
   $form['#validate'][] = 'uc_ups_admin_settings_validate';
 
   return system_settings_form($form);
diff --git a/shipping/uc_ups/uc_ups.certification.inc b/shipping/uc_ups/uc_ups.certification.inc
new file mode 100644
index 0000000..566d221
--- /dev/null
+++ b/shipping/uc_ups/uc_ups.certification.inc
@@ -0,0 +1,132 @@
+<?php
+/**
+ * @file
+ * Functions to preserve request/response information for UPS XML certification.
+ */
+
+/**
+ * Generic function to capture request and response XML for certification
+ *
+ * @param $request
+ *   The raw XML request sent to UPS.
+ * @param $resp
+ *   The raw XML response sent by UPS.
+ * @param $folder
+ *  A string containing the name of the folder to store the output XML files.
+ * @param $name
+ *   An arbritrary string indicating the type of request. The files storing the
+ *   captured XML data are named using this string.
+ */
+function uc_ups_certification_capture_xml($request, $response, $folder, $name) {
+  if (file_check_directory(file_create_path('ups_certification'), FILE_CREATE_DIRECTORY)) {
+    if (file_check_directory(file_create_path('ups_certification/' . $folder), FILE_CREATE_DIRECTORY)) {
+      $xml_request_path = file_create_path('ups_certification/' . $folder) .'/' . $name . 'Request.xml';
+      $xml_response_path = file_create_path('ups_certification/' . $folder) .'/' . $name . 'Response.xml';
+    
+      // need to get rid of the UPS access request that has the user name and
+      // password this is the first xml document in $request, but I'm not sure why
+      // explode puts it in the second array
+      $new_request = $request;
+      $new_request_array = explode('<?xml version="1.0" encoding="UTF-8"?>', $request);
+      $new_request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" . $new_request_array[2];
+    
+      if ($xml_request_file = fopen($xml_request_path, 'wb')) {
+        fwrite($xml_request_file, $new_request);
+        fclose($xml_request_file);
+        drupal_set_message(t('Wrote XML request to file %filename', array('%filename' => $xml_request_path)));
+      }
+      else {
+        drupal_set_message(t('Could not open a file to save the request XML document.'), 'error');
+      }
+    
+      if ($xml_response_file = fopen($xml_response_path, 'wb')) {
+        fwrite($xml_response_file, $resp->data);
+        fclose($xml_response_file);
+        drupal_set_message(t('Wrote XML response to file %filename', array('%filename' => $xml_response_path)));
+      }
+      else {
+        drupal_set_message(t('Could not open a file to save the response XML document.'), 'error');
+      }
+    }
+    else {
+      drupal_set_message(t('Could not find or create the directory %folder in the site files directory.', array('%folder' => 'ups_certification/' . $folder)), 'error');
+    }
+  }
+  else {
+    drupal_set_message(t('Could not find or create the directory %folder in the site files directory.', array('%folder' => 'ups_certification')), 'error');
+  }
+}
+
+/**
+ * Capture label image data of a package shipment for certification
+ *
+ * @param $html_page
+ *   The base64-encoded HTML page containing the label image sent back by UPS.
+ * @param $label_image
+ *   The base64-encoded image data sent back by UPS.
+ * @param $folder
+ *  A string containing the name of the folder to store the output XML files.
+ * @param $tracking_number
+ *   The tracking number of a package. The files storing the captured XML data
+ *   are named using this string.
+ */
+function uc_ups_certification_capture_label_image($html_page, $label_image, $folder, $tracking_number) {
+  if (file_check_directory(file_create_path('ups_certification'), FILE_CREATE_DIRECTORY)) {
+    if (file_check_directory(file_create_path('ups_certification/' . $folder), FILE_CREATE_DIRECTORY)) {
+      $label_path = file_create_path('ups_certification/' . $folder) .'/label' . $tracking_number . '.gif';
+      $html_path = file_create_path('ups_certification/' . $folder) .'/' . $tracking_number . '.html';
+
+      if ($label_file = fopen($label_path, 'wb')) {
+        fwrite($label_file, base64_decode($label_image));
+        fclose($label_file);
+        drupal_set_message(t('Wrote label image file %filename', array('%filename' => $label_path)));
+      }
+      else {
+        drupal_set_message(t('Could not open a file to save the label image.'), 'error');
+      }
+  
+      if ($html_file = fopen($html_path, 'wb')) {
+        fwrite($html_file, base64_decode($html_page));
+        fclose($html_file);
+        drupal_set_message(t('Wrote HTML page to file %filename', array('%filename' => basename($html_path), '@folder' => 'ups_certification/' . $folder)));
+      }
+      else {
+        drupal_set_message(t('Could not open a file to save %filename.', array('%filename' => $html_path)), 'error');
+      }
+    }
+    else {
+      drupal_set_message(t('Could not find or create the directory %folder in the site files directory.', array('%folder' => 'ups_certification/' . $folder)), 'error');
+    }
+  }
+  else {
+    drupal_set_message(t('Could not find or create the directory %folder in the site files directory.', array('%folder' => 'ups_certification')), 'error');
+  }
+}
+
+/**
+ * Captures the high-value report HTML page sent back by UPS.
+ *
+ * @param $receipt
+ *   The ControlLogReceipt data sent back by UPS after a ShipAccept request.
+ * @param $folder
+ *   A string containing the name of the folder to store the output XML files.
+ */
+function uc_ups_certification_capture_high_value($receipt, $folder) {
+  if (isset($receipt)) {
+    if (file_check_directory(file_create_path('ups_certification/' . $folder), FILE_CREATE_DIRECTORY)) {
+      $html_path = file_create_path('ups_certification/' . $folder) . '/high-value-report.html';
+      $html_image = $receipt->GraphicImage;
+      if ($html_file = fopen($html_path, 'wb')) {
+        fwrite($html_file, base64_decode($html_image));
+        fclose($html_file);
+        drupal_set_message(t('Wrote high value report to %file', array('%file' => $html_path)));
+      }
+      else {
+        drupal_set_message(t('Could not open a file to save the high value report.', array('@filename' => basename($html_path))), 'error');
+      }
+    }
+    else {
+      drupal_set_message(t('Could not find or create the directory %folder in the site files directory.', array('%folder' => 'ups_certification/' . $folder)), 'error');
+    }
+  }
+}
diff --git a/shipping/uc_ups/uc_ups.module b/shipping/uc_ups/uc_ups.module
index 4018343..06ba500 100644
--- a/shipping/uc_ups/uc_ups.module
+++ b/shipping/uc_ups/uc_ups.module
@@ -818,6 +818,14 @@ function uc_ups_void_shipment($shipment_number, $tracking_numbers = array()) {
       $success = (string)$response->Status->StatusType->Code;
     }
   }
+
+  if (variable_get('uc_ups_cert_mode', FALSE) && user_access('configure quotes')) {
+    require_once('uc_ups.certification.inc');
+    $folder = 'void-sid-' . $shipment_number;
+    $name = 'VoidShipment';
+    uc_ups_certification_capture_xml($request, $resp, $folder, $name);
+  }
+
   return (bool)$success;
 }
 
diff --git a/shipping/uc_ups/uc_ups.ship.inc b/shipping/uc_ups/uc_ups.ship.inc
index f666043..a34c790 100644
--- a/shipping/uc_ups/uc_ups.ship.inc
+++ b/shipping/uc_ups/uc_ups.ship.inc
@@ -279,6 +279,14 @@ function uc_ups_fulfill_order_validate($form, &$form_state) {
   $response_obj = drupal_http_request(variable_get('uc_ups_connection_address', 'https://wwwcie.ups.com/ups.app/xml/') .'ShipConfirm', array(), 'POST', $request);
   $response = new SimpleXMLElement($response_obj->data);
   //drupal_set_message('<pre>'. htmlentities($response->asXML()) .'</pre>');
+
+  if (variable_get('uc_ups_cert_mode', FALSE) && user_access('configure quotes')) {
+    require_once('uc_ups.certification.inc');
+    $folder = 'oid-' . $form_state['values']['order_id'];
+    $file = 'ShipmentConfirm';
+    uc_ups_certification_capture_xml($request, $response_obj, $folder, $file);
+  }
+
   if (isset($response->Response->Error)) {
     $error = $response->Response->Error;
     $error_msg = (string)$error->ErrorSeverity .' Error '. (string)$error->ErrorCode .': '. (string)$error->ErrorDescription;
@@ -437,8 +445,17 @@ function uc_ups_shipment_request($packages, $origin, $destination, $ups_service)
     <RequestOption>validate</RequestOption>
   </Request>
   <Shipment>";
+  // If destination is Canada or Puerto Rico
+  if ($destination->country == 124 || $destination->country == 630) {
+    $schema .= "<InvoiceLineTotal>";
+    $schema .=   "<CurrencyCode>". variable_get('uc_currency_code', 'USD') ."</CurrencyCode>";
+    $schema .=   "<MonetaryValue>". number_format($package->value, 0, '.', '') ."</MonetaryValue>";
+    $schema .= "</InvoiceLineTotal>";
+  }
+  $schema .=   "<Description>". $store['name'] ." Online Order</Description>";
   $schema .=   "<Shipper>";
   $schema .=     "<Name>". $store['name'] ."</Name>";
+  $schema .=     "<AttentionName>". $origin->first_name .' '. $origin->last_name ."</AttentionName>";
   $schema .=     "<ShipperNumber>". variable_get('uc_ups_shipper_number', '') ."</ShipperNumber>";
   if ($store['phone']) {
     $schema .=   "<PhoneNumber>". $store['phone'] ."</PhoneNumber>";
@@ -605,6 +622,14 @@ function uc_ups_confirm_shipment_submit($form, &$form_state) {
   $packages = array_keys($_SESSION['ups']['packages']);
   $request = uc_ups_request_pickup($form_state['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);
+
+  if (variable_get('uc_ups_cert_mode', FALSE) && user_access('configure quotes')) {
+    require_once('uc_ups.certification.inc');
+    $folder = 'oid-' . $order_id;
+    $name = 'ShipmentAccept';
+    uc_ups_certification_capture_xml($request, $result, $folder, $name);
+  }
+
   $response = new SimpleXMLElement($result->data);
   $code = (string)$response->Response->ResponseStatusCode;
   if ($code == 0) { // failed request
@@ -646,6 +671,7 @@ function uc_ups_confirm_shipment_submit($form, &$form_state) {
     $package =& current($shipment->packages);
     $package->tracking_number = (string)$package_results->TrackingNumber;
     $label_image = (string)$package_results->LabelImage->GraphicImage;
+
     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')) {
@@ -660,10 +686,21 @@ function uc_ups_confirm_shipment_submit($form, &$form_state) {
     else {
       drupal_set_message(t('Could not find or create the directory "ups_labels" in the file system path.'), 'error');
     }
+
+    if (variable_get('uc_ups_cert_mode', FALSE) && user_access('configure quotes')) {
+      $html_page = (string)$package_results->LabelImage->HTMLImage;
+      $folder = 'oid-' . $order_id;
+      uc_ups_certification_capture_label_image($html_page, $label_image, $folder, $package->tracking_number);
+    }
+
     unset($package);
     next($shipment->packages);
   }
 
+  if (variable_get('uc_ups_cert_mode', FALSE) && user_access('configure quotes')) {
+    uc_ups_certification_capture_high_value($response->ShipmentResults->ControlLogReceipt, $folder);
+  }
+
   uc_shipping_shipment_save($shipment);
 
   unset($_SESSION['ups']);
