银联云不提供标准数据库服务,php无法用pdo或mysqli直连;其数据需通过sftp下载对账文件(gbk编码,需phpseclib密钥登录)或调用加密api(如querytrans)并严格验签后处理。

银联云数据不是标准数据库,PHP 无法直接用 PDO 或 mysqli 连接
银联云(UnionPay Cloud)本身不提供传统意义上的「数据库服务」,它面向商户的主要是支付网关、对账文件推送、交易查询 API 等能力。所谓“银联云数据”,实际指:对账文件(.txt 或 .csv)、交易明细 JSON/XML 响应、或通过 UPOP / 全渠道接入 返回的 HTTP 接口数据。不存在 host/port/database 可供 PHP 直连。
常见误操作是试图用 file_get_contents('https://xxx/...') 直接读取银联后台页面——这必然失败,因为涉及登录态、CSRF、跳转重定向等前端逻辑,且违反银联安全规范。
- 银联不开放 Web 页面直扒,所有数据必须走其认证接口或 SFTP 下载通道
- 对账文件一般按日生成,通过银联提供的 SFTP 账号下发,路径类似
/settle/20240515/merchant_123456_20240515.txt - 实时交易查询需调用
queryTrans接口,使用 SM2/SM4 加密,请求体为 XML 或 JSON,响应也需验签
用 PHP 读取银联 SFTP 对账文件必须用 phpseclib,ssh2 扩展不可靠
银联 SFTP 服务器强制要求 SSHv2 + 密钥认证(不支持密码),且多数环境禁用 ssh2_connect()(因 libssh2 版本老旧、不支持国密算法协商)。实测稳定方案是 phpseclib/phpseclib v3.x。
示例关键步骤:
use phpseclib3\Net\SFTP;
use phpseclib3\Crypt\PublicKeyLoader;
$sftp = new SFTP('sftp.unionpay.com', 22);
$key = PublicKeyLoader::load(file_get_contents('/path/to/private_key.pem'));
if (!$sftp->login('MERCHANT_ID_123456', $key)) {
throw new Exception('SFTP login failed');
}
$remoteFile = '/settle/20240515/merchant_123456_20240515.txt';
$content = $sftp->get($remoteFile);
if ($content === false) {
throw new Exception('Failed to read ' . $remoteFile);
}
// 注意:银联对账文件是 GBK 编码,不是 UTF-8
$contentUtf8 = mb_convert_encoding($content, 'UTF-8', 'GBK');
- 银联私钥是 PEM 格式,但可能含 SM2 签名(phpseclib v3.0+ 支持,v2 不支持)
- 务必检查
$sftp->pwd()确认当前目录,银联部分环境默认不在根目录 - 对账文件首行通常是中文表头(如“交易日期|批次号|…”),
fgetcsv()需指定encoding='GBK',否则乱码
queryTrans 接口返回的 XML 必须用 simplexml_load_string() + 手动验签,不能只信 status 字段
银联全渠道接口返回的 XML 中,<respcode>000000</respcode> 仅表示通信成功,不代表交易真实有效。真正可信的是 <sign></sign> 字段对应的数据签名,必须用银联公钥验签后才可入库。
验签逻辑不能省略:
$xml = simplexml_load_string($responseXml);
$dataToVerify = (string)$xml->origQryId . (string)$xml->merId . (string)$xml->txnTime . (string)$xml->respCode;
$signature = base64_decode((string)$xml->sign);
// 使用银联提供的 RSA 公钥(PEM 格式)
$pubKey = openssl_pkey_get_public(file_get_contents('/path/to/unionpay_pubkey.pem'));
$result = openssl_verify($dataToVerify, $signature, $pubKey, OPENSSL_ALGO_SHA256);
if ($result !== 1) {
throw new Exception('Signature verification failed');
}
- 银联公钥不是通用 RSA,而是带 OID 的国密兼容格式,若
openssl_pkey_get_public()返回 false,请先用openssl x509 -in cert.cer -pubkey -noout提取纯公钥 -
origQryId是原交易查询号,不是订单号;若查不到,可能是异步通知延迟,需结合txnTime和重试机制 - XML 中金额字段(如
txnAmt)单位是分,且无小数点,需手动除以 100 转成元
写入数据到自己系统时,字段映射和空值处理最容易出错
银联返回字段命名风格与常见业务系统不一致,比如:merId 对应你系统的 merchant_code,quryId 是银联内部流水号(非你发起的 orderId),settleDate 是清算日期而非交易日期。
-
respCode为000000仅表示接口调用成功,respMsg才是业务结果(如“交易成功”、“余额不足”) - 银联字段可能为空字符串或
null,例如未退款交易的refAmt字段缺失,不能直接(int)$xml->refAmt,要先isset($xml->refAmt) - 时间字段如
txnTime格式是YYYYMMDDHHMMSS,PHP 需DateTime::createFromFormat('YmdHis', (string)$xml->txnTime)解析 - 不要把
traceNo当作唯一键——同一笔交易多次查询会返回相同traceNo,但quryId每次不同
最常被忽略的是对账文件中的“冲正交易”:类型为 03(冲正)的记录,需反向抵扣原交易,而不是当作新交易入库。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











