You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce后台订单邮件按钮异常及功能优化技术求助

问题与解决方案:WooCommerce订单通知按钮异常及功能优化

一、点击按钮后订单状态变为pending payment的原因与修复

问题根源

  1. 钩子使用错误:原代码将邮件发送逻辑挂在woocommerce_admin_order_data_after_order_details钩子上,该钩子仅用于在订单详情页渲染内容,并非处理按钮提交请求。点击按钮时触发了订单页面的默认表单提交逻辑,导致状态意外重置为pending payment。
  2. 缺少独立的提交处理逻辑:原代码未添加按钮的HTML结构,也没有专门处理按钮点击的POST请求逻辑,操作直接触发了订单页面的默认提交行为。
  3. 条件判断逻辑错误:原代码中if($status=='processing' || 'driver-assigned' || 'out-for-delivery')的写法永远为真(非空字符串在PHP中会被解析为true),正确写法需逐个判断状态是否匹配。

修复步骤

  • 拆分逻辑:将按钮渲染和提交处理分开,按钮渲染保留原钩子,提交处理使用WordPress的admin_post_*钩子(专门处理后台POST请求)。
  • 添加按钮HTML:在订单详情页插入触发邮件发送的按钮,提交到独立处理地址,避免触发订单默认表单提交。
  • 修正状态判断:使用in_array()精准匹配允许显示按钮的订单状态。

二、按钮显示条件优化

按照需求,仅在订单状态为driver-assigned或out-for-delivery时显示按钮,通过状态数组判断即可实现。

修正后的完整代码

// 1. 在订单详情页渲染通知按钮
add_action( 'woocommerce_admin_order_data_after_order_details', 'render_driver_notification_button' );
function render_driver_notification_button( $order ) {
    $status = $order->get_status();
    
    // 仅在指定状态下显示按钮
    if( in_array( $status, ['driver-assigned', 'out-for-delivery'] ) ) {
        // 检查邮件是否已发送,避免重复发送
        $email_sent = $order->get_meta( 'email_sent', true );
        $button_text = $email_sent === 'Yes' ? '通知已发送' : '通知司机自提';
        $button_disabled = $email_sent === 'Yes' ? 'disabled' : '';
        
        // 输出按钮HTML,提交到admin post处理
        echo '<div style="margin-top:15px;">
                <form action="' . admin_url( 'admin-post.php' ) . '" method="post">
                    <input type="hidden" name="action" value="send_driver_pickup_email">
                    <input type="hidden" name="order_id" value="' . $order->get_id() . '">
                    ' . wp_nonce_field( 'send_driver_pickup_nonce_' . $order->get_id(), 'send_driver_pickup_nonce', true, false ) . '
                    <button type="submit" class="button button-primary" ' . $button_disabled . '>' . $button_text . '</button>
                </form>
              </div>';
    }
}

// 2. 处理按钮提交的邮件发送逻辑
add_action( 'admin_post_send_driver_pickup_email', 'send_driver_pickup_email_handler' );
function send_driver_pickup_email_handler() {
    // 验证权限和nonce
    if( !current_user_can( 'edit_shop_orders' ) || !isset( $_POST['send_driver_pickup_nonce'] ) || !wp_verify_nonce( $_POST['send_driver_pickup_nonce'], 'send_driver_pickup_nonce_' . $_POST['order_id'] ) ) {
        wp_die( '权限验证失败' );
    }
    
    $order_id = absint( $_POST['order_id'] );
    $order = wc_get_order( $order_id );
    
    if( !$order ) {
        wp_die( '无效的订单ID' );
    }
    
    // 再次验证订单状态(防止前端篡改)
    $status = $order->get_status();
    if( !in_array( $status, ['driver-assigned', 'out-for-delivery'] ) ) {
        wp_die( '当前订单状态不允许发送通知' );
    }
    
    // 检查邮件是否已发送
    $email_sent = $order->get_meta( 'email_sent', true );
    if( $email_sent === 'Yes' ) {
        wp_die( '通知已发送,无需重复操作' );
    }
    
    // 获取司机ID
    $driver_id = $order->get_meta( 'lddfw_driverid', true );
    if( empty( $driver_id ) ) {
        wp_die( '未找到关联的司机ID' );
    }
    
    $driver = get_userdata( $driver_id );
    if( !$driver ) {
        wp_die( '无效的司机用户ID' );
    }
    
    // 发送邮件
    $subject = '订单编号 ' . $order->get_id() . ' 已准备好自提';
    $message = '您好 ' . $driver->display_name . ',<br><br>订单编号 ' . $order->get_id() . ' 现已准备好,请前往自提。';
    $headers = array( 'Content-Type: text/html; charset=UTF-8' );
    
    if( wp_mail( $driver->user_email, $subject, $message, $headers ) ) {
        // 更新邮件发送标记
        $order->update_meta_data( 'email_sent', 'Yes' );
        $order->save();
        
        // 跳转回订单详情页并提示成功
        wp_redirect( add_query_arg( array( 'post' => $order_id, 'action' => 'edit', 'email_sent' => 'success' ), admin_url( 'post.php' ) ) );
        exit;
    } else {
        wp_die( '邮件发送失败,请稍后重试' );
    }
}

// 3. 添加邮件发送成功提示
add_action( 'admin_notices', 'driver_email_sent_notice' );
function driver_email_sent_notice() {
    if( isset( $_GET['email_sent'] ) && $_GET['email_sent'] === 'success' ) {
        echo '<div class="notice notice-success is-dismissible">
                <p>司机通知邮件已成功发送!</p>
              </div>';
    }
}

// 邮件发件人设置
add_filter('wp_mail_from', 'original_mail_address_email');
function original_mail_address_email(){
    return 'admin@gmail.com';
}

add_filter('wp_mail_from_name', 'email_name_order_ready');
function email_name_order_ready(){
    return 'Oven Fresh';
}

关键改进点

  • 分离渲染与处理:避免钩子使用错误导致的订单状态异常。
  • 权限与安全验证:添加nonce验证和用户权限检查,防止恶意请求。
  • 状态校验:前后端双重验证订单状态,确保按钮仅在允许的状态下显示和操作。
  • 重复发送防护:通过自定义元数据email_sent标记邮件是否已发送,避免重复操作。
  • 用户反馈:添加邮件发送成功的后台通知,提升操作体验。

内容的提问来源于stack exchange,提问作者Rishikesh Dubey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:28:11