微信手机号解密必须用openssl_decrypt而非mcrypt_decrypt,因php 7.2+已废弃mcrypt;需先base64_decode session_key和iv,再用aes-128-cbc解密encrypteddata,最后json_decode提取phonenumber。

微信手机号解密必须用 openssl_decrypt,不是 mcrypt_decrypt
ThinkPHP 自身不提供微信手机号解密的封装,得自己写 AES-128-CBC 解密逻辑。微信返回的 encryptedData 是标准 PKCS#7 填充、AES-128-CBC 加密结果,密钥是会话密钥 session_key(32 字节),IV 是 iv(16 字节)。PHP 7.2+ 已废弃 mcrypt 扩展,硬上会报 Function mcrypt_module_open() is deprecated 或直接失败。
实操建议:
- 确认 PHP 启用了
openssl扩展(extension=openssl在 php.ini 中启用) -
session_key必须原样使用,不能 base64_decode 多次;它本身是 base64 编码过的,解密前需先base64_decode($session_key) -
iv同理,也必须base64_decode一次再传给openssl_decrypt - 解密后得到的是 JSON 字符串,需
json_decode提取phoneNumber字段
ThinkPHP 中解密代码要避开 input() 自动过滤和字符截断
微信回调或小程序前端传来的 encryptedData、iv、session_key 都是 base64 字符串,含 +、/、=。ThinkPHP 的 input() 默认会做 URL 解码和空格/加号转换(把 + 当空格),导致 base64 解码失败,报 data length is not multiple of block size 或空结果。
实操建议:
- 改用
$_POST['encryptedData']或$request->post('', '', null)(第三个参数设为null禁用过滤) - 不要对 base64 字符串做任何 trim、urldecode、htmlspecialchars 处理
- 校验三者长度:
strlen(base64_decode($encryptedData)) % 16 === 0(AES-CBC 要求明文长度是块大小倍数)
解密失败常见错误现象及对应检查点
返回空数组、null、false,或解密出乱码(如 U\u001f~...),基本是以下某处错了:
-
session_key过期或已被其他接口(如getPhoneNumber)用过 —— 微信 session_key 一次有效,且 2 小时过期 -
encryptedData和iv来自不同次调用 —— 必须是同一button点击后一次性获取的三元组 - 误把
errCode为 0 当作成功 —— 得看响应体是否含phoneNumber,微信有时 errCode=0 但 data 为空(权限未授权、用户拒授) - 没验证签名(
signature)和rawData—— 虽然不影响解密,但跳过校验会导致伪造请求直接进解密流程,风险极高
ThinkPHP 日志里别直接打 session_key 和 encryptedData
这些属于敏感凭据,日志一旦落盘就等于泄露用户手机号解密能力。TP 默认日志级别包含 debug,Log::debug('session_key: ' . $session_key) 这种写法在生产环境极其危险。
实操建议:
- 日志中只记录
substr(md5($session_key), 0, 8)或哈希摘要,不记录原文 - 解密失败时,只记错误类型(如
"aes_decrypt_failed: invalid iv length"),不记输入数据 - 确保
runtime/log目录不在 Web 可访问路径下,避免被扫描下载
session_key 不可重用、base64 字符串不能被框架自动处理、日志不能留明文凭据——这三点出问题,调试时根本看不出哪步断了。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










