Sms.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use app\common\library\Sms as Smslib;
  5. use app\common\model\Sms AS SmsModel;
  6. use app\common\model\User;
  7. use think\Hook;
  8. use fast\Random;
  9. use Exception;
  10. use think\exception\PDOException;
  11. use think\exception\ValidateException;
  12. use think\Log;
  13. /**
  14. * 手机短信接口
  15. */
  16. class Sms extends Api
  17. {
  18. protected $noNeedLogin = '*';
  19. protected $noNeedRight = '*';
  20. /**
  21. * 验证码有效时长
  22. * @var int
  23. */
  24. protected static $expire = 120;
  25. /**
  26. * 最大允许检测的次数
  27. * @var int
  28. */
  29. protected static $maxCheckNums = 10;
  30. /**
  31. * 发送验证码
  32. *
  33. * @ApiMethod (POST)
  34. * @param string $mobile 手机号
  35. * @param string $event 事件名称
  36. */
  37. public function send()
  38. {
  39. $mobile = $this->request->post("mobile");
  40. $event = $this->request->post("event");
  41. $event = $event ? $event : 'register';
  42. if (!$mobile || !\think\Validate::regex($mobile, "^1\d{10}$")) {
  43. $this->error(__('手机号不正确'));
  44. }
  45. $last = Smslib::get($mobile, $event);
  46. if ($last && time() - $last['createtime'] < 60) {
  47. $this->error(__('发送频繁'));
  48. }
  49. $ipSendTotal = \app\common\model\Sms::where(['ip' => $this->request->ip()])->whereTime('createtime', '-1 hours')->count();
  50. if ($ipSendTotal >= 5) {
  51. $this->error(__('发送频繁'));
  52. }
  53. if ($event) {
  54. $userinfo = User::getByMobile($mobile);
  55. if ($event == 'register' && $userinfo) {
  56. //已被注册
  57. $this->error(__('已被注册'));
  58. } elseif (in_array($event, ['changemobile']) && $userinfo) {
  59. //被占用
  60. $this->error(__('已被占用'));
  61. } elseif (in_array($event, ['changepwd', 'resetpwd']) && !$userinfo) {
  62. //未注册
  63. $this->error(__('未注册'));
  64. }
  65. }
  66. if (!Hook::get('sms_send')) {
  67. $this->error(__('请在后台插件管理安装短信验证插件'));
  68. }
  69. $ret = Smslib::send($mobile, null, $event);
  70. if ($ret) {
  71. $this->success(__('发送成功'));
  72. } else {
  73. $this->error(__('发送失败,请检查短信配置是否正确'));
  74. }
  75. }
  76. /**
  77. * 向国际手机号码发放短信
  78. * @return void
  79. * @throws \think\Exception
  80. */
  81. public function send_international_sms($country_code, $mobile, $event = '')
  82. {
  83. $last = SmsModel::where(['country_code' => $country_code, 'mobile' => $mobile, 'event' => $event])
  84. ->order('id', 'DESC')
  85. ->find();
  86. if ($last && time() - $last['create_time'] < 60) {
  87. $this->error(__('发送频繁'));
  88. }
  89. $ipSendTotal = SmsModel::where(['ip' => $this->request->ip()])->whereTime('create_time', '-1 hours')->count();
  90. if ($ipSendTotal >= 5) {
  91. $this->error(__('发送频繁'));
  92. }
  93. if ($event == 'register') {
  94. $userinfo = User::getByCodeAndMobile($country_code, $mobile);
  95. if (!empty($userinfo)) {
  96. //已被注册
  97. $this->error(__('已被注册'));
  98. }
  99. // elseif (in_array($event, ['changemobile']) && $userinfo) {
  100. // //被占用
  101. // $this->error(__('已被占用'));
  102. // } elseif (in_array($event, ['changepwd', 'resetpwd']) && !$userinfo) {
  103. // //未注册
  104. // $this->error(__('未注册'));
  105. // }
  106. }
  107. // if (!Hook::get('sms_send')) {
  108. // $this->error(__('请在后台插件管理安装短信验证插件'));
  109. // }
  110. $code = Random::numeric();//验证码
  111. $ret = $this->send_sms_unisms($country_code, $mobile, $code, $event);
  112. if ($ret['code']) {
  113. $time = time();
  114. $ip = request()->ip();
  115. $sms = SmsModel::create([
  116. 'country_code' => $country_code,
  117. 'event' => $event,
  118. 'mobile' => $mobile,
  119. 'code' => $code,
  120. 'ip' => $ip,
  121. ]);
  122. $this->success(__('发送成功') . '-' . $code);
  123. } else {
  124. Log::notice('短信发送失败');
  125. Log::error($ret['msg']);
  126. $this->error(__('发送失败,请检查短信配置是否正确'));
  127. }
  128. }
  129. /**
  130. * 检测验证码
  131. *
  132. */
  133. public function check($country_code, $mobile, $code, $event = 'verify'): bool
  134. {
  135. $time = time() - self::$expire;
  136. $sms = SmsModel::where(['country_code' => $country_code, 'mobile' => $mobile, 'event' => $event])
  137. ->order('id', 'DESC')
  138. ->find();
  139. if ($sms) {
  140. if ($sms['create_time'] > $time && $sms['times'] <= self::$maxCheckNums) {
  141. $correct = $code == $sms['code'];
  142. if (!$correct) {
  143. $sms->times = $sms->times + 1;
  144. $sms->save();
  145. return false;
  146. } else {
  147. //$result = Hook::listen('sms_check', $sms, null, true);
  148. return true;
  149. }
  150. }
  151. }
  152. return false;
  153. }
  154. /**
  155. * 发送短信验证码
  156. * 短信平台:https://unisms.apistd.com/
  157. */
  158. public function send_sms_unisms($country_code, $phone, $code, $event = 'verify')
  159. {
  160. return _success();
  161. $phone = '+' . $country_code . $phone;//拼接国际区号
  162. try {
  163. $url1 = "https://uni.apistd.com";
  164. $query = [
  165. 'action' => 'sms.message.send',
  166. 'accessKeyId' => 'SGnbSrqzJikDxx4PuU83kD9oTTmv7o34unZ2bPX8FqsgCrQkp'
  167. ];
  168. $url = $url1.'/?'.http_build_query($query);
  169. $data = [
  170. 'signature' => 'AEXBTC',
  171. 'to' => $phone,
  172. //'content'=>$content,
  173. 'templateId' => 'd33f1f90',
  174. 'templateData' => ['code' => $code]
  175. ];
  176. $result = xcurl($url,$data);
  177. $result = json_decode($result, true);
  178. } catch (ValidateException|PDOException|Exception $e){
  179. return _error($e->getMessage());
  180. }
  181. if ($result['code'] == 0){
  182. //Cache::set($key, $code,300);
  183. return _success();
  184. }else{
  185. return _error($result['message']);
  186. }
  187. }
  188. }