Woocommerce_payment_complete Fires After Order Received Page Is Already Shown

I'm trying to integrate a loyalty card into a WooCommerce webshop. When an order is completed, I call their API to generate the loyalty points, and store the token in a meta tag for the order. On the order confirmation page and email I want to show the QR code for the loyalty points using the token stored in the meta tag.

Everything works, except the confirmation page is shown before the token is generated and therefore cannot show the QR code.

  1. I create the token using the woocommerce_payment_complete action.
add_action( 'woocommerce_payment_complete', 'get_loyalty_token');
function get_loyalty_token( $order_id ){

    $order = wc_get_order( $order_id );
    if ( $order ) {
        $total = $order->get_total();

        $loyalty= new Loyalty(); 
        $loyalty->create_code( $total, 'webshop-' . $order->get_id() );

        $token = $loyalty->get_token() ?: '';

        add_post_meta( $order->get_id(), 'meta_loyalty_token', $token );
  1. In the order-details.php template I added this code to load and show the QR code (same for the confirmation e-mail.
$token = get_post_meta( $order->get_id(), 'meta_loyalty_token', TRUE);

$loyalty= new Loyalty(); 

echo $loyalty->html_block();

When the order confirmation is shown, there is no QR code, because the meta_loyalty_token is not set yet. If I reload the confirmation page, the QR code is shown, because by then, the token is generated and stored.

Is there an other action I should use instead of woocommerce_payment_complete? Or is there a way to show the confirmation page only after this action is completed?



You could use the woocommerce_checkout_update_order_meta hook instead.

So you get:

 * Action hook fired after an order is created used to add custom meta to the order.
 * @since 3.0.0
function action_woocommerce_checkout_update_order_meta( $order_id, $data ) {
    // Get $order object
    $order = wc_get_order( $order_id );
    // Is a WC_Order
    if ( is_a( $order, 'WC_Order' ) ) {
        // Get total
        $total = $order->get_total();

        $loyalty = new Loyalty(); 
        $loyalty->create_code( $total, 'webshop-' . $order_id );

        $token = $loyalty->get_token();
        // Update meta
        update_post_meta( $order_id, 'meta_loyalty_token', $token );
add_action( 'woocommerce_checkout_update_order_meta', 'action_woocommerce_checkout_update_order_meta', 10, 2 );