使用 2sxc Javascript Library 安全调用 Web API
明确结论
$2sxc 可以调用 2sxc Web API,并处理 anti-forgery token 等安全上下文,但它不会加密信用卡数据。Anti-forgery token 用于防止 CSRF 攻击,不能代替传输加密。
浏览器与 Web API 之间的数据应通过 HTTPS/TLS 加密。更合适的支付方案是使用支付网关提供的 Hosted Fields、iframe 或 JavaScript SDK,直接在浏览器中将卡号和 CVV 换成一次性 payment token,再把 token 发送给 2sxc Web API。这样,原始持卡人数据通常不需要经过你的服务器,可以显著缩小 PCI DSS 合规范围。
推荐的处理流程
建议采用以下流程:
- 页面和所有 API 请求只能通过 HTTPS 访问。
- 使用支付网关的 Hosted Fields 或 SDK 收集卡号、有效期和 CVV。
- 网关在前端返回一次性 token、payment method ID 或 nonce。
- 前端通过
$2sxc将该标识和订单信息发送给 Web API。 - Web API 从服务器端读取支付网关密钥并完成扣款。
- 服务器只保存业务所需的交易编号、金额、状态和卡片脱敏信息。
流程可以概括为:
Browser
└─ Card data ──HTTPS──> Payment Gateway
│
└─ payment token
│
Browser ──HTTPS + anti-forgery token──> 2sxc Web API
│
└─ Server-side charge request ──> Payment Gateway
需要特别注意,即使支付网关最终由服务器调用,只要浏览器把完整卡号或 CVV 发给你的 Web API,服务器就已经接触了持卡人数据,仍需遵守相应的 PCI DSS 要求。
$2sxc 能提供什么
$2sxc 用于简化 2sxc 前端与 Web API 之间的通信,例如:
- 附加 2sxc 请求所需的上下文信息;
- 处理 anti-forgery token;
- 调用模块对应的 Web API;
- 配合服务器端权限检查;
- 处理 JSON 请求和响应。
它不能:
- 自动加密某个 JSON 字段;
- 代替 HTTPS/TLS;
- 自动完成 PCI DSS 合规;
- 阻止页面中的恶意脚本读取卡号;
- 安全保存支付网关密钥;
- 把普通 Web API 自动变成合规的信用卡处理环境。
因此,$2sxc 是否适合调用支付 API,要看请求中发送的内容。发送 payment token 通常没有问题;如果发送原始 PAN、CVV 等数据,则必须完整评估 PCI DSS 范围和服务器安全措施。
前端调用示例
以下示例假设支付网关 SDK 已返回 paymentToken。不同 2sxc 版本的 Web API 方法签名可能不同,请以项目所用版本的 API 文档为准。
async function submitPayment() {
const paymentToken = await createPaymentTokenWithGateway();
const request = {
orderId: "ORDER-2026-001",
paymentToken,
amount: 19900,
currency: "CNY"
};
const sxc = $2sxc(moduleId);
const result = await sxc.webApi.post(
"Payment/Charge",
{},
request
);
return result;
}
不要把原始卡片数据放进请求对象:
// 不推荐
const request = {
cardNumber: "4111111111111111",
expiry: "12/29",
cvv: "123"
};
应该发送支付网关生成的临时标识:
// 推荐
const request = {
orderId: "ORDER-2026-001",
paymentToken: "gateway_generated_token"
};
无论使用 $2sxc、fetch 还是 jQuery,传输是否加密都取决于请求 URL 是否使用 HTTPS:
https://example.com/api/...
JavaScript 调用库本身不会另行建立传输加密机制。
Web API 示例
服务器端必须重新读取订单金额,不能相信浏览器提交的价格。以下代码只展示安全边界,具体基类、路由和权限特性需要按当前 2sxc 版本调整:
public class PaymentController : SxcApiController
{
[HttpPost]
public IHttpActionResult Charge(PaymentRequest request)
{
if (request == null || string.IsNullOrWhiteSpace(request.PaymentToken))
return BadRequest("Invalid payment request.");
// 必须从服务器端数据库或订单系统读取金额。
var order = LoadOrder(request.OrderId);
if (order == null || order.IsPaid)
return BadRequest("Order cannot be paid.");
// 密钥必须保存在服务器端的安全配置中。
var result = paymentGateway.Charge(new GatewayChargeRequest
{
Token = request.PaymentToken,
Amount = order.Amount,
Currency = order.Currency,
IdempotencyKey = order.PaymentAttemptId
});
if (!result.Success)
return BadRequest("Payment was declined.");
MarkOrderAsPaid(order.Id, result.TransactionId);
return Ok(new
{
success = true,
transactionId = result.TransactionId
});
}
}
支付接口还应包含身份验证、权限检查、请求限速和幂等控制。Anti-forgery token 只能证明请求来自已加载页面的上下文,无法证明订单金额正确,也不能防止重复扣款。
如果必须把卡号发送给 Web API
只有当支付网关确实要求服务器接收原始持卡人数据,而且相关环境已经按照适用的 PCI DSS 要求完成设计和评估时,才应采用这种方式。
至少要满足以下要求:
- 页面、脚本、Web API 和所有后续请求全程使用 HTTPS;
- 将 HTTP 请求强制跳转到 HTTPS,并启用 HSTS;
- 使用当前仍受支持的 TLS 配置;
- 禁止将 PAN、CVV 和请求正文写入应用日志、代理日志或错误追踪系统;
- 授权完成后不得保存 CVV;
- 对确实需要保存的持卡人数据实施严格的访问控制和静态加密;
- 在服务器端验证用户、订单、金额、币种和订单状态;
- 使用幂等键,防止双击或超时重试造成重复扣款;
- 限制请求频率并监控异常支付行为;
- 防范 XSS,因为页面中的恶意脚本可以在 HTTPS 加密前读取输入框内容;
- 请具备 PCI DSS 经验的人员确认适用的合规范围。
在 JavaScript 中自行使用 AES 或 RSA 加密字段,通常解决不了主要问题。浏览器必须获得加密代码和相应的密钥材料。一旦页面被恶意脚本控制,数据仍可能在加密前被窃取。除非支付网关明确规定了端到端字段加密协议,否则不要自行设计信用卡加密方案。
其他重要注意事项
不要把支付网关 secret key 放在前端。前端只能使用网关明确标记为 publishable、public 或 client-side 的密钥。
支付页面还应部署严格的 Content Security Policy,限制第三方脚本来源,并避免加载不必要的统计、广告和标签管理脚本。HTTPS 能保护传输过程,却无法保护已经受到 XSS 或第三方脚本污染的页面。
建议使用 $2sxc 将支付 token 提交给 Web API,同时让支付网关的前端组件直接处理原始卡片数据。$2sxc 负责请求上下文和 anti-forgery 防护,HTTPS/TLS 负责传输加密,支付网关的 tokenization 则用于避免服务器直接接触敏感卡片信息。
备注:内容仅供参考。
