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

Stripe支付成功后无法结合PHPMailer发送QR码求助

支付成功后无法通过PHPMailer发送带QR码附件的邮件

我使用Stripe、PHPMailer、phpqrcode和MySQL处理支付业务,目标是在支付成功时生成QR码并以邮件附件形式发送。目前单独生成QR码、发送邮件都能正常实现,也能在支付成功时将数据存入数据库并生成保存QR码图片,但无法在支付成功事件中结合PHPMailer完成发送操作。我使用的是Stripe测试模式,请问问题出在哪?

相关代码

<?php

require_once './stripe-php-9.0.0/init.php';
include 'db.php';
// Set your secret key. Remember to switch to your live secret key in production.
// See your keys here: https://dashboard.stripe.com/apikeys
\Stripe\Stripe::setApiKey('xxxxx');

// If you are testing your webhook locally with the Stripe CLI you
// can find the endpoint's secret by running `stripe listen`
// Otherwise, find your endpoint's secret in your webhook settings in the Developer Dashboard
$endpoint_secret = 'xxxxx';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
    $event = \Stripe\Webhook::constructEvent(
        $payload, $sig_header, $endpoint_secret
    );
} catch(\UnexpectedValueException $e) {
    // Invalid payload
    http_response_code(400);
    exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
    // Invalid signature
    http_response_code(400);
    exit();
}
$id = $event->data->object->id;
$amount = $event->data->object->amount_captured;
$currency = $event->data->object->currency;
$customer_email = $event->data->object->billing_details->email;
$customer_name = $event->data->object->billing_details->name;

// Handle the event
switch ($event->type) {
    case 'payment_intent.succeeded':
        $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
        handlePaymentIntentSucceeded($paymentIntent);
        break;
    case 'charge.succeeded':
      $stmt = $conn->prepare("INSERT INTO Tynnsuppe (txid, Amount, Currency, Customer_email, Customer_name) VALUES (?, ?, ?, ?, ?)");
      $stmt->bind_param("sdsss", $id, $amount, $currency, $customer_email, $customer_name);
      $stmt->execute();
      if (!$stmt) {
        echo "Error";
      }
      $stmt->close();
      $conn->close();

      // QR-code
      include 'phpqrcode/qrlib.php';

      //The payment-id is the qr-code
      $text = $id;
      
      //Save the qr-code as an image and the name is the payment-id.
      $folder="bilder/qr/";
      $file_name= $text.'.png';
      $file_name=$folder.$file_name;
      QRcode::png($text,$file_name);
      
      //SEND MAIL
      require_once('PHPMailer/src/PHPMailer.php');

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$bodytext = "Hei";

$mail = new PHPMailer();
$mail->SetFrom('you@example.com', 'Your Name'); //Name is optional
$mail->Subject   = 'Din billett';
$mail->Body      = $bodytext;
$mail->AddAddress( 'reciver@hotmail.com' );

$file_to_attach = 'bilder/qr/' . $text . '.png';

$mail->AddAttachment( $file_to_attach , 'KlubbkveldBillett.pdf' );

return $mail->Send();

        break;
    // ... handle other event types

    default:
        echo 'Received unknown event type ' . $event->type;
}

http_response_code(200);

?>

问题排查与解决方案

  • PHPMailer依赖不全
    你只引入了PHPMailer.php,但PHPMailer运行需要Exception.php,如果用SMTP发送还需要SMTP.php。建议直接引入完整的必要文件:

    require_once('PHPMailer/src/PHPMailer.php');
    require_once('PHPMailer/src/Exception.php');
    require_once('PHPMailer/src/SMTP.php');
    
  • 未配置邮件发送驱动
    默认PHPMailer可能使用PHP内置的mail()函数,但Webhook运行环境中该函数可能被禁用,或者服务器邮件配置不正确。建议配置SMTP方式发送,稳定性更高:

    $mail->isSMTP();
    $mail->Host = 'smtp.example.com'; // 替换为你的SMTP服务器地址
    $mail->SMTPAuth = true;
    $mail->Username = 'your_email@example.com'; // 你的邮箱账号
    $mail->Password = 'your_email_password'; // 邮箱密码或授权码
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
    $mail->Port = 587; // 对应SMTP端口
    
  • 附件路径错误
    你使用的是相对路径bilder/qr/,Webhook脚本的执行目录可能和预期不一致,导致找不到生成的QR码文件。改用绝对路径确保能正确定位文件:

    $folder = __DIR__ . '/bilder/qr/'; // __DIR__表示当前脚本所在目录
    if (!is_dir($folder)) {
        mkdir($folder, 0755, true); // 确保目录存在
    }
    $file_name = $folder . $text . '.png';
    
  • Webhook响应超时与异常未处理
    Stripe要求Webhook在10秒内返回响应,邮件发送操作可能耗时较长导致超时。另外,$mail->Send()可能抛出异常,未捕获会导致脚本中断,无法返回200响应给Stripe,进而触发重试。修改邮件发送逻辑:

    try {
        // 邮件配置代码...
        if (!$mail->send()) {
            error_log('邮件发送失败: ' . $mail->ErrorInfo); // 记录错误日志
        } else {
            error_log('邮件发送成功');
        }
    } catch (Exception $e) {
        error_log('邮件发送异常: ' . $e->getMessage());
    }
    // 不要用return,确保脚本执行到最后返回200响应
    
  • 未定义函数导致脚本中断
    在payment_intent.succeeded事件中调用了未定义的handlePaymentIntentSucceeded函数,会直接导致脚本报错终止。如果不需要处理该事件,直接注释这段代码;如果需要,实现该函数。

  • 数据库连接关闭过早
    虽然这不会直接影响邮件发送,但建议把$conn->close();移到邮件发送完成之后,避免后续操作(如果有的话)出现数据库连接问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 15:24:08