QZ Tray连接无响应:配置自定义证书与签名后websocket.connect()无法完成
我遇到过好几个开发者碰到和你一模一样的问题——配置了自定义证书和签名逻辑后,QZ Tray的websocket连接就卡壳了,连错误日志都没有,确实挺头疼的。咱们一步步来排查解决:
检查签名服务的响应格式:
QZ Tray对签名结果的格式有严格要求,你的signService.signMessage(toSign)返回的内容必须是Base64编码的PKCS#7签名(可以是带-----BEGIN PKCS7-----头的PEM格式,也可以是纯Base64串)。你现在用console.error("message", response.data)打印了响应,仔细看看有没有多余的字符(比如引号、换行、JSON包裹层)?如果服务返回的是JSON对象(比如{ "signature": "xxx" }),你得改成返回response.data.signature而不是整个response.data,否则QZ Tray无法解析签名。确认证书的格式正确性:
signService.getCertificate()返回的证书必须是完整的PEM格式(开头-----BEGIN CERTIFICATE-----,结尾-----END CERTIFICATE-----,中间是Base64编码的证书内容)。你console.log(cert)的时候,检查下有没有被截断、转义错误,或者是DER编码的二进制数据?如果是后者,得先转成PEM格式再返回。查看QZ Tray客户端的Debug日志:
前端没日志不代表QZ Tray客户端没报错!打开你电脑上的QZ Tray程序,进入设置面板,把日志级别调到「Debug」,然后重新触发连接,再去看QZ Tray的日志文件(一般在%APPDATA%\qz\logs或者~/Library/Application Support/qz/logs目录下),里面大概率会有具体的错误信息——比如证书验证失败、签名不匹配、或者消息格式不符合要求,这些都是前端catch不到的。排查异步逻辑的隐藏异常:
虽然你在Promise里加了catch,但有没有可能signService的请求出现了跨域问题?或者服务返回了200状态码,但响应内容是空的?打开浏览器的Network面板,看看getCertificate和signMessage这两个请求是不是真的成功返回了预期内容?有时候请求看似完成,但实际响应是空白,会导致QZ Tray一直等待正确的证书/签名,从而卡住连接。临时简化代码定位问题:
先把自定义证书和签名逻辑注释掉,换成QZ Tray的测试配置,比如:qz.security.setCertificatePromise(() => { return Promise.resolve("-----BEGIN CERTIFICATE-----...(测试证书内容)-----END CERTIFICATE-----"); }); qz.security.setSignaturePromise((toSign) => { // 用测试密钥签名的固定结果,仅用于临时测试 return Promise.resolve("测试签名内容"); });如果这样连接能成功,那问题100%出在你的签名/证书服务的返回内容上;如果还是卡壳,那可能是QZ Tray版本和JS库不兼容,或者本地防火墙/杀毒软件拦截了websocket连接。
版本兼容性检查:
确保你使用的qz-tray JS库版本和本地安装的QZ Tray客户端版本完全一致(比如JS库是2.2.2,客户端也要用2.2.2)。版本不匹配会导致握手协议不一致,直接卡住连接。
最后提个小细节:你在setSignaturePromise里用了console.error("message", response.data),这里用console.log会更合适,避免和真正的错误日志混淆,不过这个不影响功能。
内容来源于stack exchange

