yii2需四步适配微信小程序:禁用csrf与cookie验证、注册jsonparser解析json、配置cors支持options预检及authorization头、实现code2session登录态对接,否则出现401/403或cors错误。

Yii2 能直接支撑微信小程序后端 RESTful API,但默认配置不满足小程序要求:缺少 OPTIONS 预检处理、Access-Control-Allow-Origin 头缺失、Content-Type 解析不兼容小程序的 application/json 原始体、用户登录态需适配微信 code2Session 流程。必须手动补全这四块,否则小程序调用会卡在 401、403 或 CORS 报错。
启用 Yii2 的 REST 模块并禁用 CSRF(小程序无 Cookie 上下文)
Yii2 默认开启 csrfValidation,而小程序请求不带 X-CSRF-Token,所有 POST/PUT/DELETE 请求都会被拦截为 400。必须在控制器中显式关闭:
public function init()
{
parent::init();
$this->enableCsrfValidation = false;
}
同时确保 request 组件已配置 enableCookieValidation 为 false(小程序不依赖 Cookie 维持会话),并在 config/web.php 中确认:
'request' => [
'enableCookieValidation' => false,
'enableCsrfValidation' => false,
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
- 漏掉
enableCookieValidation = false可能导致session_start()失败或报headers already sent -
JsonParser必须显式注册,否则小程序发的 raw JSON 体不会自动解析到$request->bodyParams
处理跨域(CORS):小程序域名校验 + OPTIONS 预检响应
微信开发者工具和真机调试都严格校验响应头。Yii2 自带的 cors 行为只支持简单请求,对小程序常带的 Authorization 或自定义 header 的请求会失败。推荐用中间件方式统一注入头:
由于微信的大热,为了更好的方便使用微信的用户查询一些信息,这篇文章是入门级的微信公众平台开发教程,需要的朋友可以参考下 这篇入门教程将引导你完成如下任务: 创建百度云平台应用启用微信公众平台开发模式获取订阅、文字、图片、语音、视频消息回复文本、图文及音乐消息程序开发
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => ['https://servicewechat.com', 'https://developers.weixin.qq.com'],
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => true,
'Access-Control-Allow-Headers' => ['Authorization', 'X-Requested-With', 'Content-Type'],
],
],
];
}
-
Origin必须精确列出微信域名,不能写*(否则Allow-Credentials不生效) - 小程序登录后常带
Authorization: Bearer xxx,所以Access-Control-Allow-Headers必须显式包含Authorization - 若用 Nginx,也可在反代层加头,但 PHP 层控制更可靠,避免 Nginx 缓存预检响应
实现微信 code2Session 登录态与 Yii2 用户系统对接
小程序调用 wx.login() 获取 code 后,需后端用该 code 换取 openid 和 session_key,再生成 Yii2 可识别的登录态。不要复用 IdentityInterface 的传统密码逻辑:
public function actionLogin()
{
$code = \Yii::$app->request->post('code');
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code={$code}&grant_type=authorization_code";
$response = file_get_contents($url);
$data = json_decode($response, true);
if (!isset($data['openid'])) {
throw new BadRequestHttpException('Invalid code');
}
$user = User::findByOpenid($data['openid']);
if (!$user) {
$user = User::createWithOpenid($data['openid']);
}
$token = \Yii::$app->security->generateRandomString(32);
$user->access_token = $token;
$user->save(false);
return ['token' => $token, 'expires_in' => 7200];
}
- 别把
session_key当作 token 返回给前端——它仅用于解密敏感数据,且 2 小时过期不可续;真正给小程序的是自定义access_token - 务必校验
appid和secret是否匹配当前小程序,防止伪造 code - 后续接口用
Bearertoken 验证时,直接查User::findByToken($token),不要走Yii::$app->user->login()全流程(无 password 场景下易出错)
小程序上传文件时正确解析 multipart/form-data(非 JSON)
小程序调用 wx.uploadFile 发送的是 multipart/form-data,不是 JSON。此时 $request->bodyParams 为空,必须用 $request->getUploadedFile('file') 获取:
public function actionUpload()
{
$uploadedFile = \Yii::$app->request->getUploadedFile('file');
if (!$uploadedFile || $uploadedFile->error !== UPLOAD_ERR_OK) {
throw new BadRequestHttpException('File upload failed');
}
$path = \Yii::getAlias('@webroot/uploads/') . uniqid() . '.' . $uploadedFile->extension;
$uploadedFile->saveAs($path);
return ['url' => '/uploads/' . basename($path)];
}
- 别尝试用
JsonParser解析上传请求——它对 multipart 无效,会导致bodyParams为空且无提示 - 注意
@webroot路径权限,上传目录需 Web 服务器可写,但不能放在@webroot下直接暴露源码 - 微信 CDN 上传建议走云开发或 COS,PHP 后端只做中转鉴权,避免大文件阻塞 PHP 进程
最易被忽略的是 code2Session 返回的 session_key 绝对不能传给前端,以及所有接口必须区分「是否需要登录」——Yii2 的 authenticator 行为默认对所有动作生效,漏掉 public function behaviors() 里的 'except' => ['login', 'upload'] 会导致登录接口自己拦自己。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










