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

如何将Stripe Webhook响应数据存储到MySQL数据库

实现Stripe Webhook事件存储到MySQL(Node.js后端)

前置准备

确保你已安装Node.js和MySQL,且MySQL服务正常运行。

1. 安装依赖

在Node.js项目根目录执行:

npm install mysql2 stripe express
  • mysql2:支持Promise的MySQL驱动,适配异步操作
  • stripe:Stripe官方SDK
  • express:搭建Webhook的HTTP服务

2. 配置MySQL连接

创建db.js文件,管理数据库连接池:

const mysql = require('mysql2/promise');

// 创建连接池(比单连接更高效稳定)
const pool = mysql.createPool({
  host: 'localhost', // 本地开发填localhost,线上填对应服务器地址
  user: 'root', // MySQL用户名
  password: '你的MySQL密码', // 替换为你的密码
  database: '你的数据库名', // 提前在MySQL中创建好目标数据库
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

module.exports = pool;

3. 创建Stripe事件存储表

打开MySQL客户端(命令行/Navicat等),执行SQL创建表:

CREATE TABLE stripe_events (
  id VARCHAR(255) PRIMARY KEY, -- Stripe事件全局唯一ID
  event_type VARCHAR(100) NOT NULL, -- 事件类型(如checkout.session.completed)
  created_at BIGINT NOT NULL, -- Stripe事件生成时间戳
  data JSON NOT NULL, -- 事件原始数据,用JSON格式存储
  processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 本地存储时间
);

如果需要针对特定事件存结构化数据(比如单独的订单表),后续可扩展,先从通用事件表上手。

4. 编写Webhook处理及存储逻辑

创建server.js作为后端核心文件:

const express = require('express');
const stripe = require('stripe')('你的Stripe秘钥'); // 替换为你的Stripe秘钥
const pool = require('./db.js');

const app = express();

// 解析Stripe Webhook的原始请求体(必须用raw格式,不能用json)
app.post('/stripe-webhook', express.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  const webhookSecret = '你的Stripe Webhook签名秘钥'; // 替换为后台获取的签名秘钥

  let event;

  try {
    // 验证Webhook签名,防止伪造请求
    event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
  } catch (err) {
    console.log(`Webhook验证失败: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // 通用事件存储函数
  const saveStripeEvent = async (event) => {
    try {
      await pool.execute(
        'INSERT INTO stripe_events (id, event_type, created_at, data) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE data = ?, processed_at = CURRENT_TIMESTAMP',
        [event.id, event.type, event.created, JSON.stringify(event.data.object), JSON.stringify(event.data.object)]
      );
      console.log(`事件 ${event.id} 已存储/更新`);
    } catch (dbErr) {
      console.error(`存储事件失败: ${dbErr.message}`);
    }
  };

  // 按事件类型分支处理
  switch (event.type) {
    case 'checkout.session.completed':
      const checkoutSession = event.data.object;
      console.log('结账会话完成:', checkoutSession.id);
      // 可在此添加额外逻辑(如更新业务订单状态)
      await saveStripeEvent(event);
      break;
    case 'payment.intent.succeeded':
      const paymentIntent = event.data.object;
      console.log('支付成功:', paymentIntent.id);
      await saveStripeEvent(event);
      break;
    case 'payment.intent.failed':
      const failedPayment = event.data.object;
      console.log('支付失败:', failedPayment.id);
      await saveStripeEvent(event);
      break;
    // 可继续添加需要处理的其他事件类型
    default:
      console.log(`未处理的事件类型: ${event.type}`);
      // 可选:存储未处理事件
      await saveStripeEvent(event);
  }

  // 返回200给Stripe,确认已接收事件
  res.json({received: true});
});

// 启动服务,监听端口
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`服务运行在端口 ${PORT}`);
});

关键说明

  • 签名验证:必须保留,这是Stripe Webhook的安全机制,签名秘钥在Stripe后台Webhook设置中获取。
  • 连接池:避免频繁创建销毁数据库连接,提升性能。
  • 重复事件处理:ON DUPLICATE KEY UPDATE避免Stripe重复发送事件导致的主键冲突,同时更新最新数据。
  • JSON存储:用JSON类型存原始数据,方便后续筛选查询,若需结构化存储可后续拆分表。

测试与部署

  1. 本地测试:用Stripe CLI模拟事件,命令:stripe listen --forward-to localhost:3000/stripe-webhook
  2. 线上部署:将Node.js服务部署到云平台(Vercel/Heroku/EC2等),在Stripe后台配置Webhook端点为你的服务地址+/stripe-webhook

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:50:22