直接调用微信接口 https://api.weixin.qq.com/sns/jscode2session,传 appid、secret、js_code 和 grant_type=authorization_code,解析返回的 json 获取 openid、session_key(及可能的 unionid);session_key 须用于即时解密敏感数据或生成自有 Token,不可存储或返回前端。

怎么用 php 调用微信登录接口拿到 openid 和 session_key
直接调 https://api.weixin.qq.com/sns/jscode2session,传 appid、secret、js_code、grant_type=authorization_code 就行。别自己拼 URL 字符串,用 curl_init() 或 file_get_contents() 都可以,但必须确保 js_code 是小程序前端通过 wx.login() 拿到的、且 5 分钟内没过期。
常见错误现象:{"errcode":40029,"errmsg":"invalid code"}——基本是 js_code 已被用过、过期、或前后端传错了值;{"errcode":40125,"errmsg":"invalid appid"}——appid 和 secret 不匹配,注意不是公众号的 AppID,得是小程序后台的。
-
js_code是一次性凭证,后端拿到后必须立刻请求微信接口,不能存起来复用 - 微信返回的是 JSON,记得用
json_decode($res, true)解析,字段名是小驼峰:openid、session_key、unionid(只有绑定开放平台才可能有) - 别把
session_key直接返回给前端,它等价于“登录密钥”,泄露等于账号可控
PHP 怎么安全地存储和使用 session_key
session_key 不是拿来存数据库当用户 token 用的,它是解密手机号、加密数据的临时密钥,有效期约 2 小时,且微信不提供刷新机制。所以 PHP 后端要做的,是用它当场解密敏感数据,或生成自己的会话标识(比如 JWT 或服务端 session ID)。
典型误操作:把 session_key 存进 mysql 的 user 表,下次登录还去查——这既不安全,也违反微信设计逻辑。正确做法是:拿到 session_key 后,立即用它解密前端传来的 encryptedData(比如手机号),再根据 openid 查库或创建用户,最后返回你自己的 token 给小程序。
立即学习“PHP免费学习笔记(深入)”;
- 解密手机号必须用
openssl_decrypt(),模式是AES-128-CBC,IV 是iv参数 Base64 解码后的 16 字节值 -
session_key本身建议只在内存里用一次,不要写入日志、不存 DB、不进缓存(除非你有强隔离和自动过期策略) - 如果要用 redis 缓存用户登录态,key 应该是
"sess:{$openid}",value 是你签发的 token,而不是session_key
为什么 openid 有时会变,或者拿不到 unionid
openid 是“小程序 + 用户 + AppID”三元组唯一标识,同一个用户在不同小程序里 openid 必然不同。它不会变,除非你改了小程序的 AppID;但如果用户删了小程序重装,js_code 还是能换出同一个 openid。
unionid 只有在满足条件时才返回:用户已关注公众号 / 已绑定开放平台 / 同一主体下多个小程序共用开放平台。否则微信接口压根不返回这个字段,不是你参数漏了,也不是接口坏了。
- 检查小程序后台是否绑定开放平台:设置 → 第三方服务 → 开放平台绑定
- 如果没绑开放平台,就别在代码里硬判
isset($data['unionid'])然后报错,它本来就可以为空 - 别用
unionid当主键建用户表,除非你 100% 确认所有用户都满足返回条件
PHP 后端怎么避免被伪造 js_code 或冒用登录
微信不校验请求来源 IP,也不限制调用频率(对单个 js_code 是严格一次性的),所以防刷只能靠你自己加层:比如前端传来的 js_code 必须搭配一个带时间戳和签名的 sig,后端验证签名有效性;或者要求小程序先调你自己的 /auth/prelogin 接口获取一个临时 ticket,再把 ticket 和 js_code 一起提交。
更现实的做法是:记录每个 js_code 的首次请求时间与 IP,在日志里设阈值告警;同时确保数据库用户表有唯一索引约束 openid,防止并发重复插入。
- 别依赖前端传的
rawData或signature做身份校验,它们可被截包伪造 - 微信返回的
openid才是唯一可信凭证,一切用户关联逻辑必须基于它 - 如果你的业务需要强登录态,建议在拿到
openid后立刻生成一个短期有效的 JWT,附带 exp 和 jti,并由小程序后续所有请求携带
最常被忽略的一点:微信的 session_key 是 Base64URL 编码的,不是标准 Base64,PHP 解码前得先补全 = 号并把 - 和 _ 替换成 + 和 /,否则 openssl_decrypt() 会静默失败。