Tweaking WooCommerce payment workflows

I’m playing part-time webmaster for the choir I sing in, and as such, am getting up close and personal with WooCommerce. Quite a nifty shopping cart, but it does require a lot of tweaks to really make it work to your liking – unless you’re willing to shell out a lot of cash.

The latest modification was changing the workflow of the payment gateways – more specifically, the BACS gateway (Bank Account Clearing System – or as we mortals call it, wire transfer).

The default flow for WooCommerce (for this gateway) is:

  1. Order is put in by customer
  2. Order is automatically flagged as on-hold, and a mail is sent out to the customer with the bank info
  3. Customer (supposedly) pays
  4. Store manager sees the payment, and flags order as processing – another mail is sent out with the notification that it’s being processed
  5. Store manager (hopefully) ships the product, flags the order as completed and another mail is sent out with ‘order complete’ status.

Now, for our uses, the on-hold status is a bit superfluous (and we’ve had people getting confused by it).
We’d rather have it go straight to processing, and have that mail contain the bank information (only for BACS payments, ofcourse).

After some testing, I came up with two solutions: One very hacky, and not maintainable, the other better. Both solutions need to be inserted in your theme’s functions.php file.

/* override gateway for BACS */
function my_core_gateways($methods) {
  foreach ($methods as &$method) {
    if($method == 'WC_Gateway_BACS') {
      $method = 'WC_Gateway_BACS_custom';
    }
  }
  return $methods;
}

/* custom gateway processor for BACS */
class WC_Gateway_BACS_custom extends WC_Gateway_BACS {
  public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {

    if ( ! $sent_to_admin && 'bacs' === $order->payment_method && $order->has_status( 'processing' ) ) {
      if ( $this->instructions ) {
        echo wpautop( wptexturize( $this->instructions ) ) . PHP_EOL;
      }
 
     /* dirty hack to get access to bank_details */
     $reflector = new ReflectionObject($this);
     $method = $reflector->getMethod('bank_details');
     $method->setAccessible(true);
 
     $result = $method->invoke($this, $order->id);
    }
  }

  public function process_payment( $order_id ) {
    $order = wc_get_order( $order_id );

    // Mark as processing (we're awaiting the payment)
    $order->update_status( 'processing', __( 'Awaiting BACS payment', 'woocommerce' ) );

    // Reduce stock levels
    $order->reduce_order_stock();

    // Remove cart
    WC()->cart->empty_cart();

    // Return thankyou redirect
    return array(
      'result' => 'success',
      'redirect' => $this->get_return_url( $order )
    );
  }
}

I have several reservations with the code above: it’s basically shamelessly copying and overloading the two functions of the parent class, and calling a private function which is internal to the parent class – both of which might cause trouble if there are big changes in WooCommerce. It works, but well, it’s .. ugly. So, I looked for a better way to tackle this.

sadfasdfasdf
add_action( 'woocommerce_email_before_order_table', 'add_order_email_instructions', 10, 2 );
add_action( 'woocommerce_thankyou', 'bacs_order_payment_processing_order_status', 10, 1 );

function bacs_order_payment_processing_order_status( $order_id ) {
  if ( ! $order_id ) {
    return;
  }

  $order = new WC_Order( $order_id );
 
  if ('bacs' === $order->payment_method && ('on-hold' == $order->status || 'pending' == $order->status)) {
    $order->update_status('processing');
  } else {
    return;
  }
}

function add_order_email_instructions( $order, $sent_to_admin ) {
  if ( ! $sent_to_admin && 'bacs' === $order->payment_method && $order->has_status( 'processing' ) ) {
    $gw = new WC_Gateway_BACS();
 
    $reflector = new ReflectionObject($gw);
    $method = $reflector->getMethod('bank_details');
    $method->setAccessible(true);
 
    $result = $method->invoke($gw, $order->id);
  }
}

Still not as clean as I’d like, as we’re still invoking an internal function, but atleast we’re using the proper hooks to tweak WooCommerce. I’ll update if I ever find a better way to get to the bank details.

WordPress Widgets!

I just finished creating three new WordPress Widget Plugins. Some are conversions of older plugins I made for WordPress, one is brand stinkin’ new.

The initlal motivation for creating these was that Sade (my SO) wanted to use the Flexo Archives Widget to make the archives links look better. Unfortunately, the widget approach is an all-or-nothing approach: either you do it all in widget way, or you don’t do widgets at all. (yes I know, this is not 100% correct, but good enough for now). Since she used several older plugins to display information in the sidebar, this wasn’t ideal.

So I set out creating the needed widgets ;)

Some technical blabla: Widget plugins are plugins that sit in your sidebar, and you can easily modify the order of your sidebar without having to edit the sidebar.php file that comes with your theme. Even better: if your theme supports it, the sidebar will look identical, no matter what theme you use!

To use it, log in as administrator and go to Presentation -> Widgets.

Now, without further delay, my widgets, which you can see in action on Sade’s Blog:

  • Countdown Widget: This widget will count down the days, hours, minutes and seconds until events you can set in the configuration.
  • Projects Widget: This widget shows project status, in percentages, and also a bar-graph. You can choose between four colours for the bargraph.
  • Webrings Widget: This widget will display your webrings, with the usual next/previous/random/list links. Optionally you can set a picture instead of the name.
projects-widget-2.0.zip (30 downloads)

 

webrings-widget-2.0.zip (30 downloads)

 

countdown-widget-3.0.zip (28 downloads)

What I’ve been doing…

What have I been doing the last times… well…

1. I flashed my Moto phone with the latest stable firmware, and it still works, and I’ve got video recording and more speed and a searchable addressbook and .. and.. Well, you know – flashing it made me sweat beyond belief (like OMG is it going to work? or not? *panic*)

2. I bought some RedHat books for Enterprise Linux 3 and maybe getting the certificates for RHCT and RHCE.. and whatever. I’ll see – studying time.

3. I changed the blogging software we use on the sadevil.org website (which is the site of Diana and me) from sphpblog to WordPress, which seems to be a bit more maintained. We decided to move after Diana’s sphpblog got hacked, and well.. her new blog is now up at http://sade.sadevil.org/blog and her site is now at http://sade.sadevil.org :P (and yes it looks great :)
I’ve also ‘modded’ an existing plugin for WordPress and made a sphpblog to WP convertor: you can find those below.

4. I’ve gone back to Spain on the meanwhile too, but for that you’d better see our blog. Not gonna repeat that here. I’m WAY too lazy :p

5. I’ve gotten my girl her birthday present, it looks nice :p and I’ll say later what it is because she also reads this blog *g* :P

6. I nearly finished painting my new livingroom! Just need to throw out a bunch of crap more and paint the place that’s used by that crap, but that’ll hopefully be done in two-three weeks.. I have 12h-shifts the whole week next week, and no time in the weekends, and then going back to spain for a week, and then… well… we’ll see :p

That’s about it!

webrings-1.0.zip (30 downloads) countdown-2.0.zip (31 downloads) sphpblog2wp-0.1.zip (31 downloads)