使用 EasyWeChat 库调用微信服务的时候,在 laravel tinker 里面调试,发现每次进入 tinker 之后,第一次调用接口没有问题,第二次之后,就会报一个很诡异的错误。

$app = app('wechat');
// EasyWeChat\Foundation\Application {#628}

$users = $app->user->lists();
// EasyWeChat\Support\Collection {#756}

$user = $app->user->get('o7qrUviv1tkcDFMJ5wdXrpng9NNQ');
// GuzzleHttp\Exception\ConnectException with message 'cURL error 35: A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot. (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)'

PKCS #11 返回的错误,好高端啊。

中间的曲折就不说了。答案在一篇歪果仁的博客上找到,在 github 的评论上得到印证及解决问题的思路。

很明显的,两篇在遇到跟我相同问题的同时,都提到了一个关键词 NSS,因此,我又看了一下我自己的 curl 库信息。

curl -V
// curl 7.48.0 (x86_64-pc-linux-gnu) libcurl/7.29.0 NSS/3.19.1 Basic ECC zlib/1.2.7 libidn/1.28 libssh2/1.4.3
// Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
// Features: AsynchDNS IDN IPv6 Largefile NTLM NTLM_WB SSL libz

果然我本地的 curl 是带 NSS 的。

于是,用一个不带 NSS 的 curl 库来重新编译 php 吧。

mkdir -p /data/soft

# 编译并安装不带 nss 的 curl
cd /data/soft
wget "https://curl.haxx.se/download/curl-7.48.0.tar.bz2"
tar zxf curl-7.48.0.tar.bz2
cd curl-7.48.0
./configure --prefix=/usr --without-nss
make && make install

# 重新编译 php
cd /data/soft
wget -O "php-5.6.19.tar.bz2" "http://cn2.php.net/get/php-5.6.19.tar.bz2/from/this/mirror"
tar jxf php-5.6.19.tar.bz2
cd php-5.6.19
'./configure' \
  '--prefix=/usr/local/php-5.6.19' \
  '--with-libdir=lib64' \
  '--with-config-file-path=/usr/local/php-5.6.19/lib' \
  '--with-fpm-user=nobody' \
  '--with-fpm-group=nobody' \
  '--with-libxml-dir=/usr' \
  '--with-openssl=/usr' \
  '--with-openssl-dir=/usr' \
  '--with-zlib' \
  '--enable-bcmath' \
  '--with-bz2=/usr' \
  '--enable-calendar' \
  '--with-curl=/usr' \
  '--enable-dba' \
  '--with-gdbm=/usr' \
  '--enable-exif' \
  '--enable-ftp' \
  '--with-gd' \
  '--with-vpx-dir=/usr' \
  '--with-jpeg-dir=/usr' \
  '--with-png-dir=/usr' \
  '--with-xpm-dir=/usr' \
  '--with-zlib-dir=/usr' \
  '--with-freetype-dir=/usr' \
  '--with-gettext=/usr' \
  '--with-gmp=/usr' \
  '--with-mhash=/usr' \
  '--enable-intl' \
  '--enable-mbstring' \
  '--with-mcrypt=/usr' \
  '--with-mysql=/usr/local/mysql' \
  '--with-mysql-sock=/tmp/mysql.sock' \
  '--with-mysqli=/usr/local/mysql/bin/mysql_config' \
  '--enable-embedded-mysqli' \
  '--enable-pcntl' \
  '--enable-opcache' \
  '--with-pdo-mysql' \
  '--with-libedit=/usr' \
  '--with-readline=/usr' \
  '--enable-soap' \
  '--enable-mysqlnd' \
  '--enable-sockets' \
  '--enable-sysvmsg' \
  '--enable-sysvsem' \
  '--enable-sysvshm' \
  '--with-tidy=/usr' \
  '--enable-wddx' \
  '--with-xsl=/usr' \
  '--enable-fpm'
make && make install

# 重新启动由 supervisor 管理的 php-fpm(非必须)
supervisorctl restart php-fpm

检查 curl 的信息。

curl -V
// curl 7.48.0 (x86_64-pc-linux-gnu) libcurl/7.48.0 OpenSSL/1.0.1e zlib/1.2.7
// Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
// Features: IPv6 Largefile NTLM NTLM_WB SSL libz UnixSockets

欧耶!NSS 不见了!

再进 tinker 试试代码能否正常。

$app = app('wechat');
// EasyWeChat\Foundation\Application {#628}

$users = $app->user->lists();
// EasyWeChat\Support\Collection {#741}

$user = $app->user->get('o7qrUvryjgQlQti0Cw1XeVw2PJKk');
// EasyWeChat\Support\Collection {#722}

// 世界终于和平了!

PS:一些心得

  • 原来 CURL 之前一直有这个问题,见这则 stackoverflow 上面的答复
  • 一个基础库的小问题,会因为依赖树的关系,被无限放大;
  • AWS 在其它国家的普及程度还是相当高的啊。