codeigniter需调用微信官方接口生成小程序码,因自带curl类不支持json请求体和二进制响应,且无access_token管理机制;推荐用file_get_contents+stream_context_create直连,分拆为辅助函数、令牌模型和控制器三层处理。

CodeIgniter 框架本身不提供微信小程序码生成能力,必须通过调用微信官方 HTTPS 接口实现,且必须在服务端完成——不能把 access_token 或请求逻辑暴露到前端或小程序里。
为什么不能直接用 CI 的 curl 类或第三方 SDK 封装?
微信小程序码接口(如 getwxacode、getwxacodeunlimit)对参数校验严格,且要求 access_token 有效、签名/加密方式正确。CI 自带的 curl 类缺乏对 JSON 请求体、二进制响应(小程序码是 PNG 图片流)、错误码统一处理的支持;而多数第三方 SDK(如早期 wechat-pay)只覆盖支付,不覆盖小程序码。
- 微信返回的是原始 PNG 二进制数据,不是 JSON,CI 的
$this->curl->simple_post()默认会尝试json_decode,导致解析失败或空白响应 -
access_token需要缓存并自动刷新,CI 没有内置的 token 管理机制,硬编码或每次重取都会触发频率限制(2000 次/2h) - 路径参数
path中若含中文或特殊字符(如?scene=用户ID_123),未做urlencode会导致 41001 错误
怎么用原生 PHP + CI 控制器安全调用 getwxacodeunlimit?
推荐绕过所有封装,用 file_get_contents + stream_context_create 直接发 POST,并手动处理响应流。这是最可控、最不容易出错的方式。
让 AI 读懂微信公众号。自研 7 阶段提取管道,穿透反爬率 99.89%,Token 消耗降低 50%–87%。支持 ChatGPT、Claude、Perplexity、Gemini 等平台无缝引用。
- 构造请求 URL:
https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=YOUR_ACCESS_TOKEN - 请求体必须是 JSON 格式,且
scene字段需为字符串(最大 32 字符),page必须是已发布的小程序页面路径(如"pages/index/index") - 设置
Content-Type: application/json和Accept: image/png,否则微信可能返回 HTML 错误页 - 接收响应后,先检查 HTTP 状态码是否为 200,再检查响应头
Content-Type是否为image/png;若不是,说明是错误 JSON(如{"errcode":40013,"errmsg":"invalid appid"}),需json_decode($response, true)解析 - 成功时直接
header('Content-Type: image/png');+echo $response;输出图片,不要经过 CI 的视图渲染流程
常见报错及对应修复点
调用后返回空白或 500,大概率是以下某一项没处理好:
-
40001:access_token无效 —— 检查是否用了authorizer_access_token却没走第三方平台流程;或本地缓存的 token 已过期(2 小时),没做刷新逻辑 -
41001:缺少必填参数 ——scene是空字符串或 null,微信不接受;page路径不存在或未发布,注意大小写和斜杠方向 -
45009:调用太频繁 —— 不是“每秒多次”,而是“1 分钟内超过 5000 次”,多用于批量生成场景;建议加 Redis 限频(如INCR+EXPIRE) - 返回 HTML 页面(如
error)—— 基本是没设Content-Type: application/json,微信当表单提交处理了
CI 中如何组织这个逻辑才不易出错?
不要把所有代码塞进控制器方法里。拆成三个最小单元更可靠:
- 一个独立的
WxQrCode.php辅助函数(放在application/helpers/),只负责拼 URL、发请求、返回原始响应和状态码 - 一个
WxAccessToken.php模型(或服务类),封装getAccessToken(),支持从文件或 Redis 读取,失效时自动刷新并写回 - 控制器中只做参数校验(如
$this->input->post('scene')是否合法)、调用辅助函数、判断响应类型、输出图片或 JSON 错误
特别注意:微信小程序码接口返回的是二进制图片流,不是 base64 字符串,别试图用 base64_encode 包裹再传给前端——前端直接 <img src="/qr?scene=abc"> 就能加载,加一层 base64 反而增大体积、增加解码开销。










