Serve.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. namespace addons\shopro\controller\wechat;
  3. use addons\shopro\facade\Wechat;
  4. use app\admin\model\shopro\wechat\Reply;
  5. use app\admin\model\shopro\wechat\Material;
  6. use EasyWeChat\Kernel\Messages\Image;
  7. use EasyWeChat\Kernel\Messages\Media;
  8. use EasyWeChat\Kernel\Messages\Text;
  9. use EasyWeChat\Kernel\Messages\News;
  10. use EasyWeChat\Kernel\Messages\NewsItem;
  11. use EasyWeChat\Kernel\Messages\Video;
  12. use EasyWeChat\Kernel\Messages\Voice;
  13. use app\admin\model\shopro\ThirdOauth;
  14. class Serve
  15. {
  16. protected $noNeedLogin = ['*'];
  17. protected $noNeedRight = ['*'];
  18. protected $wechat = null;
  19. protected $openid = "";
  20. // 微信api
  21. public function index()
  22. {
  23. $this->wechat = Wechat::officialAccountManage();
  24. $this->wechat->server->push(function ($message) {
  25. $this->openid = $message['FromUserName'];
  26. return $this->reply($message);
  27. });
  28. $this->wechat->server->serve()->send();
  29. }
  30. // 回复消息
  31. private function reply($message)
  32. {
  33. switch ($message['MsgType']) {
  34. // 收到事件
  35. case 'event':
  36. switch ($message['Event']) {
  37. // 订阅(关注)事件
  38. case 'subscribe':
  39. $data = ['openid' => $this->openid];
  40. \think\Hook::listen('wechat_subscribe', $data);
  41. $reply = Reply::where('group', 'subscribe')->enable()->find();
  42. if ($reply) {
  43. $this->getReplyData($reply);
  44. }
  45. if (!empty($message['EventKey'])) {
  46. $event = str_replace('qrscene_', '', $message['EventKey']);
  47. return $this->scanQrcode($event);
  48. }
  49. break;
  50. // 取消订阅(关注)事件
  51. case 'unsubscribe':
  52. $data = ['openid' => $this->openid];
  53. \think\Hook::listen('wechat_unsubscribe', $data);
  54. break;
  55. //自定义菜单事件
  56. case 'CLICK':
  57. $event = explode('|', $message['EventKey']);
  58. return $this->getClickData($event);
  59. break;
  60. case 'SCAN':
  61. if (!empty($event = $message['EventKey'])) {
  62. return $this->scanQrcode($event);
  63. }
  64. break;
  65. }
  66. break;
  67. // 收到文本消息
  68. case 'text':
  69. //检测关键字回复
  70. $keywords = $message['Content'];
  71. $reply = Reply::where('group', 'keywords')->enable()->where('find_in_set(:keywords, keywords)', ['keywords' => $keywords])->find();
  72. if ($reply) {
  73. return $this->getReplyData($reply);
  74. }
  75. break;
  76. // 收到图片消息 暂不支持此消息类型
  77. case 'image':
  78. // 收到语音消息 暂不支持此消息类型
  79. case 'voice':
  80. // 收到视频消息 暂不支持此消息类型
  81. case 'video':
  82. // 收到坐标消息 暂不支持此消息类型
  83. case 'location':
  84. // 收到链接消息 暂不支持此消息类型
  85. case 'link':
  86. // 收到文件消息 暂不支持此消息类型
  87. case 'file':
  88. // 默认回复消息
  89. default:
  90. $reply = Reply::where('group', 'default')->enable()->find();
  91. if ($reply) {
  92. return $this->getReplyData($reply);
  93. }
  94. }
  95. return true;
  96. }
  97. // 组装回复消息的数据结构
  98. private function getReplyData($reply)
  99. {
  100. switch ($reply->type) {
  101. // 回复文本消息
  102. case 'text':
  103. $material = Material::find($reply->content);
  104. if ($material) {
  105. $data = new Text($material->content);
  106. }
  107. break;
  108. // 回复链接卡片
  109. case 'link':
  110. $material = Material::find($reply->content);
  111. if ($material) {
  112. $link = $material->content;
  113. $items = new NewsItem([
  114. 'title' => $link['title'],
  115. 'description' => $link['description'],
  116. 'url' => $link['url'],
  117. 'image' => cdnurl($link['image'], true),
  118. ]);
  119. $data = new News([$items]);
  120. }
  121. break;
  122. case 'video':
  123. $data = new Video($reply->content);
  124. break;
  125. case 'voice':
  126. $data = new Voice($reply->content);
  127. break;
  128. case 'image':
  129. $data = new Image($reply->content);
  130. break;
  131. case 'news':
  132. $data = new Media($reply->content, 'mpnews');
  133. break;
  134. }
  135. // 使用客服消息发送
  136. $this->wechat->customer_service->message($data)->to($this->openid)->send();
  137. }
  138. // 组装事件消息的数据结构
  139. private function getClickData($event)
  140. {
  141. switch ($event[0]) {
  142. // 回复文本消息
  143. case 'text':
  144. $material = Material::find($event[1]);
  145. if ($material) {
  146. $data = new Text($material->content);
  147. }
  148. break;
  149. // 回复链接卡片
  150. case 'link':
  151. $material = Material::find($event[1]);
  152. if ($material) {
  153. $link = $material->content;
  154. $items = new NewsItem([
  155. 'title' => $link['title'],
  156. 'description' => $link['description'],
  157. 'url' => $link['url'],
  158. 'image' => cdnurl($link['image'], true),
  159. ]);
  160. $data = new News([$items]);
  161. }
  162. break;
  163. case 'video':
  164. $data = new Video($event[1]);
  165. break;
  166. case 'voice':
  167. $data = new Voice($event[1]);
  168. break;
  169. case 'image':
  170. $data = new Image($event[1]);
  171. break;
  172. case 'news':
  173. $data = new Media($event[1], 'mpnews');
  174. break;
  175. }
  176. // 使用客服消息发送
  177. $this->wechat->customer_service->message($data)->to($this->openid)->send();
  178. }
  179. // 扫一扫微信二维码
  180. private function scanQrcode($eventStr)
  181. {
  182. list($flag, $event, $eventId) = explode('.', $eventStr);
  183. $text = '';
  184. if (empty($flag) || empty($event)) {
  185. $text = '未找到对应扫码事件';
  186. } else {
  187. switch ($event) {
  188. case 'login':
  189. // $text = $this->login($eventId);
  190. break;
  191. case 'bind':
  192. $text = $this->bind($eventId);
  193. break;
  194. }
  195. }
  196. if (!empty($text)) {
  197. $this->wechat->customer_service->message(new Text($text))->to($this->openid)->send();
  198. }
  199. return;
  200. }
  201. // 扫一扫绑定管理员
  202. private function bind($eventId)
  203. {
  204. $cacheKey = "wechatAdmin.bind.{$eventId}";
  205. $cacheValue = cache($cacheKey);
  206. if (empty($cacheValue)) {
  207. return '二维码已过期,请重新扫码';
  208. }
  209. $thirdOauth = ThirdOauth::where([
  210. 'provider' => 'wechat',
  211. 'platform' => 'admin',
  212. 'openid' => $this->openid
  213. ])->find();
  214. if ($thirdOauth && $thirdOauth->admin_id !== 0) {
  215. return '该微信账号已绑定其他管理员';
  216. }
  217. cache($cacheKey, ['id' => $this->openid], 1 * 60);
  218. return '正在绑定管理员快捷登录';
  219. }
  220. }