提供 CC processing 的网站需要遵循哪些 PCI 标准?
结论
只要网站接收、传输或存储信用卡持卡人数据,就需要遵守 PCI DSS(Payment Card Industry Data Security Standard,支付卡行业数据安全标准)。即使信用卡信息完全由第三方支付页面处理,商户通常也要完成相应的合规确认,但责任范围和验证工作会少很多。
PCI 并不是负责逐个审批网站的机构。PCI Security Standards Council(PCI SSC)负责制定和维护安全标准,但通常不会主动检查每个网站。合规要求主要由收单银行、支付服务商和银行卡品牌推动。验证方式可能包括自评问卷(SAQ)、外部漏洞扫描(ASV),或由合格安全评估机构(QSA)进行审计。
PCI DSS 保护什么
PCI DSS 主要保护支付账户数据,包括:
- 主账号(PAN,即信用卡号)
- 持卡人姓名
- 有效期
- 服务代码
- 敏感认证数据,例如 CVV/CVC、完整磁条数据和 PIN 数据
CVV/CVC 等敏感认证数据通常不得在授权完成后存储,即使经过加密也不行。如果需要保存完整卡号,必须采用严格的访问控制、加密、密钥管理、日志记录和数据保留策略。
PCI DSS 检查的不只是网页有没有使用 HTTPS。服务器、应用程序、网络、人员权限、供应商管理、漏洞修复和安全流程也在检查范围内。只安装 TLS 证书并不代表已经合规。
先确定网站采用哪种支付方式
网站承担多少 PCI 责任,主要取决于信用卡数据是否会进入自己的系统。
1. 跳转到支付服务商托管页面
用户点击付款后,会跳转到支付服务商的域名输入卡号,网站本身不接触信用卡数据。
这种方式的合规范围通常最小,也可能适用较简化的 SAQ 类型。具体如何分类,仍须由支付服务商或收单银行确认。
2. 在网站中嵌入托管支付字段
结账页由网站展示,但卡号输入框通过支付服务商提供的 iframe 或 Hosted Fields 加载。信用卡数据直接发送给支付服务商,网站只接收 token。
这种模式也能大幅缩小合规范围。不过,商户页面仍可能影响支付组件。例如,恶意 JavaScript 可能替换或操纵支付字段,因此网站自身的安全控制仍不可少。
3. 网站服务器接收信用卡数据
如果浏览器先把卡号提交到网站自己的后端,再由后端调用支付网关,相关前端、API、服务器、网络和运维环境通常都会被纳入 PCI DSS 范围。
除非业务确实需要,而且企业具备相应的安全能力,否则不建议自行接收或保存原始卡数据。
推荐的实施步骤
1. 联系收单银行或支付服务商
先确认以下事项:
- 商户属于哪种验证等级
- 应填写哪一种 SAQ
- 是否需要 ASV 外部漏洞扫描
- 是否需要 QSA 现场或正式评估
- 证明材料应通过什么渠道提交
- 第三方支付服务商能提供哪些 PCI DSS 合规证明
商户等级通常取决于年度交易量、银行卡品牌规则以及是否发生过数据泄露,不能只看网站规模。
2. 尽量让卡数据绕过自己的系统
优先使用支付服务商提供的:
- Hosted Checkout
- Hosted Fields
- 官方支付组件
- Tokenization
不要自行设计普通 HTML 表单,再将卡号提交到网站后端。
下面是一个概念性示例。实际 API 名称和参数必须以所选支付服务商的官方 SDK 为准:
<form id="payment-form">
<div id="hosted-card-number"></div>
<div id="hosted-expiry"></div>
<div id="hosted-cvc"></div>
<button type="submit">支付</button>
</form>
<script src="https://payments.example.com/sdk.js"></script>
<script>
const payments = PaymentProvider.create({
publicKey: "PUBLIC_KEY"
});
const fields = payments.createHostedFields({
number: "#hosted-card-number",
expiry: "#hosted-expiry",
cvc: "#hosted-cvc"
});
document
.getElementById("payment-form")
.addEventListener("submit", async (event) => {
event.preventDefault();
const result = await fields.tokenize();
await fetch("/api/payments", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": getCsrfToken()
},
body: JSON.stringify({
paymentToken: result.token
})
});
});
</script>
发送到 /api/payments 的内容应当是支付 token,而不是 PAN、有效期或 CVV。示例中的 PaymentProvider 只是占位名称,不能直接用于生产环境。
后端也只处理 token:
app.post("/api/payments", requireAuthenticatedUser, async (req, res) => {
const { paymentToken } = req.body;
if (typeof paymentToken !== "string" || paymentToken.length === 0) {
return res.status(400).json({ error: "Invalid payment token" });
}
const payment = await paymentGateway.charge({
token: paymentToken,
amount: 1999,
currency: "USD"
});
res.json({
paymentId: payment.id,
status: payment.status
});
});
金额不能只以浏览器提交的数据为准。后端应根据订单记录重新计算应付金额,并核对用户、订单、币种和支付状态。
3. 建立基本安全控制
至少应做到:
- 全站强制使用受支持的 HTTPS/TLS 配置
- 及时更新操作系统、框架、依赖和支付 SDK
- 为管理后台启用多因素认证
- 按最小权限原则分配账号和数据库权限
- 严格控制支付页面的脚本来源
- 保留安全日志并监控异常行为
- 定期扫描漏洞并修复高风险问题
- 禁止在日志、分析系统、错误报告和客服工单中记录卡号或 CVV
- 制定事件响应和数据泄露处理流程
- 定期核实第三方支付服务商的 PCI DSS 合规状态
可以为支付页面配置安全响应头,但具体策略要先在测试环境中验证,以免阻止支付服务商所需的 iframe、脚本或 API:
Content-Security-Policy: default-src 'self'; script-src 'self' https://payments.example.com; frame-src https://payments.example.com; connect-src 'self' https://api.payments.example.com; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
Strict-Transport-Security: max-age=31536000; includeSubDomains
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
这些响应头可以降低部分攻击风险,但不能单独作为 PCI DSS 合规证明。
4. 完成适用的验证
按照收单机构的要求,商户可能需要:
- 填写对应的 SAQ
- 提交合规证明(AOC)
- 由认可的 ASV 执行外部漏洞扫描
- 进行渗透测试
- 接受 QSA 评估
- 定期重新验证,而不是只在网站上线时检查一次
应使用收单银行或支付服务商当前提供的表格和版本。PCI DSS 及相关验证要求会更新,不能继续使用过期问卷或旧版清单。
常见误区
- 使用第三方支付就完全不需要 PCI DSS:通常不正确。外包支付可以缩小合规范围,但商户仍要管理网站安全和第三方服务商,也可能需要提交 SAQ。
- 不保存卡号就不受约束:不一定。如果系统传输或处理过卡数据,仍可能被纳入合规范围。
- 数据库加密后可以保存 CVV:不可以。授权完成后通常不得保存 CVV/CVC。
- 支付网关通过了 PCI 认证,所以网站也自动合规:不成立。服务商合规不能自动覆盖商户自己的系统和操作。
- PCI SSC 会主动给网站发合格证:通常不会。验证和执行主要由支付品牌、收单银行、支付服务商及合格评估机构负责。
较稳妥的架构是让网站只管理订单,把信用卡信息直接交给经过 PCI DSS 验证的支付服务商,网站后端只接收无法直接还原为卡号的支付 token。最终适用的 SAQ、扫描或审计要求,应由收单银行或支付服务商根据实际数据流确认。
备注:内容仅供参考。
