Redirecting customers to custom page after sale in WooCommerce - wordpress

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
}
}

Related

I need create custom order tracking functionality in woo commerce

Hello I have a woo commerce website and I am selling some books every thing is cleared but I need create custom order tracking functionality in woo commerce code to add order tracking functionality for end user is it possible if possible how can I do this please help me.
I create a custom page name as woocommerce-custom-order-tracking.php
and code is given below
<?php
// Register a custom endpoint to handle order tracking
function wc_register_order_tracking_endpoint() {
add_rewrite_endpoint( 'order-tracking', EP_PAGES );
}
add_action( 'init', 'wc_register_order_tracking_endpoint' );
// Display the order tracking form
function wc_display_order_tracking_form() {
if ( ! is_wc_endpoint_url( 'order-tracking' ) ) {
return;
}
// Get the order id from the query string
$order_id = absint( $_GET['order_id'] );
// Get the order
$order = wc_get_order( $order_id );
if ( $order ) {
// Display the order tracking information
echo '<p>Order Number: ' . $order->get_order_number() . '</p>';
echo '<p>Order Status: ' . wc_get_order_status_name( $order->get_status() ) . '</p>';
echo '<p>Tracking Number: ' . get_post_meta( $order_id, '_tracking_number', true ) . '</p>';
} else {
echo '<p>Invalid order ID.</p>';
}
}
add_action( 'woocommerce_before_single_product', 'wc_display_order_tracking_form' );

Hide item meta data in certain WooCommerce email notifications

I've got this code snippet in my functions.php file:
add_action( 'woocommerce_checkout_create_order_line_item', 'add_custom_field_to_order_item_meta', 10, 4 );
function add_custom_field_to_order_item_meta( $item, $cart_item_key, $values, $order ) {
$custom_field_value = get_post_meta( $item->get_product_id(), 'supplier_sku', true );
if ( ! empty($custom_field_value) ){
$item->update_meta_data( __('Supplier SKU', 'woocommerce'), $custom_field_value );
}
}
It pulls in the custom field on products, called Supplier SKU and then adds it to the WooCommerce email notifications. Which is fine, but I want to exclude it from the customer email notification and only have it display in the admin email notification.
How can I achieve this?
You could use the woocommerce_display_item_meta hook and return an empty string
function filter_woocommerce_display_item_meta ( $html, $item, $args ) {
$html = '';
return $html;
}
add_filter( 'woocommerce_display_item_meta', 'filter_woocommerce_display_item_meta', 10, 3 );
While the above would work, there would be some issues, namely:
The hook doesn't run just for email notifications, so it wouldn't show up anywhere
Even if this hook would only be executed for email notifications, we would still need to specify that this should only be the case for certain email notifications. However, this hook does not offer a solution for it by default to make this distinction
So a workaround will be needed, this can be done by creating a global variable through another hook that applies only to email notifications
Step 1) creating and adding a global variable
// Setting global variable
function action_woocommerce_email_before_order_table( $order, $sent_to_admin, $plain_text, $email ) {
$GLOBALS['email_id'] = $email->id;
}
add_action( 'woocommerce_email_before_order_table', 'action_woocommerce_email_before_order_table', 1, 4 );
Step 2) In the hook woocommerce_display_item_meta, add and check for specific conditions
Only for email notifications
Only for specific meta data
Only for admin 'new order' email
function filter_woocommerce_display_item_meta ( $html, $item, $args ) {
// For email notifications and specific meta
if ( ! is_wc_endpoint_url() && $item->is_type( 'line_item' ) && $item->get_meta( 'Supplier SKU' ) ) {
// Getting the email ID global variable
$ref_name_globals_var = isset( $GLOBALS ) ? $GLOBALS : '';
$email_id = isset( $ref_name_globals_var['email_id'] ) ? $ref_name_globals_var['email_id'] : '';
// NOT empty and targeting specific email. Multiple statuses can be added, separated by a comma
if ( ! empty ( $email_id ) && ! in_array( $email_id, array( 'new_order' ) ) ) {
$html = '';
}
}
return $html;
}
add_filter( 'woocommerce_display_item_meta', 'filter_woocommerce_display_item_meta', 10, 3 );

WooCommerce add to cart redirect hook with a query parameter passed

I am trying to use woocommerce_add_to_cart_redirect to redirect the user to the product page, and add a custom query data.
function my_custom_add_to_cart_redirect( $url ) {
$currentProductUrl = "";
$redirectUrl = esc_url( add_query_arg('cart', true, $currentProductUrl ));
return $redirectUrl;
}
add_filter( 'woocommerce_add_to_cart_redirect', __NAMESPACE__ .'\\my_custom_add_to_cart_redirect' );
How do I get $currentProductUrl ??
In woocommerce_add_to_cart_redirect hook, there is an additional argument only on normal add to cart (not with Ajax add to cart) that is the WC_Product Object instance.
This way you can get the product permalink and add to it your query arguments only on single add to cart.
add_filter( 'woocommerce_add_to_cart_redirect', 'my_custom_add_to_cart_redirect', 10, 2 );
function my_custom_add_to_cart_redirect( $url, $product ) {
if ( $product && is_a( $product, 'WC_Product' ) ) {
$url = esc_url( add_query_arg('cart', true, $product->get_permalink() ) );
}
return $url;
}
For Ajax add to cart that argument is null (see that in here).

How to save Meta Data in WordPress back-end with PHP

I am relatively new to Post Meta Data in the WordPress backend using PHP. I have written the code that creates the Meta Data. I need help saving the data for which I have written. It will also need to allow me to edit the data once saved.
In this case its for a text field.
I have created the Meta Data for the input field which displays well in the back-end WordPress admin area.
add_action( 'add_meta_boxes', 'cd_meta_box_add' );
function cd_meta_box_add()
{
add_meta_box( 'my-meta-box-id', 'Job Title', 'cd_meta_box_cb', 'people', 'normal', 'high' );
/* Save post meta on the 'save_post' hook. */
add_action( 'save_post', 'cd_meta_box_add', 10, 2 );
}
function cd_meta_box_cb()
{
echo "<input type='text' name='jobtitle'>";
}
I just need assistance with the code that will save the above Meta Data to the DB and allow for editing and revisions
You were almost there.
The final part of the puzzle is the function that saves the metadata, but first we need to make a few adjustments to your existing code:
add_action( 'save_post', 'cd_meta_box_add', 10, 2 ); has to be moved outside cd_meta_box_add(), and
Change add_action( 'save_post', 'cd_meta_box_add', 10, 2 ); into add_action( 'save_post', 'cd_meta_box_add' ); as this action hook only receives one parameter (the post ID), and
You need to define the function that will process the data (and it can't be cd_meta_box_add as you have it now so we'll create a new one called save_cd_meta_box_data).
/* Save post meta on the 'save_post' hook. */
add_action( 'save_post', 'save_cd_meta_box_data' );
function save_cd_meta_box_data( $post_id ) {
// Autosaving, bail.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// #TODO
// You should add some additional security checks here
// eg. nonce, user capabilities, etc, to prevent
// malicious users from doing bad stuff.
/* OK, it's safe for us to save the data now. */
// Make sure that it is set.
if ( ! isset( $_POST['jobtitle'] ) ) {
return;
}
// Sanitize user input.
$my_data = sanitize_text_field( $_POST['jobtitle'] );
// Update the meta field in the database.
update_post_meta( $post_id, '_job_title', $my_data );
}
Now that we're successfully saving the metadata into the database, let's allow the user to view it / edit it:
function cd_meta_box_cb( $post )
{
$job_title = get_post_meta( $post->ID, '_job_title', true );
echo "<input type='text' name='jobtitle' value='" . esc_attr( $job_title ) . "'>";
}
The final code should look like this:
/* Register and display metabox */
add_action( 'add_meta_boxes', 'cd_meta_box_add' );
function cd_meta_box_add()
{
add_meta_box( 'my-meta-box-id', 'Job Title', 'cd_meta_box_cb', 'people', 'normal', 'high' );
}
function cd_meta_box_cb( $post )
{
$job_title = get_post_meta( $post->ID, '_job_title', true );
echo "<input type='text' name='jobtitle' value='" . esc_attr( $job_title ) . "'>";
}
/* Save post meta on the 'save_post' hook. */
add_action( 'save_post', 'save_cd_meta_box_data' );
function save_cd_meta_box_data( $post_id ) {
// Autosaving, bail.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// #TODO
// You should add some additional security checks here
// eg. nonce, user capabilities, etc, to prevent
// malicious users from doing bad stuff.
/* OK, it's safe for us to save the data now. */
// Make sure that it is set.
if ( ! isset( $_POST['jobtitle'] ) ) {
return;
}
// Sanitize user input.
$my_data = sanitize_text_field( $_POST['jobtitle'] );
// Update the meta field in the database.
update_post_meta( $post_id, '_job_title', $my_data );
}

Bulk action for custom post types

I am working on a wordpress project and I want to add the bulk action on my custom post.
I have used Custom Post Type UI plugin for custom post and Advanced Custom Fields plugin for custom fields.
Please suggest me any code or plugin to add bulk action for my custom posts.
Thanks,
Aniket.
Since WordPress 4.7 (released December 2016) it is possible to add custom bulk actions without using JavaScript.
//Hooks
add_action( 'current_screen', 'my_bulk_hooks' );
function my_bulk_hooks() {
if( current_user_can( 'administrator' ) ) {
add_filter( 'bulk_actions-edit-post', 'register_my_bulk_actions' );
add_filter( 'handle_bulk_actions-edit-post', 'my_bulk_action_handler', 10, 3 );
add_action( 'admin_notices', 'my_bulk_action_admin_notice' );
}
}
//Register
function register_my_bulk_actions($bulk_actions) {
$bulk_actions['email_to_eric'] = __( 'Email to Eric', 'text_domain');
return $bulk_actions;
}
//Handle
function my_bulk_action_handler( $redirect_to, $doaction, $post_ids ) {
if ( $doaction !== 'email_to_eric' ) {
return $redirect_to;
}
foreach ( $post_ids as $post_id ) {
// Perform action for each post.
}
$redirect_to = add_query_arg( 'bulk_emailed_posts', count( $post_ids ), $redirect_to );
return $redirect_to;
}
//Notices
function my_bulk_action_admin_notice() {
if ( ! empty( $_REQUEST['bulk_emailed_posts'] ) ) {
$emailed_count = intval( $_REQUEST['bulk_emailed_posts'] );
printf( '<div id="message" class="updated fade">' .
_n( 'Emailed %s post to Eric.',
'Emailed %s posts to Eric.',
$emailed_count,
'text_domain'
) . '</div>', $emailed_count );
}
}
Note.1: You must use bulk_actions filters when WP_Screen object is defined.That's why I used current_screen action in line 2.
Note.2: if you want to add bulk action to custom page like woocommerce products page just change screen id in line 5 & 6. Ex:
add_filter( 'bulk_actions-edit-product', 'register_my_bulk_actions' );
add_filter( 'handle_bulk_actions-edit-product', 'my_bulk_action_handler', 10, 3 );
More information :
Using Custom Bulk Actions
https://make.wordpress.org/core/2016/10/04/custom-bulk-actions/
use "register_post_type" of WordPress function, It easier than the additional plugins
Reference: https://codex.wordpress.org/Function_Reference/register_post_type

Resources