GD 验证码不显示?TaoToken 这样配进 Codex 的 config.toml 查 VerifyImage
1. GD 验证码不显示先别急着改代码PHP 里用 GD 图形库封装一个VerifyImage类来生成验证码是登录模块里非常常见的做法。核心流程无非就是随机取字符串、imagecreatetruecolor建画布、imagettftext把字符写上去、加点噪点和干扰线、最后imagepng输出。听起来简单但真正跑起来的时候很多人会遇到一个很典型的现象页面一片空白图片位置只有一个裂图图标或者浏览器控制台报Failed to load resource再或者验证码出来了但全是方块乱码。这类问题的根源八成不在你的随机逻辑而在imagettftext的字体路径和 TTF 参数上。imagettftext和imagestring最大的区别就是它依赖一个真实存在的.ttf字体文件路径写错、字体没导入fonts目录、或者相对路径的基准目录和你以为的不一样都会导致验证码画不出来。更麻烦的是GD 在字体加载失败时往往不会给你一个特别明确的报错而是直接输出一张空白图让你误以为是imagepng的问题。这篇就按排障视角来走先讲清楚VerifyImage类里哪些地方最容易出问题然后说怎么用 TaoToken 配好 Codex 的config.toml让 Codex 帮你逐行对照VerifyImage.php和test.php去定位字体路径、GD 输出、点击切换这几块。TaoToken 在这里的角色很明确它只负责给 Codex 提供 Key 和 Base URL不生成验证码验证码还是你自己的 PHP 代码在跑。适合正在写 PHP 登录模块、被 GD 验证码空白或乱码卡住的同学。2. 用 TaoToken 给 Codex 配好 Key 和 Base URL在让 Codex 帮你查VerifyImage之前得先把它接上。打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册账号进控制台创建一个 API Key。这个 Key 就是你后面填进 Codex 配置里的凭证。创建 Key 的入口在控制台的 API Keys 页面直接访问 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 就能到。拿到 Key 之后先复制存好后面配置要用。这里要强调一个容易踩的点Codex 的 Base URL 填https://taotoken.net/api不要在后面加/v1也不要带任何 UTM 参数。很多人习惯性地补/v1结果请求路径拼出来就错了Codex 直接连不上。TaoToken 的接入地址就是https://taotoken.net/api这个干净的形式。如果你还没想好怎么组织 Codex 的配置可以先看看接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有 Base URL 和 Key 的填写说明。想先在网页里验证一下模型通不通也可以直接用模型对话 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 试一句确认 Key 是有效的。3. Codex 的 config.toml 可复制配置Codex 的配置一般放在用户目录下的.codex/config.toml。下面这份是可以直接抄的把你的API_KEY换成刚才创建的那串就行。# ~/.codex/config.toml model gpt-4o model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat配置里几个字段的作用字段值说明modelgpt-4o按你实际要用的模型名填base_urlhttps://taotoken.net/api不带/v1不带 UTMenv_keyTAOTOKEN_API_KEY从环境变量读 Key避免明文写进文件wire_apichat走 chat 接口Key 建议用环境变量传别直接写死在config.toml里。Linux 或 macOS 下这样设置export TAOTOKEN_API_KEY你的API_KEYWindows PowerShell 下$env:TAOTOKEN_API_KEY你的API_KEY设完环境变量后重新开一个终端让变量生效再启动 Codex。这样配置和密钥就分开了换 Key 的时候只改环境变量不用动配置文件。4. 让 Codex 对照 VerifyImage.php 逐项排查配置通了之后就可以把VerifyImage.php和test.php一起丢给 Codex让它按imagettftext、imagepng、点击切换这三块来查。下面是我实际用下来比较有效的提问方式你可以直接参考。先让 Codex 定位字体路径问题。VerifyImage类里那行$font_files array(./fonts/arial.ttf, ./fonts/consola.ttf);用的是相对路径相对的是当前执行脚本的工作目录不是VerifyImage.php所在目录。test.php里require_once MyClasses/VerifyImage.php;引入类但test.php自己可能被放在别的目录或者被img srctest.php从另一个路径请求工作目录就变了./fonts/arial.ttf自然找不到。可以这样问 Codex这是我的 VerifyImage.php 和 test.php。 imagettftext 用的字体路径是 ./fonts/arial.ttf 但验证码输出空白。请帮我分析相对路径的基准目录问题 并给出用 __DIR__ 拼接绝对路径的改法。Codex 一般会建议把字体路径改成基于__DIR__的绝对路径比如$font_files array( __DIR__ . /fonts/arial.ttf, __DIR__ . /fonts/consola.ttf, );这样不管从哪个目录请求test.php字体路径都是稳定的。改完再跑空白问题大概率就没了。接着让 Codex 检查imagettftext的参数。这个函数的签名是imagettftext($image, $size, $angle, $x, $y, $color, $fontfile, $text)参数顺序错一个就会出问题。原代码里$x (imagefontwidth($size) 5) * ($i 1);这里有个隐患imagefontwidth接收的是字体大小但它返回的是内置字体的字符宽度和 TTF 的$size不是一套体系算出来的$x可能让字符跑到画布外面。可以让 Codex 帮你把坐标计算换成更稳的方式比如按$width / $code_length均分。再让 Codex 看imagepng和输出头。header(content-type: image/png);之前不能有任何输出包括 BOM、空格、echo。如果VerifyImage.php文件开头有 UTF-8 BOM或者require_once之前有空白行头信息就发出去了图片也会坏。可以让 Codex 检查文件是否有 BOM以及imagepng前有没有多余输出。最后是test.php的点击切换逻辑。原代码里img classverifyimg srctest.php nametest.php alt验证码加载失败 title看不清则点击图片 onclickthis.src this.name?imgMath.random();这段逻辑本身没问题靠Math.random()加时间戳参数绕过缓存。但如果test.php因为字体问题返回了空白图点击切换也只是换了一张空白图看起来像点击没反应。所以排查顺序应该是先修字体再验证点击切换。可以让 Codex 帮你确认this.name和this.src的拼接结果确保每次点击请求的 URL 都带上了新的随机参数。5. 验证请求与成功结果改完字体路径后先别急着在浏览器里点直接用命令行验证test.php的输出是不是一张合法 PNG。在项目目录下执行php test.php verify.png file verify.png如果输出类似verify.png: PNG image data, 100 x 40, 8-bit/color RGB, non-interlaced说明 GD 已经正常生成图片了。如果file命令报的是ASCII text或者HTML document那说明test.php输出的不是图片多半是 PHP 报错信息混进去了这时候去看php test.php直接打印的内容错误就藏在那里。再确认一下字体文件确实存在且可读ls -l fonts/arial.ttf fonts/consola.ttf两个文件都在权限是-rw-r--r--这种可读状态就没问题。如果字体文件缺失去系统字体目录拷一份或者从可信来源下载一个开源 TTF 放进fonts目录。浏览器里验证的时候打开test.php应该直接看到一张带随机字符、噪点和干扰线的验证码图。刷新几次字符会变说明随机逻辑正常。然后在 HTML 页面里放上那个img点击图片URL 后面会多出?img0.xxxx这样的随机参数图片内容也跟着变点击切换就通了。如果你在验证过程中想换个模型再问 Codex或者想直接在网页里贴报错让它分析可以用模型对话 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 快速试。长期在项目里用 Codex 做编码和排查的话Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 会更合适额度按编码场景走。6. 本篇常见错排查6.1 验证码空白但页面没报错最常见的就是字体路径问题。imagettftext找不到字体文件时GD 不会抛异常而是静默失败imagepng照样输出一张空白图。把./fonts/arial.ttf换成__DIR__ . /fonts/arial.ttf基本能解决。另外确认fonts目录和VerifyImage.php在同一层别放错位置。6.2 报错 imagettftext(): Could not find/open font这个报错比空白好至少它明说了。原因还是路径但有时候是字体文件本身损坏或者不是合法的 TTF。用file fonts/arial.ttf看一下正常应该显示TrueType font data。如果显示别的换一个字体文件。6.3 验证码乱码或全是方块字体文件能加载但字符显示成方块通常是字体不支持你要输出的字符集。原代码CreateRandomVerifyCode里$code_type 2会生成大小写字母$code_type 3还会加数字这些 ASCII 字符一般字体都支持。如果你改成了中文验证码就得换一个带中文字形的 TTF比如思源黑体否则就是方块。6.4 图片输出坏掉浏览器显示裂图检查header(content-type: image/png);之前有没有任何输出。VerifyImage.php文件开头的 BOM、require_once前的空行、test.php里的echo都会破坏图片流。用编辑器把文件另存为无 BOM 的 UTF-8。6.5 点击切换没反应先确认test.php单独访问时能出图。如果单独访问是空白点击切换当然也是空白。如果单独访问正常检查onclick里this.name的值是不是test.php以及拼接后的 URL 有没有被浏览器缓存。加Math.random()就是干这个的确认它没被去掉。6.6 Codex 连不上 TaoToken回头检查config.toml里的base_url是不是https://taotoken.net/api有没有手滑加了/v1。再确认环境变量TAOTOKEN_API_KEY在当前终端里能echo出来。如果 Key 无效去 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 重新生成一个。接入细节以文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 为准。7. 把 Codex 接进你的 PHP 排障流程字体路径改完、test.php能稳定出图之后你会发现VerifyImage这类 GD 问题其实就那么几个坑路径、参数顺序、输出头、字符集。真正花时间的不是改代码而是定位到底是哪一环出的问题。把 Codex 配好之后你可以直接把VerifyImage.php、test.php和浏览器报错一起丢给它让它按imagettftext、imagepng、点击切换的顺序逐项过比自己在空白图和乱码之间反复试要快得多。TaoToken 在这里就是给 Codex 供 Key 和 Base URL 的入口验证码生成还是你自己的 PHP 在跑。配通之后下次再遇到 GD 相关的怪问题直接让 Codex 对照代码查就行。