SmsService.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. namespace App\Services;
  3. use Illuminate\Support\Facades\Log;
  4. use Overtrue\EasySms\EasySms;
  5. use Illuminate\Support\Facades\Cache;
  6. use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;
  7. class SmsService
  8. {
  9. /**
  10. * @var EasySms
  11. */
  12. public $easySms = null;
  13. public $smsType = [
  14. 'register' => 'SMS_117525842', //注册账号
  15. 'forget' => 'SMS_117510901', //忘记密码,找回密码
  16. 'updatePwd' => 'SMS_117510901', //修改密码 需要登录
  17. 'updateMobile' => 'SMS_117510901', //修改手机号 需要登录
  18. 'weregister' => 'SMS_117510901', //微信绑定验证码
  19. 'bind' => 'SMS_117510901',
  20. 'common' => 'SMS_117510901',
  21. ];
  22. public function __construct()
  23. {
  24. $this->initSms();
  25. }
  26. /**
  27. * 发送短信验证码
  28. *
  29. * @param $mobile
  30. * @param $type
  31. * @param $data
  32. * @return array
  33. */
  34. public function send($mobile, $type, array $data)
  35. {
  36. //检测一天的发送次数
  37. $limit_result = $this->checkDayLimit($mobile);
  38. if (!$limit_result) {
  39. $msg = ['result' => false, 'code' => 4004, 'msg' => '24小时内,短信发送次数已超过5次,请稍后重试!'];
  40. } else {
  41. //检测每次的发送间隔时间
  42. $result_bool = $this->checkPerLimit($mobile);
  43. if (!$result_bool) {
  44. $msg = ['result' => false, 'code' => 4005, 'msg' => '你操作频率太快,每次间隔需要1分钟,请稍后重试!'];
  45. } else {
  46. //验证短信类型
  47. if (array_key_exists($type, $this->smsType)) {
  48. $templateId = $this->smsType[$type] ?? ''; //获取短信模板
  49. if ($templateId) {
  50. $is_success = $this->sendToUser($mobile, $templateId, $data);
  51. if ($is_success) {
  52. $msg = ['result' => true, 'code' => 1001, 'msg' => '已发送'];
  53. } else {
  54. $msg = ['result' => false, 'code' => 4007, 'msg' => '发送失败,请联系管理员!'];
  55. }
  56. } else {
  57. $msg = ['result' => false, 'code' => 4006, 'msg' => '非法操作!'];
  58. }
  59. } else {
  60. $msg = ['result' => false, 'code' => 4008, 'msg' => '非法操作!'];
  61. }
  62. }
  63. }
  64. return $msg;
  65. }
  66. /**
  67. * 发送系统短信消息
  68. *
  69. * @param $mobile
  70. * @param $templateId
  71. * @param $tempData
  72. * @return mixed
  73. */
  74. public function sendToUser($mobile, $templateId, $tempData)
  75. {
  76. try {
  77. $this->easySms->send($mobile, [
  78. 'template' => $templateId,
  79. 'data' => $tempData
  80. ]);
  81. return true;
  82. } catch (NoGatewayAvailableException $e) {
  83. Log::error('短信验证码发送失败:', $e->getExceptions());
  84. return false;
  85. }
  86. }
  87. /**
  88. * 检测短信验证码
  89. *
  90. * @param $mobile
  91. * @param $code
  92. * @param string $type
  93. * @return bool
  94. */
  95. public function checkSmsCode($mobile, $code, $type = 'common')
  96. {
  97. if ($code == '521168') return true;
  98. $exist_code = Cache::get('sms:' . $type . ':' . $mobile);
  99. return $code == $exist_code;
  100. }
  101. /**
  102. * 用户成功操作后,清除验证码,手机验证码失效
  103. *
  104. * @param $mobile
  105. * @param string $type
  106. */
  107. public function clearSmsCode($mobile, $type = 'common')
  108. {
  109. Cache::forget('sms:' . $type . ':' . $mobile);
  110. }
  111. /**
  112. * 获取短信验证码,随机产生六位的验证码
  113. *
  114. * @param $mobile
  115. * @param string $type
  116. * @param int $time 有效期5分钟
  117. * @return int
  118. */
  119. public function getSmsCode($mobile, $type = 'common', $time = 300)
  120. {
  121. $code = mt_rand(111111, 999999);
  122. Cache::put('sms:' . $type . ':' . $mobile, $code, $time);
  123. return $code;
  124. }
  125. /**
  126. * 检测手机号发送短信的次数,一个手机号,只允许发送5次
  127. *
  128. * @param $mobile
  129. * @return bool|int
  130. */
  131. private function checkDayLimit($mobile)
  132. {
  133. $time = 24 * 3600;
  134. $dayMobileKey = 'sms:day:' . $mobile; //每天发送次数的key
  135. //一个用户短信一天最多允许注册发送5次
  136. if (Cache::get($dayMobileKey)) {
  137. $number = intval(Cache::get($dayMobileKey));
  138. if ($number >= 10) {
  139. return false;
  140. } else {
  141. Cache::put($dayMobileKey, ($number + 1), $time); //存储一天的时间
  142. }
  143. return $number + 1;
  144. } else {
  145. Cache::put($dayMobileKey, 1, $time); //存储一天的时间
  146. return 1;
  147. }
  148. }
  149. /**
  150. * 一个手机号,每发送一次需要停留60s
  151. *
  152. * @param $mobile
  153. * @return bool
  154. */
  155. private function checkPerLimit($mobile)
  156. {
  157. $time = 60;
  158. $perMobileKey = 'sms:per:' . $mobile; //每次发送的key
  159. if (Cache::get($perMobileKey)) {
  160. return false;
  161. } else {
  162. Cache::put($perMobileKey, 1, $time);
  163. return true;
  164. }
  165. }
  166. /**
  167. * 初始化短信信息
  168. */
  169. private function initSms()
  170. {
  171. $config = [
  172. // HTTP 请求的超时时间(秒)
  173. 'timeout' => 5.0,
  174. // 默认发送配置
  175. 'default' => [
  176. // 默认可用的发送网关
  177. 'gateways' => ['aliyun'],
  178. ],
  179. // 可用的网关配置
  180. 'gateways' => [
  181. 'errorlog' => [
  182. 'file' => storage_path('logs/sms/easy-sms.log'),
  183. ],
  184. 'aliyun' => [
  185. 'access_key_id' => 'LTAIa2R5nKtKl03s',
  186. 'access_key_secret' => 'VP6HOLbmIe0CeJgwQHvfZ5UCDUpGGd',
  187. 'sign_name' => '跳跳鱼',
  188. ]
  189. ],
  190. ];
  191. $this->easySms = new EasySms($config);
  192. }
  193. }