
本文详解如何在用户访问 woocommerce 结账页面且购物车非空时,精准、单次触发个性化邮件通知,并规避常见误用钩子导致的重复发送问题。
在 WooCommerce 开发中,为提升转化率或增强用户引导,常需在用户进入结账流程时发送即时提醒邮件(如“您的订单即将完成!”)。但若错误选用钩子(如 woocommerce_after_shop_loop_item),不仅无法命中结账页,还可能因页面多次渲染或 AJAX 请求导致邮件重复发送——这正是原始代码的核心缺陷。
✅ 正确钩子:woocommerce_before_checkout_form
该钩子仅在 WooCommerce 结账表单渲染前执行一次,且严格限定于 /checkout/ 页面上下文,是实现「结账页单次触发」的理想入口。同时,必须前置校验 WC()->cart 实例是否存在,避免在非 WooCommerce 环境(如后台或自定义页面)中引发 PHP 错误。
以下是经过生产环境验证的完整实现:
function send_checkout_entry_notification() {
// 仅对已登录用户生效
if ( ! is_user_logged_in() ) {
return;
}
// 安全检查:确保 WooCommerce 购物车对象可用
if ( ! WC()->cart instanceof WC_Cart ) {
return;
}
// 仅当购物车非空时继续
if ( WC()->cart->is_empty() ) {
return;
}
$current_user = wp_get_current_user();
$email = $current_user->user_email;
$name = $current_user->user_firstname;
// 防御性检查:邮箱与姓名不能为空
if ( empty( $email ) || empty( $name ) ) {
return;
}
// 构建邮件内容(使用 WordPress 国际化函数,便于多语言支持)
$subject = sprintf( __( 'Hello %s, your purchase is almost ready!', 'your-textdomain' ), esc_html( $name ) );
$body = sprintf(
__( 'Hi %s,<br><br>Your cart contains %d item(s). Proceed to checkout to complete your order!', 'your-textdomain' ),
esc_html( $name ),
WC()->cart->get_cart_contents_count()
);
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
// 发送邮件(注意:wp_mail 是异步的,无需额外处理)
wp_mail( $email, $subject, $body, $headers );
}
add_action( 'woocommerce_before_checkout_form', 'send_checkout_entry_notification' );? 进阶建议:复用 WooCommerce 邮件模板样式
若希望通知邮件与 WooCommerce 默认邮件(如订单确认)保持视觉一致(含品牌头图、CSS 样式、响应式布局),推荐使用 WooCommerce 内置邮件系统:
// 替换上述 wp_mail() 调用部分如下:
if ( ! empty( $email ) && ! empty( $name ) ) {
$mailer = WC()->mailer();
$to = $email;
$subject = __( 'Your Checkout Is Ready', 'your-textdomain' );
$message = $mailer->wrap_message(
sprintf( __( 'Hello %s', 'your-textdomain' ), esc_html( $name ) ),
sprintf(
__( 'You have %d item(s) in your cart. <a href="%s">Go to checkout now</a>!', 'your-textdomain' ),
WC()->cart->get_cart_contents_count(),
wc_get_checkout_url()
)
);
$mailer->send( $to, $subject, $message );
}⚠️ 重要注意事项 勿在循环或 AJAX 回调中直接调用:woocommerce_before_checkout_form 已天然保证单次执行,无需额外加锁或 session 标记; 避免敏感信息泄露:示例中使用 esc_html() 对用户输入进行转义,防止 XSS; 测试务必启用日志:可临时添加 error_log( 'Checkout notification sent to ' . $email ); 辅助调试; 生产环境建议加入频率限制:例如通过 update_user_meta() 记录最近发送时间,防止用户刷新页面反复触发。
通过以上方案,您将获得一个稳定、安全、可维护的结账页邮件通知机制,既符合 WooCommerce 最佳实践,又为后续扩展(如集成 Mailchimp 或添加动态商品摘要)预留清晰接口。










