成功结帐后获取订单数据的钩子

34
在WooCommerce中,我希望在客户成功结账后向API发送请求。基本上,这是一个网站,客户在线销售课程(类似于 udemy)。

当客户结账时,我想发送API请求并为该特定课程注册用户。我尝试了几个WooCommerce钩子,但都没有起作用。

这是我正在使用的代码:

add_action('woocommerce_checkout_order_processed', 'enroll_student', 10, 1);

function enroll_student($order_id)
{
    echo $order_id;
    echo "Hooked";
}

我正在为一个插件编写代码,为了让它更容易,目前我正在使用货到付款的方法。

有人可以告诉我哪里出错了吗?因为当我结帐时,我看不到我打印的“hooked”消息和$order_id

它带我去了成功页面,但没有显示我正在打印的这两件事。

3个回答

63

更新2 仅适用于Woocommerce 3+ (添加限制,仅执行一次代码)

add_action('woocommerce_thankyou', 'enroll_student', 10, 1);
function enroll_student( $order_id ) {
    if ( ! $order_id )
        return;

    // Allow code execution only once 
    if( ! get_post_meta( $order_id, '_thankyou_action_done', true ) ) {

        // Get an instance of the WC_Order object
        $order = wc_get_order( $order_id );

        // Get the order key
        $order_key = $order->get_order_key();

        // Get the order number
        $order_key = $order->get_order_number();

        if($order->is_paid())
            $paid = __('yes');
        else
            $paid = __('no');

        // Loop through order items
        foreach ( $order->get_items() as $item_id => $item ) {

            // Get the product object
            $product = $item->get_product();

            // Get the product Id
            $product_id = $product->get_id();

            // Get the product name
            $product_id = $item->get_name();
        }

        // Output some data
        echo '<p>Order ID: '. $order_id . ' — Order Status: ' . $order->get_status() . ' — Order is paid: ' . $paid . '</p>';

        // Flag the action as done (to avoid repetitions on reload for example)
        $order->update_meta_data( '_thankyou_action_done', true );
        $order->save();
    }
}

将代码放在您活动的子主题(或主题)或任何插件文件中的function.php文件中。

相关线程:

该代码已经过测试并可正常工作。


更新(根据您的评论要求获取订单项中的产品ID)

也许您可以改用woocommerce_thankyou挂钩,这样它将在订单接收页面上显示您的回显代码:

add_action('woocommerce_thankyou', 'enroll_student', 10, 1);
function enroll_student( $order_id ) {

    if ( ! $order_id )
        return;

    // Getting an instance of the order object
    $order = wc_get_order( $order_id );

    if($order->is_paid())
        $paid = 'yes';
    else
        $paid = 'no';

    // iterating through each order items (getting product ID and the product object) 
    // (work for simple and variable products)
    foreach ( $order->get_items() as $item_id => $item ) {

        if( $item['variation_id'] > 0 ){
            $product_id = $item['variation_id']; // variable product
        } else {
            $product_id = $item['product_id']; // simple product
        }

        // Get the product object
        $product = wc_get_product( $product_id );

    }

    // Ouptput some data
    echo '<p>Order ID: '. $order_id . ' — Order Status: ' . $order->get_status() . ' — Order is paid: ' . $paid . '</p>';
}

代码应该放在你激活的子主题(或主题)的function.php文件中,也可以放在任何插件文件中。

该代码已经经过测试并可用。

然后你就可以在$order对象上使用所有WC_Abstract_Order类方法。

相关:


谢谢您的回答。我使用了Thankyou页面钩子进行了检查,它显示了期望的结果,但是我能否在此钩子内获取产品数据。我想在结账后获取产品ID并将其传递给外部API。 - Syed Haris Ali Ghaznavi
一个问题:如果用户刷新了感谢页面,它将会向API发送另一个请求。 - sanjeev
@sanjeev 更新了Woocommerce 3的代码,并添加了限制,只允许该代码执行一次。 - LoicTheAztec
问题2:如果管理员手动创建订单,则无法正常工作。我自己遇到了这种情况。 - Samyer
1
@LoicTheAztec 只是想让大家知道,如果他们发现了这个问题!除了那个特定的用例,您的解决方案对我完美地起作用。 - Samyer
显示剩余5条评论

17

与其使用'woocommerce_thankyou'挂钩,更适合的是使用'woocommerce_checkout_order_processed'挂钩。 'woocommerce_checkout_order_processed'挂钩只会被调用一次,您无需为每个产品添加元数据并进行其他调用以仅运行一次代码检查。因为'woocommerce_thankyou'可能会多次调用,即每次加载感谢页面。

add_action('woocommerce_checkout_order_processed', 'enroll_student', 10, 1);
add_action('woocommerce_checkout_order_processed', 'enroll_student', 10, 1);

删除元数据和检查代码。更新后的代码为:

add_action('woocommerce_checkout_order_processed', 'enroll_student', 10, 1);
function enroll_student( $order_id ) {
// Getting an instance of the order object
$order = wc_get_order( $order_id );

if($order->is_paid())
   $paid = 'yes';
else
  $paid = 'no';

    // iterating through each order items (getting product ID and the product object) 
// (work for simple and variable products)
foreach ( $order->get_items() as $item_id => $item ) {

    if( $item['variation_id'] > 0 ){
        $product_id = $item['variation_id']; // variable product
    } else {
        $product_id = $item['product_id']; // simple product
    }

    // Get the product object
    $product = wc_get_product( $product_id );

}

// Ouptput some data
echo '<p>Order ID: '. $order_id . ' — Order Status: ' . $order->get_status() . ' — Order is paid: ' . $paid . '</p>';


4

您可以通过以下方式获取订单的订单项:

   // Getting an instance of the order object

    $order = new WC_Order( $order_id );
    $items = $order->get_items();

   //Loop through them, you can get all the relevant data:

    foreach ( $items as $item ) {
        $product_name = $item['name'];
        $product_id = $item['product_id'];
        $product_variation_id = $item['variation_id'];
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接