驗證碼類
首先將驗證碼介面平臺的配置項放進配置檔案中,如果你有其他三方平臺,那麼就放在一起。假設專案的三方平臺的配置檔案命名為 config/param.php
return [
/*
* 簡訊
*/
'sms' => [
'account' => '賬號',
'password' => '密碼',
'prefix' => '【learnKu】',// 字首
'suffix' => '',// 字尾
'ttl' => 5,// 過期時間
'template' => [
'code' => '您的驗證碼是{code},請在10分鐘內填寫。' //模板
]
],
...
];
編寫一個驗證碼類 Sms
,你可以將它放在 app/Service
目錄下(目錄隨意)。
class Sms
{
const URL = '簡訊平臺介面';
/*
* 傳送簡訊驗證碼
*
* $mobile 手機號
* $type 場景 login|signUp|editMobile|forgetPassword
* return true|errorMsg
*/
public static function sendCode($mobile,$type='login')
{
// 生成 code
if( app()->environment == 'production' ){
// N 分鐘內傳送頻繁限制 這裡選擇資料庫的目的是方便記錄異常和統計 也可以使用任何儲存介質
$count = DB::table('sms')->where('mobile',$mobile)->where('send_time','gt',time()-300)->count();
if( $count >=3 ){ return '您傳送簡訊太頻繁,請稍後再試';}
// 一天內傳送總數限制
$count = Db::table('sms')->where('mobile', $mobile)->where('send_time', 'gt', time() - 24 * 60 * 60)->count();
if( $count >= 20 ){ return '您今天傳送簡訊太頻繁,請以後再試';}
//生成驗證碼
$code = rand(100000, 999999);
}else{
$code = 123456;
}
// 替換簡訊模板
$content = str_replace('{code}',$code,config('param.sms.templete.code'));
// 傳送 測試環境返回 true
$ret = app()->environment != 'production' ? true : self::send($mobile,$content);
// 儲存傳送結果 無論傳送成功 Or 失敗
DB::table('sms')->insert([
'mobile' => $mobile,
'type' => $type,
'status' => $ret === true ? 1 : 0; //成功或失敗
'content' => $content,
'send_time' => time(),
'sms_ret_msg' => strval($ret) //true轉成1
]);
// 儲存驗證碼 用於效驗
cache()->set('sms:' . $type . ':' . $mobile, md5($code), config('param.sms.ttl'));
// 返回
retrun $ret;
}
/*
* 請求簡訊平臺介面傳送簡訊
* return true|errorMsg
*/
pubic static function send($mobile,$content)
{
$config = config('param.sms');
...
if( $code == xxx ){ return true; }
return empty($message) ? '傳送失敗' : $message;
}
/*
* 驗證簡訊驗證碼
* $code md5(code)
* return true|errorMsg
*/
public static function check($mobile,$type,$code)
{
$key = 'sms:' . $type . ':' . $mobile;
$sms_code = cache($key);
if (!$sms_code) { return '請先傳送簡訊驗證碼'; }
if ($sms_code != $code) { return '驗證碼錯誤'; }
// 銷燬驗證碼
cache()->delete($key);
return true;
}
}
傳送簡訊驗證碼
class PublicController extends Controller
{
public function sendSms(Request $request)
{
$post = $request->only(['mobile', 'type']);
$validator = Validator::make($post, [
'mobile'=> 'required|regex:/^1[3456789]{1}\d{9}$/',
'type'=> 'required|in:login,signUp,editMobile,forgetPassword'
]);
extract($post);
if ($validator->fails()) {
return // $validator->errors()
}
if ($type == 'signUp' || $type == 'editMobile') {
if (User::where('mobile', '=', $mobile)->first()) {
return // '該手機號已註冊'
}
}
if ($type == 'forgetPassword') {
if (!User::where('mobile', '=', $mobile)->first()) {
return // '手機號未註冊'
}
}
$result = Sms::sendCode($mobile, $type);
if ($result !== true) {
return // $result
}
return // '傳送成功'
}
}
註冊
class AuthController extends Controller
{
public function signUp(Request $request)
{
$post = $request->only(['mobile', 'code', 'password', 'nickname']);
$validator = Validator::make($post, [
'mobile' => 'required|unique:users|regex:/^1[3456789]{1}\d{9}$/',
'code' => 'required',
'password' => 'required|alpha_num|size:32',
'nickname' => 'max:11',
]);
if ($validator->fails()) {
return //error
}
$ret = Sms::check($post['mobile'], 'signUp', $post['code']);
if ($ret !== true) {
return //$ret
}
$post['password'] = bcrypt($post['password']);
$post['status'] = 1;
...
DB::beginTransaction();
try{
$user = User::create($post);
// 其他操作
$ret = ...
if( !$ret ){
DB::rollBack();
return // error
}
$token = auth()->login($user);
}catch (\Exception $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
return // '註冊失敗'
}
return // $this->respondWithToken($token);
}
/**
* Get the token array
*
* @param string $token
*
* @return array
*/
protected function respondWithToken($token)
{
return [
'username' => auth()->user()->username,
'access_token' => $token,
'token_type' => 'Bearer',
'expires_in' => auth()->factory()->getTTL() * 60 * 12
];
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結