Files

133 lines
4.7 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
class AliDySms
{
// 阿里云短信配置
private string $apiurl = 'https://dysmsapi.aliyuncs.com/?';
private array $config = [
// 'key' => '', // Access Key ID
// 'secret' => '', // Access Key Secret
// 'sign_name' => '' // 短信签名
];
public function __construct()
{
$config = [
'key' => SystemConfig::get('ali_sms_key'),
'secret' => SystemConfig::get('ali_sms_secret'),
'sign_name' => SystemConfig::get('ali_sms_sign_name'),
'test_code' => env('ALI_SMS_TEST_CODE'),
];
$this->config = $config;
}
/**
* 阿里云 短信验证
*
* @param $code // 验证码,变量,如263159
* @param string $template_code 短信模版code
*
* @throws \Exception
*/
public function captcha(string $code, string $tels, string $template_code = 'SMS_297490083'): void
{
$data = [
// 公共参数
'SignName' => $this->config['sign_name'],
'Format' => 'JSON',
'Version' => '2017-05-25',
'AccessKeyId' => $this->config['key'],
'SignatureVersion' => '1.0',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => uniqid(),
'Timestamp' => now('GMT')->toIso8601String(),
// 接口参数
'RegionId' => 'cn-hangzhou',
'Action' => 'SendSms',
'TemplateCode' => $template_code, // 短信模板CODE
'PhoneNumbers' => $tels, // 目标手机号,多个手机号可以逗号分隔
'TemplateParam' => '{"code":"'.$code.'"}',
];
// dd($data);
// 计算签名并把签名结果加入请求参数
$data['Signature'] = $this->computeSignature($data, $this->config['secret']);
// 发送请求 返回json转成数组
$result = Http::get($this->apiurl.http_build_query($data))->json();
if (array_key_exists('Code', $result) && $result['Code'] != 'OK') {
throw new \Exception($result['Code'].': '.$result['Message']);
}
}
/**
* 实现签名
* https://help.aliyun.com/document_detail/44363.html.
*/
public function computeSignature($parameters, $accessKeySecret): string
{
// 将参数Key按字典顺序排序
ksort($parameters);
// 生成规范化请求字符串
$canonicalizedQueryString = '';
foreach ($parameters as $key => $value) {
$canonicalizedQueryString .= '&'.$this->percentEncode($key).'='.$this->percentEncode($value);
}
// 生成用于计算签名的字符串 stringToSign
$stringToSign = 'GET&%2F&'.$this->percentencode(substr($canonicalizedQueryString, 1));
// 计算签名,注意accessKeySecret后面要加上字符'&'
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret.'&', true));
return $signature;
}
/**
* 编码规范处理.
*/
public function percentEncode(string $str): string
{
// 使用urlencode编码后,将"+","*","%7E"做替换即满足ECS API规定的编码规范
$res = urlencode($str);
$res = preg_replace('/\+/', '%20', $res);
$res = preg_replace('/\*/', '%2A', $res);
return preg_replace('/%7E/', '~', $res);
}
public function sendSms(string $tels, string $template_code, $param = null): void
{
$data = [
// 公共参数
'SignName' => $this->config['sign_name'],
'Format' => 'JSON',
'Version' => '2017-05-25',
'AccessKeyId' => $this->config['key'],
'SignatureVersion' => '1.0',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => uniqid(),
'Timestamp' => now('GMT')->toIso8601String(),
// 接口参数
'RegionId' => 'cn-hangzhou',
'Action' => 'SendSms',
'TemplateCode' => $template_code, // 短信模板CODE
'PhoneNumbers' => $tels, // 目标手机号,多个手机号可以逗号分隔
];
if (! empty($param)) {
$data['TemplateParam'] = $param;
}
// dd($data);
// 计算签名并把签名结果加入请求参数
$data['Signature'] = $this->computeSignature($data, $this->config['secret']);
// 发送请求 返回json转成数组
$result = Http::get($this->apiurl.http_build_query($data))->json();
if (array_key_exists('Code', $result) && $result['Code'] != 'OK') {
throw new \Exception($result['Code'].': '.$result['Message']);
}
}
}