PAYATHON 2026

如何用 C 将 EMV Track 1 和 Track 2 数据发送至支付网关?

支付阿杰

明确结论

可以用 C 接入收单系统,但通常没有通用的「支付网关 C API」。接口形式取决于收单银行、支付处理机构和终端厂商提供的协议与认证方案,而不是编程语言。

开发前应先联系目标收单银行或支付服务商,确认对方是否支持 VEGA-3000、印度境内银行卡网络以及所需的交易类型。不要自行将原始 Track 1、Track 2 或 PIN 封装成 XML,再发送到普通支付网关。卡片数据、PIN 加密、密钥管理和交易报文都受严格的安全规范约束。实现不当会导致认证失败,还可能造成严重的数据安全问题。

需要先纠正的几个认识

芯片交易不等于发送 Track 1 和 Track 2

磁条交易可能会读取 Track 1 和 Track 2,但 EMV 芯片交易通常需要提交一组 EMV 数据,包括:

  • 交易金额、币种和终端能力
  • 应用标识和交易计数器
  • 终端验证结果
  • 持卡人验证结果
  • 芯片生成的动态应用密文
  • Issuer Application Data
  • Track 2 Equivalent Data
  • 其他由 EMV 内核产生的 TLV 数据

收单机构通常要求将这些数据放入 ISO 8583 字段,例如 Field 55,或者转换成处理机构定义的专有报文。只发送从芯片中读取的 PAN、有效期和 Track 2 Equivalent Data,不能构成一笔合规的 EMV 交易。

应用程序也不应自行拼装 EMV 交易中的关键密码学数据。应用选择、风险管理、CVM 处理和应用密文生成,应由终端内经过认证的 EMV Kernel 完成。

PIN 不能作为普通字段发送

PIN 必须通过经过认证的 PIN Pad 输入,并由安全硬件直接生成加密的 PIN Block。应用程序不应接触、记录或保存明文 PIN。

PIN Block 的格式、加密算法、密钥注入方式和密钥轮换机制必须由收单机构确定,常见机制包括:

  • ISO 9564 PIN Block
  • DUKPT 或主密钥/会话密钥体系
  • TDES 或 AES
  • 远程或现场密钥注入
  • HSM 中的 PIN 转换和验证

不能用普通的 RSA 或 AES 示例代码自行加密 PIN,也不能将 PIN 写入 XML、JSON 或日志。

持卡人也不是每次都只需输入 PIN。实际采用的 CVM 可能是 Online PIN、Offline PIN、签名、No CVM 或 CDCVM,具体方式由卡片、EMV Kernel、终端能力、交易金额和收单规则共同决定。

应当接入谁

实体 POS 的 card-present 交易通常需要接入收单银行、支付处理机构或其认证的终端管理平台,而不是供网站和 App 使用的普通线上支付网关。

在印度地区,需要向候选机构确认:

  • 是否提供线下 POS 收单服务,而不只是网上支付
  • 是否支持 Visa、Mastercard、RuPay 及需要受理的其他卡组织
  • 是否支持 VEGA-3000,或是否允许在该设备上部署自研应用
  • 支持哪些 EMV Kernel、AID、CAPK 和终端参数
  • 使用 ISO 8583、SOAP、REST 还是专有 TCP 协议
  • 是否提供 C SDK,或仅提供协议文档和参考实现
  • 终端需要进行哪些 L2/L3、主机或端到端认证
  • PIN Pad 和安全模块需要哪些认证
  • 如何进行密钥注入、终端注册和参数下发
  • 是否提供测试主机、测试卡、测试案例和认证环境
  • 退款、撤销、冲正、预授权、结算与对账如何处理
  • 当前适用的 RBI、NPCI、PCI SSC 和卡组织要求

这些问题需要在确定架构前解决。即使代码已经完成,只要设备型号、EMV Kernel、PIN Pad 或报文格式没有获得收单机构认可,应用仍然无法上线。

C 语言如何实现接口

如果处理机构提供 HTTPS REST 或 SOAP 接口,完全可以用 C 实现。可根据设备 SDK 的支持情况选择:

  • libcurl:发送 HTTP/HTTPS 请求
  • OpenSSL 或 mbedTLS:提供 TLS、证书和密码学基础能力
  • libxml2:生成和解析 XML
  • gSOAP:根据 WSDL 生成 C/C++ SOAP 客户端
  • 处理机构或终端厂商提供的专用通信库

这些库只能解决网络通信和序列化问题,不能自动处理 EMV、PIN、密钥管理、ISO 8583 或收单认证。如果 VEGA-3000 的操作系统无法直接运行这些库,应使用设备 SDK 提供的网络、TLS 和安全模块接口。另一种方式是让终端与本地 ECR 或收银系统通信,再由经过认证的中间件连接收单主机。

SOAP 并非强制要求。只有服务商提供的接口规范或 WSDL 明确要求 SOAP 时,才需要使用它。不要因为某份示例文档采用 XML,就认定目标收单系统也接受相同格式。

一个安全边界清晰的 C 示例

下面的代码仅演示如何通过 HTTPS 提交由收单机构定义的交易载荷,其中不包含原始 Track 和明文 PIN。字段名称、URL、认证方式和响应结构都必须替换成服务商正式提供的定义。

#include <curl/curl.h>
#include <stdio.h>

static int send_authorization(
    const char *endpoint,
    const char *client_cert,
    const char *client_key,
    const char *gateway_payload)
{
    CURL *curl = curl_easy_init();
    if (curl == NULL) {
        return -1;
    }

    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/xml");
    headers = curl_slist_append(headers, "Accept: application/xml");

    curl_easy_setopt(curl, CURLOPT_URL, endpoint);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, gateway_payload);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)-1);

    /* 必须验证服务端证书和主机名。 */
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);

    /*
     * 仅在收单机构要求双向 TLS 时设置。
     * 证书与私钥应存放在设备安全区域,而不是源码或普通文件中。
     */
    curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert);
    curl_easy_setopt(curl, CURLOPT_SSLKEY, client_key);

    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);

    CURLcode result = curl_easy_perform(curl);

    long http_status = 0;
    if (result == CURLE_OK) {
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
    }

    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);

    if (result != CURLE_OK) {
        return -2;
    }

    if (http_status < 200 || http_status >= 300) {
        return -3;
    }

    return 0;
}

gateway_payload 应由收单机构的 SDK 或接口适配层生成。例如,它可以引用终端交易对象、受保护的 EMV 数据块或处理机构生成的 token:

<AuthorizationRequest>
    <TerminalId>ASSIGNED_BY_ACQUIRER</TerminalId>
    <TransactionId>UNIQUE_TRANSACTION_ID</TransactionId>
    <Amount minorUnits="true">12500</Amount>
    <Currency>INR</Currency>
    <EntryMode>CHIP</EntryMode>
    <ProtectedPaymentData>PROCESSOR_DEFINED_VALUE</ProtectedPaymentData>
</AuthorizationRequest>

ProtectedPaymentData 只是占位符,并不存在通用的数据编码方式。不能将完整的 Track 1、Track 2、PIN 或未经服务商允许的 EMV 标签直接填入其中。

生产代码还需要处理:

  • XML 转义和严格的响应解析
  • 请求唯一编号与幂等控制
  • 网络超时后的交易状态查询
  • 自动冲正和重复交易防护
  • MAC、报文签名或双向 TLS
  • 终端时间同步
  • 脱机交易和批次结算
  • 及时清除敏感缓冲区
  • 防止卡片数据出现在日志、崩溃转储和调试输出中

推荐的实施顺序

  1. 选定印度地区的收单银行或具备线下 POS 收单能力的处理机构。
  2. 向其提交终端型号、SDK、EMV Kernel、PIN Pad 和安全认证信息。
  3. 获取正式的接口规范、终端参数、测试环境和认证流程。
  4. 确认设备厂商是否已有适配该收单机构的支付应用或认证组件。
  5. 优先使用收单方提供的 SDK。如果没有 C SDK,再根据其协议,使用设备网络接口、libcurl、mbedTLS、libxml2 或 gSOAP 开发适配层。
  6. 完成密钥注入,以及测试卡交易、冲正、退款、结算和异常场景测试。
  7. 通过收单机构要求的主机认证、端到端认证和安全审查后再部署。

安全与合规注意事项

Track 数据属于高度敏感的支付卡数据。完整磁道数据和敏感认证数据通常不能在授权完成后保存。即使交易失败,也不应随意写入数据库或日志。如果确实需要展示 PAN,应按规则进行掩码处理。数据的存储、传输和访问控制应符合适用的 PCI DSS、PCI PTS、EMV、卡组织要求以及印度当地监管要求。

适用版本、认证范围和印度地区的监管要求可能会随时间和业务模式变化,应以收单银行、设备认证机构、PCI SSC、RBI、NPCI 及相关卡组织当前发布的正式要求为准。

因此,下一步应先取得收单银行或支付处理机构的接入许可和技术规范,而不是寻找一个通用的 C 库。没有这些资料,就无法可靠地确定报文格式、PIN Block、密钥体系和终端认证方式,也无法安全地完成真实交易。

备注:内容仅供参考。