How to modify WooCommerce to prevent users from selecting UPS shipping for P.O. Box addresses

Anyone who’s dealt with e-commerce in any capacity probably knows that UPS won’t deliver to P.O. boxes. Well, technically they can’t deliver to P.O. boxes. And apparently they’ll forward packages on to the box owner’s physical address, but they charge a big extra fee to do it. So, you want to avoid it.

Unfortunately, WooCommerce and its UPS Shipping add-on do not account for this, and will accept UPS orders to P.O. box addresses. Not good.

The official WooCommerce developer documentation has an article on how to block P.O. box shipping, but it applies to all shippers. Not what we want.

Also, I’m not sure if the documentation is outdated or what, but their code sample didn’t work for me with the latest version (3.4.3) of WooCommerce, because of the wc_add_notice() function.

I’ve modified the original code to add a check for UPS shipping, and also to use the $errors variable. (I also considered removing the global $woocommerce; line since it seems unnecessary, but I didn’t take the time to test whether or not it’s definitely safe to remove, so I left it in.)

add_action('woocommerce_after_checkout_validation', function($data, $errors) {
  global $woocommerce;
  if (isset($data['shipping_method'][0]) && strpos($data['shipping_method'][0], 'ups') === 0) {
    $address1 = (isset($data['shipping_address_1'])) ? $data['shipping_address_1'] : $data['billing_address_1'];
    $address2 = (isset($data['shipping_address_2'])) ? $data['shipping_address_2'] : $data['billing_address_2'];

    $replace = array(” “, “.”, “,”);
    $address1 = strtolower(str_replace($replace, '', $address1));
    $address2 = strtolower(str_replace($replace, '', $address2));

    if (strstr($address1, 'pobox') || strstr($address2, 'pobox')) {
      $errors->add('shipping', __('Sorry, UPS cannot deliver to P.O. boxes. Please enter a street address or choose another shipping method.' . $datadump, 'woocommerce'));
    }
  }
}, 10, 2);

Important notes:

1. This code may not immediately work for you; I believe the 'ups' string in the conditional line may vary depending on your Shipping Classes settings, so you may need to investigate exactly what values are returned in $data['shipping_method']. Since this code is fired off by an AJAX call, it can be difficult to debug. I was able to crudely debug it by commenting out the conditional, then appending print_r($data) to the error string.

2. This is using an anonymous function, so it won’t work in PHP versions below 5.3. But you’re not using a PHP version that old, are you? ;)

3. The original version checked the address line 1 and the postcode field, rather than address lines 1 and 2. I’ve United States-ified my code because that’s what I needed. If you’re part of the other 95% of the world, you may need to add that back in, with appropriate adjustments to the nested conditional. (I’m not really sure if this issue is as UPS-specific outside the US, so my modifications may not be relevant.)

You can’t specialize in everything

It’s been one of those weeks that a freelancer dreads. Lots of fires to put out. You’re trying to swim upstream (as always) but instead you’re treading water in a rapids. Without a team of coworkers to depend on, when a problem arises, there’s no one to pass the buck to, or at least to, uh, share it with.

The problems haven’t really been that bad. Just a few bugs to squash, a few scripts to optimize, a few clients to reassure. But when you feel like you have to be the expert at whatever you do, this kind of week can be a source of anxiety.

It doesn’t help when your main lifeline to the tech world is the expert blogs you follow. Read a few articles on A List Apart and you’ll feel both inspired and a little despondent. There are so many incredibly talented, creative people out there doing amazing things. So why am I banging my head against the wall trying to figure out why all of my form fields suddenly disappeared in IE6? (Turns out it was the position: relative on the #main element, easily fixed by overriding it with position: static in the IE6-specific CSS file I wish I didn’t have to create.)

The point is, as a freelancer, at least one who aspires to be good, if not great, at what you do, you are your own harshest critic and worst enemy. There’s no way any of my clients would ever beat me up the way I beat up myself. I don’t think I’ve ever even had one detectably angry with me. But I am constantly getting frustrated with myself for not being on top of every single technology I put my hands on, and I’m inclined to treat every bug as a personal failure.

The sad fact is, it’s impossible. You can’t specialize in everything. It’s right there in the word. Specialize. As a freelancer, you have to pick a few things to focus on as your greatest strengths, while becoming as well-rounded as you can. But there’s always someone out there who knows more about CSS3 or HTML5 or PHP or jQuery or Whatchamacallit than you do. The great thing about being a freelancer in the age of the Internet, especially if you work on the Internet, is that a lot of those superstar über-geniuses are willing to share that knowledge with you for free. All you have to do is search for it.

The biggest danger in following the superstars of your chosen field, though, is idol worship. You get to know so many facets of their work and their personalities (especially if you follow them on Twitter), that you may be tempted to think you know them personally. You might even have a brief exchange with them about baseball. But that doesn’t mean you know them or know what their lives are really like.

We all make sacrifices to live the lives we choose. It’s inherent in the finite nature of human existence. Chances are, I’ll never be a web development “rock star,” because I’ve made choices that took me on another path. I wanted to be able to work on my terms, and fit my career in as one aspect of my life. I’m not logging the kind of hours I’d need to in order to get rich doing work for hire, or building the next great social networking site. But I have time to spend with my kids and SLP (though probably still not as much as would be ideal). I can make music. I can try to set the world record on my Asteroids cocktail table. (OK, that’ll never happen, but it’s 2 feet from my desk in my home office, if I ever decide to get serious.) I can take an afternoon off to take my son to see Toy Story 3 or head down to Target Field for a Twins game or write on my coffee blog or get some fish tacos at Sea Salt.

Or, I can spend half the morning beating myself up because I’m not Jeffrey Zeldman. But, who is? (OK, he is. But that’s it.)

The point is, I’m me. I’m damn good at what I do, but I can’t do everything. And that’s OK.