BlueSnap Payment API 的 PCI 合规级别及范围限制
明确结论
如果应用通过 BlueSnap Payment API 直接接收、处理或转发银行卡号(PAN)、有效期、持卡人信息或 CVV,应用服务器和相关基础设施通常都会被纳入 PCI DSS 范围。商户一般需要填写 SAQ D,或按收单机构的要求接受更完整的合规评估。
要缩小合规范围,可以改用 BlueSnap 的托管支付方案,例如 Hosted Payment Fields 或托管结账页面。银行卡数据由用户浏览器直接提交给 BlueSnap,应用只接收支付令牌或交易结果。如果满足所有适用条件,这种架构通常可能适用 SAQ A。最终应填写哪种问卷,仍需由 BlueSnap、收单机构或 QSA 确认。
这里需要分清两个容易混淆的概念:
- PCI 商户级别(Merchant Level):主要取决于年度交易量、卡组织规则,以及是否发生过数据泄露。
- PCI 合规范围和 SAQ 类型:取决于银行卡数据如何进入系统,以及数据在系统中如何流转和存储。
使用 BlueSnap 本身既不会自动确定商户级别,也不能免除商户承担的 PCI DSS 责任。
为什么直接调用 Payment API 会扩大范围
假设支付流程如下:
Browser
-> Merchant Application
-> Merchant Backend
-> BlueSnap Payment API
银行卡数据会经过商户控制的页面、接口、服务器、日志系统和网络环境。因此,被纳入评估范围的可能不只是支付接口,还包括:
- Web 前端及其加载的 JavaScript
- API 网关、负载均衡器和反向代理
- 应用服务器及容器运行环境
- 日志、监控、链路追踪和错误报告系统
- 数据库、缓存及消息队列
- CI/CD、运维账号和密钥管理系统
- 其他能够连接或影响持卡人数据环境的系统
应用即使不保存银行卡号,只要接收、处理或转发过这些数据,通常仍在 PCI DSS 范围内。
推荐的缩小范围方案
更合适的数据流如下:
Browser
-> BlueSnap Hosted Payment Fields
-> BlueSnap
Browser
-> Merchant Backend(仅提交 BlueSnap token)
-> BlueSnap Payment API
实施时可以按以下步骤处理:
- 使用 BlueSnap 的 Hosted Payment Fields 或托管结账页面采集银行卡信息。
- 确保 PAN 和 CVV 从浏览器直接传给 BlueSnap,不经过商户后端。
- 后端只接收 BlueSnap 返回的支付令牌,再用令牌创建交易。
- 禁止任何接口接收原始银行卡号和 CVV。
- 检查日志、监控和异常上报配置,避免记录支付表单内容或完整请求体。
- 使用 BlueSnap 的 vaulted shopper 或其他令牌化功能处理后续支付。
- 适当隔离支付页面与其他业务页面,并严格控制第三方脚本。
- 保存数据流图、接口清单和责任分工,再交由收单机构或 QSA 确认适用的 SAQ。
代码层面的边界控制
下面是一种实现思路。浏览器端具体使用哪些初始化方法和参数,应以当前 BlueSnap Hosted Payment Fields 文档为准。不要把示例中的占位逻辑直接当作官方 SDK 调用。
// 浏览器端:卡号、有效期和 CVV 由 BlueSnap 托管字段采集。
// 商户代码只获取支付令牌,不读取托管字段中的原始卡数据。
async function submitPayment(blueSnapToken) {
const response = await fetch("/api/payments", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
paymentToken: blueSnapToken,
amount: "49.90",
currency: "USD"
})
});
if (!response.ok) {
throw new Error("Payment request failed");
}
return response.json();
}
后端应主动拒绝含有原始银行卡字段的请求:
import express from "express";
const app = express();
app.use(express.json());
app.post("/api/payments", async (req, res) => {
const forbiddenFields = [
"cardNumber",
"pan",
"cvv",
"cvc",
"securityCode"
];
const receivedForbiddenField = forbiddenFields.some(
(field) => req.body[field] !== undefined
);
if (receivedForbiddenField) {
return res.status(400).json({
error: "Raw card data must be submitted directly to BlueSnap"
});
}
const { paymentToken, amount, currency } = req.body;
if (!paymentToken || !amount || !currency) {
return res.status(400).json({
error: "Missing required payment data"
});
}
// 使用 paymentToken 调用 BlueSnap Payment API。
// API 地址、认证方式和请求结构以当前 BlueSnap 文档为准。
const result = await createBlueSnapTransaction({
paymentToken,
amount,
currency
});
res.status(200).json({
transactionId: result.transactionId,
status: result.status
});
});
日志也不应输出完整的请求体:
// 不推荐
logger.info("payment request", req.body);
// 推荐:只记录排查交易所需的非敏感信息
logger.info("payment request", {
orderId: req.body.orderId,
currency: req.body.currency,
amount: req.body.amount
});
必须注意的限制
使用令牌不等于自动脱离 PCI 范围
如果原始卡数据先到达商户服务器,再由服务器将其换成令牌,令牌化并不能消除已经发生的数据处理行为。要缩小范围,原始卡数据从一开始就不能进入商户系统。
CVV 不得在授权后保存
CVV 属于敏感认证数据,即使经过加密,也不能在交易授权完成后保存。日志、调试快照、会话回放、客服工单和错误追踪平台也需要逐一检查,防止它们间接记录 CVV。
托管字段不会消除所有安全责任
恶意脚本、遭到篡改的第三方依赖和错误配置仍可能影响支付页面,因此还需要采取以下措施:
- 使用 HTTPS 和安全响应头
- 配置 Content Security Policy
- 尽量减少第三方脚本
- 控制依赖项和脚本变更
- 为管理员启用多因素认证
- 定期轮换密钥并执行最小权限原则
- 开展漏洞扫描和补丁管理
- 监控支付页面的完整性
SAQ 类型需要正式确认
不能仅凭“使用了 iframe”或“没有保存卡号”,就判断应当填写 SAQ A、SAQ A-EP 还是 SAQ D。页面脚本、重定向方式、支付表单的控制权、交易流程及收单机构的要求,都可能影响最终结论。
建议向 BlueSnap 或收单机构提供完整的数据流图,并明确询问:
- 当前集成方式对应哪种 SAQ?
- 商户后端是否会接触 PAN、有效期或 CVV?
- 哪些系统属于持卡人数据环境或连接系统?
- 是否需要外部漏洞扫描(ASV scan)?
- BlueSnap 与商户分别负责哪些 PCI DSS 控制项?
如果业务必须通过后端直接处理原始银行卡数据,就应按照更大的 PCI DSS 范围设计系统,并尽早请 QSA 参与评估,不要等开发完成后再补做合规边界。
备注:内容仅供参考。