首先,我们的项目中有这么一个需求,就是需要在发送请求时,需要调用 java 写的一个加密库。所以不可避免的会使用到 php 的 exec 方法执行 shell 命令。
一切都很正常,直到,出现了中文。哎。具体的 case 如下:
样例代码:
<?php
$cmd = 'java -jar sign-maker.jar mike messi';
exec($cmd, $ret, $out);
var_dump($ret);
$cmd = 'java -jar sign-maker.jar 麦克 梅西';
exec($cmd, $ret, $out);
var_dump($ret);
其中,sign-maker.jar 就是我们按照第三方的加密协议的一个签名包(虽然也是我写的),执行这段代码,我们可以得到如下的结果:
php index.
php
array(1)
{
[0]=>
string(80) "495cc9e9269265cc0e7d58940367976571a1c4fdb90bf842ee4ba703fb1a554abf0772218e29d3d8"
}
array(2) {
[0]=>
string(80) "495cc9e9269265cc0e7d58940367976571a1c4fdb90bf842ee4ba703fb1a554abf0772218e29d3d8"
[1]=>
string(80) "e442a87d369a1a3c610bb2d18bd38fdad3b52644ab0ef86a21b57a5d0d75cb8dbf0772218e29d3d8"
}
可以看到,我们已经生成了两个 sign 值。但是,在传输过程中,对面居然报了 sign 无效的错误。觉得很奇怪,第一个 sign 是正确的,但是第二个就是败了。于是我们在终端中手动输入了这个命令:
└─[$]> java -jar sign-maker.jar 麦克 梅西
92144a18e9f75ec2e257c9bb15a05825a706064445b9492efd065dfd6c8b38d0bf0772218e29d3d8
发现 sign 果然不同。所以第一反应是字符编码的问题,尝试了 utf8encode,iconv 等等方法转换字符,但是都是无功而返。最后定为到环境变量的问题上。
解决办法
解决办法先上,在 exec 的命令前首先指定字符集:
<?php
$set
_charset =
'export LANG=en_US.UTF-8;'
;
$cmd = 'java -jar sign-maker.jar mike messi';
exec
(
$set
_charset.$cmd, $ret, $out);
var_dump($ret);
这样即可。