Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
easy-sms
提交
65762d65
E
easy-sms
项目概览
OpenDocCN
/
easy-sms
通知
3
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
easy-sms
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
65762d65
编写于
6月 01, 2017
作者:
I
iwzh
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
增加百度云短信接口
更新readme文档 Signed-off-by:
N
iwzh
<
wzhec@foxmail.com
>
上级
896eec44
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
257 addition
and
0 deletion
+257
-0
README.md
README.md
+10
-0
src/Gateways/BaiduGateway.php
src/Gateways/BaiduGateway.php
+187
-0
tests/Gateways/BaiduGatewayTest.php
tests/Gateways/BaiduGatewayTest.php
+60
-0
未找到文件。
README.md
浏览文件 @
65762d65
...
...
@@ -32,6 +32,7 @@
-
[
互亿无线
](
http://www.ihuyi.com
)
-
[
聚合数据
](
https://www.juhe.cn
)
-
[
SendCloud
](
http://www.sendcloud.net/
)
-
[
百度云
](
https://cloud.baidu.com/
)
## 环境需求
...
...
@@ -258,6 +259,15 @@ $easySms->send(13188888888, $message);
'sms_key'
=>
''
,
],
```
### [百度云](https://cloud.baidu.com/)
```
php
'baidu'
=>
[
'ak'
=>
''
,
'sk'
=>
''
,
'invoke_id'
=>
''
,
],
```
## License
...
...
src/Gateways/BaiduGateway.php
0 → 100644
浏览文件 @
65762d65
<?php
/*
* This file is part of the overtrue/easy-sms.
* (c) iwzh <wzhec@foxmail.com>
* 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 BaiduGateway
*
* @see https://cloud.baidu.com/doc/SMS/API.html
*/
class
BaiduGateway
extends
Gateway
{
use
HasHttpRequest
;
const
ENDPOINT_HOST
=
'sms.bj.baidubce.com'
;
const
ENDPOINT_URI
=
'/bce/v2/message'
;
const
BCE_AUTH_VERSION
=
'bce-auth-v1'
;
const
DEFAULT_EXPIRATION_IN_SECONDS
=
1800
;
//签名有效期默认1800秒
const
SUCCESS_CODE
=
1000
;
/**
* Send message.
*
* @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
=
[
'invoke_id'
=>
$config
->
get
(
'invoke_id'
),
'phoneNumber'
=>
$to
,
'templateCode'
=>
$message
->
getTemplate
(),
'contentVar'
=>
$message
->
getData
()
];
//默认值当前时间
date_default_timezone_set
(
"PRC"
);
$timestamp
=
new
\
DateTime
();
$timestamp
->
setTimezone
(
new
\
DateTimeZone
(
"UTC"
));
$datetime
=
$timestamp
->
format
(
"Y-m-d\TH:i:s\Z"
);
//生成json格式
$headers
=
[
'Host'
=>
self
::
ENDPOINT_HOST
,
"Content-Type"
=>
'application/json'
,
'x-bce-date'
=>
$datetime
,
'x-bce-content-sha256'
=>
hash
(
'sha256'
,
json_encode
(
$params
))];
$headersToSign
=
array
(
'host'
,
'x-bce-content-sha256'
,);
//需要签名的header头
$headers
[
'Authorization'
]
=
$this
->
generateSign
(
$headersToSign
,
$datetime
,
$headers
,
$config
);
$result
=
$this
->
request
(
'post'
,
self
::
buildEndpoint
(),
[
'headers'
=>
$headers
,
'json'
=>
$params
]);
if
(
$result
[
'code'
]
!=
self
::
SUCCESS_CODE
){
throw
new
GatewayErrorException
(
$result
[
'message'
],
$result
[
'code'
],
$result
);
}
return
$result
;
}
/**
* Build endpoint url.
*
* @return string
*/
public
static
function
buildEndpoint
()
{
return
'http://'
.
self
::
ENDPOINT_HOST
.
self
::
ENDPOINT_URI
;
}
/**
* generate Authorization.
*
* @param $headersToSign
* @param $datetime
* @param $headers
* @param Config $config
* @return string
*/
public
function
generateSign
(
$headersToSign
,
$datetime
,
$headers
,
Config
$config
)
{
//生成authString
$authString
=
self
::
BCE_AUTH_VERSION
.
'/'
.
$config
->
get
(
'ak'
)
.
'/'
.
$datetime
.
'/'
.
self
::
DEFAULT_EXPIRATION_IN_SECONDS
;
//使用sk和authString生成signKey
$signingKey
=
hash_hmac
(
'sha256'
,
$authString
,
$config
->
get
(
'sk'
));
//生成标准化URI
$canonicalURI
=
str_replace
(
'%2F'
,
'/'
,
rawurlencode
(
self
::
ENDPOINT_URI
));
// 根据RFC 3986,除了:1.大小写英文字符2.阿拉伯数字3.点'.'、波浪线'~'、减号'-'以及下划线'_' 以外都要编码
//生成标准化QueryString
$canonicalQueryString
=
''
;
//此api不需要此项。返回空字符串
$signHeaders
=
self
::
getHeadersToSign
(
$headers
,
$headersToSign
);
//获得需要签名的数据
//整理headersToSign,以';'号连接
$signedHeaders
=
empty
(
$signHeaders
)
?
''
:
strtolower
(
trim
(
implode
(
";"
,
array_keys
(
$signHeaders
))));
//生成标准化header
$canonicalHeader
=
self
::
getCanonicalHeaders
(
$signHeaders
);
//组成标准请求串
$canonicalRequest
=
"POST
\n
$canonicalURI
\n
"
.
"
$canonicalQueryString
\n
$canonicalHeader
"
;
//使用signKey和标准请求串完成签名
$signature
=
hash_hmac
(
'sha256'
,
$canonicalRequest
,
$signingKey
);
//组成最终签名串
$authorizationHeader
=
"
$authString
/
$signedHeaders
/
$signature
"
;
return
$authorizationHeader
;
}
/**
* 生成标准化http请求头串
*
* @param $headers
* @return string
*/
public
static
function
getCanonicalHeaders
(
$headers
)
{
//如果没有headers,则返回空串
if
(
count
(
$headers
)
==
0
)
{
return
''
;
}
$headerStrings
=
array
();
foreach
(
$headers
as
$k
=>
$v
)
{
//跳过key为null的
if
(
$k
===
null
)
{
continue
;
}
//如果value为null,则赋值为空串
if
(
$v
===
null
)
{
$v
=
''
;
}
//trim后再encode,之后使用':'号连接起来
$headerStrings
[]
=
rawurlencode
((
strtolower
(
trim
(
$k
))))
.
':'
.
rawurlencode
((
trim
(
$v
)));
}
//字典序排序
sort
(
$headerStrings
);
//用'\n'把它们连接起来
return
implode
(
"
\n
"
,
$headerStrings
);
}
/**
* 根据headsToSign过滤应该参与签名的header
*
* @param $headers
* @param $headersToSign
* @return array
*/
public
static
function
getHeadersToSign
(
$headers
,
$headersToSign
)
{
//value被trim后为空串的header不参与签名
$filter_empty
=
function
(
$v
)
{
return
trim
((
string
)
$v
)
!==
''
;
};
$headers
=
array_filter
(
$headers
,
$filter_empty
);
//处理headers的key:去掉前后的空白并转化成小写
$trim_and_lower
=
function
(
$str
)
{
return
strtolower
(
trim
(
$str
));
};
$temp
=
array
();
$process_keys
=
function
(
$k
,
$v
)
use
(
&
$temp
,
$trim_and_lower
)
{
$temp
[
$trim_and_lower
(
$k
)]
=
$v
;
};
array_map
(
$process_keys
,
array_keys
(
$headers
),
$headers
);
$headers
=
$temp
;
//取出headers的key以备用
$header_keys
=
array_keys
(
$headers
);
//预处理headersToSign:去掉前后的空白并转化成小写
$headersToSign
=
array_map
(
$trim_and_lower
,
$headersToSign
);
//只选取在headersToSign里面的header
$filtered_keys
=
array_intersect
(
$header_keys
,
$headersToSign
);
//返回需要参与签名的header
return
array_intersect_key
(
$headers
,
array_flip
(
$filtered_keys
));
}
}
tests/Gateways/BaiduGatewayTest.php
0 → 100644
浏览文件 @
65762d65
<?php
/*
* This file is part of the overtrue/easy-sms.
* (c) iwzh <wzhec@foxmail.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\BaiduGateway
;
use
Overtrue\EasySms\Message
;
use
Overtrue\EasySms\Support\Config
;
use
Overtrue\EasySms\Tests\TestCase
;
class
BaiduGatewayTest
extends
TestCase
{
public
function
testSend
()
{
$config
=
[
'ak'
=>
'mock-ak'
,
'sk'
=>
'mock-sk'
,
'invoke_id'
=>
'mock-invoke-id'
];
$gateway
=
\
Mockery
::
mock
(
BaiduGateway
::
class
.
'[request]'
,
[
$config
])
->
shouldAllowMockingProtectedMethods
();
$expected
=
[
'phoneNumber'
=>
18888888888
,
'templateCode'
=>
'mock-tpl-id'
,
'invoke_id'
=>
$config
[
'invoke_id'
],
'contentVar'
=>
[
'mock-data-1'
,
'mock-data-2'
],
];
$gateway
->
shouldReceive
(
'request'
)
->
with
(
'post'
,
\
Mockery
::
on
(
function
(
$api
)
{
return
0
==
strpos
(
$api
,
BaiduGateway
::
buildEndpoint
());
}),
\
Mockery
::
on
(
function
(
$params
)
use
(
$expected
)
{
ksort
(
$params
[
'json'
]);
ksort
(
$expected
);
return
$params
[
'json'
]
==
$expected
;
}))
->
andReturn
(
[
'code'
=>
BaiduGateway
::
SUCCESS_CODE
,
'message'
=>
'success'
],
[
"code"
=>
100
,
'message'
=>
'mock-msg'
])
->
twice
();
$message
=
new
Message
([
'template'
=>
'mock-tpl-id'
,
'data'
=>
[
'mock-data-1'
,
'mock-data-2'
],
]);
$config
=
new
Config
(
$config
);
$this
->
assertSame
([
'code'
=>
BaiduGateway
::
SUCCESS_CODE
,
'message'
=>
'success'
],
$gateway
->
send
(
18888888888
,
$message
,
$config
));
$this
->
expectException
(
GatewayErrorException
::
class
);
$this
->
expectExceptionCode
(
100
);
$this
->
expectExceptionMessage
(
'mock-msg'
);
$gateway
->
send
(
18888888888
,
$message
,
$config
);
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录