SmsService.php 5.4 KB
<?php
/**
+-----------------------------------------------------------------------------------------------------------------------
 * 逻辑层:短信 服务类,处理业务逻辑
+-----------------------------------------------------------------------------------------------------------------------
 *
 * PHP version 7
 *
 * @category  App\Services
 * @package   App\Services
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年11月12日 08:35:04
 * @copyright 2021-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
namespace App\Services;

use App\Http\Requests\SmsRequest;
use App\Models\System\SmsLog;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;

/**
 * Class SmsService.
 *
 * @category  App\Services
 * @package   App\Services
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年11月12日 08:35:04
 * @copyright 2021-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
class SmsService extends BaseService
{
    /**
     * SmsService constructor.
     *
     * @param SmsLog $model
     */
    public function __construct(SmsLog $model)
    {
         // 执行父类构造方法
        parent::__construct($model);
    }

    /**
     * 短信回执.
     *
     * @param  Request $request
     *
     * @return bool|Response
     */
    public function notify($request)
    {
       // {"errorCode":"DELIVRD","mobile":"15956278880","msgGroup":"0826134700000001144529","receiveDate":"20210826134700","reportStatus":"CM:0000","submitDate":"20210826134700"}
        Log::channel('sms')->info('========================= MAS 短信回执 begin =========================');
        Log::channel('sms')->info(json_encode($request->all()));
        $model = $this->model->where('out_id', $request->msgGroup)->first();
        if ($model) {
            $model->noticed_body = $request->all();
            $model->noticed_at = now()->toDateTimeString();
            $model->save();
        }
        Log::channel('sms')->info('========================= MAS 短信回执 end =========================');

        return true;
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  SmsRequest $request
     *
     * @return bool|Response
     */
    public function store(SmsRequest $request)
    {
        $user = $this->getLoginUser();
        $mobile = $request->mobile ?? optional($user)->mobile;
        if (!$mobile) {
            $this->message ='请填写手机号!';
            return false;
        }
        // type:1 注册,2:登录,3找回密码
        $type   = $request->type;

        // 验证是否频繁发送
        if (!$this -> verifyIsSentFrequently($mobile, $type)) {
            return false;
        }

        // 生成验证码
        $code = self::generateCode();

        // 发送短信、
        $sms = app(\App\Sms\Sms::class);
        $result = $sms->pushSmsCode($mobile, $code);
        // 验证发送结果
        if ($result['status'] == 'success') {
            // 发送成功
            // 用于验证是否频繁发送
            \Cache::add(self::generateCacheKey($mobile, $type, 'sendtime'), time(), SmsLog::INTERVALS);
            // 缓存中增加该手机号的验证码,保存时间为发送间隔时间
            \Cache::add(self::generateCacheKey($mobile, $type, $code), $code, SmsLog::INVALID_TIME);
            // 发送记录入库,方便统计和查询,可以放在缓存中进行校验,不查询数据
            // 发送记录入库并返回记录
            $request['code']        = $code;
            $request['send_time']   = date('Y-m-d H:i:s');
            return $this->create($request);
        }

        $this->message = $sms->getMessage();
        return false;
    }

    /**
     * 生成缓存key
     *
     * @param string $mobile
     * @param string $type
     * @return string
     */
    private static function generateCacheKey($mobile, $type, $suffix)
    {
        return 'sms_' . $mobile . '_' . $type .'-'.$suffix;
    }

    /**
     * 验证
     *
     * @param string $mobile
     * @param string $code
     * @param string $type
     * @return boolean
     */
    public static function checkCode($mobile = '', $code = '', $type = '')
    {
        // 特殊字符不进行验证
        if ($code == '000000') {
            return true;
        }

        // 获取缓存key
        $cacheKey = self::generateCacheKey($mobile, $type, $code);
        // 获取缓存
        $cacheCode = \Cache::get($cacheKey);
        if ($cacheCode != $code) {
            return false;
        }

        // 不将缓存中的验证码清空,省短信流量
        // 获取成功后,将缓存删除
        // Cache::delete($cacheKey);

        return true;
    }

    /**
     * 生成随机验证码
     *
     * @return int
     */
    public static function generateCode()
    {
        return mt_rand(100000, 999999);
    }

    /**
     * 验证是否发生频繁
     *
     * @param $mobile
     * @param $type
     * @return bool
     */
    public function verifyIsSentFrequently($mobile, $type)
    {
        $cacheKey = self::generateCacheKey($mobile, $type, 'sendtime');

        // 获取缓存
        $cacheCode = \Cache::get($cacheKey);

        if ($cacheCode) {
            $this->message ='操作频繁!';
            return false;
        }
        return true;
    }
}