Our scenario is:
The guest user enters the site and places one or more orders without the need to register. And after a while, he decides to register on the site.
Now how to link guest orders to customer account after registeration?
I use the following code, but this code only works for users who have already registered but did not log in at the time of purchase. Any advice?
//assign user in guest order
add_action( 'woocommerce_new_order', 'action_woocommerce_new_order', 10, 1 );
function action_woocommerce_new_order( $order_id ) {
$order = new WC_Order($order_id);
$user = $order->get_user();
if( !$user ){
//guest order
$userdata = get_user_by( 'email', $order->get_billing_email() );
if(isset( $userdata->ID )){
//registered
update_post_meta($order_id, '_customer_user', $userdata->ID );
}else{
//Guest
}
}
}
You can use the woocommerce_created_customer action hook and the wc_update_new_customer_past_orders() function
So you get:
function action_woocommerce_created_customer( $customer_id, $new_customer_data, $password_generated ) {
// Link past orders to this newly created customer
wc_update_new_customer_past_orders( $customer_id );
}
add_action( 'woocommerce_created_customer', 'action_woocommerce_created_customer', 10, 3 );
Related
I'm trying to learn WooCommerce and WordPress plugins so I'm tweaking around. I'm trying to create a plugin that redirects customer to a custom page after checkout. The custom page/url can be defined when I create the product. Here is my code:
<?php
/*
Plugin Name: Custom Redirect After Sale
Description: Redirects customers to a custom page after a successful sale.
*/
// Register a new meta field for products
add_action( 'add_meta_boxes', 'custom_redirect_meta_box' );
function custom_redirect_meta_box() {
add_meta_box( 'custom_redirect_meta_box', 'Custom Redirect URL', 'custom_redirect_meta_box_callback', 'product', 'side' );
}
function custom_redirect_meta_box_callback( $post ) {
$value = get_post_meta( $post->ID, '_custom_redirect_url', true );
echo '<label for="custom_redirect_url">Custom Redirect URL:</label>';
echo '<input type="text" id="custom_redirect_url" name="custom_redirect_url" value="' . esc_attr( $value ) . '" style="width:100%">';
}
// Save the meta field value when the product is saved
add_action( 'save_post_product', 'save_custom_redirect_meta_box_data' );
function save_custom_redirect_meta_box_data( $post_id ) {
if ( isset( $_POST['custom_redirect_url'] ) ) {
update_post_meta( $post_id, '_custom_redirect_url', sanitize_text_field( $_POST['custom_redirect_url'] ) );
}
}
// Redirect to the custom page after a successful sale
add_action( 'woocommerce_payment_complete', 'custom_redirect_after_sale' );
function custom_redirect_after_sale( $order_id ) {
$order = wc_get_order( $order_id );
//$order->update_status( 'completed' );
$items = $order->get_items();
// Get the first product in the order
$product = reset($items);
// Get the custom redirect URL for the product
//$redirect_url = get_post_meta( $product->get_product_id(), '_custom_redirect_url', true );
$redirect_url = get_post_meta( $product->get_id(), '_custom_redirect_url', true );
//echo "Meta retrieved: " . $redirect_url;
//error_log("callback fired");
//echo "Payment complete ho ho ho";
if( $redirect_url ) {
wp_redirect( $redirect_url );
exit;
}
}
It seems the woocommerce_payment_complete hook is not firing. I tried to echo out the redirect url and text but it doesn't seem to work.
I'm on localhost and I'm using the cash on delivery payment method.
Basing this answer on the great https://rudrastyh.com/ - specifically this tutorial https://rudrastyh.com/woocommerce/thank-you-page.html#redirects this is the code that should work for what you are trying to do.
First, you hook into the template_redirect action to determine the URL where the customer needs to go
Getting the Order ID, you can get the products purchased for that order
Once you have the purchased products, you can get their ID and meta data, the redirect URL you saved for each. Note that while you use WP functions for handling meta, when working with WooCommerce it is best practice to use its CRUD methods. In case in the future they port products to custom tables, your code will continue working.
Implement the redirect with the WP function wp_safe_redirect
Note that what you are trying to achieve will have problems if customers purchase orders with more than 1 product, and you have more than 1 redirect URL. In this implementation, the first product in the order that has a saved redirect URL will override all others
add_action( 'template_redirect', 'purchased_product_redirect');
function purchased_product_redirect(){
if( !function_exists( 'is_wc_endpoint_url' )){
return;
}
// do nothing if we are not on the order received page
if( ! is_wc_endpoint_url( 'order-received' ) || empty( $_GET[ 'key' ] ) ) {
return;
}
// Get the order ID
$order_id = wc_get_order_id_by_order_key( $_GET[ 'key' ] );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get and Loop Over Order Items
foreach ( $order->get_items() as $item_id => $item ) {
$product_id = $item->get_product_id();
$product = wc_get_product($product_id);
if(!$product){
continue;
}
//Get the first product's redirect URL
$product_redirect_url = $product->get_meta('_custom_redirect_url');
if(!$product_redirect_url){
continue;
}
wp_safe_redirect( $product_redirect_url );
exit; // always exit after using wp_safe_redirect
}
}
I'm using Gifting for WooCommerce Subscriptions which makes it possible for one person to purchase a subscription product for someone else.
When the subscription is purchased, I add a user role to the user who purchased the product:
add_action( 'woocommerce_order_status_completed', 'add_role_on_purchase' );
function add_role_on_purchase( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
$products_to_check = array( '12345' );
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id );
// Add role
$user->add_role( 'purchaser' );
// Exit the loop
break;
}
}
}
Gifting for WooCommerce Subscriptions creates a user and a user account for the recipient.
I need to add a user role to the recipient as well. Can this be done after the purchaser's subscription is set to active?
Buying a subscription as a gift, a buyer provides a recipient's email address. You can take the provided email and find the recipient using the get_user_by() function. Having a WP_User instance of the recipient, you can repeat the same logic you do for buyers.
A recipient email address provided by a buyer is probably stored somewhere in an order's meta.
This code change order first and last name after order via rest api. I want to echo the billing first name where it says "asd". olso i need to other meta related to billing information.
add_action( 'woocommerce_payment_complete', 'digger_checkout_save_user_meta');
function digger_checkout_save_user_meta( $order_id ) {
//$order = wc_get_order( $order_id );
// $user_id = $order->get_user_id();
update_post_meta($order_id, '_billing_first_name', 'asd' );
update_post_meta($order_id, '_billing_last_name','bsd' );
}
i try this update_post_meta($order_id, '_billing_first_name', 'billing_first_name' ); but it doesnt work :) thx a lot for your replay.
In our store, during checkout for every customer we create account automatically if it doesn’t already exist with same email. Now I’m looking for a way to somehow display label tag or little notice on orders list if it comes from already existing customer (returning) because these orders are handled a little differently.
Does anybody have an idea how to do that?
Thanks in advance
this snippet adds a column to orders list page in woocommerce backend and checks if customer is returning or not
add_filter( 'manage_shop_order_posts_columns', 'shalior_wc_set_custom_edit_post_columns',99,1 );
function shalior_wc_set_custom_edit_post_columns($columns) {
$columns['is-returning'] = __( 'Is returning?', 'your_text_domain' );
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column' , 'shalior_wc_is_returning', 99, 2 );
function shalior_wc_is_returning( $column, $post_id ) {
switch ( $column ) {
case 'is-returning':
$order = new WC_Order( $post_id );
$user_id = $order->get_user_id();
$orders_count = wc_get_customer_order_count( $user_id );
echo $orders_count > 1 ? "Yes" : "NO" ;
break;
}
}
I am trying to attach the billing company to the admin email. I am using this script
add_action( 'user_register', array( $this, 'user_register' ) );
function user_register( $user_id ) {
// using this function to send the email
$this->send_notification( 'admin-user', $user_id );
}
public function send_notification( $setting, $id ) {
$user_company = get_user_meta($id, 'billing_company');
wp_mail( $email, $subj, $msg.$user_company[0], $headers );
}
the issue is that get_user_meta returns empty because according to wordpress doc when you use 'user_register' action Not all user meta data has been stored. So basically when user register the usermeta table is still empty because I tried to put an existing user id and it worked fine.
https://codex.wordpress.org/Plugin_API/Action_Reference/user_register.
can anyone suggest a way to send the company name in the admin notification email?
If you are using custom registration form, you can send the email before updating the database.
add_action( 'user_register', array( $this, 'user_register' ) );
function user_register( $user_id ) {
$billing_company = $_POST['billing_company'];
wp_mail( $email, $subj, $billing_company, $headers );
}
Alternatively, you can delay the execution of the function with sleep:
add_action( 'user_register', array( $this, 'user_register' ) );
function user_register( $user_id ) {
sleep(5);
$this->send_notification( 'admin-user', $user_id );
}