本文介紹如何為公眾號添加一個菜單點擊后給用戶發(fā)送天氣預報的功能????
上一次介紹了如何為公眾號添加關注自動回復的功能,這次我們來擴展一個比較實用的功能---實況天氣查詢
程序思路
-
用戶進入公眾號會話,上傳經緯度信息,服務端進行緩存
-
用戶點擊菜單后,服務端獲取相應菜單的點擊事件并調用接口將緩存中的用戶經緯度信息進行逆地址解析為城市名稱
-
根據(jù)城市名稱調用天氣API獲取即時天氣數(shù)據(jù)并返回xml數(shù)據(jù)
開發(fā)準備
-
注冊百度地圖開放平臺,新建服務端應用,獲取百度AK
-
注冊天氣API,獲取免費實況天氣接口的appid及appsecret
-
確認在微信公眾號管理后臺開啟了獲取用戶地理位置接口權限
關鍵代碼
app.js
- ?
const getRawBody = require('raw-body')const xml2js = require('xml2js')const rp = require('request-promise')// 緩存使用node-localstorageif (typeof localStorage === 'undefined' || localStorage === null) { var LocalStorage = require('node-localstorage').LocalStorage localStorage = new LocalStorage('./scratch')}
router.post('/', async (ctx, next) => { var data = await getRawBody(ctx.req, { length: ctx.length, limit: '1mb', encoding: ctx.charset, }) const xml = await parseXMLAsync(data) const createTime = Date.parse(new Date()) const msgType = xml.xml.MsgType[0] const toUserName = xml.xml.ToUserName[0] const toFromName = xml.xml.FromUserName[0] const event = xml.xml.Event ? xml.xml.Event[0] : ''
localStorage.clear() let fromUserName = localStorage.getItem('fromUserName') || []
if (event == 'LOCATION') { let latitude = xml.xml.Latitude ? xml.xml.Latitude[0] : '' let longitude = xml.xml.Longitude ? xml.xml.Longitude[0] : ''
if (fromUserName.length > 0) { if (fromUserName.findIndex((f) => f.id == toFromName) == -1) { fromUserName.push({ id: toFromName, latitude: latitude, longitude: longitude, }) localStorage.setItem('fromUserName', fromUserName) } } else { fromUserName.push({ id: toFromName, latitude: latitude, longitude: longitude, }) localStorage.setItem('fromUserName', fromUserName) } }
if (msgType == 'event') { let replyMsg = '說些什么' if (event == 'subscribe') { replyMsg = '歡迎關注' //關注后 ctx.body = `<xml> <ToUserName><![CDATA[${toFromName}]]></ToUserName> <FromUserName><![CDATA[${toUserName}]]></FromUserName> <CreateTime>${createTime}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[${replyMsg}]]></Content> </xml>` } else if (event == 'CLICK') { let eventKey = xml.xml.EventKey ? xml.xml.EventKey[0] : '' switch (eventKey) { case 'weather': let latitude = '31.467138' let longitude = '120.286194' if (fromUserName.length > 0) { // 當前用戶的經緯度 latitude = fromUserName.find((f) => f.id == toFromName).latitude longitude = fromUserName.find((f) => f.id == toFromName).longitude } let options = { method: 'get', uri: 'http://api.map.baidu.com/geocoder?location=' + latitude + ',' + longitude + '&output=json&key=' + config.baiduAk, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, json: true, } let cityInfo = await rp(options), city = cityInfo.result.addressComponent.city.replace('市', '')
let woptions = { method: 'get', url: 'https://tianqiapi.com/api?version=v6&appid=' + config.weatherAppid + '&appsecret=' + config.weatherSecrect + '&city=' + encodeURI(city), json: true, } let weather = await rp(woptions) let weatherTip = `您當前的城市${weather.city} 天氣:${weather.wea} 溫度:${weather.tem2}~${weather.tem1}℃ 實時溫度:${weather.tem}℃ 風力:${weather.win}${weather.win_speed} 空氣質量:${weather.air_tips}` replyMsg = weatherTip ctx.body = `<xml> <ToUserName><![CDATA[${toFromName}]]></ToUserName> <FromUserName><![CDATA[${toUserName}]]></FromUserName> <CreateTime>${createTime}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[${replyMsg}]]></Content> </xml>` break default: break } } } else { //其他情況 ctx.body = `<xml> <ToUserName><![CDATA[${toFromName}]]></ToUserName> <FromUserName><![CDATA[${toUserName}]]></FromUserName> <CreateTime>${createTime}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[你說啥?]]></Content> </xml>` }})
完整代碼請移步github倉庫:
https://github.com/xuedingmiaojun/koa-demo/blob/master/wxgh-reply/app.js
掃碼體驗
測試號二維碼
效果預覽
參考資料
-
koa2實現(xiàn)微信公眾號關注自動回復消息
-
獲取用戶地理位置:https://developers.weixin.qq.com/doc/offiaccount/User_Management/Gets_a_users_location.html
-
百度地圖開放平臺:http://lbsyun.baidu.com/index.php?title=%E9%A6%96%E9%A1%B5
-
免費實況天氣接口:http://www.tianqiapi.com/index/doc?version=v6
?
?
本文摘自 :https://blog.51cto.com/x