PAYATHON 2026

使用 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 合规范围。

推荐的处理流程

建议采用以下流程:

  1. 页面和所有 API 请求只能通过 HTTPS 访问。
  2. 使用支付网关的 Hosted Fields 或 SDK 收集卡号、有效期和 CVV。
  3. 网关在前端返回一次性 token、payment method ID 或 nonce。
  4. 前端通过 $2sxc 将该标识和订单信息发送给 Web API。
  5. Web API 从服务器端读取支付网关密钥并完成扣款。
  6. 服务器只保存业务所需的交易编号、金额、状态和卡片脱敏信息。

流程可以概括为:

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 则用于避免服务器直接接触敏感卡片信息。

备注:内容仅供参考。