自定义微信大众号
闲来无事无事想每天给老婆推送一些气候、新闻,就想起了我那闲置的被冻结了的微信大众号,之前只是注册了,并没有深化运用它的功能,这两天稍微研究了一下,总结一下一些用法。
分类
微信大众号其实有三类,别离是测验号
、订阅号
、服务号
。
测验号, 无需申请大众账号、可在测验账号中体验并测验微信大众平台一切高档接口。
发送模板音讯
测验号能够直接在本地调用接口,虽然能运用一切接口,可是要看具体音讯,得去重视列表里点击才干看到(我运用的时候是这样)
重视测验号
到测验号页面有个二维码,直接扫描重视,用户列表对应的微信号,便是咱们到时候发音讯要用的
获取token
在发送音讯之前,三种类型的号都需求获取access_token,参数为对应的appID
和appsecret
。
const { appId, appSecret } = config.wechat
let res =
await axios.get(
`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`
)
// 回来的数据格局:
// {
// data: {
// access_token: '',
// expires_in: 7200
// }
// }
新建模板
拿到access_token
后,就能够去新建一个音讯模板,数据的占位符格局固定为{{数据.DATA}}
发送模板音讯
订阅号无法注册此接口,服务号有必要经过微信认证
官网回来的比如中还有色彩,现在设置的色彩已经不起作用了。
// 恳求地址 参数为上面拿到的token
const url = `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${access_token}`
const message = {
touser: '', // 重视列表里的用户微信号
template_id: '', // 模板的ID
data: {} // 需求发送的数据
}
// 这儿我用的是高德的气候API,可自己免费去申请
const {data: {forecasts}} = await axios.get('https://restapi.amap.com/v3/weather/weatherInfo?city=城市的code&key=自己的key&extensions=all')
const weatherData = forecasts[0]?.casts?.[0]
// 这儿的date、weather、temp便是对应我上面的模板里的
// {{date.DATA}} {{weather.DATA}} {{temp.DATA}}
if(weatherData){
const week = ['一', '二', '三', '四', '五', '六', '日']
message.data.date = {
value: `${weatherData.date} 星期${week[+weatherData.week - 1]}`,
}
message.data.weather = {
value: `${weatherData.dayweather===weatherData.nightweather?weatherData.dayweather:`${weatherData.dayweather}转${weatherData.nightweather}`}`,
}
message.data.temp = {
value: `${weatherData.nighttemp}~${weatherData.daytemp}`,
}
}
// 最终直接发送post恳求即可
axios.post(url, message)
最终效果 在我运用的过程中发现,每个数据占位的数据长度最多是20个字符,超过会显示’…’。所以假如有固定的东西,最好是写死在模板中,不要运用数据占位符回来。 模板音讯是咱们能够自己写服务主动发送的,另外还有一种被迫回复,根据用户输入,回来对应数据,这个回来的数据比较灵活,完全由自己组装,可是最大回来的长度为600个字符。
被迫回复
具体可看官网阐明与接入指南
测验号与其他号一样,都需求有一个自己的服务器。可是其实是有个能正确响应微信的token验证就好。另请留意,微信大众号接口有必要以http://或https://最初,别离支撑80端口和443端口。
看官网的验证写的那么杂乱,其实假如你不是商用,对安全性不是很在乎,能够直接回来它穿过来的随机字符串就能验证成功。
// 我用的koa,接口url随意
router.post('/weixin', (ctx)=>{
const { echostr } = ctx.request.body
ctx.body = echostr
})
验证成功今后,用户在大众号中发送的音讯,都会发到这个服务的/weixin
接口,后面写咱们自己的逻辑即可。
被迫回复气候
发送过来的音讯是一个xml,所以需求有对应的xml解析,我用的koa-xml-body
,解析后的数据格局便是一个目标
{
xml: {
ToUserName: [ '' ], // 一般便是大众号的id
FromUserName: [ '' ], // 发音讯的人
CreateTime: [ '1700654586' ],
MsgType: [ 'text' ], // 音讯类型
Content: [ '新闻' ], // 音讯内容
MsgId: [ '24347519821909269' ]
}
}
在获取到对应的发送人
和音讯内容
今后,就能够根据类型去发送对应的音讯了
router.post('/wechat', async (ctx) =>{
let data = ctx.request.body.xml
const content = data.Content[0];
let res = ''
if(content === '气候'){
res = await getWeather()
}
if(content === '新闻'){
res = await getNews()
}
// toUser便是上面获取到的发送人的微信号
// fromUser便是你的大众号
// content 便是回来的内容,需求留意的是假如超过600就没有数据回来,所以需求做个截取,确保数据回来
ctx.body=`
<xml>
<ToUserName><![CDATA[${data.FromUserName[0]}]]></ToUserName>
<FromUserName><![CDATA[${data.ToUserName[0]}]]></FromUserName>
<CreateTime>${new Date()}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${res.slice(0,600)}]]></Content>
</xml>`;
})
以上就基本能完成需求做的事了,如需求回来其他类型的音讯,可到官网看看对应规矩
和模板音讯的差异便是,这个是相似对话的形式
自定义菜单
上面是每次需求自己打字,那有没有简单点,点击那种常见的底部菜单,就能回来对应音讯。这儿咱们能够自定义菜单,但需求留意的是,由于咱们运用了服务回来音讯,就不能在页面上自定义菜单了,只能经过接口的形式自定义了,测验号和经过微信认证的订阅号,服务号主动获得。具体可看官网阐明
这个能够不需求服务器,能获取到token
,然后发送一个get
恳求就好了。
router.get('/setMenu', async (ctx) =>{
const access_token = await getToken()
const res = await axios.post(`https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${access_token}`, {
"button": [
{
"type": "click",
"name": "新闻",
"key": "news"
},
{
"type": "click",
"name": "气候",
"key": "weather"
}
]
})
ctx.body = res.data
})
然后修正一下对应回来数据的逻辑即可
router.post('/wechat', async (ctx) =>{
console.log(ctx.request.body)
let data = ctx.request.body.xml
const content = data.Content?.[0]; // 输入框触发的
const eventKey = data.EventKey?.[0] // 菜单触发的
let res = ''
if(content === '气候' || eventKey==='weather'){
res = await getWeather()
}
if(content === '新闻' || eventKey==='news'){
res = await getNews()
}
ctx.body=`
<xml>
<ToUserName><![CDATA[${data.FromUserName[0]}]]></ToUserName>
<FromUserName><![CDATA[${data.ToUserName[0]}]]></FromUserName>
<CreateTime>${new Date()}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${res.slice(0,600)}]]></Content>
</xml>`;
})