自定义微信大众号

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

分类

微信大众号其实有三类,别离是测验号订阅号服务号

测验号, 无需申请大众账号、可在测验账号中体验并测验微信大众平台一切高档接口

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

自定义微信大众号

发送模板音讯

测验号能够直接在本地调用接口,虽然能运用一切接口,可是要看具体音讯,得去重视列表里点击才干看到(我运用的时候是这样)

重视测验号

测验号页面有个二维码,直接扫描重视,用户列表对应的微信号,便是咱们到时候发音讯要用的

自定义微信大众号

获取token

在发送音讯之前,三种类型的号都需求获取access_token,参数为对应的appIDappsecret

自定义微信大众号

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>`;
})