WechatReplyServices.php 12 KB

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