NodeJS如何获取PHP设置的Session变量?Stripe验证后更新MySQL
解决Stripe验证后NodeJS获取PHP会话用户ID并更新MySQL的问题
首先明确:PHP和NodeJS是独立的服务,默认各自的会话系统不互通,不能直接"获取PHP的Session变量",可通过以下几种可行方案解决:
方案1:用共享会话存储(推荐,适合长期维护)
把PHP和NodeJS的会话都存在同一个Redis实例里,实现跨服务会话共享:
步骤1:配置PHP使用Redis存储会话
修改php.ini或在PHP代码中设置:
// PHP代码中配置会话存储为Redis ini_set('session.save_handler', 'redis'); ini_set('session.save_path', 'tcp://127.0.0.1:6379'); // 正常启动会话并设置用户ID session_start(); $_SESSION['user_id'] = 123; // 替换为你的实际用户ID
步骤2:NodeJS读取Redis中的会话数据
先安装依赖:
npm install redis express-session connect-redis mysql2
然后在NodeJS代码中连接Redis并处理Stripe回调:
const express = require('express'); const session = require('express-session'); const RedisStore = require('connect-redis').default; const { createClient } = require('redis'); const mysql = require('mysql2/promise'); const stripe = require('stripe')('你的Stripe Secret Key'); // 创建Redis客户端 const redisClient = createClient({ url: 'redis://127.0.0.1:6379' }); redisClient.connect().catch(console.error); const app = express(); // 配置会话中间件,和PHP保持一致的会话密钥、Cookie名 app.use(session({ store: new RedisStore({ client: redisClient }), secret: '你的PHP会话密钥(对应php.ini的session.secret)', resave: false, saveUninitialized: false, cookie: { sameSite: 'lax', httpOnly: true, maxAge: 86400000 // 和PHP会话过期时间保持一致 }, name: 'PHPSESSID' // 使用PHP默认的会话Cookie名 })); // 处理Stripe Webhook回调 app.post('/stripe-webhook', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const event = stripe.webhooks.constructEvent(req.body, sig, '你的Stripe Webhook密钥'); if (event.type === 'identity.verification_session.verified') { // 从共享会话中获取用户ID const userId = req.session.user_id; if (!userId) { return res.status(400).send('用户ID未找到'); } // 更新MySQL数据库 const connection = await mysql.createConnection({ host: '你的数据库地址', user: '数据库用户名', password: '数据库密码', database: '数据库名' }); await connection.execute('UPDATE users SET verified = 1 WHERE id = ?', [userId]); await connection.end(); res.json({ received: true }); } else { res.status(400).send(`Unhandled event type ${event.type}`); } }); app.listen(3000);
方案2:通过Stripe Metadata传递用户ID(更简单,无需共享会话)
创建Stripe Identity验证会话时,将用户ID存入metadata,验证成功后Stripe会在Webhook回调中返回该数据:
步骤1:PHP创建验证会话时添加metadata
require 'vendor/autoload.php'; $stripe = new \Stripe\StripeClient('你的Stripe Secret Key'); session_start(); $userId = $_SESSION['user_id']; $verificationSession = $stripe->identity->verificationSessions->create([ 'type' => 'document', 'metadata' => [ 'user_id' => $userId // 将用户ID存入metadata ], 'return_url' => 'https://你的域名/验证完成页' ]); // 跳转至Stripe验证页面 header("Location: " . $verificationSession->url);
步骤2:NodeJS在Webhook中获取metadata并更新数据库
const stripe = require('stripe')('你的Stripe Secret Key'); const express = require('express'); const mysql = require('mysql2/promise'); const app = express(); app.post('/stripe-webhook', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const event = stripe.webhooks.constructEvent(req.body, sig, '你的Stripe Webhook密钥'); if (event.type === 'identity.verification_session.verified') { const verificationSession = event.data.object; const userId = verificationSession.metadata.user_id; // 从metadata提取用户ID if (!userId) { return res.status(400).send('用户ID未找到'); } // 更新MySQL数据库 const connection = await mysql.createConnection({ host: '你的数据库地址', user: '数据库用户名', password: '数据库密码', database: '数据库名' }); await connection.execute('UPDATE users SET verified = 1 WHERE id = ?', [userId]); await connection.end(); res.json({ received: true }); } else { res.status(400).send(`Unhandled event type ${event.type}`); } }); app.listen(3000);
方案3:解析PHP会话文件(仅适合临时测试,不推荐生产)
如果PHP默认用文件存储会话,NodeJS可读取服务器上的会话文件并解析:
步骤1:确认PHP会话存储路径
Linux环境下默认路径一般为/var/lib/php/sessions/,可通过phpinfo()查看session.save_path的值。
步骤2:NodeJS读取并解析会话文件
const fs = require('fs'); const path = require('path'); const mysql = require('mysql2/promise'); const express = require('express'); const stripe = require('stripe')('你的Stripe Secret Key'); const app = express(); const phpSessionPath = '/var/lib/php/sessions/'; // 替换为你的PHP会话路径 app.post('/stripe-webhook', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const event = stripe.webhooks.constructEvent(req.body, sig, '你的Stripe Webhook密钥'); if (event.type === 'identity.verification_session.verified') { // 从Cookie获取PHP会话ID const phpSessId = req.cookies.PHPSESSID; if (!phpSessId) { return res.status(400).send('会话ID未找到'); } // 读取并解析会话文件 const sessionFilePath = path.join(phpSessionPath, `sess_${phpSessId}`); try { const sessionData = fs.readFileSync(sessionFilePath, 'utf8'); const sessionObj = {}; sessionData.split(';').forEach(item => { if (!item) return; const [key, valuePart] = item.split('|'); if (valuePart.startsWith('s:')) { sessionObj[key] = valuePart.slice(2, -2); // 解析字符串类型的会话值 } }); const userId = sessionObj.user_id; if (!userId) { return res.status(400).send('用户ID未找到'); } // 更新MySQL数据库 const connection = await mysql.createConnection({ host: '你的数据库地址', user: '数据库用户名', password: '数据库密码', database: '数据库名' }); await connection.execute('UPDATE users SET verified = 1 WHERE id = ?', [userId]); await connection.end(); res.json({ received: true }); } catch (err) { console.error(err); res.status(500).send('读取会话失败'); } } else { res.status(400).send(`Unhandled event type ${event.type}`); } }); app.listen(3000);
注意:方案3存在权限问题(NodeJS进程需有权限读取PHP会话目录),且会话格式可能随PHP版本变化,生产环境优先选用方案1或2。
内容的提问来源于stack exchange,提问作者Ironflipper
相关产品推荐
相关产品推荐

