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

如何将用户信息传递至Stripe Webhook以发送支付成功邮件?

解决方案:传递自定义参数到Stripe Webhook并发送邮件

要解决这个问题,你需要利用Stripe Checkout Session的**metadata字段**存储自定义数据,这些数据会在支付完成后的Webhook事件中返回,具体步骤如下:

1. 创建Checkout Session时存入自定义数据

修改Stripe结账端点代码,在stripe.checkout.sessions.create配置中添加metadata字段,将客户姓名、开始日期、结束日期及客户邮箱存入(假设前端通过req.body传递这些参数,可根据实际调整为req.query):

app.post('/stripe-checkout', async (req, res) => {
    try {
        let baseUrl = req.query.env == 'prod' ? 'https://leaf-for-business.web.app' : 'http://localhost:8080';
        // 从请求中提取所需参数
        const { customerName, startDate, endDate, customerEmail } = req.body;
        const session = await stripe.checkout.sessions.create({
            line_items: [
                {
                    price_data: {
                        currency: 'usd',
                        product_data: {
                            name: 'Promotion Payment',
                        },
                        unit_amount: req.query.amount * 100, /// 1USD = 100 Cents
                    },
                    quantity: 1,
                }
            ],
            mode: 'payment',
            payment_method_types: [ "card" ],
            success_url: baseUrl + '/home',
            // 添加metadata存储自定义业务数据
            metadata: {
                customer_name: customerName,
                start_date: startDate,
                end_date: endDate,
                email: customerEmail
            }
        });

        res.send({
            success: true,
            session_id: session.id,
            redirect_url: session.url,
        });

    } catch (error) {
        res.status(404).send({
            success: false,
            error: error.message,
        });
    }
});

2. 在Webhook中提取数据并传递给邮件函数

修改Webhook代码,从checkout.session.completed事件的session对象中取出metadata数据,再传给sendEmail函数(替代原有的直接传递request.body):

app.post('/webhook', async (request, response) => {
    const sig = request.headers['stripe-signature'];

    const endpointSecret = process.env.WEBHOOK_SECRET;
    let event;

    try {
        event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
    } catch (err) {
        response.status(400).send(`Webhook Error: ${err.message}`);
        return;
    }

    // 处理事件
    switch (event.type) {
        case 'checkout.session.completed':
            const checkoutSession = event.data.object;
            // 从session的metadata中提取需要的数据
            const emailData = {
                customer_name: checkoutSession.metadata.customer_name,
                start_date: checkoutSession.metadata.start_date,
                end_date: checkoutSession.metadata.end_date,
                email: checkoutSession.metadata.email
            };
            // 调用邮件发送函数,添加await确保执行完成
            await sendEmail(emailData);
            break;
        default:
            console.log(`Unhandled event type ${event.type}`);
    }

    // 返回200响应确认事件接收
    response.send();
});

3. 优化邮件发送函数(可选)

调整sendEmail函数的参数接收逻辑,让代码更清晰:

async function sendEmail(emailData) {
    const DOMAIN = "app.joinleaf.com";
    const SENDER_EMAIL = "no-reply@app.joinleaf.com";

    const mailgun = new Mailgun(formData);
    const mg = mailgun.client({
        username: 'api',
        key: process.env.MG_PRIVATE_KEY,
        host: "api.eu.mailgun.net",
    });

    // 解构数据
    const customerEmail = emailData.email;
    const customerName = emailData.customer_name;
    const startDate = emailData.start_date;
    const endDate = emailData.end_date;

    const emailBody = fs.readFileSync('src/email.html', 'utf8').toString();
    const finalTemp = emailBody.replaceAll('customer-name', customerName)
        .replace('start-date', startDate)
        .replace('end-date', endDate);

    const messageData = {
        from: SENDER_EMAIL,
        to: [customerEmail, "team@getleaflets.co"],
        subject: "Thank you for your purchase.",
        html: finalTemp,
    };

    try {
        const resp = await mg.messages.create(DOMAIN, messageData);
        console.log('Sent! ' + resp);
        return resp;
    } catch (err) {
        console.log(err);
        throw err;
    }
}

关键说明

  • Stripe的metadata字段是存储自定义业务数据的标准方式,会随Checkout Session事件一并返回。
  • 需确保前端调用/stripe-checkout接口时,正确传递customerName、startDate、endDate、customerEmail参数。
  • Webhook函数添加async/await,避免邮件发送逻辑异步执行导致的潜在问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:52:52