Giter Site home page Giter Site logo

phpsms's Introduction

PhpSms

StyleCI Build Status Code Coverage Latest Stable Version Total Downloads

可能是目前最聪明、优雅的 php 短信发送库了。

phpsms的任务均衡调度功能由toplan/task-balancer提供。

特别感谢以下赞助者:

短信宝

特点

  • 支持内容短信,模版短信,语音验证码,内容语音,模版语音,语音文件。
  • 支持发送均衡调度,可按代理器权重值均衡选择服务商发送。
  • 支持一个或多个备用代理器(服务商)。
  • 支持代理器调度方案热更新,可随时更新/删除/新加代理器。
  • 允许推入队列,并自定义队列实现逻辑(与队列系统松散耦合)。
  • 灵活的发送前后钩子。
  • 内置国内主流服务商的代理器。
  • 自定义代理器寄生代理器

服务商

服务商 模板短信 内容短信 语音验证码 最低消费 最低消费单价 资费标准
Luosimao × ¥850(1万条) ¥0.085/条 资费标准
云片网络 × ¥55(1千条) ¥0.055/条 资费标准
容联·云通讯 × 充值¥500 ¥0.055/条 资费标准
SUBMAIL × ¥100(1千条) ¥0.100/条 资费标准
云之讯 × -- ¥0.050/条 资费标准
聚合数据 × -- ¥0.035/条 资费标准
阿里大鱼 × -- ¥0.045/条 资费标准
SendCloud × -- ¥0.048/条 资费标准
短信宝 × ¥5(50条) ¥0.040/条(100万条) 资费标准
腾讯云 -- ¥0.045/条 资费标准
阿里云 × × -- ¥0.045/条 资费标准

安装

composer require toplan/phpsms:~1.8

开发中版本

composer require toplan/phpsms:dev-master

快速上手

1. 配置

  • 配置代理器所需参数

为你需要用到的短信服务商(即代理器)配置必要的参数。可以在config\phpsms.php中键为agents的数组中配置,也可以手动在程序中设置,示例如下:

//example:
Sms::config([
    'Luosimao' => [
        'apikey' => 'your api key',
        'voiceApikey' => 'your voice api key',
    ],
    'YunPian'  => [
        'apikey' => 'your api key',
    ],
    'SmsBao' => [
        'username' => 'your username',
        'password'  => 'your password'
    ]
]);
  • 配置代理器调度方案

可在config\phpsms.php中键为scheme的数组中配置。也可以手动在程序中设置,示例如下:

//example:
Sms::scheme([
    //被使用概率为2/3
    'Luosimao' => '20',

    //被使用概率为1/3,且为备用代理器
    'YunPian' => '10 backup',

    //仅为备用代理器
    'SmsBao' => '0 backup',
]);

调度方案解析: 如果按照以上配置,那么系统首次会尝试使用LuosimaoYunPian发送短信,且它们被使用的概率分别为2/31/3。 如果使用其中一个代理器发送失败,那么会启用备用代理器,按照配置可知备用代理器有YunPianSmsBao,那么会依次调用直到发送成功或无备用代理器可用。 值得注意的是,如果首次尝试的是YunPian,那么备用代理器将会只使用SmsBao,也就是会排除使用过的代理器。

2. Enjoy it!

require('path/to/vendor/autoload.php');
use Toplan\PhpSms\Sms;

// 接收人手机号
$to = '1828****349';
// 短信模版
$templates = [
    'YunTongXun' => 'your_temp_id',
    'SubMail'    => 'your_temp_id'
];
// 模版数据
$tempData = [
    'code' => '87392',
    'minutes' => '5'
];
// 短信内容
$content = '【签名】这是短信内容...';

// 只希望使用模板方式发送短信,可以不设置content(如:云通讯、Submail、Ucpaas)
Sms::make()->to($to)->template($templates)->data($tempData)->send();

// 只希望使用内容方式发送,可以不设置模板id和模板data(如:短信宝、云片、luosimao)
Sms::make()->to($to)->content($content)->send();

// 同时确保能通过模板和内容方式发送,这样做的好处是可以兼顾到各种类型服务商
Sms::make()->to($to)
    ->template($templates)
    ->data($tempData)
    ->content($content)
    ->send();

// 语音验证码
Sms::voice('02343')->to($to)->send();

// 语音验证码兼容模版语音(如阿里大鱼的文本转语音)
Sms::voice('02343')
    ->template('Alidayu', 'your_tts_code')
    ->data(['code' => '02343'])
    ->to($to)
    ->send();

3. 在laravel和lumen中使用

  • 服务提供器
//服务提供器
'providers' => [
    ...
    Toplan\PhpSms\PhpSmsServiceProvider::class,
]

//别名
'aliases' => [
    ...
    'PhpSms' => Toplan\PhpSms\Facades\Sms::class,
]
  • 生成配置文件
php artisan vendor:publish

生成的配置文件为config/phpsms.php,然后在该文件中按提示配置。

  • 使用

详见API,示例:

PhpSms::make()->to($to)->content($content)->send();

API

API - 全局配置

Sms::scheme([$name[, $scheme]])

设置/获取代理器的调度方案。

调度配置支持热更新,即在应用系统的整个运行过程中都能随时修改。

  • 设置

手动设置代理器调度方案(优先级高于配置文件),如:

Sms::scheme([
    'SmsBao' => '80 backup'
    'YunPian' => '100 backup'
]);
//或
Sms::scheme('SmsBao', '80 backup');
Sms::scheme('YunPian', '100 backup');
  • 获取

通过该方法还能获取所有或指定代理器的调度方案,如:

//获取所有的调度方案:
$scheme = Sms::scheme();

//获取指定代理器的调度方案:
$scheme['SmsBao'] = Sms::scheme('SmsBao');

scheme静态方法的更多使用方法见高级调度配置

Sms::config([$name[, $config][, $override]]);

设置/获取代理器的配置数据。

参数配置支持热更新,即在应用系统的整个运行过程中都能随时修改。

  • 设置

手动设置代理器的配置数据(优先级高于配置文件),如:

Sms::config([
   'SmsBao' => [
       'username' => ...,
       'password' => ...,
   ]
]);
//或
Sms::config('SmsBao', [
   'username' => ...,
   'password' => ...,
]);
  • 获取

通过该方法还能获取所有或指定代理器的配置参数,如:

//获取所有的配置:
$config = Sms::config();

//获取指定代理器的配置:
$config['SmsBao'] = Sms::config('SmsBao');

Sms::beforeSend($handler[, $override]);

发送前钩子,示例:

Sms::beforeSend(function($task, $index, $handlers, $prevReturn){
    //获取短信数据
    $smsData = $task->data;
    ...
    //如果返回false会终止发送任务
    return true;
});

更多细节请查看 task-balancerbeforeRun 钩子

Sms::beforeAgentSend($handler[, $override]);

代理器发送前钩子,示例:

Sms::beforeAgentSend(function($task, $driver, $index, $handlers, $prevReturn){
    //短信数据:
    $smsData = $task->data;
    //当前使用的代理器名称:
    $agentName = $driver->name;
    //如果返回false会停止使用当前代理器
    return true;
});

更多细节请查看 task-balancerbeforeDriverRun 钩子

Sms::afterAgentSend($handler[, $override]);

代理器发送后钩子,示例:

Sms::afterAgentSend(function($task, $agentResult, $index, $handlers, $prevReturn){
     //$result为代理器的发送结果数据
     $agentName = $agentResult['driver'];
     ...
});

更多细节请查看 task-balancerafterDriverRun 钩子

Sms::afterSend($handler[, $override]);

发送后钩子,示例:

Sms::afterSend(function($task, $taskResult, $index, $handlers, $prevReturn){
    //$result为发送后获得的结果数组
    $success = $taskResult['success'];
    ...
});

更多细节请查看 task-balancerafterRun 钩子

Sms::queue([$enable[, $handler]])

该方法可以设置是否启用队列以及定义如何推送到队列。

$handler匿名函数可使用的参数:

  • $sms : Sms实例
  • $data : Sms实例中的短信数据,等同于$sms->all()

定义如何推送到队列:

//自动启用队列
Sms::queue(function($sms, $data){
    //define how to push to queue.
    ...
});

//第一个参数为true,启用队列
Sms::queue(true, function($sms, $data){
    //define how to push to queue.
    ...
});

//第一个参数为false,暂时关闭队列
Sms::queue(false, function($sms, $data){
    //define how to push to queue.
    ...
});

如果已经定义过如何推送到队列,还可以继续设置关闭/开启队列:

Sms::queue(true);//开启队列
Sms::queue(false);//关闭队列

获取队列启用情况:

$enable = Sms::queue();
//为true,表示当前启用了队列。
//为false,表示当前关闭了队列。

API - 发送相关

Sms::make()

生成发送短信的sms实例,并返回实例。

$sms = Sms::make();

//创建实例的同时设置短信内容:
$sms = Sms::make('【签名】这是短信内容...');

//创建实例的同时设置短信模版:
$sms = Sms::make('YunTongXun', 'your_temp_id');
//或
$sms = Sms::make([
    'YunTongXun' => 'your_temp_id',
    'SubMail' => 'your_temp_id',
    ...
]);

Sms::voice()

生成发送语音验证码的sms实例,并返回实例。

$sms = Sms::voice();

//创建实例的同时设置验证码
$sms = Sms::voice($code);
  • 如果你使用Luosimao语音验证码,还需用在配置文件中Luosimao选项中设置voiceApikey
  • 语音文件ID即是在服务商配置的语音文件的唯一编号,比如阿里大鱼语音通知voice_code
  • 模版语音是另一种语音请求方式,它是通过模版ID和模版数据进行的语音请求,比如阿里大鱼的文本转语音通知

type($type)

设置实例类型,可选值有Sms::TYPE_SMSSms::TYPE_VOICE,返回实例对象。

to($mobile)

设置发送给谁,并返回实例。

$sms->to('1828*******');

//兼容腾讯云
$sms->to([86, '1828*******'])

template($agentName, $id)

指定代理器设置模版或批量设置,并返回实例。

//设置指定服务商的模板id
$sms->template('YunTongXun', 'your_temp_id')
    ->template('SubMail', 'your_temp_id');

//一次性设置多个服务商的模板id
$sms->template([
    'YunTongXun' => 'your_temp_id',
    'SubMail' => 'your_temp_id',
    ...
]);

data($key, $value)

设置模板短信的模板数据,并返回实例对象。

//单个数据
$sms->data('code', $code);

//同时设置多个数据
$sms->data([
    'code' => $code,
    'minutes' => $minutes
]);

通过templatedata方法的组合除了可以实现模版短信的数据填充,还可以实现模版语音的数据填充。

content($text)

设置内容短信的内容,并返回实例对象。

一些内置的代理器(如SmsBao、YunPian、Luosimao)使用的是内容短信(即直接发送短信内容),那么就需要为它们设置短信内容。

$sms->content('【签名】这是短信内容...');

code($code)

设置语音验证码,并返回实例对象。

file($agentName, $id)

设置语音文件,并返回实例对象。

$sms->file('Agent1', 'agent1_file_id')
    ->file('Agent2', 'agent2_file_id');

//或
$sms->file([
    'Agent1' => 'agent1_file_id',
    'Agent2' => 'agent2_fiile_id',
]);

params($agentName, $params)

直接设置参数到服务商提供的原生接口上,并返回实例对象。

$sms->params('Agent1', [
    'callbackUrl' => ...,
    'userData'    => ...,
]);

//或
$sms->params([
    'Agent1' => [
        'callbackUrl' => ...,
        'userData'    => ...,
    ],
    'Agent2' => [
        ...
    ],
]);

all([$key])

获取Sms实例中的短信数据,不带参数时返回所有数据,其结构如下:

[
    'type'      => ...,
    'to'        => ...,
    'templates' => [...],
    'data'      => [...], // template data
    'content'   => ...,
    'code'      => ...,   // voice code
    'files'     => [...], // voice files
    'params'    => [...],
]

agent($name)

临时设置发送时使用的代理器(不会影响备用代理器的正常使用),并返回实例,$name为代理器名称。

$sms->agent('SmsBao');

通过该方法设置的代理器将获得绝对优先权,但只对当前短信实例有效。

send()

请求发送短信/语音验证码。

//会遵循是否使用队列
$result = $sms->send();

//忽略是否使用队列
$result = $sms->send(true);

$result数据结构请参看task-balancer

自定义代理器

  • step 1

可将配置项(如果有用到)加入到config/phpsms.php中键为agents的数组里。

//example:
'Foo' => [
    'key' => 'your api key',
    ...
]
  • step 2

新建一个继承Toplan\PhpSms\Agent抽象类的代理器类,建议代理器类名为FooAgent,建议命名空间为Toplan\PhpSms

如果类名不为FooAgent或者命名空间不为Toplan\PhpSms,在使用该代理器时则需要指定代理器类,详见高级调度配置

  • step 3

实现相应的接口,可选的接口有:

接口 说明
ContentSms 发送内容短信
TemplateSms 发送模版短信
VoiceCode 发送语音验证码
ContentVoice 发送内容语音
TemplateVoice 发送模版语音
FileVoice 发送文件语音

高级调度配置

代理器的高级调度配置可以通过配置文件(config/phpsms.php)中的scheme项目配置,也可以通过scheme静态方法设置。 值得注意的是,高级调度配置的值的数据结构是数组。

指定代理器类

如果你自定义了一个代理器,类名不为FooAgent或者命名空间不为Toplan\PhpSms, 那么你还可以在调度配置时指定你的代理器使用的类。

  • 配置方式:

通过配置值中agentClass键来指定类名。

  • 示例:
Sms::scheme('agentName', [
    '10 backup',
    'agentClass' => 'My\Namespace\MyAgentClass'
]);

寄生代理器

如果你既不想使用内置的代理器,也不想创建文件写自定义代理器,那么寄生代理器或许是个好的选择, 无需定义代理器类,只需在调度配置时定义好发送短信和语音验证码的方式即可。

  • 配置方式:

可以配置的发送过程有:

发送过程 参数列表 说明
sendContentSms $agent, $to, $content 发送内容短信
sendTemplateSms $agent, $to, $tmpId, $tmpData 发送模版短信
sendVoiceCode $agent, $to, $code 发送语音验证码
sendContentVoice $agent, $to, $content 发送内容语音
sendTemplateVoice $agent, $to, $tmpId, $tmpData 发送模版语音
sendFileVoice $agent, $to, $fileId 发送文件语音
  • 示例:
Sms::scheme([
    'agentName' => [
        '20 backup',
        'sendContentSms' => function($agent, $to, $content){
            // 获取配置(如果设置了的话):
            $key = $agent->key;
            ...
            // 可使用的内置方法:
            $agent->curlGet($url, $params); //get
            $agent->curlPost($url, $params); //post
            ...
            // 更新发送结果:
            $agent->result(Agent::SUCCESS, true);
            $agent->result(Agent::INFO, 'some info');
            $agent->result(Agent::CODE, 'your code');
        },
        'sendVoiceCode' => function($agent, $to, $code){
            // 发送语音验证码,同上
        }
    ]
]);

Todo

  • 重新实现云通讯代理器,去掉lib/CCPRestSmsSDK.php
  • 重新实现云之讯代理器,去掉lib/Ucpaas.php
  • 升级云片接口到v2版本

License

MIT

phpsms's People

Contributors

branchzero avatar cuikangyi avatar darkal avatar domainname avatar hzkoala avatar king19800105 avatar medz avatar toplan avatar yangliuyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phpsms's Issues

发送后,如何记录详细的返回消息

你好,我现在正用阿里大于测试,可以判断发送失败或成功,但是我想记录返回的详细消息到数据库中。以方便排错之类。
请给一个返回结果的数据结构?
如何记录具体错误代码、详细错误消息?
如果使用其他服务商,返回的结果也是一样吗?

https://github.com/toplan/task-balancer 这里提到了$result结构,但是并没有关键细节,不太明白。

"toplan/phpsms": "~1.8.0-beta", composer update 报错

Problem 1
- Installation request for toplan/phpsms ~1.8.0-beta -> satisfiable by toplan/phpsms[1.8.0-beta.1].
- toplan/phpsms 1.8.0-beta.1 requires toplan/task-balancer ~0.5.0-beta -> satisfiable by toplan/task-balancer[0.5.0-beta.1] but these conflict with your requirements or minimum-stability.

能否提供一个队列实现的例子呢?

允许推入队列,并自定义队列实现逻辑(与队列系统松散耦合)。

比如 将队列存储到数据库,然后定时任务发送什么的. 要求比较过分, 不知道能否考虑.

laravel5.4最新更新后php artisan 报错[ErrorException] Illegal offset type in unset

使用最新的laravel版本,使用本扩展,在执行php artisan时报错

[ErrorException] Illegal offset type in unset

debug后发现是这段代码出错,

$this->app->singleton([
            'Toplan\\Sms\\SmsManager' => 'laravel-sms',
        ], function ($app) {
            $token = $app->request->header('access-token', null);
            if (empty($token)) {
                $token = $app->request->input('access_token', null);
            }
            $input = $app->request->all();

            return new SmsManager($token, $input);
        });

猜测应该是新版本laravel的singletion绑定时不能再使用数组,
代码更改为如下后就正常了,

$this->app->singleton('Toplan\\Sms\\SmsManager', function ($app) {
            $token = $app->request->header('access-token', null);
            if (empty($token)) {
                $token = $app->request->input('access_token', null);
            }
            $input = $app->request->all();

            return new SmsManager($token, $input);
        });

希望可以发布一个新版本修复一下,谢谢

腾讯的接口1004错误

出现1004错误
[{"driver":"Qcloud","time":{"started_at":"0.33102900 1507352277","finished_at":"0.60767200 1507352277"},"success":false,"result":{"info":"{\"result\":1004,\"errmsg\":\"package format errorcannot get \/tel\/mobile\"}","code":1004}}]

qcloud短信api错误

{ "tel": { //如需使用国际电话号码通用格式,如:"+8613788888888" ,请使用sendisms接口见下注 "nationcode": "86", //国家码 "mobile": "13788888888" //手机号码 }, "type": 0, //0:普通短信;1:营销短信(强调:要按需填值,不然会影响到业务的正常使用) "msg": "你的验证码是1234", //utf8编码 "sig": "30db206bfd3fea7ef0db929998642c8ea54cc7042a779c5a0d9897358f6e9505", //app凭证,具体计算方式见下注 "time": 1457336869, //unix时间戳,请求发起时间,如果和系统时间相差超过10分钟则会返回失败 "extend": "", //通道扩展码,可选字段,默认没有开通(需要填空)。 //在短信回复场景中,腾讯server会原样返回,开发者可依此区分是哪种类型的回复 "ext": "" //用户的session内容,腾讯server回包中会原样返回,可选字段,不需要就填空。 }

注意电话号码那一部分。是tel:{} 不是接收固定号码

详情:
https://www.qcloud.com/document/api/382/5808

同一个短信服务商多个apikey如何更好的切换?

由于审核原因,云片网的营销短信需要申请营销账号,因此会有两个apikey.
通过账号类型动态设置apikey没什么问题,但是有更好的解决方案么?
我自定义了YunPianAgent,想在Agent这边完成apikey的切换.
如果使用SMSManager,传递到Agent的业务数据已经被框架限制了.
` public function sendSms($to, $content, $tempId, array $data)
{
$this->sendContentSms($to, $content);
}

public function sendContentSms($to, $content)`

由于短信接口被调用的地方比较多,封装到Agent的话,只需要
正常使用SMSManager就可以了.

怎样在phpsms.php文件中为自定义代理指定agentClass?

namespace App\Library;

use Toplan\PhpSms\Agent;
use Toplan\PhpSms\ContentSms;

class LanzSMSAgent extends Agent implements ContentSms

上面我自定义代理类的,phpsms.php配置文件是:

'scheme' => [
        'LanzSMS'
    ],
    'agents' => [
        //自定义代理
        'LanzSMS' => [
            'userId' => 'xx',
            'account' => 'xx',
            'password' => 'xxx',

        ]

然而程序是用这个$className = "Toplan\PhpSms\{$name}Agent";,如何在phpsms.php定义agentClass

YunTongXun 短信发送成功状态判断有误

现在短信发送成功判断用的是

$result->statusCode === 0

但实际上,云通讯的状态码是 000000 。所以现在短信发送成功了,但组件返回结果 $result['success'] 为 false

ps: 云通讯和云之讯的接口几乎一样的,只是某些接口路径有一点点不同,如果有时间的话,可以考虑改成共用一个 lib .

阿里云短信发送错误

  • 阿里云短信发送, 一直提示"InvalidTimeStamp.Expired"
  • 检查时间戳字段, 没有问题
  • 咨询技术客服, 回复如下
同时,在日志查看,您其实是有用户消息服务的batchSendSms接口发送的,并且在2017-06-23 14:58:26有成功。建议您继续调整使用batchSendSms接口发送。  
  • 客服说是接口调用url错误

composer更新到1.8.0版本 阿里大鱼 发送短信报错 Invalid signature

1.8.0版本发送短信: {"success":false,"time":{"started_at":"0.47898600 1498094446","finished_at":"0.53329300 1498094446"},"logs":[{"driver":"Alidayu","time":{"started_at":"0.47902900 1498094446","finished_at":"0.53327600 1498094446"},"success":false,"result":{"info":"{\"code\":25,\"msg\":\"Invalid signature\",\"request_id\":\"zlycsgi622v2\"}","code":25}}]}

固定版本到1.7.2 发送短信成功: {"success":true,"time":{"started_at":"0.53952600 1498095191","finished_at":"0.18113300 1498095192"},"logs":[{"driver":"Alidayu","time":{"started_at":"0.53955100 1498095191","finished_at":"0.18108200 1498095192"},"success":true,"result":{"info":"{\"err_code\":\"0\",\"model\":\"108284793846^1111232052740\",\"success\":true}","code":"0"}}]}

望解决回复

laravel

$this->app->singleton([
'Toplan\Sms\SmsManager' => 'laravel-sms',
], function ($app) {
$token = $app->request->header('access-token', null);
if (empty($token)) {
$token = $app->request->input('access_token', null);
}
$input = $app->request->all();

        return new SmsManager($token, $input);
    });

[版本号:1.8]自定义代理器的同学注意下

如果你们做自定义代理器,要注意库里的代码有一处有问题,
Toplan\PhpSms\Sms.php289行开始
代码是:

if (!empty($options)) {
    self::$agents[$name] = new ParasiticAgent($config, $options);
} elseif (class_exists($className)) {
    self::$agents[$name] = new $className($config);
} else {
    throw new PhpSmsException("Not support agent `$name`.");
}

这样如果你在phpsms.php里的scheme里以数组的形式设置了你的自定义代理器并加了weight
比如

'scheme' => [
    App\agents\AAA\Agent::class => [
        '20',
        'agentClass' => App\Libs\AAA\Agent::class
    ],
    App\agents\BBB\Agent::class => [
        '10 backup',
        'agentClass' => App\Libs\BBB\Agent::class
    ]
]

那么这两个Agent经过那段代码后,就跑ParasiticAgent去了。
所以,要不就不要有weight,这样的后果 我不知道会不会造成没有权重的特性了,
我也没多看其它代码,就把elseif改了一下

if (!empty($options)) {
    self::$agents[$name] = new ParasiticAgent($config, $options);
} 
if (class_exists($className)) {
    self::$agents[$name] = new $className($config);
} else {
    throw new PhpSmsException("Not support agent `$name`.");
}

希望遇到同样问题的同学能看到,着实弄了我半天。醉了!

自定义代理器

自定义代理器类使用 Toplan/PhpSms 命名空间
对于Laravel项目 ,在重新执行 php artisan optimize ,生成的 autoload_classmap.php
中也不会出现自定义的类的相关映射.
$className = "Toplan\\PhpSms\\{$name}Agent";
class_exists($className);

beforeDriverRun建议

提供了beforeDriverRun 但是beforeDriverRun中无法标记当前agent 失效.

比如, 目前发送短信会有某个时间内的次数限制,当之前已经使用某agent进行发送了.之后又多次请求.

按理说,发送不成功应该不会计费, 但是目前的短信网关一般都是不发送,但是进行计费的.

如果在beforeDriverRun 时根据当前agent的判断, 进行当前agent跳过或直接标记agent错误,那就会好很多了.

建议增加故障判断自动切换机制

受限于网络或者运营商内部问题,即便在配置了比例、备份策略后,仍然要尽可能提高短信发送成功率。建议:

1.增加daemon程序,自动判断短信发送成功率,动态调整通道开关。能够自动开和关。甚至可以通过ui或者命令行,在不改代码的情况下,调整发送比例。

2.短信字符拆分策略,每家大同小异,但是依然可以配置是否在提交到短信服务商之前切分,还是直接发送长短信,因为各家针对拆分后的回调机制是不同的。

3.短信发送需要永久化保存,以便能够查询发送结果。

4.对于上行短信,需要配置是否支持扩展码,以自动对于下发内容。

以上4点是我们公司目前短信策略,供参考。

为什么唯独Log Scheme 发送失败

是这样的 在代码中 使用的是alidayu的scheme, 可以正常使用, 在写测试用例的时候 使用

Config::set('phpsms.scheme', ['Log']);

指定scheme 默认为Log 避免真的发送短信 但是问题来了 在代码环境中使用alidayu代码都能正常运作 甚至注释了Config这段代码 都可以正常运行,唯独在上述代码运作时 返回的success结果为false 这是为什么呢
附上日志及代码
使用send发送回来的结果dump后结果是

array:3 [
  "success" => false
  "time" => array:2 [
    "started_at" => "0.12025000 1504518904"
    "finished_at" => "0.12125500 1504518904"
  ]
  "logs" => array:1 [
    0 => array:4 [
      "driver" => "Log"
      "time" => array:2 [
        "started_at" => "0.12028900 1504518904"
        "finished_at" => "0.12123700 1504518904"
      ]
      "success" => false
      "result" => array:2 [
        "info" => null
        "code" => 0
      ]
    ]
  ]
]

发送的代码

$result = PhpSms::make()
            ->template($template)
            ->to($phone)
            ->data($data)
            ->send();

$template['Alidayu' => env('SMS_ALI_VERIFY_TEMPLATE')]
$datacompact('code')

建议增加发送短信条数限制

以防恶意调用接口,造成不必要的损失。
1.针对一个ip,限制次数。
2.针对一个手机号码,限制次数

另外,对于发送验证码的情况,我们要限制尝试次数。

使用云片发送短信时报错

我把phpsms升级到1.8.0后云片发送短信时报错,我查看了下错误,应该是在Agent.php中curl()处循环读取$opts时报错,
foreach ($opts as $key => $value) {
curl_setopt($ch, $key, $value);
}
我将其改成
curl_setopt($ch, CURLOPT_SSL_POST,$opts[3]);
curl_setopt($ch, CURLOPT_SSL_HTTPHEADER,$opts[1]);
curl_setopt($ch, CURLOPT_SSL_POSTFIELDS,http_query_bulid($opts[0]));
curl_setopt($ch, CURLOPT_SSL_HTTPURL,$opts[4]);
以后就正常发送云片短信了。

lumen使用问题

我使用lumen做为API核心处理系统,现在想用这个类库进行短信发送,但是我发现一个问题,就是PhpSmsServiceProvider类里面返回的Sms类是没有初始化的,然后整个文档都是说用门面调用,但是lumen是默认禁用门面的,我尝试用app("PhpSms")的形式加载Sms类,但是因为没有初始化Sms,所以基本上不可用。希望后面能适配一下lumen的使用。

v2 版本接口规划,欢迎有兴趣的童鞋提建议

v2目前规划:

  • 关于代理器类:所有Agent类继承Toplan\PhpSms\Agent抽象类,把抽象类中发送相关的方法再抽离出来,定义成一系列接口,需要实现模版短信的实现TemplateSms接口,需要实现内容短信的实现ContentSms接口,语音也一样,以此类推。
  • 关于短信类:定义一个超级父类:Message, 规划的子类有Sms,TemplateSms,ContentSms,Voice,TemplateVoice,FileVoice,CodeVoice
Sms::to()->content()->template()->data()->send(); //短信全能类

TemplateSms::to()->template()->data()->send(); // TemplateSms非全能,没有content方法
  • 关于全局配置:定义一个新的类Dispacher来处理:
Dispacher::scheme(...);
Dispacher::config(...);
Dispacher::queue(...);
...

聚合数据发送后判断错误

Toplan\PhpSms\JuHeAgent 方法genResult 使用if ($result['error_code'] === '0')判定,实际返回数据为0,所以永远发送失败

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.