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

包含PHPMailer函数时Webhook调用失败问题求助

问题分析与解决方案

核心矛盾:手动访问complete.php完全正常,但Webhook通过curl调用时,加入completeTestBooking发邮件函数后就失败,大概率是超时导致Webhook发起方提前终止请求,或是发邮件环节存在未被记录的隐性异常,具体排查和解决步骤如下:

一、优先解决超时问题

绝大多数支付类Webhook服务都有严格的响应超时限制(通常3-5秒),而completeTestBooking里的SMTP邮件发送涉及外部网络请求,很容易因SMTP服务器响应慢、网络延迟等导致整个请求超时,Webhook发起方会直接返回400错误,但现有代码未捕获该场景。

解决方法:异步执行邮件发送

不要在请求流程内同步执行发邮件操作,改成后台异步执行,让complete.php快速返回响应给Webhook:

  1. 新建独立的邮件处理脚本send_test_email.php:
<?php
require 'PHPMailer/PHPMailer.php';
require 'PHPMailer/SMTP.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;

function completeTestBooking($testId) {
    $mail = new PHPMailer(true);
    try {
        // 原邮件配置逻辑
        $mail->CharSet = "UTF-8";
        $mail->SMTPDebug = SMTP::DEBUG_OFF;                     
        $mail->isSMTP();                                            
        $mail->Host = 'smtp.example.com';
        $mail->Port = 465;
        $mail->SMTPAuth = true;
        $mail->SMTPSecure = 'ssl';
        $mail->Username = 'info@co.uk';
        $mail->Password = 'password';

        $mail->setFrom('info@co.uk', 'Bookings');
        $mail->addAddress('test@example.com');     

        $mail->isHTML(true);
        $mail->Subject = 'Here is the subject';
        $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
        $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

        $mail->send();
        file_put_contents('email_success.log', date('Y-m-d H:i:s') . " 邮件发送成功,测试ID: {$testId}\n", FILE_APPEND);
        return true;
    } catch (Exception $e) {
        file_put_contents('email_error.log', date('Y-m-d H:i:s') . " 测试ID: {$testId} | 错误信息: " . $e->getMessage() . "\n", FILE_APPEND);
        return false;
    }   
}

// 接收命令行传入的测试ID
$testId = $argv[1] ?? '';
if ($testId) {
    completeTestBooking($testId);
}
  1. 修改complete.php里的调用逻辑,用后台进程执行:
if ($jsonBookingDetails->type === "test") {
    // 后台执行邮件脚本,不阻塞当前请求
    exec("php /绝对路径/send_test_email.php 1234 > /dev/null 2>&1 &");
    
    savePayment($jsonBookingDetails->name, $address, $jsonBookingDetails->amount, $_GET['pid'], "Succeeded", $db);
}

注意:必须使用脚本的绝对路径,避免系统找不到文件;> /dev/null 2>&1 &用于让进程在后台静默运行,不干扰当前请求的响应。

二、补充日志排查隐性异常

现有代码中completeTestBooking的异常仅返回false,未记录任何信息,导致无法定位问题。给函数添加详细日志:
修改completeTestBooking的catch块:

catch (Exception $e) {
    // 记录错误时间、信息、栈追踪,便于排查
    $logContent = date('Y-m-d H:i:s') . "\n错误信息: " . $e->getMessage() . "\n栈追踪: " . $e->getTraceAsString() . "\n\n";
    file_put_contents('test_booking_error.log', $logContent, FILE_APPEND);
    return false;
}

同时在complete.php里记录函数执行结果:

$emailResult = completeTestBooking("1234",$db);
file_put_contents('complete_booking.log', date('Y-m-d H:i:s') . " 邮件发送结果: " . ($emailResult ? "成功" : "失败") . " | OID: {$_GET['oid']}\n", FILE_APPEND);

即使Webhook失败,也能通过日志明确邮件发送环节是否存在问题。

三、临时调整超时参数(可选)

如果暂时无法实现异步处理,可以给PHPMailer设置更短的超时时间,避免请求卡住:

// 在PHPMailer配置中添加
$mail->Timeout = 5; // 整体请求超时5秒
$mail->SMTPTimeout = 5; // SMTP连接超时5秒

同时给Webhook里的curl请求也设置超时:

curl_setopt($ch, CURLOPT_TIMEOUT, 10); // curl请求总超时10秒
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // curl连接超时5秒

内容的提问来源于stack exchange,提问作者Abu Nooh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:07:33