自建腾讯企业微信通知API
现在很多后台应用需要通知信息给用户,支持通知的方式有很多,server酱,丁丁,企业微信,bark,WxPusher,等等的五花八门,我最喜欢的则是企业微信,因为不需要安装其他应用,推送的消息也干净清爽,不夹杂其他内容。从2022年6月20日开始,企业微信新建应用发送消息的时候,必须要添加信任IP,这个IP就是发起请求端的源IP,很多家用宽带的公网IP都是动态的,重启就变,这对于使用企业微信则带来了不便。解决这个问题有两种方法,要求动手能力稍强,两种方法都需要有自己的vps。
1,利用nginx反代,把请求先发送到vps,然后由vps向腾讯发起请求,在企业微信的应用里,添加vps 的IP为信任IP即可。反代代码如下:
server {
listen 443;
server_name xxx.xxx.xxx;
add_header Strict-Transport-Security "max-age=15768000" always;
access_log /var/log/nginx/xxx.xxx.xxx.log main;
root /data/www;
index index.php index.html index.htm;
location / {
proxy_pass https://qyapi.weixin.qq.com/;
}
ssl_certificate /data/webkey/xxx.xxx.xxx.crt;
ssl_certificate_key /data/webkey/xxx.xxx.xxx.key;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_early_data on;
ssl_stapling on;
ssl_stapling_verify on;
}
server {
listen 80;
server_name xxx.xxx.xxx;
rewrite ^(.*)$ https://${server_name}$1 permanent;
if ($host != 'xxx.xxx.xxx'){
return 403;
}
}
这样一来,在应用端,把请求链接中的https://qyapi.weixin.qq.com
替换成自己的地址https://xxx.xxx.xxx
即可。
2,对于一些支持自定义通知的应用,我们还可以使用基于企业通知的接口,搭建自己的API,因为使用企业微信的通知,需要经过获取token ,然后使用token发送消息,mpnews模板还需要上传素材获取media-id这几个阶段。而支持自定义应用的配置都只让填写一行url来完成推送,一条url无法完成上述多个请求动作,所以,我考虑到把请求都有vps 来完成,网上我找了好久,找到了如下代码。我是搞硬件基础架构的,对php代码来说,一窍不通,但是凭着我对这些东西的敏感性,还是搞清楚了代码的作用。下面附上代码。代码里有些php 是我自己写的,我都佩服自己,觉得该去学编程,但是头发不够了。哈哈哈~
<?php
//获取通过post或者get传递的值并赋值给变量
$title = $_POST['title'];
$content = $_POST['content'];
$msgtype = $_POST['msgtype'];
$url = $_POST['url'];
$picurl = $_POST['picurl'];
$title = $_GET['title'];
$content = $_GET['content'];
$msgtype = $_GET['msgtype'];
$url = $_GET['url'];
$picurl = $_GET['picurl'];
if (!$content){
echo '<h1>企业微信通知API</h1>';
echo '<hr/>';
echo '<h4>输入参数以继续,支持POST或者GET请求方式。</h4>';
echo '<p><b>文本消息(text)</b>:以文字形式通知消息</p>';
echo '<p><b>示例</b>:<a href="?content=这是一条测试信息&msgtype=text">https://xxx.xxx.xxx/?content=这是一条测试信息&msgtype=text</a></p>';
echo '<hr/>';
echo '<p><b>文本卡片消息(textcard)</b>:以卡片形式通知消息</p>';
echo '<p><b>示例</b>:<a href="?title=通知测试&content=这是一条测试信息&url=https://www.mr-mao.cn&msgtype=textcard">https://xxx.xxx.xxx/?title=通知测试&content=这是一条测试信息&url=https://www.mr-mao.cn&msgtype=textcard</a></p>';
echo '<hr/>';
echo '<p><b>图文消息(news)</b>:以图文形式通知消息</p>';
echo '<p><b>示例</b>:<a href="?title=通知测试&content=这是一条测试信息&picurl=https://www.mr-mao.cn/usr/logo.png&url=https://api.mr-mao.cn/60s/pic/&msgtype=news">https://xxx.xxx.xxx/?title=通知测试&content=这是一条测试信息&picurl=https://www.mr-mao.cn/usr/logo.png&url=https://api.mr-mao.cn/60s/pic/&msgtype=news</a></p>';
echo '<hr/>';
echo '<p><b>图文消息(mpnews)</b>:以富文本图文形式通知消息</p>';
echo '<p><b>示例</b>:<a href="?title=通知测试&content=这是一条测试信息&msgtype=mpnews">https://xxx.xxx.xxx/?title=通
知测试&content=这是一条测试信息&msgtype=mpnews</a></p>';
echo '<hr/>';
}else{
// 声明页面 header
header("Content-type:text/html;charset=utf-8");
// 获取 access_token
function getToken(){
// 定义 id 和 secret
$corpid='xxxxxx';//这里填写你的企业 ID
$corpsecret='xxxxxxxxxxxxxxxx';//这里填写你刚创建的应用 secret
// 读取 access_token
include './access_token.php';
// 判断是否过期
if (time() > $access_token['expires']){
// 如果已经过期就得重新获取并缓存
$access_token = array();
$access_token['access_token'] = getNewToken($corpid,$corpsecret);
$access_token['expires']=time()+7000;
// 将数组写入 php 文件
$arr = '<?php'.PHP_EOL.'$access_token = '.var_export($access_token,true).';'.PHP_EOL.'?>';
$arrfile = fopen("./access_token.php","w");
fwrite($arrfile,$arr);
fclose($arrfile);
// 返回当前的 access_token
return $access_token['access_token'];
}else{
// 如果没有过期就直接读取缓存文件
return $access_token['access_token'];
}
}
// 获取新的 access_token
function getNewToken($corpid,$corpsecret){
$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$corpid}&corpsecret={$corpsecret}";
$access_token_Arr = https_request($url);
return $access_token_Arr['access_token'];
}
// curl 请求函数
function https_request ($url){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$out = curl_exec($curl);
curl_close($curl);
return json_decode($out,true);
}
//获取mpnews消息所需的media_id
if ($msgtype == "mpnews"){
include './access_token.php';
$token = $access_token['access_token'];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=$token&type=image",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('media'=> new CURLFILE('logo.png')),//需要在程序同级目录下放通知消息的头图文件
));
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response,true);
$media_id = $data['media_id'];
}
// 发送应用消息函数
function send($data){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token='.getToken());
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
return curl_exec($curl);
}
// 文本卡片消息体
$postdata = array(
'touser' => '@all', //不需要写联系人,会发送给所有人
'msgtype' => $msgtype,
'agentid' => 'xxxxxxxxx',//这里填写你刚创建的应用 AgentId
"$msgtype" => array(
"content" => "$content",
'title' => $title,
'description' => $content,
'url' => $url,
'articles' => array(
'title' => $title,
"author" => "FatCat", //自定义作者
"digest" => $content,
"content" => $content,
'thumb_media_id' => $media_id,
'description' => $content,
'picurl' => $picurl,
'url' => $url,
),
),
'enable_id_trans' => 0,
'enable_duplicate_check' => 0,
'duplicate_check_interval' => 1800
);
// 调用发送函数
echo send(json_encode($postdata));
// echo "$title, $description"
}
?>
至此,支持三种消息模板的api搭建完成,enjoy it!访问自己的链接,则可出现简易的参数模板,具体参数点击下面的链接查询,此时,这个api则可以用在任何支持自定义通知的应用中。同时支持post或者get请求。