准备测试公众号
mp.weixin.qq.com/debug/cgi-b…
关注,获取测试公众号
内网渗透工具
natapp.cn/login 按照教程下载客户端进行配置
后台服务接入公众号
有netapp 生成的映射外网IP => URL
搭建express开发环境
这个网上有教程,自行百度
接口配置和签名验证
接入微信平台
Token:自主设置,这个token与公众平台wiki中常提的access_token不是一回事。这个token只用于验证开发者服务器
mp.weixin.qq.com/wiki?t=reso…
// 认证开发者服务器
function sign(config, req, res, next) {const {signature,timestamp,nonce,echostr,} = req.queryconst conf = config || {}const { token } = conf.wechat// 1. 将token、timestamp、nonce三个参数进行字典序排序const array = [token, timestamp, nonce]array.sort()const str = array.toString().replace(/,/g, '')// 2. 将三个参数字符串拼接成一个字符串进行sha1加密const sha1Code = crypto.createHash('sha1')const code = sha1Code.update(str, 'utf-8').digest('hex')// 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信if (req.method === 'GET') {if (code === signature) {res.send(echostr)} else {res.send('error')}} else if (req.method === 'POST') {if (code !== signature) {return}next()}}
复制代码
获取access_token
微信公众号文档中已经详细说明了,access_token是公众号的全局唯一接口调用凭据,因此每个接口均要加上access_token mp.weixin.qq.com/wiki?t=reso…
// config.json
{"wechat" : {"appID": "","appSecret": "","token": "access_token","prefix": "https://api.weixin.qq.com/cgi-bin/","mpPrefix": "https://mp.weixin.qq.com/cgi-bin/"}
}
复制代码
/**微信相关操作api*/const config = require('./config/config')
const utils = require('./utils')const wechatApi = {}
const { appID, appSecret } = config.wechat
const api = {accessToken: `${config.wechat.prefix}token?grant_type=client_credential`,upload: `${config.wechat.prefix}media/upload?`,
}// 获取access_token
wechatApi.updateAccessToken = function () {const option = {url: `${api.accessToken}&appid=${appID}&secret=${appSecret}`,json: true,}return utils.request(option).then(data => Promise.resolve(data))
}module.exports = wechatApi复制代码
// ../routes/index.jsconst express = require('express')
const config = require('../config/config')
const utils = require('../utils')
const wechatApi = require('../wechatApi')const router = express.Router()
// 获取,验证access_token,存入redis中
// 路由之前,添加token
router.use((req, res, next) => {// 根据token从redis中获取access_tokenutils.get(config.wechat.token).then((data) => {// 获取到值--往下传递if (data) {return Promise.resolve(data)}// 没获取到值--从微信服务器端获取,并往下传递return wechatApi.updateAccessToken()}).then((data) => {// console.log(data);// 没有expire_in值--此data是redis中获取到的if (!data.expires_in) {// console.log('redis获取到值');req.accessToken = datanext()} else {// 有expire_in值--此data是微信端获取到的// console.log('redis中无值');// 保存到redis中,由于微信的access_token是7200秒过期,// 存到redis中的数据减少20秒,设置为7180秒过期utils.set(config.wechat.token, `${data.access_token}`, 7180).then((result) => {if (result === 'OK') {req.accessToken = data.access_tokennext()}})}})
})
module.exports = router复制代码
引入wechat模块
// ../routes/wechat.jsconst express = require('express')
const wechat = require('wechat')
const conf = require('../config/config')
const service = require('../service.js')const router = express.Router()
router.use(express.query())
const config = {token: conf.wechat.token,appid: conf.wechat.appID,appsecret: conf.wechat.appSecret,encodingAESKey: '',
}router.use('/', wechat(config, (req, res) => {const message = req.weixinconst {MsgType,} = messageswitch (MsgType) {case 'text': // 文本service.handleText(res, message.Content)breakdefault:res.reply('服务器内部错误,请重试')}
}))module.exports = router复制代码
开始测试
const createError = require('http-errors')
const express = require('express')
const path = require('path')
const cookieParser = require('cookie-parser')
const logger = require('morgan')
const indexRouter = require('./routes/index')
const wechatRouter = require('./routes/wechat')
const utils = require('./utils')
const config = require('./config/config.json')const app = express()// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'jade')
app.use(logger('dev'))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(cookieParser())
app.use(express.static(path.join(__dirname, 'public')))
app.use(utils.sign(config)) // 接口配置和签名验证
app.use('/', indexRouter)
app.use('/wechat', wechatRouter)// catch 404 and forward to error handler
app.use((req, res, next) => {next(createError(404))
})// error handler
app.use((err, req, res) => {// set locals, only providing error in developmentres.locals.message = err.messageres.locals.error = req.app.get('env') === 'development' ? err : {}// render the error pageres.status(err.status || 500)res.render('error')
})
module.exports = app复制代码
- 开启开发者服务
- 填写接口配置信息
- 结果