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

如何借助Stripe Node.js Webhook拦截特定邮箱域名的支付?

解决方案:拦截黑名单邮箱域名的Stripe支付链接欺诈

可行方案1:监听checkout.session.created事件,提前过期违规会话

Stripe提供checkout.session.created Webhook事件,触发时机是用户打开支付链接、结账会话生成时。你可以在这个阶段检查用户邮箱域名,匹配黑名单后直接过期会话,阻止用户完成支付。

实现步骤:

  1. 在Stripe Dashboard的Webhook设置中,启用checkout.session.created事件并配置你的Webhook端点。
  2. 在Node.js的Webhook处理逻辑中,提取会话中的用户邮箱,解析域名并对比黑名单。
  3. 匹配黑名单时,调用checkout.sessions.expire() API过期当前会话。

代码示例:

const stripe = require('stripe')('你的Stripe密钥');

// Webhook端点处理函数
app.post('/stripe-webhook', async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

  try {
    event = stripe.webhooks.constructEvent(
      req.rawBody,
      sig,
      '你的Webhook签名密钥'
    );
  } catch (err) {
    return res.status(400).send(`Webhook验证失败: ${err.message}`);
  }

  // 处理checkout.session.created事件
  if (event.type === 'checkout.session.created') {
    const session = event.data.object;
    const userEmail = session.customer_details?.email;
    
    if (!userEmail) {
      return res.json({ received: true });
    }

    // 提取邮箱域名
    const emailDomain = userEmail.split('@')[1];
    // 你的黑名单域名列表
    const blacklistedDomains = ['fraud-domain.com', 'test-card.example'];

    if (blacklistedDomains.includes(emailDomain)) {
      try {
        // 过期违规会话
        await stripe.checkout.sessions.expire(session.id);
        console.log(`已过期会话 ${session.id},对应黑名单域名:${emailDomain}`);
      } catch (err) {
        console.error('过期会话失败:', err);
      }
    }
  }

  res.json({ received: true });
});

可行方案2:配置支付链接为手动扣款,拦截违规支付Intent

通过API创建支付链接时,设置payment_intent_data.capture_method: 'manual',让支付仅完成授权、不自动扣款。之后监听payment_intent.created事件,检查用户邮箱域名,匹配黑名单时取消支付Intent,阻止后续扣款操作。

实现步骤:

  1. 通过Stripe API创建支付链接,指定手动扣款模式。
  2. 启用payment_intent.created Webhook事件,在处理逻辑中关联客户邮箱并检查黑名单。
  3. 匹配黑名单时,调用paymentIntents.cancel()取消支付Intent。

代码示例:

创建手动扣款模式的支付链接

const createPaymentLink = async () => {
  const paymentLink = await stripe.paymentLinks.create({
    line_items: [
      {
        price: '你的订阅价格ID',
        quantity: 1,
      },
    ],
    payment_intent_data: {
      capture_method: 'manual', // 设置为手动扣款
    },
  });
  return paymentLink;
};

Webhook处理支付Intent创建事件

// 接上文Webhook处理函数
if (event.type === 'payment_intent.created') {
  const paymentIntent = event.data.object;
  
  // 获取关联的客户信息
  const customer = await stripe.customers.retrieve(paymentIntent.customer);
  const userEmail = customer.email;
  
  if (!userEmail) {
    return res.json({ received: true });
  }

  const emailDomain = userEmail.split('@')[1];
  const blacklistedDomains = ['fraud-domain.com', 'test-card.example'];

  if (blacklistedDomains.includes(emailDomain)) {
    try {
      await stripe.paymentIntents.cancel(paymentIntent.id);
      console.log(`已取消支付Intent ${paymentIntent.id},对应黑名单域名:${emailDomain}`);
    } catch (err) {
      console.error('取消支付Intent失败:', err);
    }
  }
}

注意事项

  • 方案1属于事前拦截,用户会直接看到会话过期提示,体验上更直接;方案2是授权后拦截,适合需要保留授权记录的场景。
  • 如果你的支付链接是通过Stripe Dashboard创建的,无法设置手动扣款模式,必须通过API创建。
  • 确保Webhook端点的网络延迟足够低,避免在用户完成支付后才触发过期/取消操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:53:22