ComSmsService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: ywl
  5. * Date: 2017/4/14
  6. * Time: 11:38
  7. */
  8. namespace App\Common\Services;
  9. use AlibabaCloud\Client\AlibabaCloud;
  10. use AlibabaCloud\Client\Exception\ClientException;
  11. use App\Common\Models\ComSmsModel;
  12. use App\Exceptions\ApiException;
  13. use App\Services\CommonBaseService;
  14. use App\User\Models\SysAdminUserModel;
  15. use Illuminate\Database\QueryException;
  16. use Illuminate\Support\Facades\Cache;
  17. use Illuminate\Http\Request;
  18. use Illuminate\Support\Facades\DB;
  19. use Illuminate\Support\Facades\Log;
  20. use Illuminate\Support\Facades\Mail;
  21. class ComSmsService extends CommonBaseService
  22. {
  23. protected $cache = true;
  24. protected $cacheBucket = 'ComSms:';
  25. protected $tokenBucket = 'Token:';
  26. protected $activeBucket = "Active:";
  27. /**
  28. * 发送短信验证码
  29. * @param string $phone
  30. * @param string $accessKeyId
  31. * @param string $accessKeySecret
  32. * @param string $signName
  33. * @param string $templateCode
  34. * @param string $type
  35. * @return bool|mixed
  36. * @throws \App\Exceptions\ApiException
  37. * @throws ClientException
  38. */
  39. public function sendSMSInfo($smsParams,$accessKeyId = '', $accessKeySecret = '', $signName = '', $templateCode = '' )
  40. {
  41. $phone=$smsParams['phone'];
  42. if(isset($smsParams['is_send'])){
  43. $isSend=$smsParams['is_send'];
  44. }else{
  45. $isSend=1;
  46. }
  47. $appCode=empty($smsParams['app_code'])?'':$smsParams['app_code'];
  48. $countryCode=empty($smsParams['country_code'])?'86':$smsParams['country_code'];
  49. $ret=['code'=>0,'data'=>[],'message'=>''];
  50. try {
  51. $code = mt_rand(100000, 999999);
  52. if($isSend){
  53. //发送短信
  54. if (!empty($countryCode) && $countryCode != 86) {
  55. if (empty($accessKeyId)) {
  56. $accessKeyId = config('sms.foreign_access_key_id'); //阿里云短信公钥
  57. }
  58. if (empty($accessKeySecret)) {
  59. $accessKeySecret = config('sms.foreign_access_key_secret'); //阿里云短信私钥
  60. }
  61. if (empty($signName)) {
  62. $signName = config('sms.foreign_sign_name'); //阿里云短信 签名名称
  63. }
  64. if (empty($templateCode)) {
  65. $templateCode = config('sms.foreign_template_code'); //阿里云短信 短信模板ID
  66. }
  67. }else{
  68. if (empty($accessKeyId)) {
  69. $accessKeyId = config('sms.access_key_id'); //阿里云短信公钥
  70. }
  71. if (empty($accessKeySecret)) {
  72. $accessKeySecret = config('sms.access_key_secret'); //阿里云短信私钥
  73. }
  74. if (empty($signName)) {
  75. $signName = config('sms.sign_name'); //阿里云短信 签名名称
  76. $appSignName=config('sms.app_sign_name');
  77. if($appSignName&&!empty($appCode)){
  78. if(!empty($appSignName[$appCode])) {
  79. $signName=$appSignName[$appCode];
  80. }
  81. }
  82. }
  83. if (empty($templateCode)) {
  84. $templateCode = config('sms.template_code'); //阿里云短信 短信模板ID
  85. }
  86. }
  87. AlibabaCloud::accessKeyClient($accessKeyId, $accessKeySecret)
  88. ->regionId('cn-hangzhou')// replace regionId as you need
  89. ->asDefaultClient();
  90. $response = AlibabaCloud::rpc()
  91. ->product('Dysmsapi')
  92. // ->scheme('https') // https | http
  93. ->version('2017-05-25')
  94. ->action('SendSms')
  95. ->method('POST')
  96. ->host('dysmsapi.aliyuncs.com')
  97. ->options([
  98. 'query' => [
  99. 'SignName' => $signName, //阿里云短信 签名名称
  100. 'TemplateCode' => $templateCode, //阿里云短信 短信模板ID
  101. 'PhoneNumbers' => $phone, //手机号
  102. 'TemplateParam' => '{"code":' . $code . '}',//验证码参数 json格式
  103. ],
  104. ])
  105. ->request();
  106. $data = [
  107. 'phone' => $phone,
  108. 'code' => $code,
  109. 'template_code' => $templateCode,
  110. 'error' => empty($params['error']) ? '' : $params['error'],
  111. 'type' => 0
  112. ];
  113. $responseData= $response->toArray();
  114. if (isset($responseData['Code']) && $responseData['Code'] == 'OK') {
  115. $currentTime = time(); //当前时间
  116. $data['status'] = 1;
  117. $data['expire_time']=$currentTime + config('sms.expireTime');
  118. $key=$phone;
  119. $cacheKey=md5($key);
  120. $cacheTime=config('cache.sms_time');
  121. $this->setCacheData($cacheKey,$data,$cacheTime);
  122. $result = $this->updatePhoneCode($data);
  123. $resultData['id']=$result;
  124. $resultData['code']=$code;
  125. $resultData['phone']=$phone;
  126. $ret['data'] = $resultData;
  127. return $ret;
  128. } else {
  129. $data['status'] = -1;
  130. $errorMessage = empty($response->Message) ? '' : $response->Message;
  131. $errorCode = empty($response->Code) ? '' : $response->Code;
  132. $errorRequestId = empty($response->RequestId) ? '' : $response->RequestId;
  133. $data['error'] = 'ErrorRequestId' . $errorRequestId . ';ErrorCode:' . $errorCode . ';Message:' . $errorMessage;
  134. Log::info('method:error:' . $response);
  135. // throw new ApiException(1001); //短信发送参数code错误
  136. $ret['code']=1010;
  137. return $ret;
  138. }
  139. }else{
  140. $data = [
  141. 'phone' => $phone,
  142. 'code' => $code,
  143. 'template_code' => '',
  144. 'error' => '',
  145. 'type' => 0
  146. ];
  147. $currentTime = time(); //当前时间
  148. $data['status'] = 1;
  149. $data['expire_time']=$currentTime + config('sms.expireTime');
  150. $key=$phone;
  151. $cacheKey=md5($key);
  152. $cacheTime=config('cache.sms_time');
  153. $this->setCacheData($cacheKey,$data,$cacheTime);
  154. $result = $this->updatePhoneCode($data);
  155. $resultData['id']=is_array($result)?0:$result;
  156. $resultData['code']=$code;
  157. $resultData['phone']=$phone;
  158. $ret['data'] = $resultData;
  159. return $ret;
  160. }
  161. } catch (\Exception $ex) {
  162. Log::info('method:sendSMSInfo:' . $ex->getMessage());
  163. Log::info('method:sendSMSInfo:' . $ex->getTraceAsString());
  164. $ret['code']=1004;
  165. $ret['message']=$ex->getMessage();
  166. return $ret;
  167. // throw new ApiException(500); //短信发送参数错误
  168. }
  169. }
  170. /**
  171. * 短信记录
  172. * @param array $params 短信存储参数
  173. * @return bool|mixed
  174. * @throws \App\Exceptions\ApiException
  175. */
  176. public function updatePhoneCode($params = [])
  177. {
  178. //手机验证码信息
  179. $codeData = [
  180. 'phone' => $params['phone'],
  181. 'code' => $params['code'],
  182. 'template_code' => $params['template_code'],
  183. 'status' => $params['status'],
  184. 'error' => empty($params['error']) ? '' : $params['error'],
  185. 'type' => empty($params['type']) ? 0 : $params['type'],
  186. 'create_time' => nowTime()
  187. ];
  188. if(!empty($params['expire_time'])){
  189. $codeData['expire_time']= date('Y-m-d H:i:s', $params['expire_time']);
  190. }
  191. try {
  192. $result=$this->model->insertGetId($codeData);
  193. if (!$result) {
  194. Log::info('method:updatePhoneCode:保存验证码失败');
  195. $ret['code']=1004;
  196. $ret['message']= '保存验证码失败';
  197. return $ret;
  198. }
  199. return $result;
  200. } catch (QueryException $ex) {
  201. //异常处理
  202. Log::info('method:updatePhoneCode:' . $ex->getMessage());
  203. Log::info('method:updatePhoneCode:' . $ex->getTraceAsString());
  204. $ret['code']=1004;
  205. $ret['message']=$ex->getMessage();
  206. return $ret;
  207. }
  208. }
  209. /**
  210. * 校验短信验证码是否有效
  211. * @param string $phone 手机号
  212. * @param string $code 短信验证码
  213. * @return array -1 失败重新获取验证码 -2验证码错误重新输入,1 成功是否验证成功
  214. */
  215. public function validateCode($phone, $code)
  216. {
  217. //todo 通过redis 缓存来验证
  218. $result=['code'=>-1];
  219. $current_time = time();
  220. $key=$phone;
  221. $cacheKey=md5($key);
  222. $cacheData=$this->getCacheData($cacheKey);
  223. if($cacheData){
  224. if(!empty($cacheData['expire_time'])&&$cacheData['expire_time']>$current_time&&$code==$cacheData['code']){
  225. $result['code']=1;
  226. $this->removeByKey($cacheKey);
  227. }else if($code!=$cacheData['code']){
  228. $result['code']=-2;
  229. }
  230. }
  231. return $result;
  232. }
  233. /**
  234. * 校验短信验证码一分钟内是否重复发送
  235. * */
  236. public function validataPhoneMinute($phone,$type){
  237. $result=['code'=>0];
  238. $where=[
  239. 'phone' => $phone,
  240. 'type' => $type,
  241. 'status' => 1,
  242. ];
  243. $expireTime = date("Y-m-d H:i:s",strtotime("+4 minute",strtotime(nowTime()))); // 短信有效时间为5分钟。当前时间添加4分钟
  244. $smsData = $this->model->where($where)->where('expire_time','>',$expireTime)->first();
  245. if(!empty($smsData)){
  246. $result['code']=-1;
  247. }
  248. return $result;
  249. }
  250. /**
  251. * 通用缓存方法
  252. * @param string $key
  253. * @param array $data
  254. * */
  255. public function setCacheData($key, $data,$cacheTime=0)
  256. {
  257. $cacheTime=empty($cacheTime)?config('cache.def_time'):$cacheTime;
  258. Cache::put($this->getCacheKey($key), $data, $cacheTime);
  259. }
  260. /**
  261. * 获取通用缓存数据key
  262. * @param string $key
  263. * @return string
  264. * */
  265. private function getCacheKey($key)
  266. {
  267. $prefix='VERIFICATION';
  268. return $this->cacheBucket.$prefix.$key;
  269. }
  270. /**
  271. * 通用缓存方法
  272. * @param string $key
  273. * @param array $data
  274. * */
  275. public function getCacheData($key)
  276. {
  277. $dataKey= $this->getCacheKey($key);
  278. return Cache::get($dataKey);
  279. }
  280. }