程序对接微信支付时,需要在微信支付商户后台申请api证书,就是那个apiclient_cert.pem、apiclient_key.pem,想必你应该见过吧
不过这里有个坑却在等着你,坑不大,下面就展开说说
一次对接微信支付时,本地调试支付都正常,支付正常,回调也正常,使用的是yansongda/pay这个composer包开发的微信支付,
但是部署到线上后,发起创建订单时就报错如下
配置异常: 解析微信配置 [mch_public_cert_path] 出错
一般遇到这种问题,我基本上就傻眼了,相信大部分人也傻眼,你还能去深入代码理清这个报错从哪里冒出来的吗,没有半天估计是理不清的
后来搜索啊,本地调试没问题,部署到线上报错微信证书错误,本地与线上的证书参数的区别就是路径不一致,最后发现问题了
支付证书是不能放在网站可访问目录中的,意思就是网站整个目录下都不适合放微信支付证书,毕竟支付私钥证书要能被公开访问了,事情就大了
涉及到钱的事,你懂的。
所以部署到线上后,只能把微信支付证书放到网站的web根目录之外,好的,bug就在这里产生了,由于站点部署在宝塔面板上,宝塔创建站点时会默认在站点根目录创建一个
防跨站的user.ini文件,该文件的主要作用就是当前站点的程序不能访问站点目录之外的文件,就导致了微信的php代码无法访问到根目录之外的证书文件。
科学分析原因如下:
open_basedir 限制(非常典型,本地 Windows 不报错、线上 Linux 报错的经典原因) 你把证书刻意放在 web 根目录之外(/www/cert/...),而 Linux 生产环境的 PHP 通常配置了 open_basedir 只允许访问网站目录。
于是 PHP 访问 /www/cert/... 被拒绝 → is_file() 返回 false → 走 else 分支把路径字符串本身当证书传给 openssl_x509_parse → 解析失败报"解析出错"。本地 Windows 一般没设 open_basedir 或路径在允许范围内,所以正常。
解决方法
在站点的根目录下的user.ini文件中 open_basedir 允许列表追加 /www/cert/(用 : 分隔多个路径)。/www/cert是你放置支付证书的目录,这是"本地 OK 线上挂"最可能的元凶。