WechatReplyServices.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\services\wechat;
  13. use app\services\BaseServices;
  14. use app\dao\wechat\WechatReplyDao;
  15. use app\services\kefu\KefuServices;
  16. use crmeb\exceptions\AdminException;
  17. use crmeb\services\wechat\ErrorMessage;
  18. use crmeb\services\wechat\Messages;
  19. use crmeb\services\wechat\OfficialAccount;
  20. use EasyWeChat\Kernel\Messages\Image;
  21. use EasyWeChat\Kernel\Messages\News;
  22. use EasyWeChat\Kernel\Messages\Text;
  23. use EasyWeChat\Kernel\Messages\Transfer;
  24. use EasyWeChat\Kernel\Messages\Voice;
  25. use think\db\exception\DataNotFoundException;
  26. use think\db\exception\DbException;
  27. use think\db\exception\ModelNotFoundException;
  28. use think\exception\ValidateException;
  29. use think\Model;
  30. /**
  31. *
  32. * Class UserWechatuserServices
  33. * @package app\services\user
  34. * @mixin WechatReplyDao
  35. */
  36. class WechatReplyServices extends BaseServices
  37. {
  38. /**
  39. * UserWechatuserServices constructor.
  40. * @param WechatReplyDao $dao
  41. */
  42. public function __construct(WechatReplyDao $dao)
  43. {
  44. $this->dao = $dao;
  45. }
  46. /**
  47. * 消息类型
  48. * @return string[]
  49. * @var string[]
  50. */
  51. public function replyType()
  52. {
  53. return ['text', 'image', 'news', 'voice'];
  54. }
  55. /**
  56. * 自定义简单查询总数
  57. * @param array $where
  58. * @return int
  59. */
  60. public function getCount(array $where): int
  61. {
  62. return $this->dao->getCount($where);
  63. }
  64. /**
  65. * 复杂条件搜索列表
  66. * @param array $where
  67. * @param string $field
  68. * @return array
  69. */
  70. public function getWhereUserList(array $where, string $field): array
  71. {
  72. [$page, $limit] = $this->getPageValue();
  73. $list = $this->dao->getListByModel($where, $field, $page, $limit);
  74. $count = $this->dao->getCountByWhere($where);
  75. return [$list, $count];
  76. }
  77. /**
  78. * @param $key
  79. * @return array|Model|null
  80. * @throws DataNotFoundException
  81. * @throws DbException
  82. * @throws ModelNotFoundException
  83. */
  84. public function getDataByKey(string $key)
  85. {
  86. /** @var WechatKeyServices $services */
  87. $services = app()->make(WechatKeyServices::class);
  88. $data = $services->getOne(['keys' => $key]);
  89. $resdata = $this->dao->getOne(['id' => $data['reply_id'] ?? '']);
  90. $resdata['data'] = isset($resdata['data']) ? json_decode($resdata['data'], true) : [];
  91. $resdata['key'] = $key;
  92. return $resdata;
  93. }
  94. /**
  95. * @param $data
  96. * @param $key
  97. * @param $type
  98. * @param int $status
  99. * @return bool
  100. */
  101. public function redact($data, $id, $key, $type, $status = 1)
  102. {
  103. $method = 'tidy' . ucfirst($type);
  104. if ($id == 'undefined') {
  105. $id = 0;
  106. }
  107. if ((!isset($data['content']) && !isset($data['src'])) || (isset($data['content']) && $data['content'] == '' && isset($data['src']) && $data['src'] == '')) $data = $data['list'][0] ?? [];
  108. try {
  109. $res = $this->{$method}($data, $id);
  110. } catch (\Throwable $e) {
  111. throw new AdminException($e->getMessage());
  112. }
  113. if (!$res) return false;
  114. $arr = [];
  115. /** @var WechatKeyServices $keyServices */
  116. $keyServices = app()->make(WechatKeyServices::class);
  117. $count = $this->dao->getCount(['id' => $id]);
  118. if ($count) {
  119. $keyServices->delete($id, 'reply_id');
  120. $insertData = explode(',', $key);
  121. foreach ($insertData as $k => $v) {
  122. $arr[$k]['keys'] = $v;
  123. $arr[$k]['reply_id'] = $id;
  124. }
  125. $res = $this->dao->update($id, ['type' => $type, 'data' => json_encode($res), 'status' => $status], 'id');
  126. $res1 = $keyServices->saveAll($arr);
  127. if (!$res || !$res1) {
  128. throw new AdminException('保存失败!');
  129. }
  130. } else {
  131. $reply = $this->dao->save([
  132. 'type' => $type,
  133. 'data' => json_encode($res),
  134. 'status' => $status,
  135. ]);
  136. $insertData = explode(',', $key);
  137. foreach ($insertData as $k => $v) {
  138. $arr[$k]['keys'] = $v;
  139. $arr[$k]['reply_id'] = $reply->id;
  140. }
  141. $res = $keyServices->saveAll($arr);
  142. if (!$res) throw new AdminException('保存失败!');
  143. }
  144. return true;
  145. }
  146. /**
  147. * 获取所有关键字
  148. * @param array $where
  149. * @return array
  150. */
  151. public function getKeyAll($where = array())
  152. {
  153. /** @var WechatReplyKeyServices $replyKeyServices */
  154. $replyKeyServices = app()->make(WechatReplyKeyServices::class);
  155. $data = $replyKeyServices->getReplyKeyAll($where);
  156. /** @var WechatKeyServices $keyServices */
  157. $keyServices = app()->make(WechatKeyServices::class);
  158. foreach ($data['list'] as &$item) {
  159. if ($item['data']) $item['data'] = json_decode($item['data'], true);
  160. switch ($item['type']) {
  161. case 'text':
  162. $item['typeName'] = '文字消息';
  163. break;
  164. case 'image':
  165. $item['typeName'] = '图片消息';
  166. break;
  167. case 'news':
  168. $item['typeName'] = '图文消息';
  169. break;
  170. case 'voice':
  171. $item['typeName'] = '声音消息';
  172. break;
  173. }
  174. $keys = $keyServices->getColumn(['reply_id' => $item['id']], 'keys');
  175. $item['key'] = implode(',', $keys);
  176. }
  177. return $data;
  178. }
  179. /**
  180. * 查询一条
  181. * @param int $id
  182. * @return array|null|Model
  183. * @throws DataNotFoundException
  184. * @throws DbException
  185. * @throws ModelNotFoundException
  186. */
  187. public function getKeyInfo(int $id)
  188. {
  189. $resdata = $this->dao->getOne(['id' => $id]);
  190. /** @var WechatKeyServices $keyServices */
  191. $keyServices = app()->make(WechatKeyServices::class);
  192. $keys = $keyServices->getColumn(['reply_id' => $resdata['id']], 'keys');
  193. $resdata['data'] = $resdata['data'] ? json_decode($resdata['data'], true) : [];
  194. $resdata['key'] = implode(',', $keys);
  195. return $resdata;
  196. }
  197. /**
  198. * 整理文本输入的消息
  199. * @param $data
  200. * @param $key
  201. * @return array|bool
  202. */
  203. public function tidyText($data, $id)
  204. {
  205. $res = [];
  206. if (!isset($data['content']) || $data['content'] == '') {
  207. throw new AdminException('请输入回复信息内容');
  208. }
  209. $res['content'] = $data['content'];
  210. return $res;
  211. }
  212. /**
  213. * 整理图片资源
  214. * @param $data
  215. * @param $key
  216. * @return array|bool|mixed
  217. */
  218. public function tidyImage($data, $id)
  219. {
  220. if (!isset($data['src']) || $data['src'] == '') {
  221. throw new AdminException('请上传回复的图片');
  222. }
  223. $reply = $this->dao->get((int)$id);
  224. if ($reply) $reply['data'] = json_decode($reply['data'], true);
  225. if ($reply && isset($reply['data']['src']) && $reply['data']['src'] == $data['src']) {
  226. $res = $reply['data'];
  227. } else {
  228. $res = [];
  229. // 图片转media
  230. $res['src'] = $data['src'];
  231. try {
  232. $material = OfficialAccount::temporaryUpload(url_to_path($data['src']));
  233. } catch (\Throwable $e) {
  234. throw new ValidateException(ErrorMessage::getMessage($e->getMessage()));
  235. }
  236. $res['media_id'] = $material->media_id;
  237. $dataEvent = ['type' => 'image', 'media_id' => $material->media_id, 'path' => $res['src'], 'url' => $material->url ?? ''];
  238. /** @var WechatMediaServices $mateServices */
  239. $mateServices = app()->make(WechatMediaServices::class);
  240. $mateServices->save($dataEvent);
  241. }
  242. return $res;
  243. }
  244. /**
  245. * 整理声音资源
  246. * @param $data
  247. * @param $key
  248. * @return array|bool|mixed
  249. */
  250. public function tidyVoice($data, $id)
  251. {
  252. if (!isset($data['src']) || $data['src'] == '') {
  253. throw new AdminException('请上传回复的声音');
  254. }
  255. $reply = $this->dao->get((int)$id);
  256. if ($reply) $reply['data'] = json_decode($reply['data'], true);
  257. if ($reply && isset($reply['data']['src']) && $reply['data']['src'] == $data['src']) {
  258. $res = $reply['data'];
  259. } else {
  260. $res = [];
  261. // 声音转media
  262. $res['src'] = $data['src'];
  263. try {
  264. $material = OfficialAccount::materialService()->uploadVoice(url_to_path($data['src']));
  265. } catch (\Throwable $e) {
  266. throw new ValidateException(ErrorMessage::getMessage($e->getMessage()));
  267. }
  268. $res['media_id'] = $material['media_id'];
  269. $dataEvent = ['media_id' => $material['media_id'], 'path' => $res['src'], 'type' => 'voice'];
  270. /** @var WechatMediaServices $mateServices */
  271. $mateServices = app()->make(WechatMediaServices::class);
  272. $mateServices->save($dataEvent);
  273. }
  274. return $res;
  275. }
  276. /**
  277. * 整理图文资源
  278. * @param $data
  279. * @param $key
  280. * @return bool
  281. */
  282. public function tidyNews($data, $id = 0)
  283. {
  284. // $data = $data['list'][0];
  285. if (!count($data)) {
  286. throw new AdminException('请选择图文消息');
  287. }
  288. $siteUrl = sys_config('site_url');
  289. if (empty($data['url'])) $data['url'] = $siteUrl . '/pages/extension/news_details/index?id=' . $data['id'];
  290. if (count($data['image_input'])) $data['image'] = $data['image_input'][0];
  291. return $data;
  292. }
  293. /**
  294. * 获取关键字
  295. * @param $key
  296. * @param string $openId
  297. * @return array|Image|News|Text|Transfer|Voice
  298. * @throws DataNotFoundException
  299. * @throws DbException
  300. * @throws ModelNotFoundException
  301. */
  302. public function reply($key, string $openId = '')
  303. {
  304. $res = $this->dao->getKey($key);
  305. if (empty($res)) {
  306. /** @var KefuServices $services */
  307. $services = app()->make(KefuServices::class);
  308. $services->replyTransferService($key, $openId);
  309. return Messages::transfer();
  310. }
  311. return $this->replyDataByMessage($res->toArray());
  312. }
  313. /**
  314. * 根据关键字内容返回对应的内容
  315. * @param array $res
  316. * @return array|Image|News|Text|Voice
  317. */
  318. public function replyDataByMessage(array $res)
  319. {
  320. $res['data'] = json_decode($res['data'], true);
  321. if ($res['type'] == 'text') {
  322. return Messages::textMessage($res['data']['content']);
  323. } else if ($res['type'] == 'image') {
  324. return Messages::imageMessage($res['data']['media_id']);
  325. } else if ($res['type'] == 'news') {
  326. $title = $res['data']['title'] ?? '';
  327. $image = $res['data']['image'] ?? '';
  328. $description = $res['data']['synopsis'] ?? '';
  329. $url = $res['data']['url'] ?? '';
  330. return Messages::newsMessage($title, $description, $url, $image);
  331. } else if ($res['type'] == 'voice') {
  332. return Messages::voiceMessage($res['data']['media_id']);
  333. }
  334. }
  335. }