提交 d4611bc6 编写于 作者: M Mr. Tree 提交者: 安正超

增加阿里云短信API发送通道 (#27)

* 代码格式化

* 增加 AliyunGateway

* 增加阿里云短信通道

* 优化代码

* 增加获取时间戳方法

* 优化引号
上级 fb32199f
......@@ -33,6 +33,7 @@
## 平台支持
- [阿里云](https://www.aliyun.com/)
- [云片](https://www.yunpian.com)
- [Submail](https://www.mysubmail.com)
- [螺丝帽](https://luosimao.com/)
......@@ -70,7 +71,7 @@ $config = [
// 默认可用的发送网关
'gateways' => [
'yunpian', 'alidayu',
'yunpian', 'aliyun', 'alidayu',
],
],
// 可用的网关配置
......@@ -81,6 +82,11 @@ $config = [
'yunpian' => [
'api_key' => '824f0ff2f71cab52936axxxxxxxxxx',
],
'aliyun' => [
'access_key_id' => '',
'access_key_secret' => '',
'sign_name' => '',
],
'alidayu' => [
//...
],
......@@ -89,14 +95,13 @@ $config = [
$easySms = new EasySms($config);
$easySms->send(13188888888,
[
'content' => '您的验证码为: 6379',
'template' => 'SMS_001',
'data' => [
'code' => 6379
],
]);
$easySms->send(13188888888, [
'content' => '您的验证码为: 6379',
'template' => 'SMS_001',
'data' => [
'code' => 6379
],
]);
```
## 短信内容
......@@ -167,14 +172,13 @@ $easySms->extend('mygateway', function($gatewayConfig){
return new MyGateway($gatewayConfig);
});
$easySms->send(13188888888,
[
'content' => '您的验证码为: 6379',
'template' => 'SMS_001',
'data' => [
'code' => 6379
],
]);
$easySms->send(13188888888, [
'content' => '您的验证码为: 6379',
'template' => 'SMS_001',
'data' => [
'code' => 6379
],
]);
```
## 定义短信
......@@ -234,7 +238,15 @@ $easySms->send(13188888888, $message);
## 各平台配置说明
### [阿里云](https://www.aliyun.com/)
```php
'aliyun' => [
'access_key_id' => '',
'access_key_secret' => '',
'sign_name' => '',
],
```
### [阿里大于](https://www.alidayu.com/)
......
<?php
/*
* This file is part of the overtrue/easy-sms.
* (c) overtrue <i@overtrue.me>
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Overtrue\EasySms\Gateways;
use Overtrue\EasySms\Contracts\MessageInterface;
use Overtrue\EasySms\Exceptions\GatewayErrorException;
use Overtrue\EasySms\Support\Config;
use Overtrue\EasySms\Traits\HasHttpRequest;
/**
* Class AliyunGateway.
* @author carson <docxcn@gmail.com>
*
* @see https://help.aliyun.com/document_detail/55451.html
*/
class AliyunGateway extends Gateway
{
use HasHttpRequest;
const ENDPOINT_URL = 'http://dysmsapi.aliyuncs.com';
const ENDPOINT_METHOD = 'SendSms';
const ENDPOINT_VERSION = '2017-05-25';
const ENDPOINT_FORMAT = 'JSON';
const ENDPOINT_REGION_ID = 'cn-hangzhou';
const ENDPOINT_SIGNATURE_METHOD = 'HMAC-SHA1';
const ENDPOINT_SIGNATURE_VERSION = '1.0';
public function __construct(array $config)
{
parent::__construct($config);
date_default_timezone_set('GMT');
}
/**
* @param array|int|string $to
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param \Overtrue\EasySms\Support\Config $config
*
* @return array
*
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException;
*/
public function send($to, MessageInterface $message, Config $config)
{
$params = [
'RegionId' => self::ENDPOINT_REGION_ID,
'AccessKeyId' => $config->get('access_key_id'),
'Format' => self::ENDPOINT_FORMAT,
'SignatureMethod' => self::ENDPOINT_SIGNATURE_METHOD,
'SignatureVersion' => self::ENDPOINT_SIGNATURE_VERSION,
'SignatureNonce' => uniqid(),
'Timestamp' => $this->getTimestamp(),
'Action' => self::ENDPOINT_METHOD,
'Version' => self::ENDPOINT_VERSION,
'PhoneNumbers' => strval($to),
'SignName' => $config->get('sign_name'),
'TemplateCode' => $message->getTemplate(),
'TemplateParam' => json_encode($message->getData()),
];
$params['Signature'] = $this->generateSign($params);
$result = $this->get(self::ENDPOINT_URL, $params);
if ($result['Code'] != 'OK') {
throw new GatewayErrorException($result['Message'], $result['Code'], $result);
}
return $result;
}
/**
* Generate Sign.
*
* @param array $params
*
* @return string
*/
protected function generateSign($params)
{
ksort($params);
$accessKeySecret = $this->config->get('access_key_secret');
$stringToSign = 'GET' . '&%2F&' . urlencode(http_build_query($params, null, '&', PHP_QUERY_RFC3986));
return base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
}
/**
* @return false|string
*/
protected function getTimestamp()
{
$timezone = date_default_timezone_get();
date_default_timezone_set('GMT');
$timestamp = date('Y-m-d\TH:i:s\Z');
date_default_timezone_set($timezone);
return $timestamp;
}
}
......@@ -25,7 +25,7 @@ class AlidayuGatewayTest extends TestCase
'sign_name' => 'mock-api-sign-name',
'template_code' => 'mock-template-code',
];
$gateway = \Mockery::mock(AlidayuGateway::class.'[post]', [$config])->shouldAllowMockingProtectedMethods();
$gateway = \Mockery::mock(AlidayuGateway::class . '[post]', [$config])->shouldAllowMockingProtectedMethods();
$expected = [
'method' => 'alibaba.aliqin.fc.sms.num.send',
......@@ -55,14 +55,15 @@ class AlidayuGatewayTest extends TestCase
->andReturn([
'success_response' => 'mock-result',
], [
'error_response' => ['sub_msg' => 'mock-msg', 'code' => 100],
])
'error_response' => ['sub_msg' => 'mock-msg', 'code' => 100],
])
->twice();
$message = new Message([
'template' => 'mock-template-code',
'data' => ['code' => '123456', 'time' => '15'],
]);
$config = new Config($config);
$this->assertSame([
......
<?php
/*
* This file is part of the overtrue/easy-sms.
* (c) carson <docxcn@gmail.com>
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Overtrue\EasySms\Tests\Gateways;
use Overtrue\EasySms\Exceptions\GatewayErrorException;
use Overtrue\EasySms\Gateways\AliyunGateway;
use Overtrue\EasySms\Message;
use Overtrue\EasySms\Support\Config;
use Overtrue\EasySms\Tests\TestCase;
class AliyunGatewayTest extends TestCase
{
public function testSend()
{
$config = [
'access_key_id' => 'mock-api-key',
'access_key_secret' => 'mock-api-secret',
'sign_name' => 'mock-api-sign-name',
'template_code' => 'mock-template-code',
];
$gateway = \Mockery::mock(AliyunGateway::class . '[get]', [$config])->shouldAllowMockingProtectedMethods();
$expected = [
'RegionId' => 'cn-hangzhou',
'AccessKeyId' => 'mock-api-key',
'Format' => 'JSON',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureVersion' => '1.0',
// 'SignatureNonce' => uniqid(),
// 'Timestamp' => date('Y-m-d\TH:i:s\Z'),
'Action' => 'SendSms',
'Version' => '2017-05-25',
'PhoneNumbers' => strval(18888888888),
'SignName' => 'mock-api-sign-name',
'TemplateCode' => 'mock-template-code',
'TemplateParam' => json_encode(['code' => '123456']),
];
$gateway->shouldReceive('get')
->with(AliyunGateway::ENDPOINT_URL, \Mockery::on(function ($params) use ($expected) {
if (empty($params['Signature'])) {
return false;
}
unset($params['SignatureNonce'], $params['Timestamp'], $params['Signature']);
ksort($params);
ksort($expected);
return $params == $expected;
}))
->andReturn([
'Code' => 'OK',
'Message' => 'mock-result',
], [
'Code' => 1234,
'Message' => 'mock-err-msg',
])
->twice();
$message = new Message([
'template' => 'mock-template-code',
'data' => ['code' => '123456'],
]);
$config = new Config($config);
$this->assertSame([
'Code' => 'OK',
'Message' => 'mock-result',
], $gateway->send(18888888888, $message, $config));
$this->expectException(GatewayErrorException::class);
$this->expectExceptionCode(1234);
$this->expectExceptionMessage('mock-err-msg');
$gateway->send(18888888888, $message, $config);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册