XAMPP无法直接接收短信回调是因为其默认仅监听本地地址,公网不可访问;需用ngrok暴露本地服务,并确保callback.php对GET请求原样返回echostr、对POST请求做签名验证与幂等处理。

为什么 XAMPP 不能直接收短信回调
因为短信平台(如阿里云、极光、腾讯云)发起的回调请求,目标必须是公网可访问的 http:// 或 https:// 地址,且不接受端口显式指定(比如 http://localhost:8080/callback 会被拒绝)。XAMPP 默认只监听 127.0.0.1 或 localhost,外部服务根本连不上——这不是配置问题,是网络可达性问题。
用 ngrok 暴露 XAMPP 的 callback.php
ngrok 是最轻量、免注册、开箱即用的方案。它把你的本地 HTTP 服务映射成一个临时 HTTPS 域名,短信平台能正常发起回调。
- 确认 XAMPP 的 Apache 正在运行,且
callback.php放在htdocs/下(例如路径为htdocs/sms/callback.php) - 终端执行:
ngrok http 80(若 Apache 改过端口,比如 8080,则写ngrok http 8080) - 从终端输出中复制类似
https://abc123.ngrok.io的地址 - 微信/短信平台后台填写回调 URL 时,填完整路径,例如:
https://abc123.ngrok.io/sms/callback.php
每次重启 ngrok,域名都会变,务必同步更新平台后台配置,否则回调永远 404。
XAMPP 8.0.30 是一款免费、开源的跨平台 Web 服务器集成包,专为快速搭建本地 PHP 开发环境而设计。该版本核心组件包括:Apache 2.4.56、MySQL 8.0.33、PHP 8.0.30、phpMyAdmin 5.2.1 等。它支持 Windows、Linux 和 macOS 系统,可让开发者在个人电脑上轻松模拟服务器环境,无需复杂配置即可运行 WordPress、Thin
callback.php 必须通过 GET 校验并原样返回 echostr
所有主流短信平台在启用回调前,会先发一次 GET 请求,带 echostr、timestamp、nonce、signature 四个参数。你的脚本必须无条件提取 echostr 并原样输出,状态码 200,不能加空格、换行、JSON 包裹或任何额外字符。
- 错误写法:
echo json_encode(['echostr' => $_GET['echostr']]);→ 返回 JSON,校验失败 - 错误写法:
echo $_GET['echostr'] . "\n";→ 多了一个换行,校验失败 - 正确写法:
if (isset($_GET['echostr'])) { echo $_GET['echostr']; exit; } - 后续 POST 回调(如
SmsReport)才需要做签名验证和幂等处理,GET 阶段只做这一件事
Android SMS Gateway 本地模拟发送 + 回调测试的衔接点
如果你用的是 Android-SMS-Gateway(监听 http://localhost:3000),它本身不提供回调能力,但你可以手动触发回调模拟:用 curl 或 Postman 向 ngrok 映射后的地址发 POST 请求,内容仿照真实平台回调格式(如含 phone、content、status 字段)。
- 确保
callback.php在收到 POST 时不做 GET 校验逻辑(区分请求方法) - POST 处理部分要校验来源 IP(可选白名单)、解析 JSON body、提取唯一 ID(如
request_id)做缓存去重 - 不要在回调里执行耗时操作(如 DB 写入),用异步队列或写入文件后由另一进程消费
-
Android-SMS-Gateway的/send接口返回成功,只代表“已提交到手机”,不代表“已送达”,所以别拿它的响应当回调依据
真正难的不是把回调 URL 填上去,而是让 callback.php 在 GET 阶段干净利落地交出 echostr,又在 POST 阶段稳住状态、扛住重试、不重复处理。这两层逻辑混在一起写,最容易漏掉判断条件或污染响应体。

















