OfficialAccountReplyLogic.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeadmin快速开发前后端分离管理后台(PHP版)
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
  8. // | github下载:https://github.com/likeshop-github/likeadmin
  9. // | 访问官网:https://www.likeadmin.cn
  10. // | likeadmin团队 版权所有 拥有最终解释权
  11. // +----------------------------------------------------------------------
  12. // | author: likeadminTeam
  13. // +----------------------------------------------------------------------
  14. namespace app\adminapi\logic\channel;
  15. use app\common\enum\OfficialAccountEnum;
  16. use app\common\enum\YesNoEnum;
  17. use app\common\logic\BaseLogic;
  18. use app\common\model\channel\OfficialAccountReply;
  19. use app\common\service\wechat\WeChatConfigService;
  20. use app\common\service\wechat\WeChatOaService;
  21. use think\facade\Log;
  22. /**
  23. * 微信公众号回复逻辑层
  24. * Class OfficialAccountReplyLogic
  25. * @package app\adminapi\logic\channel
  26. */
  27. class OfficialAccountReplyLogic extends BaseLogic
  28. {
  29. /**
  30. * @notes 添加回复(关注/关键词/默认)
  31. * @param $params
  32. * @return bool
  33. * @author 段誉
  34. * @date 2022/3/29 10:57
  35. */
  36. public static function add($params)
  37. {
  38. try {
  39. // 关键字回复排序值须大于0
  40. if ($params['reply_type'] == OfficialAccountEnum::REPLY_TYPE_KEYWORD && $params['sort'] < 0) {
  41. throw new \Exception('排序值须大于或等于0');
  42. }
  43. if ($params['reply_type'] != OfficialAccountEnum::REPLY_TYPE_KEYWORD && $params['status']) {
  44. // 非关键词回复只能有一条记录处于启用状态,所以将该回复类型下的已有记录置为禁用状态
  45. OfficialAccountReply::where(['reply_type' => $params['reply_type']])->update(['status' => YesNoEnum::NO]);
  46. }
  47. OfficialAccountReply::create($params);
  48. return true;
  49. } catch (\Exception $e) {
  50. self::setError($e->getMessage());
  51. return false;
  52. }
  53. }
  54. /**
  55. * @notes 查看回复详情
  56. * @param $params
  57. * @return array
  58. * @author 段誉
  59. * @date 2022/3/29 11:00
  60. */
  61. public static function detail($params)
  62. {
  63. $field = 'id,name,keyword,reply_type,matching_type,content_type,content,status,sort';
  64. $field .= ',reply_type as reply_type_desc, matching_type as matching_type_desc, content_type as content_type_desc, status as status_desc';
  65. return OfficialAccountReply::field($field)->findOrEmpty($params['id'])->toArray();
  66. }
  67. /**
  68. * @notes 编辑回复(关注/关键词/默认)
  69. * @param $params
  70. * @return bool
  71. * @author 段誉
  72. * @date 2022/3/29 11:01
  73. */
  74. public static function edit($params)
  75. {
  76. try {
  77. // 关键字回复排序值须大于0
  78. if ($params['reply_type'] == OfficialAccountEnum::REPLY_TYPE_KEYWORD && $params['sort'] < 0) {
  79. throw new \Exception('排序值须大于或等于0');
  80. }
  81. if ($params['reply_type'] != OfficialAccountEnum::REPLY_TYPE_KEYWORD && $params['status']) {
  82. // 非关键词回复只能有一条记录处于启用状态,所以将该回复类型下的已有记录置为禁用状态
  83. OfficialAccountReply::where(['reply_type' => $params['reply_type']])->update(['status' => YesNoEnum::NO]);
  84. }
  85. OfficialAccountReply::update($params);
  86. return true;
  87. } catch (\Exception $e) {
  88. self::setError($e->getMessage());
  89. return false;
  90. }
  91. }
  92. /**
  93. * @notes 删除回复(关注/关键词/默认)
  94. * @param $params
  95. * @author 段誉
  96. * @date 2022/3/29 11:01
  97. */
  98. public static function delete($params)
  99. {
  100. OfficialAccountReply::destroy($params['id']);
  101. }
  102. /**
  103. * @notes 更新排序
  104. * @param $params
  105. * @author 段誉
  106. * @date 2022/3/29 11:01
  107. */
  108. public static function sort($params)
  109. {
  110. $params['sort'] = $params['new_sort'];
  111. OfficialAccountReply::update($params);
  112. }
  113. /**
  114. * @notes 更新状态
  115. * @param $params
  116. * @author 段誉
  117. * @date 2022/3/29 11:01
  118. */
  119. public static function status($params)
  120. {
  121. $reply = OfficialAccountReply::findOrEmpty($params['id']);
  122. $reply->status = !$reply->status;
  123. $reply->save();
  124. }
  125. /**
  126. * @notes 微信公众号回调
  127. * @return \Psr\Http\Message\ResponseInterface|void
  128. * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
  129. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  130. * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
  131. * @throws \ReflectionException
  132. * @throws \Throwable
  133. * @author 段誉
  134. * @date 2023/2/27 14:38\
  135. */
  136. public static function index()
  137. {
  138. $server = (new WeChatOaService())->getServer();
  139. // 事件
  140. $server->addMessageListener(OfficialAccountEnum::MSG_TYPE_EVENT, function ($message, \Closure $next) {
  141. Log::write(json_encode($message,JSON_UNESCAPED_UNICODE));
  142. switch ($message['Event']) {
  143. case OfficialAccountEnum::EVENT_SUBSCRIBE: // 关注事件
  144. $replyContent = OfficialAccountReply::where([
  145. 'reply_type' => OfficialAccountEnum::REPLY_TYPE_FOLLOW,
  146. 'status' => YesNoEnum::YES
  147. ])
  148. ->value('content');
  149. if ($replyContent) {
  150. return $replyContent;
  151. }
  152. break;
  153. case OfficialAccountEnum::EVENT_UNSUBSCRIBE: // 取消关注事件
  154. (new WeChatOaService())->getUserInfo($message['FromUserName']);
  155. break;
  156. }
  157. return $next($message);
  158. });
  159. // 文本
  160. $server->addMessageListener(OfficialAccountEnum::MSG_TYPE_TEXT, function ($message, \Closure $next) {
  161. $replyList = OfficialAccountReply::where([
  162. 'reply_type' => OfficialAccountEnum::REPLY_TYPE_KEYWORD,
  163. 'status' => YesNoEnum::YES
  164. ])
  165. ->order('sort asc')
  166. ->select();
  167. $replyContent = '';
  168. foreach ($replyList as $reply) {
  169. switch ($reply['matching_type']) {
  170. case OfficialAccountEnum::MATCHING_TYPE_FULL:
  171. $reply['keyword'] === $message['Content'] && $replyContent = $reply['content'];
  172. break;
  173. case OfficialAccountEnum::MATCHING_TYPE_FUZZY:
  174. stripos($message['Content'], $reply['keyword']) !== false && $replyContent = $reply['content'];
  175. break;
  176. }
  177. if ($replyContent) {
  178. break; // 得到回复文本,中止循环
  179. }
  180. }
  181. //消息回复为空的话,找默认回复
  182. if (empty($replyContent)) {
  183. $replyContent = static::getDefaultReply();
  184. }
  185. if ($replyContent) {
  186. return $replyContent;
  187. }
  188. return $next($message);
  189. });
  190. return $server->serve();
  191. }
  192. /**
  193. * @notes 默认回复信息
  194. * @return mixed
  195. * @author 段誉
  196. * @date 2023/2/27 14:36
  197. */
  198. public static function getDefaultReply()
  199. {
  200. return OfficialAccountReply::where([
  201. 'reply_type' => OfficialAccountEnum::REPLY_TYPE_DEFAULT,
  202. 'status' => YesNoEnum::YES
  203. ])
  204. ->value('content');
  205. }
  206. }