Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
easy-sms
提交
896eec44
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 搜索 >>
提交
896eec44
编写于
5月 31, 2017
作者:
增
增辉
提交者:
GitHub
5月 31, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1 from overtrue/master
拉取超哥的更新
上级
b7ed8d05
22753d1c
变更
13
显示空白变更内容
内联
并排
Showing
13 changed file
with
386 addition
and
44 deletion
+386
-44
.travis.yml
.travis.yml
+1
-0
README.md
README.md
+163
-19
src/Gateways/AlidayuGateway.php
src/Gateways/AlidayuGateway.php
+2
-2
src/Gateways/ErrorlogGateway.php
src/Gateways/ErrorlogGateway.php
+5
-2
src/Gateways/HuyiGateway.php
src/Gateways/HuyiGateway.php
+1
-1
src/Gateways/JuheGateway.php
src/Gateways/JuheGateway.php
+5
-0
src/Gateways/LuosimaoGateway.php
src/Gateways/LuosimaoGateway.php
+1
-1
src/Gateways/SendcloudGateway.php
src/Gateways/SendcloudGateway.php
+88
-0
src/Gateways/SubmailGateway.php
src/Gateways/SubmailGateway.php
+1
-1
src/Gateways/YuntongxunGateway.php
src/Gateways/YuntongxunGateway.php
+9
-8
src/Messenger.php
src/Messenger.php
+3
-2
tests/Gateways/AlidayuGatewayTest.php
tests/Gateways/AlidayuGatewayTest.php
+21
-8
tests/Gateways/SendcloudGatewayTest.php
tests/Gateways/SendcloudGatewayTest.php
+86
-0
未找到文件。
.travis.yml
浏览文件 @
896eec44
...
...
@@ -6,6 +6,7 @@ php:
-
7.1
-
hhvm
dist
:
trusty
sudo
:
false
install
:
travis_retry composer install --no-interaction --prefer-source
...
...
README.md
浏览文件 @
896eec44
...
...
@@ -12,29 +12,58 @@
<a
href=
"https://packagist.org/packages/overtrue/easy-sms"
><img
src=
"https://poser.pugx.org/overtrue/easy-sms/license"
alt=
"License"
></a>
</p>
## 特点
# 环境需求
1.
支持目前市面多家服务商
1.
一套写法兼容所有平台
1.
简单配置即可灵活增减服务商
1.
内置多种服务商轮询策略、支持自定义轮询策略
1.
统一的返回值格式,便于日志与监控
1.
自动轮询选择可用的服务商
1.
更多等你去发现与改进...
## 平台支持
-
[
云片
](
https://www.yunpian.com
)
-
[
Submail
](
https://www.mysubmail.com
)
-
[
螺丝帽
](
https://luosimao.com/
)
-
[
阿里大于
](
https://www.alidayu.com/
)
-
[
容联云通讯
](
http://www.yuntongxun.com
)
-
[
互亿无线
](
http://www.ihuyi.com
)
-
[
聚合数据
](
https://www.juhe.cn
)
-
[
SendCloud
](
http://www.sendcloud.net/
)
## 环境需求
-
PHP >= 5.6
# 安装
#
#
安装
```
shell
$
composer require
"overtrue/easy-sms"
```
# 使用
#
#
使用
```
php
use
Overtrue\EasySms\EasySms
;
$config
=
[
// HTTP 请求的超时时间(秒)
'timeout'
=>
5.0
,
// 默认发送配置
'default'
=>
[
// 网关调用策略,默认:顺序调用
'strategy'
=>
\
Overtrue\EasySms\Strategies\OrderStrategy
::
class
// 默认可用的发送网关
'gateways'
=>
[
'yunpian'
,
'alidayu'
,
],
],
// 可用的网关配置
'gateways'
=>
[
'errorlog'
=>
[
'file'
=>
'/tmp/easy-sms.log'
,
...
...
@@ -49,10 +78,58 @@ $config = [
];
$easySms
=
new
EasySms
(
$config
);
$easySms
->
send
(
13188888888
,
'hello world!'
);
$easySms
->
send
(
13188888888
,
'content'
=>
'您的验证码为: 6379'
,
'template'
=>
'SMS_001'
,
'data'
=>
[
'code'
=>
6379
],
]);
```
## 短信内容
由于使用多网关发送,所以一条短信要支持多平台发送,每家的发送方式不一样,但是我们抽象定义了以下公用属性:
-
`content`
文字内容,使用在像云片类似的以文字内容发送的平台
-
`template`
模板 ID,使用在以模板ID来发送短信的平台
-
`data`
模板变量,使用在以模板ID来发送短信的平台
所以,在使用过程中你可以根据所要使用的平台定义发送的内容。
## 发送网关
默认使用
`default`
中的设置来发送,如果某一条短信你想要覆盖默认的设置。在
`send`
方法中使用第三个参数即可:
```
php
$easySms
->
send
(
13188888888
,
[
'content'
=>
'您的验证码为: 6379'
,
'template'
=>
'SMS_001'
,
'data'
=>
[
'code'
=>
6379
],
],
[
'yunpian'
,
'juhe'
]);
// 这里的网关配置将会覆盖全局默认值
```
# 定义短信
## 返回值
由于使用多网关发送,所以返回值为一个数组,结构如下:
```
php
[
'yunpian'
=>
[
'status'
=>
'success'
,
'result'
=>
[
...
]
// 平台返回值
],
'juhe'
=>
[
'status'
=>
'erred'
,
'exception'
=>
\
Overtrue\EasySms\Exceptions\GatewayErrorException
对象
],
//...
]
```
## 定义短信
你可以根本发送场景的不同,定义不同的短信类,从而实现一处定义多处调用,你可以继承
`Overtrue\EasySms\Message`
来定义短信模型:
...
...
@@ -60,11 +137,14 @@ $easySms->send(13188888888, 'hello world!');
<?php
use
Overtrue\EasySms\Message
;
use
Overtrue\EasySms\Contracts\GatewayInterface
;
use
Overtrue\EasySms\Strategies\OrderStrategy
;
class
OrderPaidMessage
extends
Messeage
{
protected
$order
;
protected
$gateways
=
[
'alidayu'
,
'yunpian'
];
// 定义本短信的适用平台,覆盖全局配置中的 `enabled_gateways`
protected
$strategy
=
OrderStrategy
::
class
;
// 定义本短信的网关使用策略,覆盖全局配置中的 `default.strategy`
protected
$gateways
=
[
'alidayu'
,
'yunpian'
,
'juhe'
];
// 定义本短信的适用平台,覆盖全局配置中的 `default.gateways`
public
function
__construct
(
$order
)
{
...
...
@@ -72,19 +152,19 @@ class OrderPaidMessage extends Messeage
}
// 定义直接使用内容发送平台的内容
public
function
getContent
()
public
function
getContent
(
GatewayInterface
$gateway
=
null
)
{
return
sprintf
(
'您的订单:%s, 已经完成付款'
,
$this
->
order
->
no
);
}
// 定义使用模板发送方式平台所需要的模板 ID
public
function
getTemplate
()
public
function
getTemplate
(
GatewayInterface
$gateway
=
null
)
{
return
'SMS_003'
;
}
// 模板参数
public
function
getData
()
public
function
getData
(
GatewayInterface
$gateway
=
null
)
{
return
[
'order_no'
=>
$this
->
order
->
no
...
...
@@ -104,17 +184,81 @@ $message = new OrderPaidMessage($order);
$easySms
->
send
(
13188888888
,
$message
);
```
# 平台支持
## 各平台配置说明
### [阿里大于](https://www.alidayu.com/)
```
php
'alidayu'
=>
[
'app_key'
=>
''
,
'sign_name'
=>
''
,
],
```
### [云片](https://www.yunpian.com)
-
[
云片
](
https://github.com/overtrue/easy-sms/wiki/GateWays---Yunpian
)
-
[
Submail
](
https://github.com/overtrue/easy-sms/wiki/GateWays---Submail
)
-
[
螺丝帽
](
https://github.com/overtrue/easy-sms/wiki/GateWays---Luosimao
)
-
[
阿里大鱼
](
https://github.com/overtrue/easy-sms/wiki/GateWays---AliDayu
)
-
[
容联云通讯
](
https://github.com/overtrue/easy-sms/wiki/GateWays---Yuntongxun
)
-
[
互亿无线
](
https://github.com/overtrue/easy-sms/wiki/GateWays---Huyi
)
-
[
聚合数据
](
https://github.com/overtrue/easy-sms/wiki/GateWays---Juhe
)
-
SendCloud
```
php
'yunpian'
=>
[
'api_key'
=>
''
,
],
```
### [Submail](https://www.mysubmail.com)
```
php
'submail'
=>
[
'app_id'
=>
''
,
'app_key'
=>
''
,
'project'
=>
''
,
],
```
### [螺丝帽](https://luosimao.com/)
```
php
'luosimao'
=>
[
'api_key'
=>
''
,
],
```
### [容联云通讯](http://www.yuntongxun.com)
```
php
'yuntongxun'
=>
[
'app_id'
=>
''
,
'account_sid'
=>
''
,
'account_token'
=>
''
,
'is_sub_account'
=>
false
,
],
```
### [互亿无线](http://www.ihuyi.com)
```
php
'huyi'
=>
[
'api_id'
=>
''
,
],
```
### [聚合数据](https://www.juhe.cn)
```
php
'juhe'
=>
[
'app_key'
=>
''
,
],
```
### [SendCloud](http://www.sendcloud.net/)
```
php
'sendcloud'
=>
[
'sms_user'
=>
''
,
'sms_key'
=>
''
,
],
```
# License
#
#
License
MIT
src/Gateways/AlidayuGateway.php
浏览文件 @
896eec44
...
...
@@ -33,7 +33,7 @@ class AlidayuGateway extends Gateway
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param \Overtrue\EasySms\Support\Config $config
*
* @return
mixed
* @return
array
*
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException;
*/
...
...
@@ -48,7 +48,7 @@ class AlidayuGateway extends Gateway
'sms_type'
=>
'normal'
,
'sms_free_sign_name'
=>
$config
->
get
(
'sign_name'
),
'app_key'
=>
$config
->
get
(
'app_key'
),
'sms_template_code'
=>
$
config
->
get
(
'template_code'
),
'sms_template_code'
=>
$
message
->
getTemplate
(
),
'rec_num'
=>
strval
(
$to
),
'sms_param'
=>
json_encode
(
$message
->
getData
()),
];
...
...
src/Gateways/ErrorlogGateway.php
浏览文件 @
896eec44
...
...
@@ -22,7 +22,7 @@ class ErrorlogGateway extends Gateway
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param \Overtrue\EasySms\Support\Config $config
*
* @return
bool
* @return
array
*/
public
function
send
(
$to
,
MessageInterface
$message
,
Config
$config
)
{
...
...
@@ -39,6 +39,9 @@ class ErrorlogGateway extends Gateway
json_encode
(
$message
->
getData
())
);
return
error_log
(
$message
,
3
,
$this
->
config
->
get
(
'file'
,
ini_get
(
'error_log'
)));
$file
=
$this
->
config
->
get
(
'file'
,
ini_get
(
'error_log'
));
$status
=
error_log
(
$message
,
3
,
$file
);
return
compact
(
'status'
,
'file'
);
}
}
src/Gateways/HuyiGateway.php
浏览文件 @
896eec44
...
...
@@ -32,7 +32,7 @@ class HuyiGateway extends Gateway
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param \Overtrue\EasySms\Support\Config $config
*
* @return
mixed
* @return
array
*
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException;
*/
...
...
src/Gateways/JuheGateway.php
浏览文件 @
896eec44
...
...
@@ -14,6 +14,11 @@ use Overtrue\EasySms\Exceptions\GatewayErrorException;
use
Overtrue\EasySms\Support\Config
;
use
Overtrue\EasySms\Traits\HasHttpRequest
;
/**
* Class JuheGateway.
*
* @see https://www.juhe.cn/docs/api/id/54
*/
class
JuheGateway
extends
Gateway
{
use
HasHttpRequest
;
...
...
src/Gateways/LuosimaoGateway.php
浏览文件 @
896eec44
...
...
@@ -32,7 +32,7 @@ class LuosimaoGateway extends Gateway
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param \Overtrue\EasySms\Support\Config $config
*
* @return
mixed
* @return
array
*
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException;
*/
...
...
src/Gateways/SendcloudGateway.php
0 → 100644
浏览文件 @
896eec44
<?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 SendcloudGateway.
*
* @see http://sendcloud.sohu.com/doc/sms/
*/
class
SendcloudGateway
extends
Gateway
{
use
HasHttpRequest
;
const
ENDPOINT_TEMPLATE
=
'http://www.sendcloud.net/smsapi/%s'
;
/**
* Send a short message.
*
* @param int|string|array $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
=
[
'smsUser'
=>
$config
->
get
(
'sms_user'
),
'templateId'
=>
$message
->
getTemplate
(),
'phone'
=>
is_array
(
$to
)
?
join
(
','
,
$to
)
:
$to
,
'vars'
=>
$this
->
formatTemplateVars
(
$message
->
getData
()),
'timestamp'
=>
time
(),
];
$params
[
'signature'
]
=
$this
->
sign
(
$params
,
$config
->
get
(
'sms_key'
));
$result
=
$this
->
post
(
sprintf
(
self
::
ENDPOINT_TEMPLATE
,
'send'
),
$params
);
if
(
!
$result
[
'result'
])
{
throw
new
GatewayErrorException
(
$result
[
'message'
],
$result
[
'statusCode'
],
$result
);
}
return
$result
;
}
/**
* @param array $vars
*
* @return string
*/
protected
function
formatTemplateVars
(
array
$vars
)
{
$formatted
=
[];
foreach
(
$vars
as
$key
=>
$value
)
{
$formatted
[
sprintf
(
'%%%s%%'
,
trim
(
$key
,
'%'
))]
=
$value
;
}
return
json_encode
(
$formatted
);
}
/**
* @param array $params
* @param string $key
*
* @return string
*/
protected
function
sign
(
$params
,
$key
)
{
ksort
(
$params
);
return
md5
(
sprintf
(
'%s&%s&%s'
,
$key
,
urldecode
(
http_build_query
(
$params
)),
$key
));
}
}
src/Gateways/SubmailGateway.php
浏览文件 @
896eec44
...
...
@@ -31,7 +31,7 @@ class SubmailGateway extends Gateway
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param \Overtrue\EasySms\Support\Config $config
*
* @return
mixed
* @return
array
*
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException;
*/
...
...
src/Gateways/YuntongxunGateway.php
浏览文件 @
896eec44
...
...
@@ -36,7 +36,7 @@ class YuntongxunGateway extends Gateway
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param \Overtrue\EasySms\Support\Config $config
*
* @return
mixed
* @return
array
*
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException;
*/
...
...
@@ -44,7 +44,7 @@ class YuntongxunGateway extends Gateway
{
$datetime
=
date
(
'YmdHis'
);
$endpoint
=
$this
->
buildEndpoint
(
'SMS'
,
'TemplateSMS'
,
$datetime
);
$endpoint
=
$this
->
buildEndpoint
(
'SMS'
,
'TemplateSMS'
,
$datetime
,
$config
);
$result
=
$this
->
request
(
'post'
,
$endpoint
,
[
'json'
=>
[
...
...
@@ -73,17 +73,18 @@ class YuntongxunGateway extends Gateway
* @param string $type
* @param string $resource
* @param string $datetime
* @param \Overtrue\EasySms\Support\Config $config
*
* @return string
*/
protected
function
buildEndpoint
(
$type
,
$resource
,
$datetime
)
protected
function
buildEndpoint
(
$type
,
$resource
,
$datetime
,
Config
$config
)
{
$serverIp
=
$this
->
config
->
get
(
'debug'
)
?
self
::
DEBUG_SERVER_IP
:
self
::
SERVER_IP
;
$accountType
=
$this
->
config
->
get
(
'is_sub_account'
)
?
'SubAccounts'
:
'Accounts'
;
$sig
=
strtoupper
(
md5
(
$
this
->
config
->
get
(
'account_sid'
)
.
$this
->
config
->
get
(
'account_token'
)
.
$datetime
));
$sig
=
strtoupper
(
md5
(
$
config
->
get
(
'account_sid'
)
.
$
config
->
get
(
'account_token'
)
.
$datetime
));
return
sprintf
(
self
::
ENDPOINT_TEMPLATE
,
$serverIp
,
self
::
SERVER_PORT
,
self
::
SDK_VERSION
,
$accountType
,
$
this
->
config
->
get
(
'account_sid'
),
$type
,
$resource
,
$sig
);
return
sprintf
(
self
::
ENDPOINT_TEMPLATE
,
$serverIp
,
self
::
SERVER_PORT
,
self
::
SDK_VERSION
,
$accountType
,
$config
->
get
(
'account_sid'
),
$type
,
$resource
,
$sig
);
}
}
src/Messenger.php
浏览文件 @
896eec44
...
...
@@ -117,6 +117,7 @@ class Messenger
$setting
=
[];
}
$formatted
[
$gateway
]
=
$setting
;
$globalSetting
=
$config
->
get
(
"gateways.
{
$gateway
}
"
,
[]);
if
(
is_string
(
$gateway
)
&&
!
empty
(
$globalSetting
)
&&
is_array
(
$setting
))
{
...
...
tests/Gateways/AlidayuGatewayTest.php
浏览文件 @
896eec44
...
...
@@ -27,7 +27,7 @@ class AlidayuGatewayTest extends TestCase
];
$gateway
=
\
Mockery
::
mock
(
AlidayuGateway
::
class
.
'[post]'
,
[
$config
])
->
shouldAllowMockingProtectedMethods
();
$
params
=
[
$
expected
=
[
'method'
=>
'alibaba.aliqin.fc.sms.num.send'
,
'format'
=>
'json'
,
'v'
=>
'2.0'
,
...
...
@@ -39,7 +39,19 @@ class AlidayuGatewayTest extends TestCase
'rec_num'
=>
strval
(
18888888888
),
'sms_param'
=>
json_encode
([
'code'
=>
'123456'
,
'time'
=>
'15'
]),
];
$gateway
->
shouldReceive
(
'post'
)
->
with
(
'https://eco.taobao.com/router/rest'
,
\
Mockery
::
subset
(
$params
))
$gateway
->
shouldReceive
(
'post'
)
->
with
(
'https://eco.taobao.com/router/rest'
,
\
Mockery
::
on
(
function
(
$params
)
use
(
$expected
)
{
if
(
empty
(
$params
[
'timestamp'
])
||
empty
(
$params
[
'sign'
]))
{
return
false
;
}
unset
(
$params
[
'timestamp'
],
$params
[
'sign'
]);
ksort
(
$params
);
ksort
(
$expected
);
return
$params
==
$expected
;
}))
->
andReturn
([
'success_response'
=>
'mock-result'
,
],
[
...
...
@@ -48,6 +60,7 @@ class AlidayuGatewayTest extends TestCase
->
twice
();
$message
=
new
Message
([
'template'
=>
'mock-template-code'
,
'data'
=>
[
'code'
=>
'123456'
,
'time'
=>
'15'
],
]);
$config
=
new
Config
(
$config
);
...
...
tests/Gateways/SendcloudGatewayTest.php
0 → 100644
浏览文件 @
896eec44
<?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\Tests\Gateways
;
use
Overtrue\EasySms\Exceptions\GatewayErrorException
;
use
Overtrue\EasySms\Gateways\SendcloudGateway
;
use
Overtrue\EasySms\Message
;
use
Overtrue\EasySms\Support\Config
;
use
Overtrue\EasySms\Tests\TestCase
;
class
SendcloudGatewayTest
extends
TestCase
{
public
function
testSend
()
{
$config
=
[
'sms_user'
=>
'mock-user'
,
'sms_key'
=>
'mock-key'
,
];
$gateway
=
\
Mockery
::
mock
(
SendcloudGateway
::
class
.
'[post]'
,
[
$config
])
->
shouldAllowMockingProtectedMethods
();
$expected
=
[
'smsUser'
=>
'mock-user'
,
'templateId'
=>
'mock-tpl-id'
,
'phone'
=>
18188888888
,
'vars'
=>
json_encode
([
'%code%'
=>
1234
]),
];
$gateway
->
shouldReceive
(
'post'
)
->
with
(
sprintf
(
SendcloudGateway
::
ENDPOINT_TEMPLATE
,
'send'
),
\
Mockery
::
on
(
function
(
$params
)
use
(
$expected
,
$config
)
{
$expected
[
'timestamp'
]
=
$params
[
'timestamp'
];
ksort
(
$expected
);
$signString
=
[];
foreach
(
$expected
as
$key
=>
$value
)
{
$signString
[]
=
"
{
$key
}
=
{
$value
}
"
;
}
$signString
=
join
(
'&'
,
$signString
);
$expectedSignature
=
md5
(
"
{
$config
[
'sms_key'
]
}
&
{
$signString
}
&
{
$config
[
'sms_key'
]
}
"
);
return
$params
[
'smsUser'
]
==
$expected
[
'smsUser'
]
&&
$params
[
'templateId'
]
==
$expected
[
'templateId'
]
&&
$params
[
'phone'
]
==
$expected
[
'phone'
]
&&
$params
[
'vars'
]
==
$expected
[
'vars'
]
&&
$params
[
'timestamp'
]
>=
time
()
&&
$params
[
'signature'
]
==
$expectedSignature
;
}))
->
andReturn
([
'message'
=>
'操作成功'
,
'result'
=>
true
,
'statusCode'
=>
200
,
],
[
'message'
=>
'手机号不存在'
,
'result'
=>
false
,
'statusCode'
=>
400
,
])
->
times
(
2
);
$message
=
new
Message
([
'content'
=>
'This is a huyi test message.'
,
'template'
=>
'mock-tpl-id'
,
'data'
=>
[
'code'
=>
1234
,
],
]);
$config
=
new
Config
(
$config
);
$this
->
assertSame
([
'message'
=>
'操作成功'
,
'result'
=>
true
,
'statusCode'
=>
200
,
],
$gateway
->
send
(
18188888888
,
$message
,
$config
));
$this
->
expectException
(
GatewayErrorException
::
class
);
$this
->
expectExceptionCode
(
400
);
$this
->
expectExceptionMessage
(
'手机号不存在'
);
$gateway
->
send
(
18188888888
,
$message
,
$config
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录