本帖最后由 zhypy 于 2020-8-17 15:02 编辑
一、申请阿里云短信:文档地址
https://help.aliyun.com/document ... .558.bf264e6azfNgfe 获取
AccessKey ID、AccessKey Secret 、SignName、RegionId在申请对应功能短信模版。
[/p]二、配置config\sms.php配置文件地址:config\sms.php增加新的驱动模式为aliyun,根据云信template_id 完成aliyun 短信模版对应,增加和template_id同级配置参数:sign_name,access_key_id,access_key_secret,region_id;
详细的模版template_id请去申请对应完成配置
[/p]三、增加短信发送类目录结构:crmeb\services\sms\storage\Aliyun.php
[/p]1:自己写发送请求以及请求参数的组合<?php
namespace crmeb\services\sms\storage;
use think\facade\Config;
use crmeb\basic\BaseSms;
use crmeb\services\HttpService;
/**
* 阿里云短信服务
* Class Aliyun
* @package crmeb\services
*/
class Aliyun extends BaseSms
{
protected $header = ['x-sdk-client' => 'php/2.0.0'];
protected $AccessKeySecret = '';
protected $param = [
'AccessKeyId' => '',
'Action' => 'SendSms',
'Format' => 'JSON',
'PhoneNumbers' => '',
'RegionId' => 'cn-hangzhou',
'SignName' => '',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => '',
'SignatureVersion' => '1.0',
'Timestamp' => '',
'Version' => '2017-05-25',
];
protected $apiUrl = 'http://dysmsapi.aliyuncs.com/';
protected function initialize(array $config = [])
{
parent::initialize($config);
$conf = Config::get('sms.stores.aliyun', []);
$this->param['SignName'] = $config['sign_name'] ?? $conf['sign_name'] ?? '';
$this->param['AccessKeyId'] = $config['access_key_id'] ?? $conf['access_key_id'] ?? '';
$this->AccessKeySecret = $config['access_key_secret'] ?? $conf['access_key_secret'] ?? '';
$this->param['RegionId'] = $config['region_id'] ?? $conf['region_id'] ?? '';
$this->param['SignatureNonce'] = uniqid(mt_rand(0, 0xffff), true);
$this->param['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
}
public function send(string $phone, string $templateId, array $data = [])
{
if (empty($phone)) {
return $this->setError('Mobile number cannot be empty');
}
$param = $this->param;
if (!$param['SignName'] || !$param['AccessKeyId'] || $param['RegionId'] || !$this->AccessKeySecret) {
return $this->setError('请先配置短信秘钥');
}
$param['TemplateCode'] = $this->templates[$templateId];
$param['TemplateParam'] = $data;
$body = $this->rpc($param);
$result = HttpService::request($this->apiUrl, 'POST', $body, $this->header);
if ($result === false) {
return $this->setError(HttpService::getCurlError());
}
$json = json_decode($result);
if ($json === false) {
return $this->setError(json_last_error_msg());
}
if ($json['Code'] != 'OK') {
return $this->setError($json->Message);
}
return [
'data' => [
'id' => $json['RequestId'],
'content' => $param['TemplateParam'],
'template' => $param['TemplateCode'],
]
];
}
/**
* 组合参数
* @param array $params
* @param string $method
* @return string
*/
private function rpc(array $params = [], string $method = 'POST')
{
if (isset($params['TemplateParam']) && is_array($params['TemplateParam'])) {
$params['TemplateParam'] = json_encode($params['TemplateParam'], JSON_UNESCAPED_UNICODE);
}
$sortedQuery = $this->toString($params);
$signature = $method . '&%2F&' . $this->percentEncode($sortedQuery);
$signature = base64_encode(hash_hmac('sha1', $signature, $this->accessKeySecret . '&', true));
$body = 'Signature=' . $signature . '&' . $sortedQuery;
return $body;
}
/**
* @return bool|string
*/
private function toString($data)
{
$this->ksort($data);
$string = '';
foreach ($data as $key => $value) {
if ($value === '' || $value === null) {
continue;
}
$string .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
}
$string = substr($string, 1);
return $string;
}
/**
* @return $this
*/
private function ksort($data)
{
ksort($data);
}
/**
* @param string $string
*
* @return null|string|string[]
*/
private function percentEncode($string)
{
$result = urlencode($string);
$result = str_replace(['+', '*'], ['%20', '%2A'], $result);
$result = preg_replace('/%7E/', '~', $result);
return $result;
}
}
2:引入阿里云短信sdk :执行 composer require alibabacloud/client 引入sdk扩展包,(文件AliyunSms.php)<?php
namespace crmeb\services\sms\storage;
use think\facade\Config;
use crmeb\basic\BaseSms;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
/**
* 阿里云短信服务
* Class Aliyun
* @package crmeb\services
*/
class AliyunSms extends BaseSms
{
protected $SignName = '';
protected function initialize(array $config = [])
{
parent::initialize($config);
$conf = Config::get('sms.stores.aliyun', []);
$this->SignName = $config['sign_name'] ?? $conf['sign_name'] ?? '';
$AccessKeyId = $config['access_key_id'] ?? $conf['access_key_id'] ?? '';
$AccessKeySecret = $config['access_key_secret'] ?? $conf['access_key_secret'] ?? '';
$RegionId = $config['region_id'] ?? $conf['region_id'] ?? '';
if(!$AccessKeyId || !$AccessKeySecret || !$RegionId || !$this->SignName){
return $this->setError('请先配置短信秘钥');
}
AlibabaCloud::accessKeyClient($AccessKeyId, $AccessKeySecret)
->regionId($RegionId)
->asDefaultClient();
}
public function send(string $phone, string $templateId, array $data = [])
{
if (empty($phone)) {
return $this->setError('Mobile number cannot be empty');
}
try {
$TemplateCode = $this->getTemplateCode($templateId);
$TemplateParam = json_encode($data);
$result = AlibabaCloud::rpc()
->product('Dysmsapi')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->host('dysmsapi.aliyuncs.com')
->options([
'query' => [
'RegionId' => $this->SignName,
'TemplateCode' => $TemplateCode,
'TemplateParam' => $TemplateParam
],
])
->request();
$result = $result->toArray();
} catch (ClientException $e) {
return $this->setError($e->getErrorMessage());
} catch (ServerException $e) {
return $this->setError($e->getErrorMessage());
}
return [
'data' => [
'id' => $result['RequestId'],
'content' => $TemplateParam,
'template' => $TemplateCode,
]
];
}
}
四:使用方法:引入sms类 (use crmeb\services\sms\Sms)
[/p]$sms = new Sms('aliyun', [‘sign_name’=>’your sign_name’,’access_key_id’=>’your access_key_id’,’access_key_secret’,’region_id’=>’your_region_id’]);第二个参数也可以不传,要在第二步配置文件中配置。
注意:其中代码并非完整代码,需要自己配置测试之后在使用。
{{item.user_info.nickname ? item.user_info.nickname : item.user_name}}
作者 管理员 企业
{{itemf.name}}
{{itemc.user_info.nickname}}
{{itemc.user_name}}
回复 {{itemc.comment_user_info.nickname}}
{{itemf.name}}