Ali.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <?php
  2. namespace ali;
  3. use app\common\model\SettingModel;
  4. use think\facade\Log;
  5. /**
  6. * 阿里云短信服务 PHP 示例
  7. *
  8. * 功能:
  9. * 1. 自动生成签名
  10. * 2. 支持单条短信发送
  11. * 3. 完善的错误处理
  12. * 4. 响应结果解析
  13. */
  14. class Ali
  15. {
  16. // 阿里云短信服务配置
  17. private $accessKeyId; // 替换为您的AccessKey ID
  18. private $accessKeySecret; // 替换为您的AccessKey Secret
  19. private $signName; // 短信签名
  20. private $regionId = 'cn-hangzhou'; // 区域ID
  21. private $endpoint = 'dysmsapi.aliyuncs.com'; // 短信服务域名
  22. // 发送短信
  23. public function send($phone, $smslog_param)
  24. {
  25. $config = SettingModel::getConfigValue(['sms_ali_accesskeyid', 'sms_ali_accesskeysecret', 'sms_ali_signname']);
  26. if (empty($config['sms_ali_accesskeyid']) || empty($config['sms_ali_accesskeysecret']) || empty($config['sms_ali_signname'])) {
  27. return ['code' => 1, 'msg' => '请绑定模板参数'];
  28. }
  29. //模板编号
  30. $templateCode = $smslog_param['template']['ali'];
  31. if (empty($templateCode)) {
  32. return ['code' => 1, 'msg' => '系统未配置阿里模板编号'];
  33. }
  34. $this->accessKeyId = $config['sms_ali_accesskeyid'];
  35. $this->accessKeySecret = $config['sms_ali_accesskeysecret'];
  36. $this->signName = $config['sms_ali_signname'];
  37. $templateParam = $smslog_param['template_param'];
  38. // 公共参数
  39. $params = [
  40. 'RegionId' => $this->regionId,
  41. 'AccessKeyId' => $this->accessKeyId,
  42. 'Format' => 'JSON',
  43. 'SignatureMethod' => 'HMAC-SHA1',
  44. 'SignatureVersion' => '1.0',
  45. 'SignatureNonce' => uniqid(),
  46. 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
  47. 'Action' => 'SendSms',
  48. 'Version' => '2017-05-25',
  49. 'PhoneNumbers' => $phone,
  50. 'SignName' => $this->signName,
  51. 'TemplateCode' => $templateCode,
  52. ];
  53. // 添加模板参数(如果有)
  54. if (!empty($templateParam)) {
  55. $params['TemplateParam'] = json_encode($templateParam);
  56. }
  57. // 生成签名
  58. $params['Signature'] = $this->generateSignature($params);
  59. // 构建请求URL
  60. $url = 'https://' . $this->endpoint . '/?' . http_build_query($params);
  61. // 发送HTTP请求
  62. return $this->sendRequest($url);
  63. }
  64. // 生成签名
  65. private function generateSignature($params)
  66. {
  67. // 参数排序
  68. ksort($params);
  69. // 构造查询字符串
  70. $queryString = '';
  71. foreach ($params as $key => $value) {
  72. $queryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
  73. }
  74. // 构造签名字符串
  75. $stringToSign = 'GET&%2F&' . $this->percentEncode(substr($queryString, 1));
  76. // 计算签名
  77. $signature = base64_encode(hash_hmac('sha1', $stringToSign, $this->accessKeySecret . '&', true));
  78. return $signature;
  79. }
  80. // URL编码
  81. private function percentEncode($str)
  82. {
  83. $res = urlencode($str);
  84. $res = str_replace(['+', '*'], ['%20', '%2A'], $res);
  85. $res = preg_replace('/%7E/', '~', $res);
  86. return $res;
  87. }
  88. // 发送HTTP请求
  89. private function sendRequest($url)
  90. {
  91. $ch = curl_init();
  92. curl_setopt($ch, CURLOPT_URL, $url);
  93. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  94. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  95. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  96. curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  97. $response = curl_exec($ch);
  98. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  99. if (curl_errno($ch)) {
  100. Log::error('短信发送失败:' . curl_error($ch));
  101. return ['code' => 1, 'msg' => '短信发送失败'];
  102. }
  103. curl_close($ch);
  104. if ($httpCode !== 200) {
  105. Log::error('短信发送失败,状态码:' . $httpCode);
  106. return ['code' => 1, 'msg' => '短信发送失败,状态码:' . $httpCode];
  107. }
  108. $res = json_decode($response, true);
  109. if ($res['Code'] == 'OK') {
  110. return ['code' => 0];
  111. } else {
  112. Log::error('短信发送失败:' . $response . "。原始参数:" . $url);
  113. return ['code' => 1, 'msg' => $res['Message']];
  114. }
  115. }
  116. }