作者 lyh

gx

  1 +<?php
  2 +
  3 +namespace App\Helper;
  4 +
  5 +class AliSms
  6 +{
  7 +
  8 + private $_msg = array( //状态对照
  9 + 1 => "发送成功",
  10 + 0 => "其他系统错误",
  11 + -1 => "短信余额不足",
  12 + -2 => "资金账户被锁定",
  13 + -3 => "用户被锁定",
  14 + -4 => "号码在黑名单内",
  15 + -5 => "用户名或密码不正确",
  16 + -6 => "号码不正确",
  17 + -7 => "接口连接失败",
  18 + -8 => "号码格式错误",
  19 + -9 => "通道编号错误",
  20 + -10 => "定时发送时间不正确",
  21 + -11 => "没有输入短信内容",
  22 + -12 => "短信内容超出长度限制",
  23 + -15 => "内容含非法关键字",
  24 + -16 => "超出发送时间范围",
  25 + -17 => "通道被关闭",
  26 + -18 => "短信内容没有签名",
  27 + -30 => "手机未认证",
  28 + -31 => "身份未认证",
  29 + -32 => "请勿重复发送",
  30 + -33 => "验证码已过期,请重新获取",
  31 + -34 => "手机号码格式不正确",
  32 + -35 => "验证码不正确",
  33 + );
  34 + // 保存错误信息
  35 + public $error;
  36 + public $_code = "";
  37 + public $_name = "";
  38 + public $_key_str = ""; // cache full name.
  39 + protected $_expire = 600; // 验证码过期时间(s)
  40 + public $_key = [
  41 + ];
  42 + // Access Key ID
  43 + private $accessKeyId = '';
  44 + // Access Key Secret
  45 + private $accessKeySecret = '';
  46 + // 签名
  47 + private $signName = '';
  48 + // 模版ID
  49 + public $templateCode = '';
  50 +
  51 + public function __construct($config = array())
  52 + {
  53 + $config = array(
  54 + 'accessKeyId' => config('aliyunsms.access_key'),
  55 + 'accessKeySecret' => config('aliyunsms.access_secret'),
  56 + 'signName' => config('aliyunsms.sign_name'),
  57 + 'templateCode' => config('aliyunsms.login_sms_temp'),
  58 + );
  59 + // 配置参数
  60 + $this->accessKeyId = $config['accessKeyId'];
  61 + $this->accessKeySecret = $config['accessKeySecret'];
  62 + $this->signName = $config['signName'];
  63 + $this->templateCode = $config['templateCode'];
  64 + }
  65 +
  66 + /**
  67 + * 规范化字符串以符合阿里云短信接口
  68 + * @param $string
  69 + * @return mixed|string
  70 + */
  71 + private function percentEncode($string)
  72 + {
  73 + $string = urlencode($string);
  74 + $string = preg_replace('/\+/', '%20', $string);
  75 + $string = preg_replace('/\*/', '%2A', $string);
  76 + $string = preg_replace('/%7E/', '~', $string);
  77 + return $string;
  78 + }
  79 +
  80 + /**
  81 + * 签名
  82 + *
  83 + * @param unknown $parameters
  84 + * @param unknown $accessKeySecret
  85 + * @return string
  86 + */
  87 + private function computeSignature($parameters, $accessKeySecret)
  88 + {
  89 + ksort($parameters);
  90 + $canonicalizedQueryString = '';
  91 + foreach ($parameters as $key => $value) {
  92 + $canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
  93 + }
  94 + $stringToSign = 'GET&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
  95 + $signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
  96 + return $signature;
  97 + }
  98 +
  99 + /**
  100 + * 发送验证码 https://help.aliyun.com/document_detail/44364.html?spm=5176.doc44368.6.126.gSngXV
  101 + *
  102 + * @param unknown $mobile
  103 + * @param unknown $verify_code
  104 + *
  105 + */
  106 + public function send_sms($mobile, $paramstring)
  107 + {
  108 + $params = array(
  109 + // 公共参数
  110 + 'SignName' => $this->signName,
  111 + 'Format' => 'JSON',
  112 + 'Version' => '2016-09-27',
  113 + 'AccessKeyId' => $this->accessKeyId,
  114 + 'SignatureVersion' => '1.0',
  115 + 'SignatureMethod' => 'HMAC-SHA1',
  116 + 'SignatureNonce' => uniqid(),
  117 + 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
  118 + // 接口参数
  119 + 'Action' => 'SingleSendSms',
  120 + 'TemplateCode' => $this->templateCode,
  121 + 'RecNum' => $mobile,
  122 + 'ParamString' => $paramstring,
  123 + );
  124 + // 计算签名并把签名结果加入请求参数
  125 + $params['Signature'] = $this->computeSignature($params, $this->accessKeySecret);
  126 +
  127 + // 发送请求
  128 + $url = 'https://sms.aliyuncs.com/?' . http_build_query($params);
  129 + $result = http_get($url); //TODO:上线前打开
  130 + if (isset($result['Code'])) {
  131 + $this->error = $this->getErrorMessage($result['Code']);
  132 + return false;
  133 + }
  134 + return true;
  135 + }
  136 +
  137 + /**
  138 + * 发送验证码 https://help.aliyun.com/document_detail/44364.html?spm=5176.doc44368.6.126.gSngXV
  139 + *
  140 + * @param unknown $mobile
  141 + * @param unknown $verify_code
  142 + *
  143 + */
  144 + public function send_verify($mobile)
  145 + {
  146 + if ($this->checkMobile($mobile) === false) {
  147 + $this->error = $this->_msg[-34];
  148 + return -34;
  149 + }
  150 + $session = cache($this->_key_str . $mobile);
  151 + if ($session && time() - $session['time'] < 60) {
  152 + if ($session['code'] == null) {
  153 + return true;
  154 + } else {
  155 + $this->error = $this->_msg[-32];
  156 + return -32;
  157 + }
  158 + }
  159 + $this->_code = rand(1000, 9999);
  160 + $params = array(
  161 + // 公共参数
  162 + 'SignName' => $this->signName,
  163 + 'Format' => 'JSON',
  164 + 'Version' => '2016-09-27',
  165 + 'AccessKeyId' => $this->accessKeyId,
  166 + 'SignatureVersion' => '1.0',
  167 + 'SignatureMethod' => 'HMAC-SHA1',
  168 + 'SignatureNonce' => uniqid(),
  169 + 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
  170 + // 接口参数
  171 + 'Action' => 'SingleSendSms',
  172 + 'TemplateCode' => $this->templateCode,
  173 + 'RecNum' => $mobile,
  174 + 'ParamString' => '{"msgcode":"' . $this->_code . '"}',
  175 + );
  176 + // 计算签名并把签名结果加入请求参数
  177 + $params['Signature'] = $this->computeSignature($params, $this->accessKeySecret);
  178 + // 发送请求
  179 + $url = 'https://sms.aliyuncs.com/?' . http_build_query($params);
  180 + $result = http_get($url); //TODO:上线前打开
  181 + // $result =1;
  182 + if ($result) {
  183 + $session = array();
  184 + $session['code'] = $this->_code; // 把校验码保存到session
  185 + $session['time'] = time(); // 验证码创建时间
  186 + cache($this->_key_str . $mobile, $session, $this->_expire);
  187 + } else {
  188 + return $this->error = $this->_msg[0];
  189 + }
  190 + if (isset($result['Code'])) {
  191 + $this->error = $this->getErrorMessage($result['Code']);
  192 + return false;
  193 + }
  194 + return true;
  195 + }
  196 + /**
  197 + * 验证手机号码
  198 + */
  199 + public function checkMobile($tel)
  200 + {
  201 + if (preg_match("/^1[3,4,6,5,8,7,9][0-9]{1}[0-9]{8}$/", $tel)) {
  202 + //验证通过
  203 + return true;
  204 + } else {
  205 + $this->error = $this->_msg[-34];
  206 + //手机号码格式不对
  207 + return false;
  208 + }
  209 + }
  210 +
  211 + /**
  212 + * 验证码是否正确
  213 + * @param string $key 手机号码
  214 + * @param int|string $code 验证码
  215 + * @param int|string $type 类型 reg-注册时获取 sms-快速登录时 pwd-修改密码时 bind-绑定手机时 unbind-解绑时
  216 + * @return boolean 验证短信验证码是否正确
  217 + */
  218 + public function check($key, $code, $type = 'reg')
  219 + {
  220 + $this->_key_str = $type . '_' . $key;
  221 + $session = cache($this->_key_str);
  222 + if (empty($code) || empty($session)) {
  223 + $this->error = $this->_msg[-33] . $this->_key_str;
  224 + return false;
  225 + }
  226 + if (time() - $session['time'] > $this->_expire) {
  227 + cache($this->_key_str, null);
  228 + $this->error = $this->_msg[-33] . $this->_key_str;
  229 + return false;
  230 + }
  231 + if ($code == $session['code']) {
  232 + return true;
  233 + }
  234 + $this->error = $this->_msg[-35] . $this->_key_str;
  235 + return false;
  236 + }
  237 +
  238 + /**
  239 + * 验证成功后调用清空验证码
  240 + */
  241 + public function afterCheck()
  242 + {
  243 + cache($this->_key_str, null);
  244 + }
  245 +
  246 + /**
  247 + * 获取详细错误信息
  248 + *
  249 + * @param unknown $status
  250 + */
  251 + public function getErrorMessage($status)
  252 + {
  253 +
  254 + $message = array(
  255 + 'InvalidDayuStatus.Malformed' => '账户短信开通状态不正确',
  256 + 'InvalidSignName.Malformed' => '短信签名不正确或签名状态不正确',
  257 + 'InvalidTemplateCode.MalFormed' => '短信模板Code不正确或者模板状态不正确',
  258 + 'InvalidRecNum.Malformed' => '目标手机号不正确,单次发送数量不能超过100',
  259 + 'InvalidParamString.MalFormed' => '短信模板中变量不是json格式',
  260 + 'InvalidParamStringTemplate.Malformed' => '短信模板中变量与模板内容不匹配',
  261 + 'InvalidSendSms' => '1小时只能请求7次,谢谢',
  262 + 'InvalidDayu.Malformed' => '变量不能是url,可以将变量固化在模板中',
  263 + );
  264 + if (isset($message[$status])) {
  265 + return $message[$status];
  266 + }
  267 + return $status;
  268 + }
  269 +
  270 + private function _addlog($name, $title)
  271 + {
  272 + $this->_keys["code"] = $this->_code;
  273 +// addlog($this->_keys, $title, 1, $this->_url);
  274 + }
  275 +}