liangji 发表于 2023-9-18 17:25

利用nodejs结合企业微信机器人,定时推送公司收入状况

最近公司需要实时监控超市里面的收入状况,利用微信进行推送给老板
有考虑过用千寻微信框架的
但担心微信会面临封号的危险
所以考虑到利用企业微信群里面的群机器人来进行推送
实现效果如图


实现思路:
一 .

[*]先获取收银软件所执行的SQL语句,因为软件是用的 sql2008数据库
[*]所以利用Microsoft SQL Server Management Studio里面的SQL ServerProfiler对收银软件的sql语句抓包
[*]
[*]打开SQL ServerProfiler后,对“事件选择”这里进行过滤只要下面TSQL 最后点击运行
[*]
[*]接下来打开收银软件的后台,选择对应的要查询的数据的表格进行查询,
[*]
[*]此时回到SQL ServerProfiler 发现出现了一堆sql语句经过筛选对比后 最终发现是下面图中的sql语句
[*]
[*]然后我利用NavicatPremium(个人喜欢用NavicatPremium)将上面的sql语句进行精简后选择对应的数据库,执行sql语句
[*]效果如下:
[*]


二 . 在对数据抓包成功后,下一步进行推送代码的实现,我这里是使用的nodejs作为技术栈

[*]先获取拿到企业微信机器人的Webhook地址,具体方法自行百度
[*]
[*]新建nodejs项目,这里也不多赘述,代码如下,这里连接SQL2008的模块我用的是mssql这个模块,执行npm i mssql 进行安装
[*]const sql = require('mssql');
const request = require('request');
const config = {
user: '数据库用户名',
password: '数据库密码',
server: '数据库的IP地址',
database: '要连接的数据库名字',
options: {
    encrypt: false
}
};
var times = ""
setInterval(() => { //开启一个一秒的定时任务
const currentDate = new Date();
const year = currentDate.getFullYear();
const month = String(currentDate.getMonth() + 1).padStart(2, '0');
const day = String(currentDate.getDate()).padStart(2, '0');
var hour = currentDate.getHours().toString().padStart(2, '0');
if (hour !== times) { //判断现在的“时”是不是和上一个存放在变量times里面的值一样,如果不一样就执行查询发送
    sql.connect(config)
      .then(() => {
      return sql.query(`
          SELECT
            工号 = b.user_id,
            收银员 = b.user_name,
            机构 = LEFT(a.branch_no, 2),
            日期 = LEFT(CONVERT(VARCHAR(10), a.oper_date, 112), CONVERT(INT, '8')),
            总单数 = COUNT(DISTINCT CASE WHEN pos_type = '1' OR pos_type = '2' THEN a.sheet_no ELSE NULL END),
            总收入 = SUM(CASE WHEN pos_type = '1' OR pos_type = '2' OR pos_type = '3' THEN d.allpay_amt ELSE 0 END),
            优惠金额 = SUM(a.pos_org_amt - a.pos_total_amt),
            净收入 = SUM(CASE WHEN pos_type = '1' OR pos_type = '2' OR pos_type = '3' THEN d.allpay_amt ELSE 0 END) - SUM(a.pos_org_amt - a.pos_total_amt),
            现金 = SUM(d.pay01_amt),
            找零 = SUM(d.pay31_amt),
            实收现金 = SUM(d.pay01_amt + d.pay31_amt),
            移动支付 = SUM(d.pay51_amt)
          FROM
            view_pos_sale_master a
            JOIN t_sys_user b ON (b.user_id = a.user_id)
            JOIN view_pos_sale_pay d ON (a.sheet_no = d.sheet_no)
          WHERE
            a.pos_status = '9' AND
            (
            (a.oper_date >= '${year}-${month}-${day}') AND
            (a.oper_date <= '${year}-${month}-${day} 23:59:59.997') AND
            (LEFT(a.branch_no, 2) IN ('00', '*'))
            )
          GROUP BY
            b.user_id,
            b.user_name,
            LEFT(a.branch_no, 2),
            LEFT(CONVERT(VARCHAR(10), a.oper_date, 112), CONVERT(INT, '8'))
      `);
      })
      .then(result => {
      if (result.recordset.length > 0) {
          var detail = `### 超市收入情况!\n
            ### 日期:${result.recordset.日期}\n`
          let allBill = 0
          let allIncome = 0
          for (let i = 0; i < result.recordset.length; i++) {
            allBill = allBill + result.recordset.总单数
            allIncome = allIncome + result.recordset.净收入
            detail += `>------收银员:${result.recordset.收银员}-----\n
            >工号:<font color=\"info\" >${result.recordset.工号}</font>\n
            >总单数:<font color=\"info\" >${result.recordset.总单数}单</font>\n
            >现金:<font color=\"info\" >${result.recordset.现金}元</font>\n
            >找零:<font color=\"info\" >${result.recordset.找零}元</font>\n
            >实收现金:<font color=\"info\" >${result.recordset.实收现金}元</font>\n
            >移动支付:<font color=\"info\" >${result.recordset.移动支付}元</font>\n
            >总收入:<font color=\"info\" >${result.recordset.总收入}元</font>\n
            >优惠金额:<font color=\"info\" >${result.recordset.优惠金额}元</font>\n
            >净收入:<font color=\"info\" >${result.recordset.净收入}元</font>
            `
            if (i === result.recordset.length - 1) {
            detail += `>----------合计----------\n
                >合计总单数:<font color=\"warning\" >${allBill}单</font>\n
                >合计总收入:<font color=\"warning\" >${allIncome.toFixed(2)}元</font>\n
                `
            }
          }
          var data = {
            "msgtype": "markdown",
            "markdown": {
            "content": detail
            }
          }
          const wechatOptions = {
            url: '这里写微信机器人的Webhook地址',
            method: 'POST',
            headers: {
            'content-type': 'application/json'
            },
            body: JSON.stringify(data)
          };
          request(wechatOptions, (err, req, res) => {
            console.log(res);
            times = hour //这里把当前查询的“时”存放在变量times里
          })
      }
      })
      .catch(err => {
      console.error(err);
      });
}
}, 1000);
[*]把上述代码新建一个js文件(如:index.js) 丢进去 , 最后在终端里执行 node index.js命令
[*]
[*]最终接收到回调{"errcode":0,"errmsg":"ok"},代表推送成功

上面就是本人所运用的技术,如有不妥的地方,望各位大佬指点提出,本人必虚心学习

照在指尖的星光 发表于 2023-9-19 11:05

本帖最后由 照在指尖的星光 于 2023-9-19 11:14 编辑

有没有考虑做成网页 网页封装成安卓app或者苹果描述文件。网页可以展示的数据更加多元化,表格、圆饼图、柱状图、折线图等等。要不然企业微信实时接收账单详情太过频繁,这个消息还没看,下条消息就推上来了,展示也过于单一,光看数字得不到更多的数字之外的数据信息。
做成网页也是wss,实时获取数据,实时加载成折线图和顶部总收入总单数。再封装成app(封装成app很简单,网址一输入就生成了),这样效果更好。
如果是一天查询一次企业微信这种挺好。

小雨网络 发表于 2023-9-18 18:26

不错,感谢分享讨论

1203489300 发表于 2023-9-18 20:20

你很厉害 我一脸懵逼,因为我啥也不懂

aq425518860 发表于 2023-9-18 20:25

那谁框架 封号厉害 你这样还不如用投递方式 稳定又不会封号

就是那个秋 发表于 2023-9-18 20:37

aq425518860 发表于 2023-9-18 20:25
那谁框架 封号厉害 你这样还不如用投递方式 稳定又不会封号

投递方式?求指教

微笑丶永远 发表于 2023-9-18 20:44

有消息数量限制的

xiao_1245 发表于 2023-9-18 20:54

厉害厉害,学习了

earlc 发表于 2023-9-18 21:02

这个挺实用的,学习了

xs20010601 发表于 2023-9-18 21:17

特别实用,谢谢大佬分享知识

moruye 发表于 2023-9-18 21:24

页: [1] 2 3
查看完整版本: 利用nodejs结合企业微信机器人,定时推送公司收入状况