Skip to content

Commit c3c5b3b

Browse files
authored
增加电信天翼云接口 (#366)
1 parent 204792c commit c3c5b3b

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
- [时代互联](https://www.now.cn/)
5959
- [火山引擎](https://console.volcengine.com/sms/)
6060
- [移动云MAS(黑名单模式)](https://mas.10086.cn)
61+
- [电信天翼云](https://www.ctyun.cn/document/10020426/10021544)
6162

6263
## 环境需求
6364

@@ -1013,6 +1014,30 @@ $easySms->send(18888888888, [
10131014
]);
10141015
```
10151016

1017+
### [电信天翼云](https://www.ctyun.cn/)
1018+
1019+
短信使用 `content`
1020+
1021+
```php
1022+
'ctyun' => [
1023+
'access_key' => '', //用户access
1024+
'secret_key' => '', //开发密钥secret
1025+
'sign' => '验证码测试', // 短信下发签名,
1026+
],
1027+
```
1028+
1029+
发送示例:
1030+
1031+
```php
1032+
$easySms->send(18888888888, [
1033+
'content' => $content,
1034+
'template' => 'SMS64124870510', // 模板ID
1035+
'data' => [
1036+
"code" => 123456,
1037+
],
1038+
]);
1039+
```
1040+
10161041
## :heart: 支持我
10171042

10181043
[![Sponsor me](https://github.com/overtrue/overtrue/blob/master/sponsor-me.svg?raw=true)](https://github.com/sponsors/overtrue)

src/Gateways/CtyunGateway.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace Overtrue\EasySms\Gateways;
4+
5+
use Overtrue\EasySms\Contracts\MessageInterface;
6+
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
7+
use Overtrue\EasySms\Exceptions\GatewayErrorException;
8+
use Overtrue\EasySms\Gateways\Gateway;
9+
use Overtrue\EasySms\Support\Config;
10+
use Overtrue\EasySms\Traits\HasHttpRequest;
11+
12+
/**
13+
* Class CtyunGateway
14+
*
15+
* @see https://www.ctyun.cn/document/10020426/10021544
16+
*/
17+
class CtyunGateway extends Gateway
18+
{
19+
use HasHttpRequest;
20+
21+
public const SUCCESS_CODE = 'OK';
22+
23+
public const ENDPOINT_HOST = 'https://sms-global.ctapi.ctyun.cn';
24+
25+
/**
26+
* Send a short message.
27+
*
28+
* @return array
29+
*
30+
* @throws GatewayErrorException
31+
*/
32+
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
33+
{
34+
$data = $message->getData($this);
35+
$endpoint = self::ENDPOINT_HOST . '/sms/api/v1';
36+
return $this->execute($endpoint, [
37+
'phoneNumber' => (string)$to,
38+
'templateCode' => $this->config->get('template_code'),
39+
'templateParam' => '{"code":"' . $data['code'] . '"}',
40+
'signName' => $this->config->get('sign_name'),
41+
'action' => 'SendSms'
42+
]);
43+
}
44+
45+
46+
/**
47+
* @return array
48+
*
49+
* @throws GatewayErrorException
50+
*/
51+
protected function execute(string $url, array $data)
52+
{
53+
$uuid = date('ymdHis', time()) . substr(microtime(), 2, 6) . sprintf('%03d', rand(0, 999));
54+
$time = date('Ymd', time()) . 'T' . date('His') . 'Z';
55+
$timeDate = substr($time, 0, 8);
56+
57+
$body = bin2hex(hash("sha256", json_encode($data), true));
58+
$query = '';
59+
$strSignature = "ctyun-eop-request-id:" . $uuid . "\n" . "eop-date:" . $time . "\n" . "\n" . $query . "\n" . $body;
60+
61+
$kTime = $this->sha256($time, $this->config->get('secret_key'));
62+
$kAk = $this->sha256($this->config->get('access_key'), $kTime);
63+
64+
$kDate = $this->sha256($timeDate, $kAk);
65+
66+
$signature = base64_encode($this->sha256(($strSignature), $kDate));
67+
$headers['Content-Type'] = 'application/json';
68+
$headers['ctyun-eop-request-id'] = $uuid;
69+
$headers['Eop-Authorization'] = $this->config->get('access_key') . ' Headers=ctyun-eop-request-id;' . 'eop-date Signature=' . $signature;
70+
$headers['eop-date'] = $time;
71+
72+
$result = $this->postJson($url, $data, $headers);
73+
if ($result['code'] !== self::SUCCESS_CODE) {
74+
throw new GatewayErrorException($result['message'], $result['code'], $result);
75+
}
76+
return $result;
77+
}
78+
79+
public function sha256($str, $pass): string
80+
{
81+
return (hash_hmac("sha256", ($str), ($pass), true));
82+
}
83+
84+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
4+
namespace Overtrue\EasySms\Tests\Gateways;
5+
6+
use Overtrue\EasySms\Exceptions\GatewayErrorException;
7+
use Overtrue\EasySms\Gateways\CtyunGateway;
8+
use Overtrue\EasySms\Message;
9+
use Overtrue\EasySms\PhoneNumber;
10+
use Overtrue\EasySms\Support\Config;
11+
use Overtrue\EasySms\Tests\TestCase;
12+
13+
class CtyunGatewayTest extends TestCase
14+
{
15+
public function testSend()
16+
{
17+
$config = [
18+
'secret_key' => 'mock-secrey-key',
19+
'access_key' => 'mock-access-key',
20+
];
21+
$gateway = \Mockery::mock(CtyunGateway::class.'[request]', [$config])->shouldAllowMockingProtectedMethods();
22+
23+
$gateway->shouldReceive('request')
24+
->andReturn([
25+
'code' => CtyunGateway::SUCCESS_CODE,
26+
], [
27+
'code' => 'FAIL',
28+
'message' => 'error',
29+
'requestId' => 'cv7ai1fagnl5nmbiuil0',
30+
])->twice();
31+
32+
$message = new Message([
33+
'content' => 'mock-content',
34+
'template' => 'mock-tpl-id', // 模板ID
35+
'data' => [
36+
"code" => 123456,
37+
],
38+
]);
39+
40+
$config = new Config($config);
41+
42+
$this->assertSame([
43+
'code' => CtyunGateway::SUCCESS_CODE,
44+
], $gateway->send(new PhoneNumber(18888888888), $message, $config));
45+
46+
$this->expectException(GatewayErrorException::class);
47+
$this->expectExceptionMessage('error');
48+
49+
$gateway->send(new PhoneNumber(18888888888), $message, $config);
50+
}
51+
}

0 commit comments

Comments
 (0)