Last active
July 19, 2024 16:21
-
-
Save damiencarbery/bb51c59f227683135e88e29264afc453 to your computer and use it in GitHub Desktop.
View WooCommerce order on front end - Use an encrypted link to allow a customer view order details on the front end. https://www.damiencarbery.com/2024/01/view-woocommerce-order-on-front-end/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: View WooCommerce order on front end | |
Plugin URI: https://www.damiencarbery.com/2024/01/view-woocommerce-order-on-front-end/ | |
Description: Use an encrypted link to allow a customer view order details on the front end. | |
Author: Damien Carbery | |
Author URI: https://www.damiencarbery.com | |
Version: 0.3.20240719 | |
WC tested to: 9.1.2 | |
Requires Plugins: woocommerce | |
*/ | |
defined( 'ABSPATH' ) || exit; | |
class ViewOrderOnFrontEnd { | |
// Returns an instance of this class. | |
public static function get_instance() { | |
if ( null == self::$instance ) { | |
self::$instance = new self; | |
} | |
return self::$instance; | |
} | |
// Initialize the plugin variables. | |
public function __construct() { | |
$this->init(); | |
} | |
// Set up WordPress specfic actions. | |
public function init() { | |
add_action( 'init', array( $this, 'init_rewrite_tag' ) ); | |
add_action( 'woocommerce_email_order_details', array( $this, 'add_view_order_info_to_order_email' ), 5, 4 ); | |
add_shortcode( 'view_order', array( $this, 'view_order_shortcode' ) ); | |
// Handle submissions from form in the [view_order] page. 'action' is 'view_order'. | |
add_action( 'admin_post_nopriv_view_order', array( $this, 'validate_submitted_order_info' ) ); | |
add_action( 'admin_post_view_order', array( $this, 'validate_submitted_order_info' ) ); | |
} | |
public function init_rewrite_tag() { | |
// Make WordPress aware of custom 'view_order' querystring variable. | |
add_rewrite_tag( '%view_order%', '([^&]+)'); | |
} | |
// Find ID of page with [view_order] shortcode. | |
private function find_view_order_shortcode() { | |
$args = array( 'post_type'=>'page', 'posts_per_page' => 1, 'fields' => 'ids', 's' => '[view_order]', 'no_found_rows' => true, 'update_post_term_cache' => false, 'update_post_meta_cache' => false ); | |
$shortcode_query = new WP_Query( $args ); | |
$shortcode_pages = $shortcode_query->posts; // This is the 'loop'! | |
wp_reset_postdata(); | |
if ( empty( $shortcode_pages ) ) { | |
return false; | |
} | |
else { | |
return $shortcode_pages[0]; | |
} | |
} | |
// Generate the encoded url | |
public function get_view_order_url( $order_id, $order_email ) { | |
$view_order_page_id = $this->find_view_order_shortcode(); // ID of page with [view_order] shortcode. | |
if ( ! $view_order_page_id ) { return; } // Quit if no page has [view_order]. | |
$param = $order_id . '|' . $order_email; | |
$encoded = bin2hex( $param ); // See: https://stackoverflow.com/questions/14086970/php-encode-e-mail-address | |
return esc_url( add_query_arg( 'view_order', $encoded, get_permalink( $view_order_page_id ) ) ); | |
} | |
// Add link to view order without logging in. | |
public function add_view_order_info_to_order_email( $order, $sent_to_admin, $plain_text, $email ) { | |
// Can limit this to specific emails. | |
//if ( 'customer_completed_order' != $email->id ) { return; } | |
$view_order_url = $this->get_view_order_url( $order->get_id(), $order->get_billing_email() ); | |
if ( empty( $view_order_url ) ) { return; } // Quit if no page has [view_order]. | |
if ( $plain_text ) { | |
printf( 'View order and status at: %s%s', $view_order_url, "\n\n" ); | |
} | |
else { | |
printf( '<p><a href="%s"><button>View order and status</button></a>.</p>', $view_order_url ); | |
} | |
} | |
// Process the shortcode. | |
public function view_order_shortcode() { | |
ob_start(); | |
?> | |
<style> | |
form.view_order { display: flex; gap: 1em; margin-bottom: 2em; } | |
@media(max-width: 767px){ | |
form.view_order { flex-wrap: wrap; } | |
form.view_order input { width: 100%; } | |
} | |
</style> | |
<form class="view_order" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post"> | |
<input type="number" required name="order_id" placeholder="Enter order number" /> | |
<input type="email" required name="order_email" placeholder="Enter order email address" /> | |
<input type="hidden" name="action" value="view_order" /> | |
<button type="submit">View Order</button> | |
</form> | |
<?php | |
if ( get_query_var( 'view_order' ) ) { | |
$decoded = hex2bin( get_query_var( 'view_order' ) ); | |
if ( $decoded ) { | |
// Validate and sanitise the order id and email. | |
$id_and_email = explode( '|', $decoded ); | |
$order_id = isset( $id_and_email[0] ) ? (int) filter_var( $id_and_email[0], FILTER_SANITIZE_NUMBER_INT ) : false; | |
$order_email = isset( $id_and_email[1] ) ? filter_var( $id_and_email[1], FILTER_VALIDATE_EMAIL ) : false; | |
$order = wc_get_order( $order_id ); | |
if ( $order && $order_email == $order->get_billing_email() ) { | |
// Remove the 'Order again' button as the user is not logged in when viewing this page. | |
remove_action( 'woocommerce_order_details_after_order_table', 'woocommerce_order_again_button' ); | |
// In woocommerce/templates/order/order-details.php the customer details are shown only when | |
// the user is logged and the user ID matches the order user ID. As this plugin may be used | |
// when users are not logged in, we override this behaviour. | |
if ( !is_user_logged_in() || $order->get_user_id() !== get_current_user_id() ) { | |
add_action( 'woocommerce_after_order_details', array( $this, 'show_order_customer_details' ), 100 ); | |
} | |
// Code below copied from woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php | |
// The deprecated 'status' parameters have been removed. | |
// This will render the same info as My Account/Orders/View Order. | |
// Any custom actions that run there will run here. | |
wc_get_template( | |
'myaccount/view-order.php', | |
array( | |
'order' => $order, | |
'order_id' => $order->get_id(), | |
) | |
); | |
} | |
else { | |
echo '<p>Error: Invalid data provided in the url. Please contact the store.</p>'; | |
} | |
} | |
else { | |
echo '<p>Error: Invalid data provided in the url. Please contact the store.</p>'; | |
} | |
} | |
return ob_get_clean(); | |
} | |
// Manually display order customer details as the WooCommerce template will not when the user | |
// is not logged in. | |
public function show_order_customer_details( $order ) { | |
wc_get_template( 'order/order-details-customer.php', array( 'order' => $order ) ); | |
} | |
// Sanitize the data submitted in the View Order form, then redirect to the View Order page. | |
// Note that the data is not validated! If invalid data is submitted the error message | |
// displayed in view_order_shortcode() will not be very helpful. Ajax submission would have | |
// a better UX but it is a good bit more work. | |
public function validate_submitted_order_info() { | |
$order_id = isset( $_REQUEST['order_id'] ) ? (int) filter_var( $_REQUEST['order_id'], FILTER_SANITIZE_NUMBER_INT ) : false; | |
$order_email = isset( $_REQUEST['order_email'] ) ? filter_var( $_REQUEST['order_email'], FILTER_VALIDATE_EMAIL ) : false; | |
// Redirect to the page with the [view_order] shortcode. The encoded order ID and email are in the url. | |
$redirect_url = $this->get_view_order_url( $order_id, $order_email ); | |
if ( empty( $redirect_url ) ) { $redirect_url = home_url(); } | |
wp_redirect( $redirect_url ); | |
} | |
} | |
$ViewOrderOnFrontEnd = new ViewOrderOnFrontEnd(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment