MasSms.php
13.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
<?php
/**
+-----------------------------------------------------------------------------------------------------------------------
* 短信工厂类:移动云 MAS 短信
* 适配移动云 MAS 系统的 http 请求发送普通短信功能的类
* 需要配置 http 请求的接口的相关账号, 数据可以维护到 config/config.INI 中
* ------------------------------------------------------------------
* 接口参数说明:
* @param string $ecName
* @param string $apId
* @param string $mobiles 逗号分隔手机号码
* @param string $content
* @param string $sign 下载的签名中有
* @param string $addSerial 扩展码, 根据向移动公司申请的通道填写, 如果申请的精确匹配通道, 则填写空字符串(""), 否则添加移动公司允许的扩展码
* @param string $Mac API 输入参数签名结果, 签名算法: 将 ecName,apId,secretKey,mobiles,content ,sign,addSerial 按照顺序拼接, 然后通过 md5(32 位小写)计算后得出的值
* 以上数据需要字符集 utf8
* POST 请求路径: http://112.35.1.155:1992/sms/norsubmit
* ------------------------------------------------------------------
* 使用范例:
* require_once "util/mas.10086.class.PHP";
* $mas = new Mas10086();
* $response = $mas->sendSms('138 XXXX XXXX', 'Hello World!');
* var_dump($response);
* ------------------------------------------------------------------
* version 1.0
* 可以通过 http 接口, 发送 sms 普通短信, 接口适配 mas 的 HTTP2.1 版本
+-----------------------------------------------------------------------------------------------------------------------
*
* PHP version 7
*
* @category App\Sms
* @package App\Sms
* @author Richer <yangzi1028@163.com>
* @date 2021年8月19日10:04:55
* @copyright 2020-2022 Richer (http://www.Richer.com/)
* @license http://www.Richer.com/ License
* @link http://www.Richer.com/
*/
namespace App\Sms;
use App\Models\System\SmsLog;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Overtrue\EasySms\EasySms;
/**
* Class MasSms
*
* @category App\Sms
* @package App\Sms
* @author Richer <yangzi1028@163.com>
* @date 2021年8月19日10:04:55
* @copyright 2020-2022 Richer (http://www.Richer.com/)
* @license http://www.Richer.com/ License
* @link http://www.Richer.com/
*/
class MasSms
{
protected $message = '短信发送成功!';
/**
* 项目常量配置,
*/
private $apId;// 接口账号用户名
private $sign;// 签名编码。在云MAS平台『管理』→『接口管理』→『短信接入用户管理』获取
private $addSerial;// 扩展码。依据申请开户的服务代码匹配类型而定,如为精确匹配,此项填写空字符串("");如为模糊匹配,此项可填写空字符串或自定义的扩展码,注:服务代码加扩展码总长度不能超过20位
private $secretKey;// 用户密码
private $ecName; // 企业名称
private $norSmsUrl;// 普通短信发送 url
private $tmpSmsUrl;// 模板短信发送 url
private $mac; // 参数校验序列,生成方法:将ecName、apId、secretKey、templateId、mobiles、params、sign、addSerial按序拼接(无间隔符),通过MD5(32位小写)计算出的值
/**
* 初始化操作: 读取 config, 设定配置参数
* 如果没有配置, 则使用默认
*/
public function __construct()
{
$this->apId = config('mas.AP_ID');
$this->sign = config('mas.SIGN');
$this->addSerial = config('mas.ADD_SERIAL');
$this->secretKey = config('mas.SECRET_KEY');
$this->ecName = config('mas.EC_NAME');
$this->norSmsUrl = config('mas.NOR_SMS_URL');
$this->tmpSmsUrl = config('mas.TMP_SMS_URL');
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* 根据 MAS 的接口规范, 需要装配一组 Mac 字符串做验证
* @param string $mobiles 逗号分隔得电话号码字符串
* @param string $content
* @return string
*/
private function makeMacString(string $mobiles, string $content): string
{
$macstr = $this->ecName . $this->apId . $this->secretKey . $mobiles . $content . $this->sign . $this->addSerial;
return $this->mac = strtolower(md5($macstr));
}
/**
* 参数校验序列,生成方法:将ecName、apId、secretKey、templateId、mobiles、params、sign、addSerial按序拼接(无间隔符),通过MD5(32位小写)计算出的值
*
* @param string $mobiles 逗号分隔得电话号码字符串
* @param string $templateId
* @param string $params
* @return string
*/
private function makeTmpMacString(string $mobiles, string $templateId, string $params): string
{
$macstr = $this->ecName . $this->apId . $this->secretKey . $templateId. $mobiles . $params . $this->sign . $this->addSerial;
return $this->mac = strtolower(md5($macstr));
}
/**
* 发送消息
*
* @param $smslog
* @param string $module 模块
* @param Model $model 对象模型
* @param string $target 发送目标
* @param string $operate 操作
*
* @return array
* @throws GuzzleException
*/
public function pushNotification($smslog, $mobile, $module, $model, $target = 'user', $operate = 'warning')
{
// 本地环境以外的环境才进行短信消息推送
if (request('test') === 'test' || (config('app.env') !== 'local1' && config('app.open_SMS'))) {
$data = Template::getTemplate($module, $model, $target, $operate);
if (!$data) {
return false;
}
//发送确认消息给用户
$params = Arr::get($data, 'params');
$template = Arr::get($data, 'template');
$content = Arr::get($data, 'content');
$type = Arr::get($data, 'type');
$smslog->sent_body = $params;
$smslog->sent_at = now()->toDateTimeString();
$smslog->save();
if ($template) {
// 发送短信
$result = $this->sendTmpSms($mobile, $template, $params);
} else {
// 发送短信
$result = $this->sendSms($mobile, $content);
}
// 发送状态
$code = Arr::get($result, 'code');
$data = Arr::get($result, 'data');
// $return['mobile'] = $mobile;
if ($code == 0) {
$smslog->result = SmsLog::SEND_SUCCESS;
$smslog->received_body = $data;
$smslog->received_at = now()->toDateTimeString();
$smslog->out_id = Arr::get($data, 'msgGroup');
$smslog->save();
return true;
$return['code'] = 0;
} else {
$smslog->result = SmsLog::SEND_FAIL;
$smslog->received_body = $data;
$smslog->received_at = now()->toDateTimeString();
$smslog->out_id = Arr::get($data, 'msgGroup');
$smslog->save();
return false;
$return['code'] = 1;
$return['message'] = $this->message;
}
return $return;
}
}
/**
* 发送普通短信函数
*
* @param string|array $mobiles 手机号
* @param string $content 短信文本
* @return false|object
* @throws GuzzleException
*/
public function sendSms($mobiles, $content = '')
{
if (is_array($mobiles)) {
if (count($mobiles) === 0) {
$this->message = '发送方手机号为空!';
return false;
}
$mobiles = implode(',', $mobiles);
}
// $content .= "\n\r".'[系统短信, 请勿回复]';
// 去掉前后的逗号
$mobiles = ltrim(rtrim($mobiles, ','), ',');
// 生成参数校验序列
$this->makeMacString($mobiles, $content);
// 组合请求参数
$data = [
'ecName' => $this->ecName,
'apId' => $this->apId,
'mobiles' => $mobiles,
'content' => $content,
'sign' => $this->sign,
'addSerial' => $this->addSerial,
'mac' => $this->mac
];
return $this->httpPost($this->norSmsUrl, $data);
}
/**
* 发送模板短信
*
* @param string|array $mobiles 手机号
* @param string $templateId 短信模板
* @param string[] $params 模板变量。格式:[“param1”,“param2”],无变量模板填[""]。
* @return false|object
*/
public function sendTmpSms($mobiles, $templateId = '', $params = '')
{
Log::channel('sms')->info("=============================== MAS 短信 begin ===============================");
if (is_array($mobiles)) {
if (count($mobiles) === 0) {
$this->message = '发送方手机号为空!';
return false;
}
$mobiles = implode(',', $mobiles);
}
// $content .= "\n\r".'[系统短信, 请勿回复]';
// 去掉前后的逗号
$mobiles = ltrim(rtrim($mobiles, ','), ',');
// 生成参数校验序列
$this->makeTmpMacString($mobiles, $templateId, $params);
// 组合请求参数
$data = [
'ecName' => $this->ecName,
'apId' => $this->apId,
'templateId'=> $templateId,
'mobiles' => $mobiles,
'params' => $params,
'sign' => $this->sign,
'addSerial' => $this->addSerial,
'mac' => $this->mac
];
return $this->httpPost($this->tmpSmsUrl, $data);
}
/**
* @param $url
* @param $data
* @return false|JsonResponse|mixed
* @throws GuzzleException
*/
public function httpPost($url, $data)
{
// 生成Client时候添加 verify 为false 参数即可,这样强制关闭ssl的验证
$client = new Client(['verify' => false]);
$dataContent = base64_encode(json_encode($data));
try {
Log::channel('sms')->info("请求内容:".json_encode($data));
$response = $client->request('POST', $url, [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $dataContent
]);
Log::channel('sms')->info("响应内容:".json_encode($response));
$status = $response->getStatusCode(); // 200
$reason = $response->getReasonPhrase(); // OK
Log::channel('sms')->info("响应 status:".$status);
Log::channel('sms')->info("响应 reason:".$reason);
if ($status == 200) {
$content = json_decode($response->getBody()->getContents());
Log::channel('sms')->info("响应 content:".json_encode($content));
$rspcod = $content->rspcod;
$return = [
'data' => obj_2_array($content),
];
if ($rspcod === 'success') {
$return['code'] = 0;
// return $content;
} else {
$return['code'] = 1001;
$return['message'] = $reason;
$this->message = $reason;
// return false;
}
return $return;
} else {
$return['code'] = 1001;
$return['message'] = $reason;
$this->message = $reason;
return $return;
return false;
}
} catch (\Exception $e) {
// dump($e);
if ($e->getMessage()) {
$message = $e->getMessage();
// dump($e->getMessage());
// dump($e->getCode());
// dd($e);
switch ($e->getCode()) {
case 500:
case 404:
break;
}
$this->message = $message;
} else {
if ($e->hasResponse()) {
$exception = (string)$e->getResponse()->getBody();
$exception = json_decode($exception);
$json = new JsonResponse($exception, $e->getCode());
$data = $json->getData();
$this->message = $data->error_msg;
} else {
dd(new JsonResponse($e->getMessage(), 503));
return new JsonResponse($e->getMessage(), 503);
}
return false;
}
// if ($throwable instanceof ClientException) {
// //doing something
// dd(1);
// return;
// }
// if ($throwable instanceof ServerException) {
// //doing something
// dd(2);
//
// return ;
// }
//doing something
Log::channel('sms')->info('请求错误信息 1:' . $this->message);
return false;
}
}
}