Ali.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. $this->accessKeyId = $config['sms_ali_accesskeyid'];
  30. $this->accessKeySecret = $config['sms_ali_accesskeysecret'];
  31. $this->signName = $config['sms_ali_signname'];
  32. $templateCode = $smslog_param['template_code'];
  33. $templateParam = $smslog_param['template_param'];
  34. // 公共参数
  35. $params = [
  36. 'RegionId' => $this->regionId,
  37. 'AccessKeyId' => $this->accessKeyId,
  38. 'Format' => 'JSON',
  39. 'SignatureMethod' => 'HMAC-SHA1',
  40. 'SignatureVersion' => '1.0',
  41. 'SignatureNonce' => uniqid(),
  42. 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
  43. 'Action' => 'SendSms',
  44. 'Version' => '2017-05-25',
  45. 'PhoneNumbers' => $phone,
  46. 'SignName' => $this->signName,
  47. 'TemplateCode' => $templateCode,
  48. ];
  49. // 添加模板参数(如果有)
  50. if (!empty($templateParam)) {
  51. $params['TemplateParam'] = json_encode($templateParam);
  52. }
  53. // 生成签名
  54. $params['Signature'] = $this->generateSignature($params);
  55. // 构建请求URL
  56. $url = 'https://' . $this->endpoint . '/?' . http_build_query($params);
  57. // 发送HTTP请求
  58. return $this->sendRequest($url);
  59. }
  60. // 生成签名
  61. private function generateSignature($params)
  62. {
  63. // 参数排序
  64. ksort($params);
  65. // 构造查询字符串
  66. $queryString = '';
  67. foreach ($params as $key => $value) {
  68. $queryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
  69. }
  70. // 构造签名字符串
  71. $stringToSign = 'GET&%2F&' . $this->percentEncode(substr($queryString, 1));
  72. // 计算签名
  73. $signature = base64_encode(hash_hmac('sha1', $stringToSign, $this->accessKeySecret . '&', true));
  74. return $signature;
  75. }
  76. // URL编码
  77. private function percentEncode($str)
  78. {
  79. $res = urlencode($str);
  80. $res = str_replace(['+', '*'], ['%20', '%2A'], $res);
  81. $res = preg_replace('/%7E/', '~', $res);
  82. return $res;
  83. }
  84. // 发送HTTP请求
  85. private function sendRequest($url)
  86. {
  87. $ch = curl_init();
  88. curl_setopt($ch, CURLOPT_URL, $url);
  89. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  90. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  91. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  92. curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  93. $response = curl_exec($ch);
  94. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  95. if (curl_errno($ch)) {
  96. Log::error('短信发送失败:' . curl_error($ch));
  97. return ['code' => 1, 'msg' => '短信发送失败'];
  98. }
  99. curl_close($ch);
  100. if ($httpCode !== 200) {
  101. Log::error('短信发送失败,状态码:' . $httpCode);
  102. return ['code' => 1, 'msg' => '短信发送失败,状态码:' . $httpCode];
  103. }
  104. $res = json_decode($response, true);
  105. if ($res['Code'] == 'OK') {
  106. return ['code' => 0];
  107. } else {
  108. Log::error('短信发送失败:' . $response . "。原始参数:" . $url);
  109. return ['code' => 1, 'msg' => $res['Message']];
  110. }
  111. }
  112. }