send($mobile, $content); } public function sendBatch(array $mobile, $content) { $smsSender = make(SmsSender::class); if (!$smsSender) { throw new BusinessException('系统异常,请联系客服'); } $smsSender->sendBatch($mobile, $content); } public function sendCode($mobile, array $options) { $clientIp = $options['client_ip'] ?? ''; $smsSender = make(SmsSender::class); if (!$smsSender) { throw new BusinessException('系统异常,请联系客服'); } if ($clientIp && $this->isIpOutOfDayCount($clientIp)) { throw new BusinessException('每天发送数量不能超过' . self::IP_DAY_COUNT . '条'); } if ($this->isOutOfRate($mobile)) { throw new BusinessException('发送过于频繁,请稍后再试'); } $code = $this->getCode(); $sms = new Sms(); $sms->code = $code; $sms->mobile = $mobile; $sms->client_ip = $clientIp; $sms->channel = $smsSender->channel; $sms->save(); try { $smsSender->sendCode($mobile, $code, Sms::ACTIVE_MINUTE); $sms->status = Sms::STATUS_SUCCESS; $sms->result = 'success'; $sms->save(); } catch (\Exception $e) { $sms->status = Sms::STATUS_ERROR; $sms->result = 'error'; $sms->save(); Log::error( 'SMS_SEND_ERROR: ' . $e->getMessage(), ['mobile' => $mobile, 'options' => $options], 'sms' ); } } public function check($mobile, $code): bool { $sms = Sms::where('mobile', $mobile) ->where('is_checked', 0) ->where('status', Sms::STATUS_SUCCESS) ->orderBy('created_at', 'desc') ->first(); if (!$sms) { return false; } if ($sms->isExpired()) { return false; } if ($sms->code == $code) { $sms->is_checked = 1; $sms->save(); return true; } return false; } private function getCode() { return rand(100000, 999999); } private function isOutOfRate($mobile): bool { $lastSms = Sms::select(['created_at'])->where(['mobile' => $mobile])->orderBy('created_at', 'desc')->first(); if ($lastSms && strtotime($lastSms->created_at) + self::INTERVAL_MINUTE * 60 > time()) { return true; } return false; } private function isIpOutOfDayCount($ip): bool { $count = Sms::where('client_ip', $ip) ->where('status', Sms::STATUS_SUCCESS) ->whereBetween('created_at', [date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')]) ->count(); return $count > self::IP_DAY_COUNT; } }