first commit

This commit is contained in:
2023-09-11 09:44:39 +08:00
commit fa76d02135
9 changed files with 348 additions and 0 deletions

34
README.md Normal file
View File

@@ -0,0 +1,34 @@
# Jason/Sms 短信发送扩展
## 安装
```
$ composer require jasonc/sms
$ php artisan vendor:publish --tag='sms'
$ php artisan migrate
```
## 短信发送
```
\Sms::send($mobile, $channel = 'DEFAULT');
```
## 短信验证
```
\Sms::check($mobile, $code, $channel = 'DEFAULT');
```
扩展验证规则
```
sms_check:MOBILEFIELD,CHANNEL 短信验证码验证
MOBILEFIELD手机号码字段名称
CHANNEL验证通道
```

31
composer.json Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "jasonc/sms",
"description": "",
"license": "MIT",
"authors": [
{
"name": "C.Jason",
"email": "chenjxlg@163.com"
}
],
"require": {
"php": ">=7.1.3",
"overtrue/easy-sms": "^2.0",
"laravel/framework": "*"
},
"autoload": {
"psr-4": {
"Jason\\Sms\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Jason\\Sms\\ServiceProvider"
],
"aliases": {
"Sms": "Jason\\Sms\\Facade"
}
}
}
}

61
config/config.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
return [
// 模拟调试,不会真正发送验证码,验证后也不会失效
'debug' => true,
// 调试模式发送的验证码
'debug_code' => '0000',
// HTTP 请求的超时时间(秒)
'timeout' => 5.0,
// 默认发送配置
'default' => [
// 网关调用策略,默认:顺序调用
'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,
// 默认可用的发送网关
'gateways' => [
'aliyun',
],
],
// 验证码长度
'length' => 4,
// 验证后立即失效
'once_used' => true,
// 模板与通道映射
'template' => [
'DEFAULT' => '',
'LOGIN' => '',
'REGISTER' => '',
],
// 可用的网关配置
'gateways' => [
'errorlog' => [
'file' => storage_path('logs/easy-sms.log'),
],
// 阿里云 AccessKeyID
'aliyun' => [
'access_key_id' => '',
'access_key_secret' => '',
'sign_name' => '',
],
// 阿里云Rest
'aliyunrest' => [
'app_key' => '',
'app_secret_key' => '',
'sign_name' => '',
],
// 云片
'yunpian' => [
'api_key' => '',
'signature' => '',
],
// ... 具体参数请参考 https://github.com/overtrue/easy-sms/blob/master/README.md
],
];

View File

@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSmsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('sms', function (Blueprint $table) {
$table->increments('id');
$table->string('mobile', 16);
$table->string('channel', 16);
$table->string('code', 16);
$table->boolean('used')->default(0);
$table->timestamps();
$table->index(['mobile', 'channel']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('sms');
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Jason\Sms\Exceptions;
use Exception;
class SmsSendException extends Exception
{
}

19
src/Facade.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
namespace Jason\Sms;
use Illuminate\Support\Facades\Facade as LaravelFacade;
/**
* Class Facade
* @package Jason\Sms
* @method static \Jason\Sms\Sms send($mobile, $channel)
* @method static \Jason\Sms\Sms check($mobile, $code, $channel)
*/
class Facade extends LaravelFacade
{
protected static function getFacadeAccessor()
{
return \Jason\Sms\Sms::class;
}
}

12
src/Models/Sms.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
namespace Jason\Sms\Models;
use Illuminate\Database\Eloquent\Model;
class Sms extends Model
{
protected $guarded = [];
}

50
src/ServiceProvider.php Normal file
View File

@@ -0,0 +1,50 @@
<?php
namespace Jason\Sms;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
class ServiceProvider extends LaravelServiceProvider
{
/**
* 部署时加载
* @Author:<C.Jason>
* @Date:2018-06-22T16:01:20+0800
* @return void
*/
public function boot()
{
if ($this->app->runningInConsole()) {
$this->publishes([__DIR__ . '/../config/config.php' => config_path('sms.php')], 'sms');
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations/');
}
/**
* 短信验证码验证
*/
Validator::extend('sms_check', function ($attribute, $code, $parameters) {
if (empty($code)) {
return false;
}
$mobileFiled = $parameters[0] ?? 'mobile';
$channel = $parameters[1] ?? 'DEFAULT';
$mobile = request()->input($mobileFiled);
return \Sms::check($mobile, $code, $channel);
});
}
/**
* 注册服务提供者
* @Author:<C.Jason>
* @Date:2018-06-22T16:01:12+0800
* @return void
*/
public function register()
{
$this->mergeConfigFrom(__DIR__ . '/../config/config.php', 'sms');
}
}

95
src/Sms.php Normal file
View File

@@ -0,0 +1,95 @@
<?php
namespace Jason\Sms;
use Illuminate\Support\Facades\DB;
use Jason\Sms\Exceptions\SmsSendException;
use Jason\Sms\Models\Sms as SmsModel;
use Overtrue\EasySms\EasySms;
class Sms
{
/**
* Notes: 发送短信
* @Author: <C.Jason>
* @Date : 2020/1/14 4:34 下午
* @param string $mobile 手机号码
* @param string $channel 验证通道
* @param array $appends 验证码附加内容
* @return bool
* @throws SmsSendException
*/
public function send(string $mobile, string $channel = 'DEFAULT', array $appends = [])
{
try {
$config = config('sms');
if (!isset($config['template'][$channel]) || empty($config['template'][$channel])) {
throw new SmsSendException('不合法的验证通道' . $config['template'][$channel]);
}
DB::transaction(function () use ($mobile, $channel, $config, $appends) {
$data = [];
if ($config['debug']) {
$data['code'] = $config['debug_code'];
} else {
$data['code'] = sprintf("%0" . $config['length'] . "d", mt_rand(1, pow(10, $config['length']) - 1));
}
if (!empty($appends)) {
$data = array_merge($data, $appends);
}
if ($config['debug'] != true) {
$easySms = new EasySms($config);
$easySms->send($mobile, [
'template' => $config['template'][$channel],
'data' => $data,
]);
}
SmsModel::create([
'mobile' => $mobile,
'channel' => $channel,
'code' => $data['code'],
]);
});
return true;
} catch (\Exception $e) {
throw new SmsSendException($e->getMessage());
}
}
/**
* 验证短信
* @Author:<C.Jason>
* @Date :2018-11-07T14:26:38+0800
* @param string $mobile 手机号码
* @param string $code 验证码
* @param string $channel 验证通道
* @return bool
*/
public function check(string $mobile, string $code, string $channel = 'DEFAULT')
{
$Sms = SmsModel::where('mobile', $mobile)->where('channel', $channel)->orderBy('id', 'desc')->first();
if ($Sms) {
if ($Sms->code == $code) {
if ($Sms->used == 1 && config('sms.once_used') && config('sms.debug') == false) {
return false;
}
$Sms->used = 1;
$Sms->save();
return true;
} else {
return false;
}
} else {
return false;
}
}
}