Преглед на файлове

add: 支持企业微信机器人通知

joe преди 4 години
родител
ревизия
ed490e876a
променени са 5 файла, в които са добавени 188 реда и са изтрити 6 реда
  1. 4 0
      config/app.php
  2. 88 0
      crmeb/services/QyWeixinService.php
  3. 82 0
      crmeb/services/async/WechatNotify.php
  4. 2 0
      crmeb/subscribes/TaskSubscribe.php
  5. 12 6
      crmeb/utils/Redis.php

+ 4 - 0
config/app.php

@@ -42,4 +42,8 @@ return [
     'error_message'    => '页面错误!请稍后再试~',
     // 显示错误信息
     'show_error_msg'   => false,
+    // 企业微信机器人
+    'redis_robot_msg_key' => 'qywechatpush',
+    // 亚里士多得
+    'qy_weixin_robot_aristotle' => 'a17b9d56-b566-404b-904e-4476b95dc8d7',
 ];

+ 88 - 0
crmeb/services/QyWeixinService.php

@@ -0,0 +1,88 @@
+<?php
+namespace crmeb\services;
+
+/**
+ * 使用
+ *      $key = Config::get('app.qy_weixin_robot_aristotle');
+ *      $svc = QyWeixinService::instance();
+ *      $svc->key($key)->markdown("### good\n>hhhh")->post();
+ *
+ * Class QyWeixinService
+ * @package crmeb\services
+ */
+class QyWeixinService {
+    // api addr
+    protected $addr = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=';
+
+    // robot key
+    protected $key = '';
+    protected $content = '';
+    protected $msgtype = 'text';
+
+    protected static $inst = null;
+
+    public static function instance()
+    {
+        if (is_null(self::$inst)) {
+            self::$inst = new self();
+        }
+        return self::$inst;
+    }
+
+    public function key(string $key)
+    {
+        $this->key = $key;
+        return $this;
+    }
+
+    public function text(string $text)
+    {
+        $this->msgtype = 'text';
+        $this->content = $text;
+        return $this;
+    }
+
+    /**
+     * # title
+     * ###### title6
+     * **bold**
+     * [link](url)
+     * `code`
+     * > refer
+     * <font color="info"/"comment"/"warning">words</font>
+     * @param string $md markdown text
+     * @return $this
+     */
+    public function markdown(string $md)
+    {
+        $this->msgtype = 'markdown';
+        $this->content = $md;
+        return $this;
+    }
+
+    public function post()
+    {
+        $data = [
+            'msgtype' => $this->msgtype,
+            $this->msgtype => [
+                'content' => $this->content,
+            ],
+        ];
+        $url = $this->addr . $this->key;
+        $ret = json_decode(QyWeixinService::post_json($url, $data), true);
+        return isset($ret['errcode']) && $ret['errcode'] == 0;
+    }
+
+    public function post_json(string $url, array $data, array $headers=[], int $timeout=15)
+    {
+        $h = curl_init();
+        curl_setopt($h, CURLOPT_URL, $url);
+        curl_setopt($h, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($h, CURLOPT_POST, true);
+        $js = json_encode($data);
+        curl_setopt($h, CURLOPT_POSTFIELDS, $js);
+        $ret = curl_exec($h);
+        curl_close($h);
+        return $ret;
+    }
+}

+ 82 - 0
crmeb/services/async/WechatNotify.php

@@ -0,0 +1,82 @@
+<?php
+
+namespace crmeb\services\async;
+
+use crmeb\utils\Redis;
+use crmeb\services\QyWeixinService;
+use think\facade\Config;
+
+/**
+ * 异步机器人通知.
+ * 消息格式:
+ * {"type":"type_name", "key":"1234", "desc":{}}
+ * Class WechatNotify
+ */
+class WechatNotify
+{
+    public static $TYPE_ORDER = 'order';
+    public static $TYPE_REFUND = 'refund';
+    public static $TYPE_WITHDRAW = 'withdraw';
+    public static $TYPE_MESSAGE = 'message';
+    public static $TYPE_COMPLIANT = 'compliant';
+    public static $TYPE_RECHARGE = 'recharge';
+    public static $TYPE_COMMENT = 'comment';
+
+    public static function push(string $type, string $key, string $desc = '')
+    {
+        $r = Redis::instance();
+        $rk = Config::get('app.redis_robot_msg_key');
+        $arr = [
+            'type' => $type,
+        ];
+        if ($key) {
+            $arr['key'] = $key;
+        }
+        if ($desc) {
+            $arr['desc'] = $desc;
+        }
+
+        $json = json_encode($arr);
+
+        $r->lpush($rk, $json);
+    }
+
+    /**
+     * this function should be called in timer process.
+     */
+    public static function notify()
+    {
+        $r = Redis::instance();
+        $k = Config::get('app.redis_robot_msg_key');
+        $aristotle = Config::get('app.qy_weixin_robot_aristotle');
+        $supported_types = [
+            'refund' => '退款',
+            'order' => '订单',
+            'compliant' => '反馈建议',
+            'withdraw' => '提现请求',
+            'message' => '客服消息',
+            'recharge' => '充值',
+            'comment' => '商品评论',
+        ];
+        $total = $r->llen($k);
+        while ($total > 0) {
+            $json = $r->rpop($k);
+            $arr = json_decode($json, true);
+            if (!isset($arr['type']) || !is_string($arr['type'])) {
+                continue;
+            }
+            $type = $arr['type'];
+            $key = isset($arr['key']) ? $arr['key'] : '';
+            if (!isset($supported_types[$type])) {
+                continue;
+            }
+            $desc = isset($arr['desc']) ? $arr['desc'] : '';
+            $msg = $supported_types[$type];
+            $md = "### 新" . $msg . "\n>key: " . $key
+                . "\n备注:" . $desc;
+            QyWeixinService::instance()->key($aristotle)
+                ->markdown($md)->post();
+            $total = $r->llen($k);
+        }// while
+    }//
+}

+ 2 - 0
crmeb/subscribes/TaskSubscribe.php

@@ -8,6 +8,7 @@ use app\models\store\StoreOrder;
 use app\models\store\StorePink;
 use app\models\user\UserToken;
 use think\facade\Db;
+use crmeb\services\async\WechatNotify;
 
 /**
  * 定时任务类
@@ -40,6 +41,7 @@ class TaskSubscribe
      */
     public function onTask_10()
     {
+        WechatNotify::notify();
     }
 
     /**

+ 12 - 6
crmeb/utils/Redis.php

@@ -1,10 +1,7 @@
 <?php
-
 namespace crmeb\utils;
 
-use think\facade\Config;
 use think\facade\Cache;
-
 /**
  * Redis 操作
  * Class Redis
@@ -71,27 +68,36 @@ class Redis
      * @param mixed ...$value
      * @return bool|int
      */
-    public function push(string $key, ...$value)
+    public function lpush(string $key, ...$value)
     {
         return $this->redis->lPush($this->options['prefix'] . $key, ...$value);
     }
 
+    public function rpush(string $key, ...$value)
+    {
+        return $this->redis->rPush($this->options['prefix'] . $key, ...$value);
+    }
+
     /**
      * 移出并获取列表的第一个元素
      * @param string $key
      * @return string
      */
-    public function pop(string $key)
+    public function lpop(string $key)
     {
         return $this->redis->lPop($this->options['prefix'] . $key);
     }
 
+    public function rpop(string $key)
+    {
+        return $this->redis->rPop($this->options['prefix'] . $key);
+    }
     /**
      * 获取长度
      * @param string $key
      * @return int
      */
-    public function len(string $key)
+    public function llen(string $key)
     {
         return $this->redis->lLen($this->options['prefix'] . $key);
     }