利用微信服务号实现早安自动化
7 min read
最近抖音一直刷到利用微信服务号实现早安自动化,感觉挺有意思的,所以自己也整了一个。参考项目 daily_morning,该项目托管于 Github Actions
,确实方便一些不懂编程的朋友很快入门,不过身为有点基础且有服务器的博主来说,必须整活。
原项目中描述为:给别人家的女朋友发早安,所以仅仅只给一个人别人的家的女朋友发显然是不够的,博主简单用 PHP 重写了一下,新功能如下:
- 薅光免费资源 支持100人群发/10个模板(不可能所有的宝都叫一个名字吧),舔一个人叫舔,舔一百个人叫…
- 实时推送详情 实时通知推送成功/失败数量和具体名字
具体效果如图所示(推送提醒
仅主人才会收到)
食用方法
申请测试号
前往 微信公众平台
申请 接口测试帐号
,因为只有 服务号
有 模板消息
推送功能, 订阅号
没有( 服务号
需要 企业
才能申请
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
获取appID和appsecret
登录过后我们得到一个测试号,我们需要保存的信息 appID
和 appsecret
获取微信号
假设我们们要推送给张三,让张三扫描左侧的 测试号二维码
关注,右侧会列出 微信号
,我们把需要推送的用户的 微信号
保存下来
获取模板ID
我们在 模板消息接口
中点击 新建测试模板
,模板标题
即为推送卡片的标题,这里博主填写为 早安呀~
, 模板内容
填入如下内容
今日天气: {{weather.DATA}}
当前温度: {{temp.DATA}}
今日温度: {{tempRange.DATA}}
今天是我们的第 {{loveDay.DATA}} 天
距离你的生日还有 {{birthDay.DATA}} 天
{{rainbow.DATA}}
我们再次重复上面的步骤,模板标题
填写 推送提醒
, 模板内容
填入如下内容
共推送 {{count.DATA}} 人
成功: {{successNum.DATA}} | 失败: {{errorNum.DATA}}
成功用户: {{success.DATA}}
失败用户: {{error.DATA}}
这样我们就得到了两个 模板ID
,保存下来。
填写配置
目前的得到的信息清单如下,直接对照着填入下面的 php
代码中即可
appID,appsecret,微信号,两个模板ID
另外,开源地址为 GoodMorning,欢迎 star
和 fork
<?php
header('Access-Control-Allow-Origin:*');
$config = array(
'APP_ID' => 'appID',
'APP_SECRET' => 'appsecret',
'TEMPLATE_ID' => '默认模板ID',
// 一次舔多人,最多可以舔100个人,模板最多只能10个
'user' => array(
array(
// name可看做是备注
'name' => '001',
'id' => '被推送人的微信号',
// 这里是开始恋爱的日期,格式必须是 2017-01-01
'date' => '2017-01-01',
// 城市只定位到市级即可
'city' => '潍坊',
// 这里是对方的生日日期,格式必须是 05-20
'birthday' => '05-20',
// 每个编号可对应一个模板,为空则使用默认模板ID
'TEMPLATE_ID' => '早安呀的模板ID',
),
// 这里是多用户写法
// array(
// 'name' => '002',
// 'id' => '被推送人的微信号',
// 'date' => '2017-01-01',
// 'city' => '济南',
// 'birthday' => '05-20',
// 'TEMPLATE_ID' => '',
// ),
),
// 用来推送是否成功
'MASTER_ID' => '主人的微信号',
'MASTER_TEMPLATE_ID' => '推送提醒的模板ID',
);
$getToken = json_decode(GET("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=". $config['APP_ID'] ."&secret=". $config['APP_SECRET']), true)['access_token'];
$url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' . $getToken;
$userList = array('success' => array(), 'error' => array());
foreach ($config['user'] as $k => $v){
$weather = getWeather($v['city'])['weather'];
$temp = getWeather($v['city'])['temp'] . '℃';
$tempRange = getWeather($v['city'])['low'] . '℃~' . getWeather($v['city'])['high'] . '℃';
$loveDay = getLoveDay($v['date']);
$birthdayDay = getBirthday($v['birthday']);
$rainbow = getRainbow();
$data = array(
'touser' => $v['id'],
'template_id' => $templateID = $v['TEMPLATE_ID'] ? $v['TEMPLATE_ID'] : $config['TEMPLATE_ID'],
'data' => array(
'weather' => array(
'value' => $weather,
'color' => getRandomColor(),
),
'temp' => array(
'value' => $temp,
'color' => getRandomColor(),
),
'tempRange' => array(
'value' => $tempRange,
'color' => getRandomColor(),
),
'loveDay' => array(
'value' => $loveDay,
'color' => getRandomColor(),
),
'birthDay' => array(
'value' => $birthdayDay,
'color' => getRandomColor(),
),
'rainbow' => array(
'value' => $rainbow,
'color' => getRandomColor(),
),
),
);
$json = json_decode(POST($url, $data), true);
if($json['errcode'] == 0){
array_push($userList['success'], $v['name']);
}else{
array_push($userList['error'], $v['name']);
}
}
$success = implode(',', $userList['success']);
$error = implode(',', $userList['error']);
$successNum = count($userList['success']);
$errorNum = count($userList['error']);
$data = array(
'touser' => $config['MASTER_ID'],
'template_id' => $config['MASTER_TEMPLATE_ID'],
'data' => array(
'count' => array(
'value' => $successNum + $errorNum,
),
'success' => array(
'value' => $success,
),
'error' => array(
'value' => $error,
),
'successNum' => array(
'value' => $successNum,
),
'errorNum' => array(
'value' => $errorNum,
),
),
);
$json = json_decode(POST($url, $data), true);
if($json['errcode'] == 0){
$reJson = array(
'code' => 200,
'msg' => '执行完成'
);
}else{
$reJson = array(
'code' => 201,
'msg' => '执行失败'
);
}
echo json_encode($reJson, JSON_NUMERIC_CHECK | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
function getRainbow()
{
$url = 'https://tenapi.cn/chp/';
$Json = json_decode(GET($url), true);
return $Json['data']['text'];
}
function getWeather($city)
{
$url = 'http://autodev.openspeech.cn/csp/api/v2.1/weather?openId=aiuicus&clientType=android&sign=android&city='. $city;
$Json = json_decode(GET($url), true);
return $Json['data']['list'][0];
}
function getLoveDay($time)
{
$time = time() - strtotime($time);
$day = floor($time / (24 * 3600));
return $day;
}
function getBirthday($birthday)
{
$today = time();
$next = strtotime(date('Y') . '-' . $birthday);
if ($next < $today) {
$next = strtotime(date('Y') + 1 . '-' . $birthday);
}
return ceil(($next - $today) / (24 * 3600));
}
function getRandomColor()
{
$str = '0123456789abcdef';
$color = '#';
for ($i = 0; $i < 6; $i++) {
$color .= $str[mt_rand(0, 15)];
}
return $color;
}
function GET($url)
{
$ch=curl_init((string)$url);
curl_setopt($ch,CURLOPT_HEADER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_TIMEOUT,5000);
$result = curl_exec($ch);
return $result;
}
function POST($url, $data)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
定时推送
我们可以把上面的 php
文件上传到网站中,使用宝塔计划任务进行触发,或者说写个 shell
脚本,python
脚本之类的搭配 crontab
定时触发