Skip to content

Instantly share code, notes, and snippets.

@damiencarbery
Last active January 19, 2024 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save damiencarbery/bb51c59f227683135e88e29264afc453 to your computer and use it in GitHub Desktop.
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/
<?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.2
WC tested to: 8.5.1
*/
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' ) );
do_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; }
</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