From 64aab0a76cd6e6e2ba411137e7982a70b25253df Mon Sep 17 00:00:00 2001 From: Jiajian Chan Date: Thu, 18 Jan 2018 10:26:33 +0800 Subject: [PATCH] Add Qcloud (#78) --- README.md | 12 +++ composer.json | 2 +- src/Gateways/QcloudGateway.php | 105 +++++++++++++++++++++++++++ tests/Gateways/QcloudGatewayTest.php | 77 ++++++++++++++++++++ 4 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 src/Gateways/QcloudGateway.php create mode 100644 tests/Gateways/QcloudGatewayTest.php diff --git a/README.md b/README.md index ad6678f..080655d 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ - [253云通讯(创蓝)](https://www.253.com/) - [融云](http://www.rongcloud.cn) - [天毅无线](http://www.85hu.com/) +- [腾讯云 SMS](https://cloud.tencent.com/product/sms) ## 环境需求 @@ -417,6 +418,17 @@ $easySms->send(13188888888, $message); ], ``` +### [腾讯云 SMS](https://cloud.tencent.com/product/sms) + +短信内容使用 `content`。 + +```php + 'qcloud' => [ + 'sdk_app_id' => '', // SDK APP ID + 'app_key' => '', // APP KEY + ], +``` + ## License MIT diff --git a/composer.json b/composer.json index f96c847..e7d16c4 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "^5.7", + "phpunit/phpunit": "^6.5", "mockery/mockery": "1.0.x-dev" }, "autoload": { diff --git a/src/Gateways/QcloudGateway.php b/src/Gateways/QcloudGateway.php new file mode 100644 index 0000000..f9fbe48 --- /dev/null +++ b/src/Gateways/QcloudGateway.php @@ -0,0 +1,105 @@ + + * + * 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 AlidayuGateway. + * + * @see https://yun.tim.qq.com/v5/tlssmssvr/sendsms?sdkappid=xxxxx&random=xxxx + */ +class QcloudGateway extends Gateway +{ + use HasHttpRequest; + + const ENDPOINT_URL = 'https://yun.tim.qq.com/v5/'; + + const ENDPOINT_METHOD = 'tlssmssvr/sendsms'; + + const ENDPOINT_VERSION = 'v5'; + + const ENDPOINT_FORMAT = 'json'; + + /** + * Get gateway name. + * + * @return string + */ + public function getName() + { + return 'qcloud'; + } + + /** + * @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 = [ + 'tel' => [ + 'nationcode' => $message->getData($this)['notioncode'] ?? '86', + 'mobile' => $to, + ], + 'type' => $message->getData($this)['type'] ?? 0, + 'msg' => $message->getContent($this), + 'time' => time(), + 'extend' => '', + 'ext' => '', + ]; + + $random = str_random(10); + + $params['sig'] = $this->generateSign($params, $random); + + $url = self::ENDPOINT_URL . self::ENDPOINT_METHOD . '?sdkappid=' . $config->get('sdk_app_id') . '&random=' . $random; + + $result = $this->request('post', $url, [ + 'headers' => ['Accept' => 'application/json'], + 'json' => $params, + ]); + + if ($result['result'] != 0) { + throw new GatewayErrorException($result['errmsg'], $result['result'], $result); + } + + return $result; + } + + /** + * Generate Sign. + * + * @param array $params + * @param string $random + * + * @return string + */ + protected function generateSign($params, $random) + { + ksort($params); + + return hash("sha256", sprintf('appkey=%s&random=%s&time=%s&mobile=%s', + $this->config->get('app_key'), + $random, + $params['time'], + $params['tel']['mobile']), false); + } +} diff --git a/tests/Gateways/QcloudGatewayTest.php b/tests/Gateways/QcloudGatewayTest.php new file mode 100644 index 0000000..4e644bc --- /dev/null +++ b/tests/Gateways/QcloudGatewayTest.php @@ -0,0 +1,77 @@ + + * + * 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\QcloudGateway; +use Overtrue\EasySms\Message; +use Overtrue\EasySms\Support\Config; +use Overtrue\EasySms\Tests\TestCase; + +class QcloudGatewayTest extends TestCase +{ + public function testGetName() + { + $this->assertSame('tencent', (new QcloudGateway([]))->getName()); + } + + public function testSend() + { + $config = [ + 'sdk_app_id' => 'mock-sdk-app-id', + 'app_key' => 'mock-api-key', + ]; + $gateway = \Mockery::mock(QcloudGateway::class.'[request]', [$config])->shouldAllowMockingProtectedMethods(); + + $expected = [ + 'tel' => [ + 'nationcode' => '86', + 'mobile' => strval(18888888888), + ], + 'type' => 0, + 'msg' => 'This is a test message.', + 'timestamp' => time(), + 'extend' => '', + 'ext' => '', + ]; + + $gateway->shouldReceive('request') + ->andReturn([ + 'result' => 0, + 'errmsg' => 'OK', + 'ext' => '', + 'sid' => 3310228982, + 'fee' => 1 + ], [ + 'result' => 1001, + 'errmsg' => 'sig校验失败', + ])->twice(); + + $message = new Message(['data' => [ 'type' => 0 ], 'content' => 'This is a test message.']); + + $config = new Config($config); + + $this->assertSame([ + 'result' => 0, + 'errmsg' => 'OK', + 'ext' => '', + 'sid' => 3310228982, + 'fee' => 1 + ], $gateway->send(18888888888, $message, $config)); + + $this->expectException(GatewayErrorException::class); + $this->expectExceptionCode(1001); + $this->expectExceptionMessage('sig校验失败'); + + $gateway->send(18888888888, $message, $config); + } +}