I created the plugins and added custom fields on the checkout page like payment_mode & transaction id.
public function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
$order->update_status($this->order_status, __( 'Awaiting payment', 'payment' ));
wc_reduce_stock_levels( $order_id );
$wcorder = wc_get_order($order_id);
$payment_mode = $_POST['payment_mode'];
$transaction = $_POST['transaction'];
if( isset($transaction) && isset($payment_mode) ) {
$wcorder->add_meta_data( 'payment_mode', $payment_mode );
$wcorder->add_meta_data( 'transaction_id', $transaction );
$wcorder->save();
}
}
Here the payment mode & transaction is custom filed, It gets the data from users and adds the database table.
In the above coding, $order->update_status - Its working fine. But $wcorder->add_meta_data is not working. It does not show any error and the data is not added to the table.
Try replacing add_meta_data with update_meta_data.
Alternatively you can try with:
update_post_meta( $order_id, 'payment_mode', $payment_mode );
update_post_meta( $order_id, 'transaction_id', $transaction );
instead of:
$wcorder->add_meta_data( 'payment_mode', $payment_mode );
$wcorder->add_meta_data( 'transaction_id', $transaction );
Related
I am trying to add a custom user meta field to the order meta data.
And I want to add this when I am changing my order status to "wordt-verwerkt" which is a custom order status I added with the WooCommerce plugin for custom order statuses.
I tried to use the code from this post, but I am getting an error when I change my order status.
(I also tried it with the status "processing", and didn't have any success neither)
What I have now is the following code:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
function add_order_meta_from_custom_user_meta( $order, $data ) {
$user_id = $order->get_user_id(); // Get the user id
if( $WefactEmail = get_user_meta( $user_id, 'KVK_nummer_2', true ) ) {
$order->update_meta_data( 'WeFact_email', $WefactEmail );
}
if( isset($WefactEmail) ) {
$order->save();
}
}
There are some mistakes in your code (the hooked function arguments are wrong).
See the related source code for this composite hook located in WC_Order status_transition() method (on line 363):
do_action( 'woocommerce_order_status_' . $status_transition['to'], $this->get_id(), $this );
where $this is $order (the WC_Order Object) and $this->get_id() is $order_id (the order Id).
Use instead the following:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
function add_order_meta_from_custom_user_meta( $order_id, $order ) {
$user_id = $order->get_user_id(); // Get the user id
$wf_email = get_user_meta( $user_id, 'KVK_nummer_2', true );
if( ! empty($wf_email) ) {
$order->update_meta_data( 'WeFact_email', $wf_email );
$order->save();
}
}
or also this works too:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
function add_order_meta_from_custom_user_meta( $order_id, $order ) {
$user_id = $order->get_user_id(); // Get the user id
$wf_email = get_user_meta( $user_id, 'KVK_nummer_2', true );
if( ! empty($wf_email) ) {
update_post_meta( $order_id, 'WeFact_email', $wf_email );
}
}
Code goes in functions.php file of the active child theme (or active theme). both should work.
For processing status, replace:
add_action( 'woocommerce_order_status_wordt-verwerkt', 'add_order_meta_from_custom_user_meta', 10, 2 );
with:
add_action( 'woocommerce_order_status_processing', 'add_order_meta_from_custom_user_meta', 10, 2 );
Here’s the situation: I initially set users that once they have completed a form, their user role is set to "Interviewed".
The problem arises when the subscription payment gets renewed (user role goes back to "Subscriber") or there's some temporary payment renewal issue (user role is set to "Customer").
I need the User's role to stay on "Interviewed" if the Order status is Completed.
So this is what I came up with:
add_action( 'woocommerce_order_status_completed', 'keep_role_interviewed' );
function keep_role_interviewed( $order_id ) {
$order = wc_get_order( $order_id );
if ( $order->user_id > 0 ) {
$user = new WP_User( $order->user_id );
$user_data = array( 'ID' => $user->ID,'role' => 'Interviewed' );
wp_update_user( $user_data );
}
}
But it doesn’t work.
Here I finally made it work.
add_action( 'woocommerce_subscription_status_updated', 'keep_interviewed_role' );
function keep_interviewed_role( $subscription) {
// Get the WC_Order Object from subscription
$order = wc_get_order( $subscription->get_parent_id() );
$order_status = $order->get_status();
// Get an instance of the customer WP_User Object
$user = $order->get_user();
if( is_a( $user, 'WP_User' ) && !in_array('interviewed', $user->roles)
&& $order_status == ('completed')); {
$user->set_role( 'interviewed' );
}
}
I am creating an event ticketing WordPress theme and I am using WooCommerce and Advanced custom fields (ACF) plugins.
I want to update a custom post type called event. With the stock of a specific ticket. That way my client does not need to look at the woo-commerce products page but can just simply open an "Event"
I tried using the update_post_meta hook but that only works when an admin updates the product in the admin tool. Not with a new order.
function sync_product_stock( $meta_id, $post_id, $meta_key, $meta_value ) {
$postType = get_post_type( $post_id );
if ($postType == 'product' ) {
if ( $meta_key == '_stock' ) {
$product = wc_get_product( $post_id );
$eventId = $product->get_attribute( 'event_id' );
$productName = $product->get_name();
if ($productName.include('Early Bird')) {
update_field( 'event_early_bird_group_event_early_bird_amount_of_tickets', $meta_value, $eventId );
} else if ($productName.include('Regular')) {
update_field( 'event_regular_group_event_regular_amount_of_tickets', $meta_value, $eventId );
} else if ($productName.include('Member')) {
// nothing needs to be updated
}
}
}
}
add_action( 'updated_post_meta', 'sync_product_stock', 10, 4);
How can I get notified when the _stock field is updated? (I don't want to handle the stock-keeping myself
There are some mistakes in your code. Try the following using woocommerce hooks:
// On processed update product stock event
add_action( 'woocommerce_updated_product_stock', 'wc_updated_product_stock_callback' );
// On admin single product creation/update
add_action( 'woocommerce_process_product_meta', 'wc_updated_product_stock_callback' );
// On admin single product variation creation/update
add_action( 'woocommerce_save_product_variation', 'wc_updated_product_stock_callback' );
function wc_updated_product_stock_callback( $product_id ) {
// get an instance of the WC_Product Object
$product = wc_get_product( $product_id );
$stock_qty = $product->get_stock_quantity();
$event_id = $product->get_attribute('event_id');
$product_name = $product->get_name();
if ( strpos($product_name, 'Early Bird') !== false ) {
update_field( 'event_early_bird_group_event_early_bird_amount_of_tickets', $stock_qty, $event_id );
} elseif ( strpos($product_name, 'Regular') !== false ) {
update_field( 'event_regular_group_event_regular_amount_of_tickets', $stock_qty, $event_id );
} elseif ( strpos($product_name, 'Member') !== false ) {
// nothing needs to be updated
}
}
Code goes in function.php file of the active child theme (or active theme). It should work.
I am creating a payment gateway for woocommerce but I am facing an issue that after successful payment I am redirecting to thank you page and my order status is not updating to 'processing' or 'completed'.
I am using woocommerce_thankyou hook in my plugins main file.
add_action( 'woocommerce_thankyou_epg', 'my_change_status_function', 10, 1 );
function my_change_status_function( $order_id ) {
$order = new WC_Order( $order_id );
$order->update_status( 'processing', __( 'Payment received.', 'wc-gateway-offline' ) );
}
Actually in this functions before updating the status I want to send a API call to check the status of the payment and than according to the response I want to update the status of the order.
Can anybody help me in sorting this out.
Change the hook to:
add_action( 'woocommerce_thankyou', 'my_change_status_function', 20, 1 );
function my_change_status_function( $order_id ) {
$order = new WC_Order( $order_id );
$order_pay_method = get_post_meta( $order->id, '_payment_method', true );
if($order_pay_method == 'epg'){
$order->update_status( 'processing', __( 'Payment received.', 'wc-gateway-offline' ) );
}
}
Corrected the hook.
add_action( 'woocommerce_thankyou', 'my_change_status_function', 10, 1 );
function my_change_status_function( $order_id ) {
$order = new WC_Order( $order_id );
$order->update_status( 'processing', __( 'Payment received.', 'wc-gateway-offline' ) );
}
I'm using this little peace of code on WooCommerce from this answer to auto-complete paid processing orders based on payment gateways:
/**
* 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 ( ( get_post_meta($order->id, '_payment_method', true) == 'bacs' ) || ( get_post_meta($order->id, '_payment_method', true) == 'cod' ) || ( get_post_meta($order->id, '_payment_method', true) == 'cheque' ) ) {
return;
}
// "completed" updated status for paid Orders with all others payment methods
else {
$order->update_status( 'completed' );
}
}
This is working mostly perfect
Mainly using a special payment gateway by SMS which API is bridged on 'cod' payment method and that can process payment after 'woocommerce_thankyou, out side frontend. In that case the ON HOLD status orders are passed afterward to PROCESSING status. To automate an autocomplete behavior on those cases, I use this other peace of code from this answer and it works:
function auto_update_orders_status_from_processing_to_completed(){
// Get all current "processing" customer orders
$processing_orders = wc_get_orders( $args = array(
'numberposts' => -1,
'post_status' => 'wc-processing',
) );
if(!empty($processing_orders))
foreach($processing_orders as $order)
$order->update_status( 'completed' );
}
add_action( 'init', 'auto_update_orders_status_from_processing_to_completed' );
THE PROBLEM: I am getting repetitive emails notifications concerning the new completed orders.
How can I avoid this repetitive email notifications cases?
Thanks
Updated (2019)
Added version code for Woocommerce 3+ - Added Woocommerce version compatibility.
To avoid this strange fact of repetitive email notifications, is possible to create a custom meta key/value for each processed order, when changing order status to completed, using WordPress update_post_meta() function. Then we will test before in a condition, if this custom meta data key/value exist with get_post_meta() function for each processed order.
So your two code snippets will be now:
1) AUTO COMPLETE PAID ORDERS IN WOOCOMMERCE (2019 update)
For woocommerce 3+:
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
if ( ! $order->has_status('completed') && $order->get_meta('_order_processed') != 'yes') {
$order->update_meta_data('_order_processed', 'yes');
$status = 'completed';
}
return $status;
}
For all woocommerce versions (compatibility since version 2.5+):
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order = null ) {
// Getting the custom meta value regarding this autocomplete status process
$order_processed = get_post_meta( $order_id, '_order_processed', true );
// Getting the WC_Order object from the order ID
$order = wc_get_order( $order_id );
if ( ! $order->has_status( 'completed' ) && $order_processed != 'yes' ) {
$order = wc_get_order( $order_id );
// setting the custom meta data value to yes (order updated)
update_post_meta($order_id, '_order_processed', 'yes');
$order->update_status( 'completed' ); // Update order status to
}
return $status;
}
2) SCAN ALL "processing" orders to auto-complete them (added Woocommerce compatibility)
add_action( 'init', 'auto_update_orders_status_from_processing_to_completed' );
function auto_update_orders_status_from_processing_to_completed(){
if( version_compare( WC_VERSION, '3.0', '<' ) {
$args = array('numberposts' => -1, 'post_status' => 'wc-processing'); // Before WooCommerce version 3
} else {
$args = array('limit' => -1, 'status' => 'processing'); // For WooCommerce 3 and above
}
// Get all current "processing" customer orders
$processing_orders = (array) wc_get_orders( $args );
if( sizeof($processing_orders) > 0 ){
foreach($processing_orders as $order ) {
// Woocommerce compatibility
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Checking if this custom field value is set in the order meta data
$order_processed = get_post_meta( $order_id, '_order_processed', true );
if (! $order->has_status( 'completed' ) && $order_processed != 'yes' ) {
// Setting (updating) custom meta value in the order metadata to avoid repetitions
update_post_meta( $order_id, '_order_processed', 'yes' );
$order->update_status( 'completed' ); // Updating order status
}
}
}
}
Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.
I have test this code and it should work for you (due to your particular SMS bridged payment method)