栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > PHP

「PHP开发APP接口实战012」发送短信验证码之生成并缓存验证码(Memcache)

PHP 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

「PHP开发APP接口实战012」发送短信验证码之生成并缓存验证码(Memcache)

配置参数
  1. Memcache 配置, 在 /app/config/config.ini 文件添加以下代码:

[memcache]
host = 127.0.0.1
port = 11211
prefix = api

在 Visual NMP 中,默认已经安装了 Memcache, 可直接使用。如服务未开启,直接打开即可。 默认连接端口:11211。缓存键名前缀:prefix = api,方便区分项目,可随意设置, 一般设置为项目名。
「PHP开发APP接口实战001」开发环境搭建

  1. 短信配置, 在 /app/config/config.php 文件添加以下代码:

    'sms' => [        'times' => 3, // 同一手机一小时内发送短信次数, 0 为不限制
        'interval' => 60, // 同一手机两次发送间隔时间(单位:秒), 0 为不限制
        'valid_time' => 300, // 短信验证码有效时间(单位:秒), 0 为久有效
    ],
创建 Memcache 操作类 XMemcache

在 /app/library 目录下创建文件 XMemcache.php, 添加以下代码:

memcache = new Memcache();        // 加载配置参数
        $this->config = Config::instance()->get('memcache', 'ini');        // 连接Memcache服务器
        $this->memcache->addServer($this->config['host'], $this->config['port']);        $this->tag = $tag;
    }    
    public static function instance($tag = null)
    {        if (!self::$instance) self::$instance = new self($tag);        return self::$instance;
    }    
    public function append($key, $value, $timeout = 604800, $iszip = 0)
    {        if ($values = $this->get($key)) {
            $values[] = $value;
        } else {
            $values = [$value];
        }        $this->set($key, $values, $timeout, $iszip);
    }    
    public function set($key, $value, $timeout = 604800, $iszip = 0)
    {
        $value = serialize($value);        return $this->memcache->set($this->formatKey($key), $value, $iszip, $timeout);
    }    
    public function get($key)
    {
        $value = $this->memcache->get($this->formatKey($key));        return unserialize($value);
    }    
    public function delete($key)
    {        return $this->memcache->delete($this->formatKey($key));
    }    
    public function flush()
    {        return $this->memcache->flush();
    }    
    private function formatKey($key)
    {        return $this->config['prefix'] . ':' . $this->tag . ':' . $key;
    }

}

这里重写了一些 Memcache 常用的操作函数。 如:设置缓存 set(),  追加缓存 append(),  获取缓存 get(), 删除缓存 delete(), 清空缓存 flush()
值得注意的是,我们还对缓存键名进行了重写,方便区分项目和模块。

生成短信验证码
  1. 在 /app/library 目录下创建文件 SMS.php, 添加以下代码:

config = Config::instance()->get('sms');
    }    public static function instance()
    {        if (!self::$instance) self::$instance = new self();        return self::$instance;
    }
  
}

这里实现了实例化时,自己加载配置参数。

  1. 增加验证码改送函数 send(), 用于外部调用。如:

     
    public function send($mobile)
    {

    }

此函数里面分四步走:

  1. 验证指定手机号,当前是否可以发送验证码

  2. 生成四位数字验证码,并配置上生成时间

  3. 调用 XMemcache 缓存验证码

  4. 调用第三方接口,发送验证码,并返回发送状态。(市场上有许多发送第三方平台,都有)

  1. 这里调换一下顺序,先讲解生成和缓存验证码。
    首先,添加函数generateCode(), 随机生成4位数字验证码

    
    private function generateCode()
    {        return rand(1000, 9999);
    }

然后,在 send() 函数中添加代码:

        $item = [            'code' => $this->generateCode(), // 生成短信验证码
            'time' => time(), // 生成时间
            'verified' => 0,  // 验证状态: 0 未验证, 1 已验证
        ];

这里除了生成验证码,同时初始化生成时间time, 验证状态verified,用于验证发送时间和检查验证码是否已验证。

  1. 缓存验证码,在 send() 函数中添加代码:

        // 缓存短信验证码
        XMemcache::instance('sms')->append($mobile, $item, 3600);

这里完成了几个工作:

  • 将 $item 存于以指定手机号为键名的缓存下

  • 同一手机号多次发送,都存在同一键名下,用于统计1小时内验证码发送次数。

  • 缓存有效时间设置为 1 小时

  1. 现在我们再回来讲解验证是否允许向指定手机号发送验证码。

验证规则:

  • 同一手机两次发送间隔时间1分钟(可配置间隔时间)

  • 同一手机1小时内最多只能发送3次验证码(可配置发送次数)

首先,添加函数 getCacheCodes() 和 validateSend(), 如:

    
    private function getCacheCodes($mobile)
    {
        $codes = XMemcache::instance('sms')->get($mobile);        if (!$codes)            return [];        foreach ($codes as $index => $item) {            // 过滤发送超过1小时的验证码
            if (time() - $item['time'] > 3600) {                unset($codes[$index]);
            }
        }        // 重置数组索引
        $codes = array_values($codes);        // 更新缓存
        XMemcache::instance('sms')->set($mobile, $codes);        return $codes;
    }    
    private function validateSend($mobile)
    {
        $codes = $this->getCacheCodes($mobile);        if ($this->config['times'] > 0 && count($codes) >= $this->config['times']) {            throw new Exception('一小时内最多只能发送' . $this->config['times'] . '次短信验证码');
        }

        $lastCode = end($codes);        if ($this->config['interval'] > 0 && time() - $lastCode['time'] <= $this->config['interval']) {            throw new Exception('发送频率太快');
        }
    }
  1. 函数 getCacheCodes() 获取指定手机1小时内发送的验证码。

  2. 函数 validateSend() 实现:
    验证一小时内向同一手机发送短信验证码次数是否超过了配置次数;
    验证上次发送验证码是否已经超过配置时间;

然后在 send() 函数中,所有代码之前插入代码 $this->validateSend($mobile);。
send() 函数完整代码:

    
    public function send($mobile)
    {        // 验证短信发送次数
        $this->validateSend($mobile);

        $item = [            'code' => $this->generateCode(), // 生成短信验证码
            'time' => time(), // 生成时间
            'verified' => 0,  // 验证状态: 0 未验证, 1 已验证
        ];        // 缓存短信验证码
        XMemcache::instance('sms')->append($mobile, $item, 3600);        // 发送短信验证码
        

        return $item;
    }
  1. 再在控制器 SmsController 类的 sendAction() 函数中加入以下代码:

        // 发送验证码
        $result = SMS::instance()->send($this->getPost('user_mobile'));        if ($result) {//            Output::instance($this->response)->success(’发送成功‘);
            Output::instance($this->response)->success((object)$result);
        } else {
            Output::instance($this->response)->fail('发送失败');
        }

这里没有真正实现调用第三方接口,而是直接返回了发送的验证码,以供测试使用。正式代码,只返回发送状态。

SmsController.php 完整代码:
isPost();        // 验证请求参数
        XValidationSms::send($this->getPost());        // 发送验证码
        $result = SMS::instance()->send($this->getPost('user_mobile'));        if ($result) {//            Output::instance($this->response)->success(’发送成功‘);
            Output::instance($this->response)->success((object)$result);
        } else {
            Output::instance($this->response)->fail('发送失败');
        }

    }
}
接口调试示例
  • 请求地址:http://127.0.0.1:20081/sms/send

  • 请求方式:POST

  • 请求参数:user_mobile=18088888888

  • 返回数据:

{    "status": "1",    "value": "发送成功"}

开发调试时返回数据 :

{    "status": "1",    "item": {        "code": "1139",        "time": "1520663958",        "verified": "0"
    }
}



作者:一念觀心
链接:https://www.jianshu.com/p/0dbdf556b4f3


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/227240.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号