如何结合WooCommerce钩子实现仅同步Processing状态的已支付订单
解决方案
核心问题分析
woocommerce_new_order钩子在订单刚创建时触发,此时订单默认状态通常是pending(待支付),无法直接满足“仅在订单变为processing时同步”的需求。更可靠的方式是监听订单状态变更为processing的事件,或者在原钩子中增加严格的状态校验(但后者存在异步支付场景下漏同步的风险)。
方案一:替换为状态变更专用钩子(推荐)
使用woocommerce_order_status_processing钩子,该钩子仅在订单状态变为processing时触发,完美匹配你的需求。同时增加“已同步”标记,避免重复发送请求。
修改后的完整代码:
// 替换原钩子,监听订单状态变为processing的事件 add_action('woocommerce_order_status_processing', 'call_order_to_tsm', 10, 1); function call_order_to_tsm($order_id) { $order = wc_get_order($order_id); // 检查是否已同步过,避免重复请求 if ($order->get_meta('_tsm_sync_completed')) { return; } // 获取订单信息(保留你原有的逻辑) $first_name = $order->get_billing_first_name(); $last_name = $order->get_billing_last_name(); $phone = $order->get_billing_phone(); $email = $order->get_billing_email(); $city = $order->get_billing_city(); $address = $order->get_billing_address_1(); $price = $order->get_total(); $items = $order->get_items(); $status = $order->get_status(); // 处理支付日期(注意判断是否为空,避免报错) $datePayment = ''; $payment_date = $order->get_date_paid(); if ($payment_date) { $temp2 = date_create($payment_date); $datePayment = date_format($temp2, "Y/m/d H:i:s"); } $order_date = $order->get_date_created(); $temp = date_create($order_date); $date = date_format($temp, "Y/m/d H:i:s"); $products = []; foreach ($items as $index => $item) { $product = []; $product_name = $item->get_name(); $product_quantity = $item->get_quantity(); $product['produktas'] = $product_name; $product['kiekis'] = $product_quantity; $products[] = $product; } $json = json_encode($products, JSON_UNESCAPED_UNICODE); $message = 'Užsakymo data: ' . $date . "\n" . 'Vardas: ' . $first_name . "\n" . 'Pavardė: ' . $last_name . "\n" . 'Miestas: ' . $city . "\n" . 'Adresas: ' . $address . "\n" . 'Prekės: ' . $json ."\n" . 'Kaina: ' . $price . "\n" . 'Apmokejimo data: ' . $datePayment . "\n" . 'Statusas: ' . $status; $TotalOrders = [ 'email' => $email, 'phone' => $phone, 'objectname' => 'web_testas', 'msg' => $message ]; // CURL请求优化:捕获错误并记录日志 $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://www.url.com', // 注意补全协议头(http/https) CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => http_build_query($TotalOrders), // 若接口需要JSON格式,改为json_encode($TotalOrders) CURLOPT_HTTPHEADER => array( 'HTTP_X_REQUESTED_WITH: XMLHttpRequest' ), )); $response = curl_exec($curl); $error = curl_error($curl); curl_close($curl); // 记录同步结果,方便排查问题 if ($error) { $order->add_meta_data('_tsm_sync_error', $error, true); error_log('TSM同步失败,订单ID:'.$order_id.',错误信息:'.$error); } else { $order->add_meta_data('_tsm_sync_completed', 'yes', true); $order->add_meta_data('_tsm_sync_response', $response, true); error_log('TSM同步成功,订单ID:'.$order_id); } $order->save(); }
关键优化点:
- 替换为
woocommerce_order_status_processing钩子,确保仅在订单支付完成、状态变为processing时触发 - 增加
_tsm_sync_completed自定义字段,标记订单是否已同步,避免重复发送请求 - 增加支付日期的非空判断,避免因异常场景导致的报错
- 补全CURL请求的协议头(
https://),避免请求失败 - 捕获CURL错误并记录日志,同时保存同步结果到订单元数据,方便后续排查问题
- 可根据外部接口要求调整
CURLOPT_POSTFIELDS格式:若需要JSON,将http_build_query($TotalOrders)改为json_encode($TotalOrders),并添加Content-Type: application/json请求头
方案二:在原woocommerce_new_order钩子中增加状态校验(仅适用于即时支付场景)
如果你的支付方式都是即时完成(比如信用卡、PayPal即时到账),订单创建后立刻变为processing,可以在原函数开头增加状态判断:
add_action('woocommerce_new_order', 'call_order_to_tsm', 2 ); function call_order_to_tsm($order_id) { $order = wc_get_order($order_id); // 仅处理processing状态的订单,直接跳过其他状态 if ($order->get_status() !== 'processing') { return; } // 以下保留你原有的订单信息获取、CURL请求逻辑... }
注意事项:
- 该方案仅适用于即时支付场景,若用户使用异步支付(比如银行转账、COD),订单创建时状态是pending,后续支付完成后状态变为processing,此时
woocommerce_new_order钩子已经触发过,会导致漏同步。
内容的提问来源于stack exchange,提问作者Ugnius Vaidila
相关产品推荐
相关产品推荐

