WooCommerce AutoComplete Order - No Emails sent - php

I'm using WC with it's original membership plugin. I'm selling an online course (which is obviously a virtual product). Following should work: Someone purchases the product, order will be automatically completed, user gets an email with password and order confirmation.
I had following code in my functions.php:
/**
* Auto Complete all WooCommerce orders.
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_order');
function custom_woocommerce_auto_complete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
The Problem now is that the order is completed but the users won't
receive their login credentials and invoice. How do I handle this -
what's wrong?

Related

Send an Email notification to the admin for processing order status in WooCommerce

In WooCommerce, when a customer submit the order, the order can be set to "processing" payment. Or "on hold". The Admin doesn't received any email about.
I would like to send an email to Admin for this kind of orders. How can I do it?
Tryed this code (for "Processing" status):
// New order notification only for "Process" Order status
add_action( 'woocommerce_checkout_order_processed', 'process_new_order_notification', 20, 1 );
function process_new_order_notification( $order_id ) {
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Only for "Process" order status
if( ! $order->has_status( 'process' ) ) return;
// Send "New Email" notification (to admin)
WC()->mailer()->get_emails()['WC_Email_New_Order']->trigger( $order_id );
}
But something wrong and still no email
Help please

Set Woocommerce new orders to "On hold" without going to "Processing"

Is it possible to set all new orders to on hold without them going to processing first?
I need to capture the funds, but the order needs to go as on-hold rather than processing so that I can make sure the payment is received before triggering the email to our supplier.
I have found some code that allows me to change all new orders to on-hold, however when payment is authorized the order is set to processing.
pending payment --> processing (triggers email) --> on-hold
Screenshot of Order Notes that show this
This is the code that I found:
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_onhold_order' );
function custom_woocommerce_auto_onhold_order( $order_id ) {
global $woocommerce;
if ( !$order_id )
return;
$order = new WC_Order( $order_id );
$order->update_status( 'on-hold' ); //All new orders go to "on-hold"
}
I've been looking for the action which triggers the order status to be set to processing on payment authorization however I cannot find it.
All help is greatly appreciated!
Edit: I've managed to stumble upon a snippet of code that appears to work.
add_filter( 'woocommerce_payment_complete_order_status', 'custom_update_order_status', 10, 2 );
function custom_update_order_status( $order_status, $order_id ) {
return 'on-hold';
}
All orders start with a "pending" status in Woocommerce. That status is set before they go through the payment gateway...
There is no email notifications for "Pending" orders staus
You can try the following, that will set the status "on-hold" on order creation (The update status action comes once the order has been created ans saved in database):
add_action( 'woocommerce_checkout_create_order', 'force_new_order_status', 20, 1 );
function force_new_order_status( $order ) {
if( ! $order->has_status('on-hold') )
$order->set_status( 'on-hold', 'Forced status by a custom script' );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

WooCommerce: Auto complete paid orders

Normally wooCommerce should autocomplete orders for virtual products. But it doesn't and this is a real problem, even a BUG like.
So at this point you can find somme helpful things(but not really convenient):
1) A snippet code (that you can find in wooCommerce docs):
/**
* Auto Complete all WooCommerce orders.
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_order');
function custom_woocommerce_auto_complete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
But this snippet does not work for BACS*, Pay on delivery and Cheque payment methods. It's ok for Paypal and Credit Card gateways payment methods.
*BACS is a Direct Bank transfer payment method
And …
2) A plugin: WooCommerce Autocomplete Orders
This plugin works for all payment methods, but not for other Credit Card gateways payment methods.
My question:
Using (as a base) the wooCommerce snippet in point 1:
How can I implement conditional code based on woocommerce payment methods?
I mean something like: if the payment methods aren't "BACS", "Pay on delivery" and "Cheque" then apply the snippet code (update status to "completed" for paid orders concerning virtual products).
Some help will be very nice.
The most accurate, effective and lightweight solution (For WooCommerce 3 and above) - 2019
This filter hook is located in:
WC_Order Class inside payment_complete() method which is used by all payment methods when a payment is required in checkout.
WC_Order_Data_Store_CPT Class inside update() method.
As you can see, by default the allowed paid order statuses are "processing" and "completed".
###Explanations:
Lightweight and effective:
As it is a filter hook, woocommerce_payment_complete_order_status is only triggered when an online payment is required (not for "cheque", "bacs" or "cod" payment methods). Here we just change the allowed paid order statuses.
So no need to add conditions for the payment gateways or anything else.
Accurate (avoid multiple notifications):
This is the only way to avoid sending 2 different customer notifications at the same time:
• One for "processing" orders status
• And one for "completed" orders status.
So customer is only notified once on "completed" order status.
Using the code below, will just change the paid order status (that is set by the payment gateway for paid orders) to "completed":
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
return 'completed';
}
Code goes in function.php file of the active child theme (or active theme).
Related: WooCommerce: autocomplete paid orders based on shipping method
2018 - Improved version (For WooCommerce 3 and above)
Based on Woocommerce official hook, I found a solution to this problem *(Works with WC 3+).
In Woocommerce for all other payment gateways others than bacs (Bank Wire), cheque and cod (Cash on delivery), the paid order statuses are "processing" and "completed".
So I target "processing" order status for all payment gateways like Paypal or credit card payment, updating the order status to complete.
The code:
add_action( 'woocommerce_thankyou', 'wc_auto_complete_paid_order', 20, 1 );
function wc_auto_complete_paid_order( $order_id ) {
if ( ! $order_id )
return;
// Get an instance of the WC_Product object
$order = wc_get_order( $order_id );
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
if ( in_array( $order->get_payment_method(), array( 'bacs', 'cod', 'cheque', '' ) ) ) {
return;
}
// For paid Orders with all others payment methods (paid order status "processing")
elseif( $order->has_status('processing') ) {
$order->update_status( 'completed' );
}
}
Code goes in function.php file of the active child theme (or active theme).
Original answer (For all woocommerce versions):
The code:
/**
* AUTO COMPLETE PAID ORDERS IN WOOCOMMERCE
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_paid_order', 10, 1 );
function custom_woocommerce_auto_complete_paid_order( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
if ( ( 'bacs' == get_post_meta($order_id, '_payment_method', true) ) || ( 'cod' == get_post_meta($order_id, '_payment_method', true) ) || ( 'cheque' == get_post_meta($order_id, '_payment_method', true) ) ) {
return;
}
// For paid Orders with all others payment methods (with paid status "processing")
elseif( $order->get_status() === 'processing' ) {
$order->update_status( 'completed' );
}
}
Code goes in function.php file of the active child theme (or active theme).
With the help of this post: How to check payment method on a WooCommerce order by id?
with this : get_post_meta( $order_id, '_payment_method', true ); from helgatheviking
"Bank wire" (bacs), "Cash on delivery" (cod) and "Cheque" (cheque) payment methods are ignored and keep their original order status.
Updated the code for compatibility with WC 3.0+ (2017-06-10)
For me this hook was called even if the payment did not go through or failed, and this resulted to completed failed payments. After some research I changed it to use 'woocommerce_payment_complete' because it's called only when payment is complete and it covers the issue that #LoicTheAztec mentions above –
add_action( 'woocommerce_payment_complete', 'wc_auto_complete_paid_order', 20, 1 );
function wc_auto_complete_paid_order( $order_id ) {
if ( ! $order_id )
return;
// Get an instance of the WC_Product object
$order = wc_get_order( $order_id );
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
if ( in_array( $order->get_payment_method(), array( 'bacs', 'cod', 'cheque', '' ) ) ) {
return;
// Updated status to "completed" for paid Orders with all others payment methods
} else {
$order->update_status( 'completed' );
}
}
For me, the simplest hook to modify order status when payment is completed is 'woocommerce_order_item_needs_processing' as this filter hook is meant to modify the target order status when payment completes.
This is what the final snippet will look alike:
add_filter('woocommerce_order_item_needs_processing', '__return_false',999);
It also compatible with the other plugins on sites.
For me, on a testing system with PayPal Sandbox (WooCommerce PayPal Payments plugin) the LoicTheAztec solution (2019 update) worked only when I added the $order->update_status( 'completed' ); code line. The return 'completed'; has not an effect in my case, I left it just because it's a filter.
add_filter( 'woocommerce_payment_complete_order_status', function( $status, $order_id, $order ) {
$order->update_status( 'completed' );
return 'completed';
}, 10, 3 );
If you are looking for autocompletion of virtual orders (like courses, ebooks, downloadables etc), this might be useful.
* Auto Complete all WooCommerce virtual orders.
*
* #param int $order_id The order ID to check
* #return void
*/
function custom_woocommerce_auto_complete_virtual_orders( $order_id ) {
// if there is no order id, exit
if ( ! $order_id ) {
return;
}
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
if ( in_array( $order->get_payment_method(), array( 'bacs', 'cod', 'cheque', '' ) ) ) {
return;
}
// get the order and its exit
$order = wc_get_order( $order_id );
$items = $order->get_items();
// if there are no items, exit
if ( 0 >= count( $items ) ) {
return;
}
// go through each item
foreach ( $items as $item ) {
// if it is a variation
if ( '0' != $item['variation_id'] ) {
// make a product based upon variation
$product = new WC_Product( $item['variation_id'] );
} else {
// else make a product off of the product id
$product = new WC_Product( $item['product_id'] );
}
// if the product isn't virtual, exit
if ( ! $product->is_virtual() ) {
return;
}
}
/*
* If we made it this far, then all of our items are virual
* We set the order to completed.
*/
$order->update_status( 'completed' );
}
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_virtual_orders' );
Adapted from https://gist.github.com/jessepearson/33f383bb3ea33069822817cfb1da4258

Add custom functionality on WooCommerce complete button

I've a situation to add some data to the database tables on order status completed button.
I can see the url in class-wc-admin-post-types.php
Can someone help me for any hook? Or how the admin-ajax.php works? I have to add status to some of mine custom database tables.
this code will fire a customer's order is set to completed..
add_action( 'woocommerce_order_status_completed', 'custom_task' );
function custom_task( $order_id ) {
// Only continue if have $order_id
if ( ! $order_id ) {
return;
}
// Get order
$order = wc_get_order( $order_id );
// Do your thing
}

Woocommerce custom stock update after successful order

I have a custom database table linked to my Woocommerce tables with some information like SKU and Stock. I want to add custom function to update this table after successful order (when Woocommerce updates product stock). I've tried to do something with this:
add_action( 'woocommerce_reduce_order_stock', 'wpet_testnote' );
function wpet_testnote() {
// Lets grab the order
$order = wc_get_order( $order_id );
$order->add_order_note( 'Stock Updated.' );
I've tried to testing my action with basic order note adding, but it's not working. Any ideas?
you forgot to submit the $order_id. this one works on my end:
add_action( 'woocommerce_reduce_order_stock', 'wpet_testnote' );
function wpet_testnote( $order_id ) {
$order = wc_get_order( $order_id );
$order->add_order_note( 'Stock Updated.' );
}

Categories