来展示:
1、首先你得装阿里短信sdk
composer require alibabacloud/sdk
发短信控制器
namespace App\Controllers; | |
use App\Requests\App\AppSendSmsRequest; | |
use App\Services\SmsService as Service; | |
use Framework\BaseController; | |
use Framework\Hope; | |
use Mews\Captcha\Facades\Captcha; | |
class SmsController extends BaseController | |
{ | |
/** | |
* @var Service | |
*/ | |
private $service; | |
public function __construct(Service $service) | |
{ | |
$this->service = $service; | |
} | |
/** 提交图形验证码 | |
* @param AppSendSmsRequest $request | |
*/ | |
public function send_sms(AppSendSmsRequest $request) | |
{ | |
$phone = $request->phone(); | |
$key = $request->key(); | |
$code = $request->code(); | |
$flg = captcha_api_check($code, $key); | |
if (!$flg && (!Hope::isProduct() && $code != 'ASDF')) { | |
$this->retError('图形验证码错误'); | |
} | |
if(!Hope::isProduct()){ | |
$code = substr($phone, -4); | |
$redis = Hope::getRedis(); | |
$redis->setex("sms:" . $phone, 60 * 5, $code); | |
}else{ | |
//获取短信验证码 | |
$this->getVerifyCode($phone); | |
} | |
$this->retSuccess(true); | |
} | |
/** | |
* 获取图形验证码 | |
*/ | |
public function get_sms() | |
{ | |
$res = Captcha::create('default', true); | |
$this->retSuccess($res); | |
} | |
/** | |
* 获取短信验证码 | |
*/ | |
public function getVerifyCode($phone) | |
{ | |
$this->service->sendSmsVerifyCode($phone); | |
} | |
} |
服务层
namespace App\Services; | |
use App\Services\Sms\HttpService; | |
use Carbon\Carbon; | |
use Framework\BaseService; | |
use Framework\Hope; | |
class SmsService extends BaseService | |
{ | |
/** 发送短信验证码 | |
* @param string $phone | |
* @return bool | |
* @throws \AlibabaCloud\Client\Exception\ClientException | |
*/ | |
public function sendSmsVerifyCode(string $phone) | |
{ | |
if(!Hope::isProduct()){ | |
return true; | |
} | |
$redis = Hope::getRedis(); | |
$key = $this->getKey($phone); | |
$limitKey = 'code_limit'; | |
// 验证码重发限制 | |
$jsonData = $redis->get($key); | |
$data = $jsonData ? json_decode($jsonData, true) : []; | |
if ($data && Carbon::now()->timestamp < $data['resend_expire']) { | |
$this->retError( '短信已在1分钟内发出,请耐心等'); | |
} | |
// 手机号限制 | |
$sendCnt = $redis->zScore($limitKey, $phone); | |
if ($sendCnt && $sendCnt >= env('ONE_DAY_FREQ', 1)) { | |
$this->retError("获取验证码次数已达上限"); | |
} | |
//生成4位验证码 | |
$code = $this->createVerifyCode($phone); | |
//发送短信获取验证码 | |
app(HttpService::class)->sendSms($phone,$code); | |
//redis中存储验证码 | |
$this->saveSmsCode($phone, $code, $key, $limitKey); | |
} | |
public function saveSmsCode(string $phone, string $code, string $key, string $limitKey) | |
{ | |
$redis = Hope::getRedis(); | |
$data = [ | |
'code' => $code, | |
'resend_expire' => Carbon::now()->addSeconds(env('RESEND_SEC', 60))->timestamp, | |
]; | |
$redis->set($key, json_encode($data)); | |
$redis->expire($key, (int) env('EXPIRE_SEC', 1800)); // 设置验证码过期时间 | |
// 设置手机号限制 | |
$redis->zIncrBy($limitKey, 1, $phone); | |
$redis->expireAt($limitKey, (int) Carbon::today()->addDay()->timestamp); | |
if (! Hope::isProduct()) { | |
return true; | |
} | |
} | |
/** | |
* 验证短信验证码 | |
* @param string $phone 手机号 | |
* @param string $code 验证码 | |
* @return bool | |
*/ | |
public function checkSmsCode(string $phone, string $code): bool | |
{ | |
$testSmsCode = config('constant.sms_code'); | |
if (env('APP_ENV', 'dev') != 'prod' && $code == $testSmsCode) { | |
return true; | |
} | |
$arr = [$testSmsCode, $this->createVerifyCode($phone)]; | |
if (!Hope::isProduct() && in_array($code, $arr )) { | |
return true; | |
} | |
$key = $this->getKey($phone); | |
$jsonData = Hope::getRedis()->get($key); | |
$data = $jsonData ? json_decode($jsonData, true) : []; | |
if ($data && $code === $data['code']) { | |
return true; | |
} | |
$this->retError("验证码有误,请重新输入!"); | |
} | |
/** | |
* @param string $phone 手机号 | |
* @return string | |
*/ | |
private function getKey(string $phone): string | |
{ | |
return "code:" . $phone; | |
} | |
/** | |
* 创建4位验证码 | |
* @param string $phone 手机号 | |
* @return string | |
*/ | |
private function createVerifyCode(string $phone): string | |
{ | |
if(!Hope::isProduct()){ | |
return substr($phone, -4); | |
} | |
return (string)mt_rand(1000, 9999); | |
} | |
} |
顺便把公共函数贴出来
namespace Framework; | |
use App\Services\UploadService; | |
use Illuminate\Redis\Connections\PhpRedisConnection; | |
use Illuminate\Support\Facades\Redis; | |
use SimpleSoftwareIO\QrCode\BaconQrCodeGenerator; | |
class Hope | |
{ | |
public static function isProduct(): bool | |
{ | |
$env = env('APP_ENV', 'local'); | |
if ($env === 'prod') { | |
return true; | |
} | |
return false; | |
} | |
public static function getRedis(string $connection = 'default'): PhpRedisConnection | |
{ | |
/** @var PhpRedisConnection $redis */ | |
$redis = Redis::connection($connection); | |
return $redis; | |
} | |
public static function getLoginId(): int | |
{ | |
$jwt = app(Jwt::class); | |
$user_id = $jwt->checkToken(); | |
if ($user_id === false) { | |
return 0; | |
} | |
return $user_id; | |
} | |
/** | |
* 获取随机邀请码 | |
* @return string | |
*/ | |
public static function makeInviterCode() { | |
$code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; | |
$rand = $code[rand(0,25)] | |
.strtoupper(dechex(date('m'))) | |
.date('d').substr(time(),-5) | |
.substr(microtime(),2,5) | |
.sprintf('%02d',rand(0,99)); | |
for( | |
$a = md5( $rand, true ), | |
$s = '0123456789ABCDEFGHIJKLMNOPQRSTUV', | |
$d = '', | |
$f = 0; | |
$f < 8; | |
$g = ord( $a[ $f ] ), | |
$d .= $s[ ( $g ^ ord( $a[ $f + 8 ] ) ) - $g & 0x1F ], | |
$f++ | |
); | |
return $d; | |
} | |
/** | |
* 创建二维码 | |
* @param $inviterCode | |
* @return string | |
*/ | |
public static function makeInviterQrcode($inviterCode) | |
{ | |
$text = $_SERVER["HTTP_HOST"] . '/app.apk'; | |
$size = 200; | |
//$img = public_path('/logo.png'); | |
$qr = new BaconQrCodeGenerator(); | |
$img = $qr->format('png')->size($size)->margin(1)->generate($text); | |
$type = 'qrcode'; | |
$path = app(UploadService::class)->uploadQiniu($img,$type,$inviterCode); | |
return $path; | |
} | |
/** | |
* @param string $prefix | |
* @return string | |
*/ | |
public static function random_order($prefix='MC') | |
{ | |
return $prefix . date('YmdHis', time()) . substr(microtime(), 2, 6) . sprintf('%03d', rand(0, 999)); | |
} | |
public static function name_auth($name,$id_card){ | |
$host = "https://idcert.market.alicloudapi.com"; | |
$path = "/idcard"; | |
$method = "GET"; | |
$appcode = "111111111111111111111";//开通服务后 买家中心-查看AppCode | |
$headers = array(); | |
array_push($headers, "Authorization:APPCODE " . $appcode); | |
$querys = "idCard={$id_card}&name=".urlencode($name); | |
$bodys = ""; | |
$url = $host . $path . "?" . $querys; | |
$curl = curl_init(); | |
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); | |
curl_setopt($curl, CURLOPT_URL, $url); | |
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); | |
curl_setopt($curl, CURLOPT_FAILONERROR, false); | |
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($curl, CURLOPT_HEADER, true); | |
if (1 == strpos("$" . $host, "https://")) { | |
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); | |
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); | |
} | |
$out_put = curl_exec($curl); | |
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); | |
list($header, $body) = explode("\r\n\r\n", $out_put, 2); | |
if ($httpCode == 200) { | |
return $body; | |
} | |
} | |
} |
最后短信基类
namespace App\Services\Sms; | |
use AlibabaCloud\Client\AlibabaCloud; | |
use AlibabaCloud\Client\Exception\ClientException; | |
use AlibabaCloud\Client\Exception\ServerException; | |
use Framework\BaseService; | |
use Framework\Hope; | |
class HttpService extends BaseService | |
{ | |
/** 阿里短信配置 | |
* @param string $phone | |
* @param string $code | |
* @return bool | |
* @throws ClientException | |
*/ | |
public function sendSms(string $phone, string $code) | |
{ | |
if(!Hope::isProduct()){ | |
return true; | |
} | |
$accessKey = env('ALIYUN_SMS_ACCESS_KEY'); | |
$secretKey = env('ALIYUN_SMS_ACCESS_SECRET'); | |
$query = [ | |
'PhoneNumbers' => $phone, | |
'SignName' => env('ALIYUN_SMS_SIGN_NAME'), | |
'TemplateCode' => env('ALIYUN_SMS_SEND_CODE'), | |
'TemplateParam' => json_encode(['code' => $code]), | |
]; | |
AlibabaCloud::accessKeyClient($accessKey, $secretKey) | |
->regionId('cn-hangzhou') | |
->asDefaultClient(); | |
try { | |
$result = AlibabaCloud::rpc() | |
->product('Dysmsapi') | |
->scheme('https') | |
->version('2017-05-25') | |
->action('SendSms') | |
->method('POST') | |
->host('dysmsapi.aliyuncs.com') | |
->options([ | |
'query' => $query | |
]) | |
->request(); | |
} catch (ClientException $e) { | |
$this->retError("短信发送失败"); | |
} catch (ServerException $e) { | |
$this->retError("短信发送失败"); | |
} | |
$result = $result->toArray(); | |
if ($result['Code'] == 'OK') { | |
return true; | |
} else { | |
$this->retError("短信发送失败"); | |
} | |
} | |
} |
最后在推荐一个类也很好用哦,有兴趣可以去了解一下
overtrue/easy-sms