前言
我一生的文章都会放在这里,我的博客,我希望每一行代码,每一段文字都能帮助你。https://github.com/CrazyCodes…
大家好,我是 CrazyCodes,在日常开发中有没有遇到过发送短信验证码的接口需要开发?你是如何处理短信验证码发送的呢?本篇我分享下短信验证码发送的设计。
初学者
以聚合数据为例,初学者会酱紫做
百度
找到一串既熟悉又陌生的代码 (咋整也记不住的代码)
// 初始化
$curl = curl_init();
// 设置抓取的 url
curl_setopt($curl, CURLOPT_URL, 'http://www.baidu.com');
// 设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 1);
// 设置获取的信息以文件流的形式返回,而不是直接输出。curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 设置 post 方式提交
curl_setopt($curl, CURLOPT_POST, 1);
// 设置 post 数据
$post_data = array(
"username" => "coder",
"password" => "12345"
);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
// 执行命令
$data = curl_exec($curl);
// 关闭 URL 请求
curl_close($curl);
// 显示获得的数据
print_r($data);
官方也给出了一段维护性略差的代码
<?php
/*
*** 聚合数据(JUHE.CN)短信 API 服务接口 PHP 请求示例源码
***DATE:2015-05-25
*/
header('content-type:text/html;charset=utf-8');
$sendUrl = 'http://v.juhe.cn/sms/send'; // 短信接口的 URL
$smsConf = array(
'key' => '*****************', // 您申请的 APPKEY
'mobile' => '1891351****', // 接受短信的用户手机号码
'tpl_id' => '111', // 您申请的短信模板 ID,根据实际情况修改
'tpl_value' =>'#code#=1234&#company#= 聚合数据' // 您设置的模板变量,根据实际情况修改
);
$content = juhecurl($sendUrl,$smsConf,1); // 请求发送短信
if($content){$result = json_decode($content,true);
$error_code = $result['error_code'];
if($error_code == 0){
// 状态为 0,说明短信发送成功
echo "短信发送成功, 短信 ID:".$result['result']['sid'];
}else{
// 状态非 0,说明失败
$msg = $result['reason'];
echo "短信发送失败 (".$error_code."):".$msg;
}
}else{
// 返回内容异常,以下可根据业务逻辑自行修改
echo "请求发送短信失败";
}
/**
* 请求接口返回内容
* @param string $url [请求的 URL 地址]
* @param string $params [请求的参数]
* @param int $ipost [是否采用 POST 形式]
* @return string
*/
function juhecurl($url,$params=false,$ispost=0){$httpInfo = array();
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_USERAGENT , 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22' );
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , 30);
curl_setopt($ch, CURLOPT_TIMEOUT , 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER , true);
if($ispost)
{curl_setopt( $ch , CURLOPT_POST , true);
curl_setopt($ch , CURLOPT_POSTFIELDS , $params);
curl_setopt($ch , CURLOPT_URL , $url);
}
else
{if($params){curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params);
}else{curl_setopt( $ch , CURLOPT_URL , $url);
}
}
$response = curl_exec($ch);
if ($response === FALSE) {//echo "cURL Error:" . curl_error($ch);
return false;
}
$httpCode = curl_getinfo($ch , CURLINFO_HTTP_CODE);
$httpInfo = array_merge($httpInfo , curl_getinfo( $ch) );
curl_close($ch);
return $response;
}
这样看,“也不是不好,就是想再改改,至于改什么,不知道,就是想再改改”
接口
那么我就开始自己的表演了。首先看本篇你需要了解
- 设计模式中的策略模式
- 依赖注入
- 接口 (interface)
否则,你看的会很懵 (大佬请略过)
首先我们要写一个 interface 用于规范发短信这个动作
namespace App\Api\Common;
interface MessageUseInterface
{public function insert($mobile, $code);
}
要求所有发短信的动作都必须继承这个接口,并且实现 insert 方法。
短信类
接口设定好,我们需要设定一个父类,既发短信的类,具体实现如下
namespace App\Api\Common;
use GuzzleHttp\Client;
class Message
{
/**
* @param $mobile
* @param $tpl
* @param $code
* @param MessageUseInterface $use
* @return mixed
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function send($mobile, $tpl, $code, MessageUseInterface $use)
{$client = new Client();
$response = $client->request('POST', 'http://v.juhe.cn/sms/send', [
'form_params' => [
'mobile' => $mobile,
'tpl_id' => $tpl,
'tpl_value' => sprintf('#code#=%s', $code),
'key' => 'xxxxxxxxxxxx'
]
]);
$use->insert($mobile, $code);
return json_decode($response->getBody(), true);
}
}
这个类创建了 send 方法,参数分别为
- mobile 既接收短信验证码的手机号码
- tpl_id 聚合数据提供的模板编码
- code 发送的验证码
- MessageUseInterface 上面创建的接口 interface
具体实现则是使用 GuzzleHttp 去实现 POST 请求,并按聚合数据规定发送验证码。
$use->insert($mobile, $code);
则是调用通过 MessageUseInterface 传进来的实体类
实体类
之后我们创建实体类, 这里以手机号 + 验证码登录为例
namespace App\Api\Common\Message;
use App\Api\Common\MessageUseInterface;
use App\Api\Common\Redis;
class Login implements MessageUseInterface
{public function insert($mobile, $code)
{$redis = Redis::init();
$key = sprintf('login_code:%s', $mobile);
$redis->setex($key, 600, $code);
}
}
Login 继承接口 MessageUseInterface 并实现 insert 方法。这里 redis 设定的规范为
module: 手机号 -> value(需要发送的验证码)
至此,我们的短信验证码发送的例子就结束了。
使用
我们可以下列方式调用,或者使用 Laravel 的服务提供者
(new Message())->send($tel, 141345, mt_rand(100000, 999999), new Register());
这样既解决了乱七八糟的各种验证码,还提高了代码的可维护性,如果老板有新的需求,例如,支付验证码什么的,你只需要新建一个 Pay 的验证码类,即完成支付验证码的功能。
致谢
上述只是一个简单的例子,实体类并未做更多的延伸,请自行发挥创造力。
感谢你看到这里,希望本篇文章可以帮到你。谢谢。