GJ 站长论坛・社区规则,请知晓

船说 CMS 短信验证码接口怎么对接

域名注册
域名注册 初级会员超兽战士 👑年卡会员
发布于 2026-10-08 20:15 ·7 浏览 ·0 回复

学完这篇,你能在船说 CMS 上把短信验证码从「发不出去」变成「能发、能验、防刷」的完整闭环。

第一步:先确认版本和短信通道,拿到 4 个参数

船说 CMS 不同版本的短信配置入口不一样,动手前先登录后台看一眼左上角版本号。2.x 版本在 后台 → 系统 → 系统设置 → 短信设置;3.x 版本通常拆到了 后台 → 插件 → 短信插件,或者直接写死在 include/config.inc.php 里。找不到菜单就先用文本工具搜代码:

grep -rn "sms\|短信" include/ admin/ --include=*.php -l

确定入口后,去短信服务商(阿里云、腾讯云、短信宝、云片都行)后台申请三样东西,缺一不可:

  • AccessKey / API Key(账号)
  • AccessSecret / API 密码
  • 已审核通过的签名和模板 ID(模板内容里必须含 ${code} 变量)

注意:短信模板审核一般要 1-2 小时,别等到代码写完才发现模板没过审,接口会返回 isv.SMS_TEMPLATE_ILLEGAL。

第二步:把发送逻辑写成一个独立文件

这一步要拿到一个「传手机号进去、能发出短信」的函数。在网站根目录新建 api/sms_send.php,用最不容易出错的原生 cURL 写法(以短信宝为例):

<?php
define('SMS_USER', '你的账号');
define('SMS_PASS', '你的密码');

function send_sms($mobile, $code) {
    $content = '【你的签名】您的验证码是' . $code . ',5分钟内有效。';
    $url = 'https://api.smsbao.com/sms?u=' . SMS_USER
         . '&p=' . md5(SMS_PASS)
         . '&m=' . $mobile
         . '&c=' . urlencode($content);
    $res = file_get_contents($url);
    return $res === '0'; // 短信宝返回 0 表示成功
}

用阿里云的话就把这段换成官方 SDK:composer require alibabacloud/dysmsapi-20170525,引入 vendor/autoload.php 后调 SendSms 接口。

注意:这个文件必须放网站根目录下的独立目录,别塞进 admin/,否则会跟着后台的登录验证一起被拦掉,前端请求直接返回登录页 HTML。

第三步:接上验证码的生成、存储和校验

光会发没有用,得让验证码能对得上。接着在 sms_send.php 里补上完整流程:

session_start();
header('Content-Type: application/json; charset=utf-8');

$mobile = trim($_POST['mobile'] ?? '');
if (!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
    exit(json_encode(['code' => 0, 'msg' => '手机号格式不对']));
}

// 60 秒限流
if (isset($_SESSION['sms_time']) && time() - $_SESSION['sms_time'] < 60) {
    exit(json_encode(['code' => 0, 'msg' => '操作太频繁,请稍后再试']));
}

$code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
if (send_sms($mobile, $code)) {
    $_SESSION['sms_code']   = $code;
    $_SESSION['sms_mobile'] = $mobile;
    $_SESSION['sms_expire'] = time() + 300;
    $_SESSION['sms_time']   = time();
    echo json_encode(['code' => 1, 'msg' => '发送成功']);
} else {
    echo json_encode(['code' => 0, 'msg' => '发送失败,请稍后重试']);
}

校验放在真正提交表单的那一步(注册、找回密码等):

if ($_SESSION['sms_code'] !== $code
    || $_SESSION['sms_mobile'] !== $mobile
    || time() > $_SESSION['sms_expire']) {
    exit('验证码错误或已过期');
}
unset($_SESSION['sms_code']); // 用完立刻销毁,防止重放

注意:船说 CMS 很多模板页自带 session_start(),如果 sms_send.php 里再启一次会报 session already started 警告,加上 if (session_status() === PHP_SESSION_NONE) 判断更保险。

第四步:前端按钮挂上请求

打开你用的模板文件,一般是 templates/默认模板/user/register.html,找到发送验证码的按钮,写成:

<input type="text" id="mobile" placeholder="手机号">
<button type="button" id="getCode">获取验证码</button>
<script>
document.getElementById('getCode').onclick = function () {
  var btn = this, n = 60;
  fetch('/api/sms_send.php', {
    method: 'POST',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    body: 'mobile=' + document.getElementById('mobile').value
  }).then(r => r.json()).then(d => {
    alert(d.msg);
    if (d.code !== 1) return;
    btn.disabled = true;
    var t = setInterval(() => {
      btn.textContent = --n + '秒后重发';
      if (n <= 0) { clearInterval(t); btn.disabled = false; btn.textContent = '获取验证码'; }
    }, 1000);
  });
};
</script>

第五步:上线前做三件事

  1. 用真实手机号发一条,确认能收到;收不到就看服务商控制台的发送记录,报错码直接搜。
  2. 后台把 api/sms_send.php 之外的调试代码删掉,尤其别把 AccessSecret 打在页面上。
  3. 服务器时间同步一次:ntpdate ntp.aliyun.com,时间偏差超过 15 分钟,阿里云会直接返回 SignatureDoesNotMatch。

小结

  • 参数先行:签名、模板 ID、密钥缺一不可,模板提前送审。
  • 发送单独成文件,放根目录的 api/ 下,避开后台鉴权。
  • 验证码存 session,带 5 分钟过期和 60 秒限流。
  • 校验成功后立刻 unset,防重放。
  • 收不到短信先查服务商控制台记录,再看服务器时间。
版权声明:本文来自 GJ站长论坛《船说 CMS 短信验证码接口怎么对接》
原文链接:https://www.gj0.com/thread-1173.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~