写在前面

如今网络上有很多消息推送应用,如server酱,wxpusher,Qmsg酱等。可以通过发起get或者post请求传入相关参数实现消息推送功能。
前几天看了一下企业微信的开发文档,发现企业微信可以推送很多类型丰富的消息,包括文本消息、图片消息、语音消息、视频消息、文件消息、文本卡片消息等等,灵机一动,是不是可以利用企业微信来做一个个人的消息推送助手呢。随后去查看了一下有没有消息推送频率限制,官方文档里是这样说的:

  1. 每企业不可超过帐号上限数*30人次/天(注:若调用api一次发给1000人,算1000人次;若企业帐号上限是500人,则每天可发送15000人次的消息)
  2. 每应用对同一个成员不可超过30条/分,超过部分会被丢弃不下发

而申请的企业微信基础人数上限是200,也就是说每天可以推送6000条消息,对个人来说完全够用!
而且可以不用下载安装企业微信,在微信里照样可以接收推送的消息

准备事项

  1. 注册企业微信一个(个人就可以注册)
  2. 一台具有公网ip的服务器
  3. 一个备案域名

企业微信配置

1. 注册企业微信

进入注册地址,填写个人相关信息即可注册

2. 创建消息推送应用

登录企业微信管理后台,选择【应用管理】,在下方自建栏点击创建应用,上传logo,填写相关信息创建一个用来推送消息的微信应用:

这里推荐一个查找图标的好地方,阿里云矢量图标库,里面有很多精美的免费图标,值得拥有
还有你可以在你申请的企业应用里创建部门,这样可以自定义创建的微信应用对哪些部门成员可见。

创建应用后跳转到应用详情页面,请记住如下图所示的两个参数:应用ID与应用秘钥,后面有用

3. 确定接口参数

接下来编写消息接口,我们的思路是通过向该消息接口发送get或者post请求,传入相关参数来实现利用微信应用来向指定人员推送消息

首先需要确定一下要用到哪些参数:

  1. 需要确定推送消息的对象,关注企业微信的每个成员都有一个userid,可以利用这个参数确定推送消息的对象
  2. 因为推送的消息可以有多种类型,这里使用一个msgtype来确定推送的消息类型
  3. 每一种类型的消息都有各种参数,详情如下:

图片消息、语音消息、视频消息、文件消息这四个媒体文件类型比较麻烦,消息接口就暂时不支持这四种消息类型。还有markdown消息、任务卡片消息不支持在微信里打开,必须要用企业微信才能打开,但是目前企业微信的使用远远没有微信普遍,因此这里也不考虑这几种消息类型。最后小程序通知消息需要绑定微信小程序,这里也不考虑了

文本消息

参数是否必要说明
msgtype消息类型,此时固定为:text
content消息内容,最长不超过2048个字节,超过将截断

特殊说明:其中content参数可以支持换行、以及a标签,即可打开自定义的网页(注意:换行符请用转义过的n)

文本卡片消息

参数是否必要说明
msgtype消息类型,此时固定为:textcard
title标题,不超过128个字节,超过会自动截断
description描述,不超过512个字节,超过会自动截断
url点击后跳转的链接。最长2048字节,请确保包含了协议头(http/https)
btntxt按钮文字。 默认为“详情”, 不超过4个文字,超过自动截断

卡片消息的展现形式非常灵活,支持使用br标签或者空格来进行换行处理,也支持使用div标签来使用不同的字体颜色,目前内置了3种文字颜色:灰色(gray)、高亮(highlight)、默认黑色(normal),将其作为div标签的class属性即可

图文消息

参数是否必要说明
msgtype消息类型,此时固定为:news
title标题,不超过128个字节,超过会自动截断
description描述,不超过512个字节,超过会自动截断
url点击后跳转的链接。最长2048字节,请确保包含了协议头(http/https)
picurl图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图 1068 455,小图150 150。

编写消息接口

首先在服务器上创建一个网站并将域名解析到该站点,在站点根目录下创建index.php文件,用于接收请求并处理参数,实现消息推送逻辑功能
这里先贴出所有代码:

<?php

header("content-type:application/json");

$send = new SendMsg();

if (!empty($_GET['userid'])) {
    print_r($send->send_msg($_GET));
} elseif (!empty($_POST['userid'])) {
    print_r($send->send_msg($_POST));
}else{
    echo '{"status": "error","info": "缺少必要的请求参数!"}';
}


class SendMsg
{
    var $secret = "消息推送应用秘钥";
    var $corpId = "企业ID";
    var $agentId = 应用ID;
    
    // 获取access_token
    function get_tocken($bool){
        if($bool){
            $file = fopen("access_token.txt", "w");
            $tocken_api = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=".$this->corpId."&corpsecret=".$this->secret;
            $tocken = json_decode(file_get_contents($tocken_api),true)['access_token'];
            fwrite($file, $tocken);
            fclose($file);
            return $tocken;
        }else{
            $tocken = file_get_contents("access_token.txt");
            return $tocken;
        }
    }
    
    function send_msg($data){
        if($data['msgtype'] == 'text'){
            $msg = array(
                "content" => $data['msg']
            );
        }elseif($data['msgtype'] == 'textcard'){
            $msg = array(
                "title" => $data['title'],
                "description" => $data['description'],
                "url" => $data['url'],
                "btntxt" => $data['btntxt']
            );            
        }elseif($data['msgtype'] == 'news'){
            $msg = array("articles" => array(array(
                "title" => $data['title'],
                "description" => $data['description'],
                "url" => $data['url'],
                "picurl" => $data['picurl']
            )));            
        }
        $result = $this->send($data['userid'],$data['msgtype'],$msg);
        return $result;
    }
    
    
    function send($user_id,$msg_type,$msg){
        $tocken = $this->get_tocken(false);
        $send_api = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' . $tocken;
        $params = array(
            'touser'    => $user_id,
            'msgtype'   => $msg_type,
            'agentid'   => $this->agentId,
            $msg_type   => $msg,
        );   
        $context = stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => 'Content-type: application/x-www-form-urlencoded',
                'content' => json_encode($params,true)
            ]
        ]);
        $result = json_decode(file_get_contents($send_api, false, $context),true);
        if ($result['errmsg'] != "ok"){
            $tocken = $this->get_tocken(true);
            $send_api = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' . $tocken;
            $result = json_decode(file_get_contents($send_api, false, $context),true);
            return json_encode($result);
        }else{
            return json_encode($result);
    }
        
        
    }
}

获取access_token

使用get_tocken方法获取access_token

function get_tocken($bool){
    if($bool){
        $file = fopen("access_token.txt", "w");
        $tocken_api = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=".$this->corpId."&corpsecret=".$this->secret;
        $tocken = json_decode(file_get_contents($tocken_api),true)['access_token'];
        fwrite($file, $tocken);
        fclose($file);
        return $tocken;
    }else{
        $tocken = file_get_contents("access_token.txt");
        return $tocken;
    }
}

获取access_token是调用企业微信API接口的第一步,相当于创建了一个登录凭证,其它的业务API接口,都需要依赖于access_token来鉴权调用者身份。

请求方式: GET(HTTPS)
请求地址: https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET

注:此处标注大写的单词ID和SECRET,为需要替换的变量,根据实际获取值更新。

参数说明:

  • corpid,企业ID,在企业微信管理后台【我的企业】标签栏最底部复制粘贴获取
  • corpsecret,应用的凭证密钥,就是上面创建应用时让记住的应用秘钥

这里之所以使用一个txt文件来存储access_token,是因为不能频繁调用gettoken接口,否则会受到频率拦截,所以使用一个文件来存储access_token,当access_token失效后再重新请求接口获取,并写入文件,下次就可以直接从txt文件里读取access_token而不用请求access_token接口了。

判断消息类型

使用send_msg()方法判断要推送的消息类型,以便于编辑不同类型消息所需的参数:

function send_msg($data){
    if($data['msgtype'] == 'text'){
        $msg = array(
            "content" => $data['text']
        );
    }elseif($data['msgtype'] == 'textcard'){
        $msg = array(
            "title" => $data['title'],
            "description" => $data['description'],
            "url" => $data['url'],
            "btntxt" => $data['btntxt']
        );            
    }elseif($data['msgtype'] == 'news'){
        $msg = array("articles" => array(array(
            "title" => $data['title'],
            "description" => $data['description'],
            "url" => $data['url'],
            "picurl" => $data['picurl']
        )));            
    }
    $result = $this->send($data['userid'],$data['msgtype'],$msg);
    return $result;
}

推送消息

这一步没啥好说的,直接看代码:

function send($user_id,$msg_type,$msg){
    $tocken = $this->get_tocken(false);
    $send_api = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' . $tocken;
    $params = array(
        'touser'    => $user_id,
        'msgtype'   => $msg_type,
        'agentid'   => $this->agentId,
        $msg_type   => $msg,
    );   
    $context = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => 'Content-type: application/x-www-form-urlencoded',
            'content' => json_encode($params,true)
        ]
    ]);
    $result = json_decode(file_get_contents($send_api, false, $context),true);
    if ($result['errmsg'] != "ok"){
        $tocken = $this->get_tocken(true);
        $send_api = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' . $tocken;
        $result = json_decode(file_get_contents($send_api, false, $context),true);
        return json_encode($result);
    }else{
        return json_encode($result);
    }
}

总体流程

  1. 准备一台服务器,一个域名
  2. 注册一个企业微信
  3. 在企业微信管理后台创建一个微信应用
  4. 编写接口(直接将上方代码复制粘贴到index.php文件中即可)

成品展示

纯属分享,本人非专业人士,若有不足,敬请见谅