I found that Ubercart will happily accept a 6-digit zip code during checkout.

A quick search turned up a this documentation which suggests that I should implement a hook().

I'm surprised that this aspect of postal codes is not validated by Ubercart, given the other extensive validation UC does around addresses.
Is there anyway to enable this kind of validation through the extensive UC config, or do I really have to put this into code?
Should this be considered a bug, since zip codes must be 5 digits? (or 10 digits in zip+4 format)?

Comments

longwave’s picture

Title: howto: postal code / address validation on checkout » Zip/postal code validation on checkout
Category: support » feature

Yeah, there is no support for this in Ubercart core at present, so changing this to a feature request. I think we could easily validate zip/postal codes for a number of countries with regular expressions.

For reference, UK postcodes can be validated using the regex found here:
http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation

longwave’s picture

Note this is not a bug because zip codes in the US must be 5 or 5+4, but this does not necessarily apply in other countries!

mattcasey’s picture

Here's a similar example. My client only delivers to a local area, so I wrote a module that only allows zipcodes from a preset list during checkout. The zipcodes are added under Checkout/Settings/Zipcode validation


function zipcode_validate_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('This module limits the zip codes allowed for delivery in checkout.');
  }
}

function zipcode_validate_menu() {
  $items = array();

    $items['admin/store/settings/checkout/edit/zipcodes'] = array(
      'title' => 'Valid zipcodes',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('zipcode_validate_page_form'),
      'access arguments' => array('administer site configuration'),
      'type' => MENU_NORMAL_ITEM,
	  'weight'=> 100,
    );
  return $items;
}

function zipcode_validate_page_form() {

  $zipcode_string = implode(", ", variable_get('zipcode_validate_list', array()));
  
  $form['zipcodes'] = array(
    '#type' => 'textarea',
    '#title' => t('Enter a list of acceptable zip codes separated by commas'),
	'#default_value' => $zipcode_string,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

// Store list of zipcodes in Drupal $variables array
function zipcode_validate_page_form_submit($form_id, $form_values) {
  $array = array_map('trim', explode(",", $form_values['values']['zipcodes']));
  variable_set('zipcode_validate_list', $array);
  }

function zipcode_validate_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'uc_cart_checkout_form') {
    // Add our validation function to delivery zip code
    $form['panes']['delivery']['delivery_postal_code']['#element_validate'] = array('_profile_validate');
  }
}

// Validation function for delivery zipcode
function _profile_validate($form, &$form_state) {
  $zipcode_list = variable_get('zipcode_validate_list', array());
  
  $zipcode = $form_state['values']['panes']['delivery']['delivery_postal_code'];
  if (in_array($zipcode, $zipcode_list)) {
    return true;
  } else {
    form_set_error('delivery_postal_code', t('We do not deliver to that zip code yet. You can request delivery to your area <a id="webform-popup" href="/mailchimp-news">here</a>.'));
  }
}

allanp’s picture

Has anyone come up with a method of limiting the postal code field to 5 digits for U.S. shipping?
Any help would be appreciated.

TR’s picture

Status: Active » Closed (won't fix)

I don't think ZIP code validation belongs in core Ubercart. This is country specific, and many countries don't even have a postal code to validate. This can easily be done in a contributed module, as demonstrated by #3, so there's no reason to carry around extra code in core (e.g for US and UK validation) that isn't relevant to most users. If you would like to see this feature, please help make and maintain said contributed module.

longwave’s picture

Version: 6.x-2.x-dev » 7.x-3.x-dev
Status: Closed (won't fix) » Active

http://drupal.org/project/postal_code_validation provides an API to do this for many countries, so we could optionally support this in core.

TR’s picture

My preference would be to contribute a patch for that module to have it support Ubercart and automatically work on the checkout form. This would just be a simple hook_form_alter() in that module to add a validation function to the Ubercart checkout form. I think that's a much better way of doing things than adding module_exists() code in Ubercart.

longwave’s picture

I suspect that will go the way of #1814522: Support for address field module?. Alternatively, there could just be a very small glue module as a separate contrib.

DanZ’s picture

So, add this validation on addresses entered by customers?

Probably, make a configuration option checkbox to turn this on and off?

Do a check to see if the module is available, and disable both the validation and the option checkbox if it's not there.

This can fill in the state/province, and maybe even the country. Is that a good idea?

This should obviously be used on the checkout page. Probably, the admin order edit page, too. Anywhere else?

This has all sorts of AJAX implications, I imagine.

TR’s picture

Probably, make a configuration option checkbox to turn this on and off?

My suggestion was to build this into the postal_code_validation module, so if you wanted it you would just enable that module. If you didn't want it, you wouldn't install that module. I don't think it has any AJAX implications, because it would just be an additional form validation function added to the checkout (and possibly other) pages. This is just a few lines of hook_form_alter().

Postal code validation by that module is done by a regular expression, so it's really only a minimal check on length and allowed characters. It doesn't, for instance, check that the ZIP code agrees with the State or City entered - you have to go to a web service to do that.

Shipping services like FedEx, UPS, and USPS provide address validation web services which can validate *all* address fields, correct/rewrite addresses into a standard format, and determine whether an address is residential or commercial. I've written code for all of these services to integrate this validation with the checkout form (the only code I've released is in my uc_fedex module, the others are still in sandbox). This does NOT require modifications to Ubercart core, which is why I don't think there should be modifications to support postal_code_validation. Any module which wants to add validation or any functionality to the Ubercart checkout form can do so now, and Ubercart core doesn't need to know anything about it. A site builder can just enable whichever additional modules he/she wants, if additional address validations are desired.

TR’s picture

Issue summary: View changes
Status: Active » Closed (won't fix)

For the reasons I stated in #5, #7, and #10.