一、server.js文件

const express = require('express')
const app = express()
const crypto = require('crypto')  //引入node内置加密模块
const randomstring = require('randomstring')  //引入第三方产生随机字符串模块,来产生nonceStr
const axios = require('axios')  //请求获取access_token对应的接口(查看文档)
const hash = require('./model/hash.js') //引入封装的hash加密模块

const appId = 'wxff781f2d374c2a1a'
const appSecret ='04dd0125daf8ae53d0448513fe6428e9'

const path=require('path')
const ejs = require('ejs')   //引入ejs模板引擎
app.set(path.join(__dirname,'./views'),'views')
app.set('view engine','ejs')


//*********************************   token验证   ***************************/
app.get('/token',(req,res)=>{       //  http://hmx.nat300.top/token
    console.log(req.query)
    let token = 'hahaha'            //   对应的  token == 'haha'
    let {signature,echostr,timestamp,nonce} = req.query     // signature = timestamp + nonce + token 
    let str = [timestamp,nonce,token].sort().join('')     //进行字典排序,组成新的字符串
    let hash = crypto.createHash('sha1').update(str).digest('hex')  //通过内置模块Hash加密,digest('hex')是转换成十六进制
        if(hash === signature){         // 按照微信平台加密规则获取的hash === 微信系统产生的signature,则token 一样,验证通过
            res.send(echostr)           // 验证通过,返回echostr,通知微信平台服务器配置
        }else{
            res.send('验证失败')
        }
})
//*********************************   JS-SDK安全域名配置   ***************************/
app.get('/wx/MP_verify_QmSer2vGh4wSH8Q3.txt',(req,res)=>{
    res.send('QmSer2vGh4wSH8Q3')
})
//*********************************   配置JS-SDK   ***************************/
//appId 公众号的唯一标识,timestamp 生成签名的时间戳,nonceStr 生成签名的随机串,signature签名

app.get('/jssdk',(req,res)=>{
    let tmpDate = (new Date()).getTime().toString() //得到毫秒时间戳
    let timestamp = tmpDate.substring(0,tmpDate.length-3)  //转换以秒为单位的时间戳
    let nonceStr = randomstring.generate(16);   //第三方模块,randomstring产生随机字符串
    let config = {
        appId,
        timestamp,
        nonceStr,
        jsapi_ticket: '',
        signature: '',
        url: 'http://hmx.nat300.top/jssdk'  //当前调用jssdk页面的url
    }
    // console.log(config)
    //------ 获取access_token ---------
    let access_url = `https://api.weixin.qq/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`
    axios.get(access_url)
    .then((result)=>{
        // console.log(result.data)
        let access_token = result.data.access_token
        //--------- 获取jsapi_ticket  --------
        let ticket_url = `https://api.weixin.qq/cgi-bin/ticket/getticket?access_token=${access_token}&type=jsapi`
        return axios.get(ticket_url)
    })
    .then((result)=>{
        // console.log(result.data)
        if(result.data.errcode===0){
            config.jsapi_ticket = result.data.ticket
            //将config对象传过去,进行加密,返回加密后的signature,--------  获取signature --------
            config.signature= hash.createSignatue(config)  
            console.log(config)
            res.render('index',config)
        }else{
            throw new Error(result.data.errmsg)
        }
    })
    .catch((err)=>{
        //出错的话,打印err,查看错误信息
        console.log(err)
    })
    
})

app.listen(80,()=>{
    console.log('服务器启动')
})

二、signature加密,model文件夹下的hash,js文件

const crypto = require('crypto')  //引入node内置加密模块

const hash = {
    createSignatue(obj){
        // console.log(obj)
        let {nonceStr,jsapi_ticket,timestamp,url} = obj
        let str = `jsapi_ticket=${jsapi_ticket}&noncestr=${nonceStr}&timestamp=${timestamp}&url=${url}`
        //进行hash加密
        let signature = crypto.createHash('sha1').update(str).digest('hex')
        return signature  
    }
}
module.exports=hash

三、页面渲染,引入ejs模板,views文件夹下的index.ej文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://res2.wx.qq/open/js/jweixin-1.4.0.js"></script>
</head>
<body>
    哈哈
    <script>
        wx.config({
            debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: '<%= appId%>', // 必填,公众号的唯一标识
            timestamp: '<%= timestamp%>', // 必填,生成签名的时间戳
            nonceStr: '<%= nonceStr%>', // 必填,生成签名的随机串
            signature: '<%= signature%>',// 必填,签名
            jsApiList: [] // 必填,需要使用的JS接口列表
        });
        wx.ready(function(res){
            console.log(res)
            console.log('配置ok')
        });
        wx.error(function(res){
            // console.log(res)
            console.log('配置不正确')
        });

    </script>

</body>
</html>

这里购买了NATAPP域名并完成配置:http://hmx.nat300.top,开启内网穿透,NATAPP
(购买了NATAPP域名、配置操作链接:https://blog.csdn/qq_41287423/article/details/86547044)


打开开发者工具,选择微信公众号项目,输入对应的接口,如以上配置的:http://hmx.nat300.top/jssdk,进行测试

更多推荐

微信公众号开发,配置完整代码,示例