YunxinSmsService.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. <?php
  2. /**
  3. * @package merchant
  4. *
  5. * @author xaboy
  6. * @day 2020-05-18
  7. *
  8. *
  9. */
  10. namespace crmeb\services;
  11. use app\common\dao\system\sms\SmsRecordDao;
  12. use app\common\repositories\merchant\apply\MerchantHaikeApplyRepository;
  13. use app\common\repositories\store\broadcast\BroadcastRoomRepository;
  14. use app\common\repositories\store\order\StoreGroupOrderRepository;
  15. use app\common\repositories\store\order\StoreOrderRepository;
  16. use app\common\repositories\store\order\StoreRefundOrderRepository;
  17. use app\common\repositories\store\service\StoreServiceRepository;
  18. use app\common\repositories\system\config\ConfigValueRepository;
  19. use app\traits\HaikeApiRequest;
  20. use crmeb\exceptions\SmsException;
  21. use FormBuilder\Exception\FormBuilderException;
  22. use FormBuilder\Factory\Elm;
  23. use FormBuilder\Form;
  24. use think\exception\ValidateException;
  25. use think\facade\Config;
  26. use think\facade\Log;
  27. use think\facade\Route;
  28. /**
  29. * Class YunxinSmsService
  30. * @package crmeb\services
  31. * @author xaboy
  32. * @day 2020-05-18
  33. */
  34. class YunxinSmsService
  35. {
  36. use HaikeApiRequest;
  37. /**
  38. * api
  39. */
  40. const API = 'https://sms.crmeb.net/api/';
  41. /**
  42. * @var array
  43. */
  44. protected $config;
  45. /**
  46. * YunxinSmsService constructor.
  47. * @param array $config
  48. */
  49. public function __construct(array $config = [])
  50. {
  51. $this->config = $config;
  52. if (isset($this->config['sms_token'])) {
  53. $this->config['sms_token'] = $this->getToken();
  54. }
  55. }
  56. public static function sendMessage($tempId, $id)
  57. {
  58. if ($tempId == 'DELIVER_GOODS_CODE') {
  59. if (!systemConfig('sms_fahuo_status')) return;
  60. $order = app()->make(StoreOrderRepository::class)->get($id);
  61. if (!$order || !$order->user_phone) return;
  62. $nickname = $order->user->nickname;
  63. $store_name = $order->orderProduct[0]['product']['store_name'] . count($order->orderProduct) ? '等' : '';
  64. $order_id = $order->order_sn;
  65. self::create()->send($order->user_phone, $tempId, compact('nickname', 'store_name', 'order_id'));
  66. } else if ($tempId == 'TAKE_DELIVERY_CODE') {
  67. if (!systemConfig('sms_take_status')) return;
  68. $order = app()->make(StoreOrderRepository::class)->get($id);
  69. if (!$order || !$order->user_phone) return;
  70. $order_id = $order->order_sn;
  71. $store_name = $order->orderProduct[0]['product']['store_name'] . count($order->orderProduct) ? '等' : '';
  72. self::create()->send($order->user_phone, $tempId, compact('store_name', 'order_id'));
  73. } else if ($tempId == 'PAY_SUCCESS_CODE') {
  74. if (!systemConfig('sms_pay_status')) return;
  75. $order = app()->make(StoreGroupOrderRepository::class)->get($id);
  76. if (!$order || !$order->user_phone) return;
  77. $pay_price = $order->pay_price;
  78. $order_id = $order->group_order_sn;
  79. self::create()->send($order->user_phone, $tempId, compact('pay_price', 'order_id'));
  80. } else if ($tempId == 'PRICE_REVISION_CODE') {
  81. if (!systemConfig('sms_revision_status')) return;
  82. $order = app()->make(StoreOrderRepository::class)->get($id);
  83. if (!$order || !$order->user_phone) return;
  84. $pay_price = $order->pay_price;
  85. $order_id = $order->order_sn;
  86. self::create()->send($order->user_phone, $tempId, compact('pay_price', 'order_id'));
  87. } else if ($tempId == 'ORDER_PAY_FALSE') {
  88. if (!systemConfig('sms_pay_false_status')) return;
  89. $order = app()->make(StoreGroupOrderRepository::class)->get($id);
  90. if (!$order || !$order->user_phone) return;
  91. $order_id = $order->group_order_sn;
  92. self::create()->send($order->user_phone, $tempId, compact('order_id'));
  93. } else if ($tempId == 'REFUND_FAIL_CODE') {
  94. if (!systemConfig('sms_refund_fail_status')) return;
  95. $order = app()->make(StoreRefundOrderRepository::class)->get($id);
  96. if (!$order || !$order->order->user_phone) return;
  97. $order_id = $order->refund_order_sn;
  98. $store_name = $order->refundProduct[0]->product['product']['store_name'] . count($order->refundProduct) ? '等' : '';
  99. self::create()->send($order->order->user_phone, $tempId, compact('order_id', 'store_name'));
  100. } else if ($tempId == 'REFUND_SUCCESS_CODE') {
  101. if (!systemConfig('sms_refund_success_status')) return;
  102. $order = app()->make(StoreRefundOrderRepository::class)->get($id);
  103. if (!$order || $order->order->user_phone) return;
  104. $order_id = $order->refund_order_sn;
  105. $store_name = $order->refundProduct[0]->product['product']['store_name'] . count($order->refundProduct) ? '等' : '';
  106. self::create()->send($order->order->user_phone, $tempId, compact('order_id', 'store_name'));
  107. } else if ($tempId == 'REFUND_CONFORM_CODE') {
  108. if (!systemConfig('sms_refund_confirm_status')) return;
  109. $order = app()->make(StoreRefundOrderRepository::class)->get($id);
  110. if (!$order || !$order->order->user_phone) return;
  111. $order_id = $order->order_sn;
  112. $store_name = $order->refundProduct[0]->product['product']['store_name'] . count($order->refundProduct) ? '等' : '';
  113. self::create()->send($order->order->user_phone, $tempId, compact('order_id', 'store_name'));
  114. } else if ($tempId == 'ADMIN_PAY_SUCCESS_CODE') {
  115. if (!systemConfig('sms_admin_pay_status')) return;
  116. $order = app()->make(StoreGroupOrderRepository::class)->get($id);
  117. if (!$order) return;
  118. foreach ($order->orderList as $_order) {
  119. self::sendMerMessage($_order->mer_id, $tempId, [
  120. 'order_id' => $_order->order_sn
  121. ]);
  122. }
  123. } else if ($tempId == 'ADMIN_RETURN_GOODS_CODE') {
  124. if (!systemConfig('sms_admin_return_status')) return;
  125. $order = app()->make(StoreRefundOrderRepository::class)->get($id);
  126. if (!$order) return;
  127. self::sendMerMessage($order->mer_id, $tempId, [
  128. 'order_id' => $order->refund_order_sn
  129. ]);
  130. } else if ($tempId == 'ADMIN_TAKE_DELIVERY_CODE') {
  131. if (!systemConfig('sms_admin_take_status')) return;
  132. $order = app()->make(StoreOrderRepository::class)->get($id);
  133. if (!$order) return;
  134. self::sendMerMessage($order->mer_id, $tempId, [
  135. 'order_id' => $order->order_sn
  136. ]);
  137. } else if ($tempId == 'ADMIN_DELIVERY_CODE') {
  138. if (!systemConfig('sms_admin_postage_status')) return;
  139. $order = app()->make(StoreOrderRepository::class)->get($id);
  140. if (!$order) return;
  141. self::sendMerMessage($order->mer_id, $tempId, [
  142. 'order_id' => $order->order_sn
  143. ]);
  144. } else if ($tempId == 'BROADCAST_ROOM_CODE') {
  145. if (!systemConfig('sms_broadcast_room_status')) return;
  146. $room = app()->make(BroadcastRoomRepository::class)->get($id);
  147. if (!$room) return;
  148. self::create()->send($room->phone, $tempId, [
  149. 'wechat' => $room->anchor_wechat
  150. ]);
  151. } else if ($tempId == 'HAIKE_CHECK_FAIL_CODE') {
  152. if (!systemConfig('haike_check_merchant_status')) return;
  153. $order = app()->make(MerchantHaikeApplyRepository::class)->get($id);
  154. if (!$order || !$order->phone) return;
  155. self::create()->send($order->phone, $tempId, [
  156. 'date' => $order->create_time,
  157. 'mer' => $order->mer_name,
  158. 'reason' => $order->check_result,
  159. ]);
  160. } else if ($tempId == 'HAIKE_CHECK_WX_AUTH_SUCCESS_CODE') {
  161. if (!systemConfig('haike_check_merchant_status')) return;
  162. $order = app()->make(MerchantHaikeApplyRepository::class)->get($id);
  163. if (!$order || !$order->phone) return;
  164. self::create()->send($order->phone, $tempId, [
  165. 'mer' => $order->mer_name,
  166. ]);
  167. }
  168. }
  169. public static function sendMerMessage($merId, string $tempId, array $data)
  170. {
  171. $noticeServiceInfo = app()->make(StoreServiceRepository::class)->getNoticeServiceInfo($merId);
  172. $yunxinSmsService = self::create();
  173. foreach ($noticeServiceInfo as $service) {
  174. if (!$service['phone']) continue;
  175. $data['nickname'] = $service['nickname'];
  176. $yunxinSmsService->send($service['phone'], $tempId, $data);
  177. }
  178. }
  179. /**
  180. * @return string
  181. * @author xaboy
  182. * @day 2020-05-18
  183. */
  184. protected function getToken()
  185. {
  186. return md5($this->config['sms_account'] . $this->config['sms_token']);
  187. }
  188. /**
  189. * @author xaboy
  190. * @day 2020-05-18
  191. */
  192. public function checkConfig()
  193. {
  194. if (!isset($this->config['sms_account']) || !$this->config['sms_account']) {
  195. throw new ValidateException('请登录短信账户');
  196. }
  197. if (!isset($this->config['sms_token']) || !$this->config['sms_token']) {
  198. throw new ValidateException('请登录短信账户');
  199. }
  200. }
  201. /**
  202. * 发送注册验证码
  203. * @param $phone
  204. * @return mixed
  205. */
  206. public function captcha($phone)
  207. {
  208. return json_decode(HttpService::getRequest(self::API . 'sms/captcha', compact('phone')), true);
  209. }
  210. /**
  211. * 短信注册
  212. * @param $account
  213. * @param $password
  214. * @param $url
  215. * @param $phone
  216. * @param $code
  217. * @param $sign
  218. * @return mixed
  219. */
  220. public function register($account, $password, $url, $phone, $code, $sign)
  221. {
  222. return $this->registerData(compact('account', 'password', 'url', 'phone', 'code', 'sign'));
  223. }
  224. /**
  225. * @param array $data
  226. * @return mixed
  227. * @author xaboy
  228. * @day 2020-05-18
  229. */
  230. public function registerData(array $data)
  231. {
  232. return json_decode(HttpService::postRequest(self::API . 'sms/register', $data), true);
  233. }
  234. /**
  235. * 公共短信模板列表
  236. * @param array $data
  237. * @return mixed
  238. */
  239. public function publictemp(array $data = [])
  240. {
  241. $this->checkConfig();
  242. $data['account'] = $this->config['sms_account'];
  243. $data['token'] = $this->config['sms_token'];
  244. $data['source'] = 'crmeb_merchant';
  245. return json_decode(HttpService::postRequest(self::API . 'sms/publictemp', $data), true);
  246. }
  247. /**
  248. * 公共短信模板添加
  249. * @param $id
  250. * @param $tempId
  251. * @return mixed
  252. */
  253. public function use($id, $tempId)
  254. {
  255. $this->checkConfig();
  256. $data = [
  257. 'account' => $this->config['sms_account'],
  258. 'token' => $this->config['sms_token'],
  259. 'id' => $id,
  260. 'tempId' => $tempId,
  261. ];
  262. return json_decode(HttpService::postRequest(self::API . 'sms/use', $data), true);
  263. }
  264. /**
  265. * @param string $templateId
  266. * @return mixed
  267. * @author xaboy
  268. * @day 2020-05-18
  269. */
  270. public function getTemplateCode(string $templateId)
  271. {
  272. return Config::get('sms.template_id.' . $templateId);
  273. }
  274. /**
  275. * 发送短信
  276. * @param string $phone
  277. * @param string $templateId
  278. * @param array $data
  279. * @return bool|string
  280. * @throws SmsException
  281. */
  282. public function send(string $phone, string $templateId, array $data = [])
  283. {
  284. if (!$phone) {
  285. throw new SmsException('Mobile number cannot be empty');
  286. }
  287. $this->checkConfig();
  288. $formData['uid'] = $this->config['sms_account'];
  289. $formData['token'] = $this->config['sms_token'];
  290. $formData['mobile'] = $phone;
  291. $formData['template'] = $this->getTemplateCode($templateId);
  292. if (is_null($formData['template']))
  293. throw new SmsException('Missing template number');
  294. if (!empty($data)) {
  295. $formData['param'] = json_encode($data);
  296. } else {
  297. $formData['param'] = "";
  298. }
  299. $resource = json_decode(HttpService::postRequest(self::API . 'sms/send', $formData), true);
  300. if ($resource['status'] === 400) {
  301. throw new SmsException($resource['msg']);
  302. }else{
  303. app()->make(SmsRecordDao::class)->create([
  304. 'uid' => $formData['uid'],
  305. 'phone' => $phone,
  306. 'content' => $resource['data']['content'],
  307. 'template' => $resource['data']['template'],
  308. 'record_id' => $resource['data']['id']
  309. ]);
  310. }
  311. return $resource;
  312. }
  313. /**
  314. * 账号信息
  315. * @return mixed
  316. */
  317. public function count()
  318. {
  319. $this->checkConfig();
  320. return json_decode(HttpService::postRequest(self::API . 'sms/userinfo', [
  321. 'account' => $this->config['sms_account'],
  322. 'token' => $this->config['sms_token']
  323. ]), true);
  324. }
  325. /**
  326. * 支付套餐
  327. * @param $page
  328. * @param $limit
  329. * @return mixed
  330. */
  331. public function meal($page, $limit)
  332. {
  333. return json_decode(HttpService::getRequest(self::API . 'sms/meal', [
  334. 'page' => $page,
  335. 'limit' => $limit
  336. ]), true);
  337. }
  338. /**
  339. * 支付码
  340. * @param $payType
  341. * @param $mealId
  342. * @param $price
  343. * @param $attach
  344. * @param $notify
  345. * @return mixed
  346. */
  347. public function pay($payType, $mealId, $price, $attach, $notify = null)
  348. {
  349. $this->checkConfig();
  350. $data['uid'] = $this->config['sms_account'];
  351. $data['token'] = $this->config['sms_token'];
  352. $data['payType'] = $payType;
  353. $data['mealId'] = $mealId;
  354. $data['notify'] = $notify ?? Route::buildUrl('SmsNotify')->build();
  355. $data['price'] = $price;
  356. $data['attach'] = $attach;
  357. return json_decode(HttpService::postRequest(self::API . 'sms/mealpay', $data), true);
  358. }
  359. /**
  360. * 申请模板消息
  361. * @param $title
  362. * @param $content
  363. * @param $type
  364. * @return mixed
  365. */
  366. public function apply($title, $content, $type)
  367. {
  368. $this->checkConfig();
  369. $data['account'] = $this->config['sms_account'];
  370. $data['token'] = $this->config['sms_token'];
  371. $data['title'] = $title;
  372. $data['content'] = $content;
  373. $data['type'] = $type;
  374. return json_decode(HttpService::postRequest(self::API . 'sms/apply', $data), true);
  375. }
  376. /**
  377. * 短信模板列表
  378. * @param $data
  379. * @return mixed
  380. */
  381. public function template(array $data)
  382. {
  383. $this->checkConfig();
  384. return json_decode(HttpService::postRequest(self::API . 'sms/template', $data + [
  385. 'account' => $this->config['sms_account'], 'token' => $this->config['sms_token']
  386. ]), true);
  387. }
  388. /**
  389. * 获取短息记录状态
  390. * @param $record_id
  391. * @return mixed
  392. */
  393. public function getStatus(array $record_id)
  394. {
  395. return json_decode(HttpService::postRequest(self::API . 'sms/status', [
  396. 'record_id' => json_encode($record_id)
  397. ]), true);
  398. }
  399. /**
  400. * @return YunxinSmsService
  401. * @author xaboy
  402. * @day 2020-05-18
  403. */
  404. public static function create()
  405. {
  406. /** @var ConfigValueRepository $make */
  407. $make = app()->make(ConfigValueRepository::class);
  408. $config = $make->more(['sms_account', 'sms_token'], 0);
  409. return new static($config);
  410. }
  411. /**
  412. * @param string $sms_account
  413. * @param string $sms_token
  414. * @return $this
  415. * @author xaboy
  416. * @day 2020-05-18
  417. */
  418. public function setConfig(string $sms_account, string $sms_token)
  419. {
  420. $this->config = compact('sms_token', 'sms_account');
  421. $this->config['sms_token'] = $this->getToken();
  422. return $this;
  423. }
  424. /**
  425. * @return Form
  426. * @throws FormBuilderException
  427. * @author xaboy
  428. * @day 2020-05-18
  429. */
  430. public function form()
  431. {
  432. return Elm::createForm(Route::buildUrl('smsCreate')->build(), [
  433. Elm::input('title', '模板名称'),
  434. Elm::input('content', '模板内容')->type('textarea'),
  435. Elm::radio('type', '模板类型', 1)->options([['label' => '验证码', 'value' => 1], ['label' => '通知', 'value' => 2], ['label' => '推广', 'value' => 3]])
  436. ])->setTitle('申请短信模板');
  437. }
  438. /**
  439. * @return mixed
  440. * @author xaboy
  441. * @day 2020-05-18
  442. */
  443. public function account()
  444. {
  445. $this->checkConfig();
  446. return $this->config['sms_account'];
  447. }
  448. public function smsChange($data)
  449. {
  450. $this->checkConfig();
  451. $data['account'] = $this->config['sms_account'];
  452. return json_decode(HttpService::postRequest(self::API . 'sms/modify',$data),true);
  453. }
  454. }