船说 CMS 短信验证码接口怎么对接
学完这篇,你能在船说 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>
第五步:上线前做三件事
- 用真实手机号发一条,确认能收到;收不到就看服务商控制台的发送记录,报错码直接搜。
- 后台把
api/sms_send.php之外的调试代码删掉,尤其别把 AccessSecret 打在页面上。 - 服务器时间同步一次:
ntpdate ntp.aliyun.com,时间偏差超过 15 分钟,阿里云会直接返回SignatureDoesNotMatch。
小结
- 参数先行:签名、模板 ID、密钥缺一不可,模板提前送审。
- 发送单独成文件,放根目录的
api/下,避开后台鉴权。 - 验证码存 session,带 5 分钟过期和 60 秒限流。
- 校验成功后立刻
unset,防重放。 - 收不到短信先查服务商控制台记录,再看服务器时间。
原文链接:https://www.gj0.com/thread-1173.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。