Google Pay返回ECv2格式Token的处理及支付集成问题
Google Pay集成:ECv2令牌处理与后端支付对接指南
问题1:如何处理ECv2格式的tokenizationData.token载荷
你拿到的是Google Pay的ECv2加密令牌,这是使用DIRECT令牌化类型时的标准返回格式,和Stripe等网关返回的带id的简化token本质不同:
- 前端不需要做任何解密或验证操作,直接把整个解析后的令牌对象转发到后端即可。ECv2令牌包含签名、加密消息等安全信息,这些都需要支付处理器(或后端结合Google提供的工具)来验证和解密。
- 为什么不是带
id的简单token?因为你当前的Google Pay配置用的是DIRECT令牌化模式,这种模式下Google会直接返回加密的支付凭证,而非通过支付网关转换后的简化token。如果想拿到Stripe风格的id,需要在前端配置里切换为PAYMENT_GATEWAY类型,并指定对应的网关参数(比如Stripe的gateway: 'stripe'和stripe: {version: '...', publishableKey: '...'})。
问题2:后端如何对接支付处理器
后端需要根据你使用的支付服务提供商(PSP),调用对应的API来处理ECv2令牌:
情况1:使用Stripe
如果要通过Stripe处理Google Pay支付,推荐在前端切换为PAYMENT_GATEWAY模式,这样Google Pay会直接返回Stripe的payment_method ID,后端直接用Stripe SDK创建支付即可:
// 前端配置示例(切换为PAYMENT_GATEWAY) const baseRequest = { apiVersion: 2, apiVersionMinor: 0, allowedPaymentMethods: [ { type: 'CARD', parameters: { allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], allowedCardNetworks: ['AMEX', 'VISA', 'MASTERCARD'] }, tokenizationSpecification: { type: 'PAYMENT_GATEWAY', parameters: { gateway: 'stripe', stripe: { version: '2020-08-27', publishableKey: 'pk_your_stripe_publishable_key' } } } } ] };
如果已经用了DIRECT模式拿到ECv2令牌,Stripe也支持接收该令牌,通过PaymentMethod.create接口传入:
// 后端Node.js/Express代码示例 const stripe = require('stripe')('sk_your_stripe_secret_key'); app.post('/process-payment', async (req, res) => { try { const { paymentToken } = req.body; // 用Google Pay的ECv2令牌创建Stripe支付方式 const paymentMethod = await stripe.paymentMethods.create({ type: 'card', card: { token: JSON.stringify(paymentToken) // 直接传入整个ECv2对象的JSON字符串 } }); // 后续创建PaymentIntent完成扣款 const paymentIntent = await stripe.paymentIntents.create({ amount: 1000, // 金额(分) currency: 'eur', payment_method: paymentMethod.id, confirm: true }); res.json({ success: true, transactionId: paymentIntent.id }); } catch (error) { res.json({ success: false, error: error.message }); } });
情况2:使用Monext
根据Monext的集成规范,你需要将完整的ECv2令牌(包括signature、intermediateSigningKey、signedMessage等字段)通过Monext的专属支付API提交。具体步骤:
- 后端接收前端传来的完整ECv2令牌对象
- 按照Monext API要求的格式,将令牌数据封装到请求体中
- 使用Monext提供的商户密钥进行请求签名(如果需要)
- 调用Monext的支付创建接口,完成扣款流程
示例后端代码(Node.js/Express):
const axios = require('axios'); const monextConfig = { apiUrl: 'https://api.monext.fr/payment/googlepay', // 替换为Monext实际API地址 merchantId: 'your_merchant_id', secretKey: 'your_secret_key' }; app.post('/process-payment', async (req, res) => { try { const { paymentToken } = req.body; // 构造Monext请求体 const requestBody = { merchantId: monextConfig.merchantId, amount: 1000, // 金额(分) currency: 'EUR', googlePayToken: paymentToken, // 直接传入完整ECv2令牌 orderId: 'unique_order_id_123' // 自定义唯一订单ID }; // 添加签名(根据Monext要求实现) const signature = generateMonextSignature(requestBody, monextConfig.secretKey); const response = await axios.post(monextConfig.apiUrl, requestBody, { headers: { 'Content-Type': 'application/json', 'X-Monext-Signature': signature } }); if (response.data.status === 'SUCCESS') { res.json({ success: true, transactionId: response.data.transactionId }); } else { res.json({ success: false, error: response.data.errorMessage }); } } catch (error) { res.json({ success: false, error: error.response?.data?.errorMessage || error.message }); } }); // 辅助函数:生成Monext签名(按其文档指定的算法实现) function generateMonextSignature(data, secretKey) { const crypto = require('crypto'); const payload = JSON.stringify(data); return crypto.createHmac('sha256', secretKey).update(payload).digest('hex'); }
关键注意事项
- 令牌化类型选择:如果你的支付处理器支持
PAYMENT_GATEWAY模式(如Stripe),优先使用该模式,可简化前后端处理流程,无需直接处理ECv2加密令牌。 - 安全要求:ECv2令牌包含敏感支付信息,必须通过HTTPS传输,后端处理时要确保密钥安全,避免泄露。
- 错误处理:要捕获并处理支付处理器返回的各种错误状态(如支付失败、令牌无效、金额不符等),并将清晰的错误信息返回给前端。
内容的提问来源于stack exchange,提问作者bouazra mouheb
相关产品推荐
相关产品推荐

