Skip to content

Commit

Permalink
增加电信天翼云接口 (#366)
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyfd authored Mar 10, 2025
1 parent 204792c commit c3c5b3b
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
- [时代互联](https://www.now.cn/)
- [火山引擎](https://console.volcengine.com/sms/)
- [移动云MAS(黑名单模式)](https://mas.10086.cn)
- [电信天翼云](https://www.ctyun.cn/document/10020426/10021544)

## 环境需求

Expand Down Expand Up @@ -1013,6 +1014,30 @@ $easySms->send(18888888888, [
]);
```

### [电信天翼云](https://www.ctyun.cn/)

短信使用 `content`

```php
'ctyun' => [
'access_key' => '', //用户access
'secret_key' => '', //开发密钥secret
'sign' => '验证码测试', // 短信下发签名,
],
```

发送示例:

```php
$easySms->send(18888888888, [
'content' => $content,
'template' => 'SMS64124870510', // 模板ID
'data' => [
"code" => 123456,
],
]);
```

## :heart: 支持我

[![Sponsor me](https://github.com/overtrue/overtrue/blob/master/sponsor-me.svg?raw=true)](https://github.com/sponsors/overtrue)
Expand Down
84 changes: 84 additions & 0 deletions src/Gateways/CtyunGateway.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace Overtrue\EasySms\Gateways;

use Overtrue\EasySms\Contracts\MessageInterface;
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
use Overtrue\EasySms\Exceptions\GatewayErrorException;
use Overtrue\EasySms\Gateways\Gateway;
use Overtrue\EasySms\Support\Config;
use Overtrue\EasySms\Traits\HasHttpRequest;

/**
* Class CtyunGateway
*
* @see https://www.ctyun.cn/document/10020426/10021544
*/
class CtyunGateway extends Gateway
{
use HasHttpRequest;

public const SUCCESS_CODE = 'OK';

public const ENDPOINT_HOST = 'https://sms-global.ctapi.ctyun.cn';

/**
* Send a short message.
*
* @return array
*
* @throws GatewayErrorException
*/
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
{
$data = $message->getData($this);
$endpoint = self::ENDPOINT_HOST . '/sms/api/v1';
return $this->execute($endpoint, [
'phoneNumber' => (string)$to,
'templateCode' => $this->config->get('template_code'),
'templateParam' => '{"code":"' . $data['code'] . '"}',
'signName' => $this->config->get('sign_name'),
'action' => 'SendSms'
]);
}


/**
* @return array
*
* @throws GatewayErrorException
*/
protected function execute(string $url, array $data)
{
$uuid = date('ymdHis', time()) . substr(microtime(), 2, 6) . sprintf('%03d', rand(0, 999));
$time = date('Ymd', time()) . 'T' . date('His') . 'Z';
$timeDate = substr($time, 0, 8);

$body = bin2hex(hash("sha256", json_encode($data), true));
$query = '';
$strSignature = "ctyun-eop-request-id:" . $uuid . "\n" . "eop-date:" . $time . "\n" . "\n" . $query . "\n" . $body;

$kTime = $this->sha256($time, $this->config->get('secret_key'));
$kAk = $this->sha256($this->config->get('access_key'), $kTime);

$kDate = $this->sha256($timeDate, $kAk);

$signature = base64_encode($this->sha256(($strSignature), $kDate));
$headers['Content-Type'] = 'application/json';
$headers['ctyun-eop-request-id'] = $uuid;
$headers['Eop-Authorization'] = $this->config->get('access_key') . ' Headers=ctyun-eop-request-id;' . 'eop-date Signature=' . $signature;
$headers['eop-date'] = $time;

$result = $this->postJson($url, $data, $headers);
if ($result['code'] !== self::SUCCESS_CODE) {
throw new GatewayErrorException($result['message'], $result['code'], $result);
}
return $result;
}

public function sha256($str, $pass): string
{
return (hash_hmac("sha256", ($str), ($pass), true));
}

}
51 changes: 51 additions & 0 deletions tests/Gateways/CtyunGatewayTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php


namespace Overtrue\EasySms\Tests\Gateways;

use Overtrue\EasySms\Exceptions\GatewayErrorException;
use Overtrue\EasySms\Gateways\CtyunGateway;
use Overtrue\EasySms\Message;
use Overtrue\EasySms\PhoneNumber;
use Overtrue\EasySms\Support\Config;
use Overtrue\EasySms\Tests\TestCase;

class CtyunGatewayTest extends TestCase
{
public function testSend()
{
$config = [
'secret_key' => 'mock-secrey-key',
'access_key' => 'mock-access-key',
];
$gateway = \Mockery::mock(CtyunGateway::class.'[request]', [$config])->shouldAllowMockingProtectedMethods();

$gateway->shouldReceive('request')
->andReturn([
'code' => CtyunGateway::SUCCESS_CODE,
], [
'code' => 'FAIL',
'message' => 'error',
'requestId' => 'cv7ai1fagnl5nmbiuil0',
])->twice();

$message = new Message([
'content' => 'mock-content',
'template' => 'mock-tpl-id', // 模板ID
'data' => [
"code" => 123456,
],
]);

$config = new Config($config);

$this->assertSame([
'code' => CtyunGateway::SUCCESS_CODE,
], $gateway->send(new PhoneNumber(18888888888), $message, $config));

$this->expectException(GatewayErrorException::class);
$this->expectExceptionMessage('error');

$gateway->send(new PhoneNumber(18888888888), $message, $config);
}
}

0 comments on commit c3c5b3b

Please sign in to comment.