今天突然发现微信分享缩略图不见了。打开debug一看,果然出了问题,截图如下:
这个问题是我从阿里云linux主机切换到自己配置的window主机后发生的。

当然,我会百度搜一圈,很上火。都是互相抄来抄去的内容。
这时只能自己去逐个排查了。因为我用的是php,用了微信官方提供的jssdk.php。
发现:

<?php
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
$res = json_decode($this->httpGet($url));

$res返回的竟然是null。怀疑httpGet方法环节出了问题。果然问题点在这里:

private function httpGet($url) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 500);
    // 为保证第三方服务器与微信服务器之间数据传输的安全性,所有微信接口采用https方式调用,必须使用下面2行代码打开ssl安全校验。
    // 如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
    curl_setopt($curl, CURLOPT_URL, $url);

    $res = curl_exec($curl);
    curl_close($curl);

    return $res;
  }

CURLOPT_SSL_VERIFYPEER改成false,只要不验证ssl,就能正确获取access token。但是这样当然不行。那么上面的注释很好的提供了线索。

<?php
//如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。

我继续查cacert.pem是什么鬼。得到一个方法就是在curl请求时,将这个证书赋给CURLOPT_CAINFO。这样jssdk.php里的httpGet方法就变成下面所示,假设我把下载好的cacert.pem放到X:\ssl\cacert.pem这里:

  private function httpGet($url) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 500);
    // 为保证第三方服务器与微信服务器之间数据传输的安全性,所有微信接口采用https方式调用,必须使用下面2行代码打开ssl安全校验。
    // 如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
    curl_setopt($curl, CURLOPT_CAINFO, 'X:\ssl\cacert.pem');
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
    curl_setopt($curl, CURLOPT_URL, $url);

    $res = curl_exec($curl);
    curl_close($curl);

    return $res;
  }

当然,我在想,我总不能每次配置curl请求时都要设置一遍吧。最后得到最佳方案应该是在php.ini中配置curl.cainfo。打开php.ini,找到curl.cainfo一行,去掉注释,设置pem文件路径,重启apache即可。大概位置如下:


; Absolute path used to store shared lockfiles (for *nix only).
;opcache.lockfile_path=/tmp

[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo = 'E:\ssl\cacert.pem';

[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.