自定义微信公众号

自定义微信公众号

闲来无事无事想每天给老婆推送一些天气、新闻,就想起了我那闲置的被冻结了的微信公众号,之前只是注册了,并没有深入使用它的功能,这两天稍微研究了一下,总结一下一些用法。

分类

微信公众号其实有三类,分别是测试号订阅号服务号

测试号, 无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。

订阅号服务号的某些接口权限使用会有不同

发送模板消息

测试号可以直接在本地调用接口,虽然能使用所有接口,但是要看详细消息,得去关注列表里点击才能看到(我使用的时候是这样)

关注测试号

测试号页面有个二维码,直接扫描关注,用户列表对应的微信号,就是我们到时候发消息要用的

获取token

在发送消息之前,三种类型的号都需要获取access_token,参数为对应的appIDappsecret

javascript 复制代码
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}}

发送模板消息

订阅号无法开通此接口,服务号必须通过微信认证
官网返回的例子中还有颜色,现在设置的颜色已经不起作用了。

javascript 复制代码
  // 请求地址 参数为上面拿到的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端口。

看官网的验证写的那么复杂,其实如果你不是商用,对安全性不是很在乎,可以直接返回它穿过来的随机字符串就能验证成功。

javascript 复制代码
// 我用的koa,接口url随意
router.post('/weixin', (ctx)=>{
  const { echostr } = ctx.request.body
  ctx.body = echostr
})

验证成功以后,用户在公众号中发送的消息,都会发到这个服务的/weixin接口,后面写我们自己的逻辑即可。

被动回复天气

发送过来的消息是一个xml,所以需要有对应的xml解析,我用的koa-xml-body,解析后的数据格式就是一个对象

javascript 复制代码
{
  xml: {
    ToUserName: [ '' ], // 一般就是公众号的id
    FromUserName: [ '' ], // 发消息的人
    CreateTime: [ '1700654586' ],
    MsgType: [ 'text' ], // 消息类型
    Content: [ '新闻' ], // 消息内容
    MsgId: [ '24347519821909269' ]
  }
}

在获取到对应的发送人消息内容以后,就可以根据类型去发送对应的消息了

javascript 复制代码
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请求就好了。

javascript 复制代码
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
})

然后修改一下对应返回数据的逻辑即可

javascript 复制代码
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>`;
})
相关推荐
有颜有货10 分钟前
PMC生产排产的4种算法,一次讲清
java·服务器·前端
小虎牙00713 分钟前
Android kotlin图片库Coil源码详解
android·前端
随风一样自由22 分钟前
【前端领域】前端开发核心应用场景与落地实践
前端·前端框架
an317421 小时前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
谢尔登1 小时前
【React】 状态管理方案
前端·react.js·前端框架
用户2136610035721 小时前
Vue商品详情与放大镜组件
前端·javascript
半个落月1 小时前
从Tapas小Demo理清localStorage、事件与this
前端·javascript
李明卫杭州1 小时前
Vue2 中 v-model 处理不同数据结构的技巧
前端·javascript·vue.js
李明卫杭州1 小时前
使用 computed 处理 v-model 复杂数据结构
前端·javascript·vue.js
丨我是张先生丨2 小时前
日语单词 Web Page
前端·css·css3