thinkphp微信开发:安全模式消息加解密
使用thinkphp官方的WeChat包,使用不同模式可以成功,但是安全模式就是不行,现将分析解决结果做下记录。
TRight
分析问题:
解密微信服务器消息老是不成功,下载下微信公众平台官方给出的解密文件和WechatCrypt.class.php进行比对发现也没有问题。用file_put_contents函数保存下解密后的文件进行分析。发现官方包解密的xml不是标准的xml格式,所以simplexml_load_string函数无法处理。
/**
* 对密文进行解密
* @param string $encrypt 密文
* @return string 明文*/publicfunctiondecrypt($encrypt){//BASE64解码$encrypt=base64_decode($encrypt);//打开加密算法模块$td= mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');//初始化加密算法模块mcrypt_generic_init($td,$this->cyptKey,substr($this->cyptKey, 0, 16));//执行解密$decrypt= mdecrypt_generic($td,$encrypt);//去除PKCS7补位$decrypt= self::PKCS7Decode($decrypt, mcrypt_enc_get_key_size($td));//关闭加密算法模块mcrypt_generic_deinit($td);
mcrypt_module_close($td);if(strlen($decrypt) < 16){thrownew\Exception("非法密文字符串!");
}//去除随机字符串$decrypt=substr($decrypt, 16);//获取网络字节序$size=unpack("N",substr($decrypt, 0, 4));$size=$size[1];//APP_ID$appid=substr($decrypt,$size+ 4);//验证APP_IDif($appid!==$this->appId){thrownew\Exception("非法APP_ID!");
}//明文内容$text=substr($decrypt, 4,$size);return$text;
}/**
* PKCS7填充字符
* @param string $text 被填充字符
* @param integer $size Block长度*/PRivatestaticfunctionPKCS7Encode($text,$size){//字符串长度$str_size=strlen($text);//填充长度$pad_size=$size- ($str_size%$size);$pad_size=$pad_size? :$size;//填充的字符$pad_chr=chr($pad_size);//执行填充$text=str_pad($text,$str_size+$pad_size,$pad_chr,STR_PAD_RIGHT);return$text;
}/**
* 删除PKCS7填充的字符
* @param string $text 已填充的字符
* @param integer $size Block长度*/privatestaticfunctionPKCS7Decode($text,$size){//获取补位字符$pad_str=ord(substr($text, -1));if($pad_str< 1 ||$pad_str>$size) {$pad_str= 0;
}returnsubstr($text, 0,strlen($text) -$pad_str);
}
解决方法: 输出的xml文件是这样的
1<xml>2<ToUserName><![CDATA[gh_249aeb986d99]]><\/ToUserName>\n3<FromUserName><![CDATA[oopVmxHZaeQkDPsRcbpwXKkH-J2Q]]><\/FromUserName>\n4<CreateTime>1448944621<\/CreateTime>\n5<MsgType><![CDATA[text]]><\/MsgType>\n6<Content><![CDATA[\u7ecf\u7406]]><\/Content>\n7<MsgId>6223169761311044588<\/MsgId>\n8<\/xml>
所以需要进行处理才能让simplexml_load_string处理
在输出的明文内容后面加上
1//明文内容2$text = substr($decrypt, 4, $size);3//去掉多余的内容4$text=str_replace('<\/','</', $text);5$text=str_replace('>\n','>',$text);6return $text;
安全模式就能正常使用了。