When a particular order status is triggered, a custom email is sent to the shopper. I would like to include a link in the email for them to pay for the order.

From my current understanding, the payment URL should look something like:

http://www.example.com/checkout/order-pay/[order number here]

Here is my function which sends the email and generates the payment URL:

add_action("woocommerce_order_status_changed", "my_notification");

function my_notification($order_id) {
   global $woocommerce;
   $order = new WC_Order( $order_id );
   if($order->status === 'prop' ) {
      $payment_page = get_permalink( woocommerce_get_page_id( 'pay' ) ) . '/order-pay/' . $order->get_order_number();

      // Create a mailer
      $mailer = $woocommerce->mailer();

      $message_body = __( 'My message to the shopper with payment <a href="'.$payment_page.'">link</a>' );

      $message = $mailer->wrap_message(
      // Message head and message body.
      sprintf( __( 'Order %s received' ), $order->get_order_number() ), $message_body );

      // Send email
      $mailer->send( $order->billing_email, sprintf( __( 'Order %s received' ), $order->get_order_number() ), $message );

      // Set status to pending payment

The above generates the URL as I expect it to, however when browsing to the generated URL, I get the Woocommerce error:

Sorry, this order is invalid and cannot be paid for.

I have also tried:

$checkout_url = $woocommerce->cart->get_checkout_url();

Which ends up with a fatal error when the order status is triggered:

Call to a member function get_checkout_url() on a non-object in ... functions.php on line ...

How would I generate a valid payment URL for an order?


The correct method for generating a payment URL is:


So my code changed to to:

$payment_page = $order->get_checkout_payment_url();

Which generates the following URL:


Which is what I was looking for.

Note that the order status must be set to unpaid or pending in order for the generated link to be valid

Not the answer you're looking for? Browse other questions tagged or ask your own question.