AliSms.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <?php
  2. declare (strict_types=1);
  3. namespace library\utils\Sms;
  4. // +----------------------------------------------------------------------
  5. // | [ WE CAN DO IT MORE SIMPLE ]
  6. // +----------------------------------------------------------------------
  7. // | Copyright (c) 2018-2020 rights reserved.
  8. // +----------------------------------------------------------------------
  9. // | Author: TABLE ME
  10. // +----------------------------------------------------------------------
  11. // | Date: 2020-08-31 15:18
  12. // +----------------------------------------------------------------------
  13. use app\model\api\SmsSend;
  14. use app\model\api\SmsTpl;
  15. class AliSms {
  16. /**
  17. * 转义的模板信息
  18. * @param $content
  19. * @return mixed
  20. */
  21. function SmsTmpParam($content) {
  22. $data = func_get_args();
  23. foreach ($data[1] as $k => $v) {
  24. $content = str_replace('${' . $k . '}', $v, $content);
  25. }
  26. return $content;
  27. }
  28. /**
  29. * 发送模板的数据
  30. * @param type $tpl
  31. * @param type $code
  32. */
  33. function SmsSendTmplete($tel, $code,$sassid, $array = []) {
  34. $sData = SmsTpl::where("code",$code)->find();
  35. $r = false;
  36. $error = '';
  37. $req = null;
  38. if (!empty($sData)) {
  39. $req = $this->SmsSend($tel, $code, $array);
  40. if (!empty($req['Code']) && $req['Code'] == 'OK') {
  41. $r = true;
  42. } else {
  43. $error = $req['Message'];
  44. }
  45. $datax['mobile'] = $tel;
  46. $datax['content'] = $this->SmsTplParm($sData['content'], $array);
  47. $datax['time'] = time();
  48. $datax['code'] = $code;
  49. $datax['sassid'] = $sassid;
  50. if ($r) {
  51. $datax['is_success'] = 1;
  52. } else {
  53. $datax['is_success'] = -1;
  54. $datax['error'] = $error;
  55. }
  56. ( new SmsSend)->insert($datax);
  57. }
  58. return $req;
  59. }
  60. /**
  61. * 发送短信
  62. * @param type $tel 手机号码
  63. * @param type $sms_templ 模板名称
  64. * @param type $smsParam 模板参数
  65. */
  66. function SmsSend($tel, $sms_templ, $smsParam = []) {
  67. $config = config('sms');
  68. foreach ($smsParam as $k => $v) {
  69. $smsParam[$k] = (string) $v;
  70. }
  71. $params =[];
  72. $accessKeyId = $config['accessKeyId'];
  73. $accessKeySecret = $config['accessKeySecret'];
  74. // fixme 必填: 短信接收号码
  75. $params["PhoneNumbers"] = $tel;
  76. // fixme 必填: 短信签名,应严格按"签名名称"填写,请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/sign
  77. $params["SignName"] = $config['sign_name'];
  78. // fixme 必填: 短信模板Code,应严格按"模板CODE"填写, 请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/template
  79. $params["TemplateCode"] = $sms_templ;
  80. // fixme 可选: 设置模板参数, 假如模板中存在变量需要替换则为必填项
  81. $params['TemplateParam'] = $smsParam;
  82. // *** 需用户填写部分结束, 以下代码若无必要无需更改 ***
  83. if (!empty($params["TemplateParam"]) && is_array($params["TemplateParam"])) {
  84. $params["TemplateParam"] = json_encode($params["TemplateParam"], JSON_UNESCAPED_UNICODE);
  85. }
  86. $content = $this->request($accessKeyId, $accessKeySecret, "dysmsapi.aliyuncs.com", array_merge(
  87. $params,
  88. [ "RegionId" => "cn-hangzhou",
  89. "Action" => "SendSms",
  90. "Version" => "2017-05-25"
  91. ]
  92. ));
  93. $resp = json_decode(json_encode($content), true);
  94. return $resp;
  95. }
  96. /**
  97. * 生成签名并发起请求
  98. *
  99. * @param $accessKeyId string AccessKeyId (https://ak-console.aliyun.com/)
  100. * @param $accessKeySecret string AccessKeySecret
  101. * @param $domain string API接口所在域名
  102. * @param $params array API具体参数
  103. * @param $security boolean 使用https
  104. * @return bool|\stdClass 返回API接口调用结果,当发生错误时返回false
  105. */
  106. public function request($accessKeyId, $accessKeySecret, $domain, $params, $security = false) {
  107. $apiParams = array_merge(array(
  108. "SignatureMethod" => "HMAC-SHA1",
  109. "SignatureNonce" => uniqid((string) mt_rand(0, 0xffff) , true),
  110. "SignatureVersion" => "1.0",
  111. "AccessKeyId" => $accessKeyId,
  112. "Timestamp" => gmdate("Y-m-d\TH:i:s\Z"),
  113. "Format" => "JSON",
  114. ), $params);
  115. ksort($apiParams);
  116. $sortedQueryStringTmp = "";
  117. foreach ($apiParams as $key => $value) {
  118. $sortedQueryStringTmp .= "&" . $this->encode($key) . "=" . $this->encode($value);
  119. }
  120. $stringToSign = "GET&%2F&" . $this->encode(substr($sortedQueryStringTmp, 1));
  121. $sign = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret . "&", true));
  122. $signature = $this->encode($sign);
  123. $url = ($security ? 'https' : 'http') . "://{$domain}/?Signature={$signature}{$sortedQueryStringTmp}";
  124. try {
  125. $content = $this->fetchContent($url);
  126. return json_decode($content);
  127. } catch (\Exception $e) {
  128. return false;
  129. }
  130. }
  131. private function encode($str)
  132. {
  133. $res = urlencode($str);
  134. $res = preg_replace("/\+/", "%20", $res);
  135. $res = preg_replace("/\*/", "%2A", $res);
  136. $res = preg_replace("/%7E/", "~", $res);
  137. return $res;
  138. }
  139. private function fetchContent($url) {
  140. $ch = curl_init();
  141. curl_setopt($ch, CURLOPT_URL, $url);
  142. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  143. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  144. curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  145. "x-sdk-client" => "php/2.0.0"
  146. ));
  147. if(substr($url, 0,5) == 'https') {
  148. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  149. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  150. }
  151. $rtn = curl_exec($ch);
  152. if($rtn === false) {
  153. trigger_error("[CURL_" . curl_errno($ch) . "]: " . curl_error($ch), E_USER_ERROR);
  154. }
  155. curl_close($ch);
  156. return $rtn;
  157. }
  158. }