nodejs使用express框架实现微信个性化分享H5

在这里插入图片描述

1.实现微信个性化分享H5的必要条件

一是非个人主体的公众号。
在这里插入图片描述
在这里插入图片描述
二是要有备案的域名,要求将密钥文件放在服务器根目录,通过域名能够访问到密钥文件。
在这里插入图片描述
在这里插入图片描述
最后还要把 IP 填入白名单,IP要固定,否则访问接口会报错。
在这里插入图片描述

2.项目整体结构

在这里插入图片描述
2-1 根目录建立server.js

//server.js
const express = require('express');
const {
    
     resolve } = require('path');
const bodyParser= require('body-parser');
const server = express();

const publucPath = resolve('./www');
const initControllers = require('./controller');

// 设置跨域访问
server.all("*",function(req,res,next){
    
        
    res.header("Access-Control-Allow-Origin","*");  //设置允许跨域的域名,*代表允许任意域名跨域    
    res.header("Access-Control-Allow-Headers","content-type");  //允许的header类型    
    res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");  //跨域允许的请求方式 
    if (req.method.toLowerCase() == 'options'){
    
    
		res.send(200);  //让options尝试请求快速结束		
	}else{
    
    
		next();
	}

})

const app = async function(){
    
    
    server.use(bodyParser.urlencoded({
    
     extended: false }));//处理表单入参
    server.use(bodyParser.json({
    
     extended: false }));//处理json入参
    server.use(express.static(publucPath)); //托管静态文件,能通过http方式访问
    server.use(await initControllers());
    server.listen(8080,function(){
    
    
        console.log('server run at http://127.0.0.1:8080');
    })
}
app();

2-2 根目录建立config文件夹,再创建index.js
【注意:此文件有三个参数要修改成自己的】

// 路径config/index.js

 module.exports = {
    
       
	localPath:'http://lindawei.cn1.utools.club',  //换成自己的域名
    appid:'wx2xxxxxxxxxxx380',  //换成自己的开发者ID(AppID)
    secret:'250bxxxxxxxxxxxd363',  //换成自己的开发者密码(AppSecret)	

    timestamp:new Date().getTime().toString().slice(0,10), //取时间戳的前十位
    grant_type:'client_credential',
    nonceStr:'Wm3WZYTPz0wzccnW',	
	Token:'accesstoken',    
}


2-3 根目录建立controller文件夹,再创建index.js

// 路径 contriller/index.js

const {
    
     Router } = require('express');
const access_tokenController = require('./access_token.js');
const jsapi_ticketController = require('./jsapi_ticket.js');
const signatureController = require('./signature.js');
const wx_configController = require('./wx_config.js');

module.exports = async function(){
    
    
    const router = Router();
    router.use('/access_token', await access_tokenController());
	router.use('/jsapi_ticket', await jsapi_ticketController());
	router.use('/signature', await signatureController());
	router.use('/wx_config', await wx_configController());
    return router;
}

2-4 在controller文件夹里创建 access_token.js

// 路径 contriller/access_token.js

const {
    
     Router } =require("express");
const axios = require('axios');
const config = require('../config');
class Axios {
    
    
    async init(){
    
    
        const router =  Router();
        router.get('/',this.get);
        return router;
    }
    get = async (req,res)=>{
    
    
        let url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${
      
      config.appid}&secret=${
      
      config.secret}`;
        const {
    
     data } = await axios.get(url);
        res.json(data);
    }
}

module.exports = async function(){
    
    
    return await new Axios().init();
}

2-5 在controller文件夹里创建 jsapi_ticket.js

// 路径 contriller/jsapi_ticket.js

const {
    
     Router } = require('express');
const axios = require('axios');
const urlUtil = require("url");
const querystring = require("querystring");

class Jsapi_ticket {
    
    
    async init(){
    
    
        const router = Router();
        router.use('/',this.get);
        return router;
    }
    get = async (req,res)=>{
    
    
        //获取返回的url对象的query属性值 
        var arg = urlUtil.parse(req.url).query;

        //将arg参数字符串反序列化为一个对象
        var params = querystring.parse(arg);
        const url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${
      
      params.access_token}&type=jsapi`;
        const {
    
     data } = await axios.get(url);
        res.json(data);
    }
}

module.exports = async function(){
    
    

    return await new Jsapi_ticket().init();
}

2-6 在controller文件夹里创建 signature.js

// 路径 contriller/signature.js

const {
    
     Router } = require('express');
const axios = require('axios'); 
const config = require('../config');
const urlUtil = require("url");
const querystring = require("querystring");

class Signature{
    
    
    async init(){
    
    
        const router = Router();
        router.get('/',this.get)
        return router;
    }
    get = async (req,res)=>{
    
    
        //获取返回的url对象的query属性值 
        var arg = urlUtil.parse(req.url).query;
        console.log('arg:'+arg);
        //将arg参数字符串反序列化为一个对象
        var params = querystring.parse(arg);
        let access_token ='';
        {
    
    
            const {
    
     data } = await axios.get(`${
      
      config.localPath}/access_token`);
            if( data.access_token ){
    
    
                access_token = data.access_token;
            }else{
    
    
                res.json(data);
                return;
            }
            console.log('access_token:'+access_token);
        }
        {
    
    
            const {
    
     data } = await axios.get(`${
      
      config.localPath}/jsapi_ticket?access_token=${
      
      access_token}`);
            let ticket = '';
            if(data.ticket){
    
    
                ticket = data.ticket;
            }else{
    
    
                res.json(data);
                return
            }
            console.log('ticket:'+ticket);
            console.log('url:'+params.url)
            const signature = `jsapi_ticket=${
      
      ticket}&noncestr=${
      
      config.nonceStr}&timestamp=${
      
      config.timestamp}&url=${
      
      params.url}`;
            console.log('signature:'+signature);
            res.json({
    
    signature});

        }


    }
}

module.exports = async function(){
    
    
    return await new Signature().init();
}

2-7 在controller文件夹里创建 wx_config.js

// 路径 contriller/wx_config.js

const {
    
     Router } = require('express');
const axios = require('axios');
const sha1 = require('node-sha1');
const config = require('../config');

class Wx_config {
    
    
    async init(){
    
    
        const router = Router();
        router.use('/',this.post);
        return router;
    }
    post = async (req,res)=>{
    
    
        //console.log('req.body'+JSON.stringify(req.body))
        //console.log('req.body.url:'+req.body.url);
        const {
    
     data } = await axios(`${
      
      config.localPath}/signature?url=${
      
      req.body.url}`);
        let signature = '';

        if(data.signature){
    
    
            signature = data.signature;
        }else{
    
    
            res.json(data);
            return;
        }
		
		//把参数返回前端
        res.json({
    
      
			appId : config.appid,
            timestamp : config.timestamp,
            nonceStr : config.nonceStr,
            signature:sha1(signature),
        })
    }
}

module.exports = async function(){
    
    
    return await new Wx_config().init();
}

2-8 根目录建立www文件夹用于放置网站静态文件,新建index.html 主页文件
【注意:此文件有两个地方要修改成自己的】


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>这是网页的标题</title>
	<script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
	<script>
	    const xhr = new XMLHttpRequest();
	    function wx_config(){
      
      
	        return new Promise(res =>{
      
      
	            xhr.onreadystatechange = function(event){
      
      
	                if(event.target.status == 200 && event.target.readyState == 4){
      
      
	                    res(xhr.responseText);
	                }
	            }
	            //换成自己的域名http://lindawei.cn1.utools.club
	            xhr.open('post', 'http://lindawei.cn1.utools.club/wx_config');  
	            xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
	            xhr.send(`url=${ 
        encodeURIComponent(location.href.split('#')[0])}`);
	        })
	    }
	    let configs = '';
	    (async function(){
      
      
	        configs = await wx_config();
	        //console.log(configs)
	        const {
      
       appId,timestamp,nonceStr,signature } = JSON.parse(configs); //从后端返回的参数
	        let config = {
      
      
	            debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
	            appId: appId,// 必填,公众号的唯一标识	
	            timestamp: timestamp, // 必填,生成签名的时间戳
	            nonceStr: nonceStr, // 必填,生成签名的随机串
	            signature: signature,// 必填,签名
	            jsApiList: [		// 必填,需要使用的JS接口列表			
					'onMenuShareTimeline', //朋友圈
					'onMenuShareAppMessage', //朋友
				] 
	        }
	        wx.config(config);
	
	        wx.ready(function(){
      
      
	        	//此处是自定义配置
	            let config={
      
       
	                title: '测试的标题', // 分享标题
	                desc: '你看这个行不行', // 分享描述
	                link: location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
	                type: 'link',//分享类型,music、video或link,不填默认为link,
	                imgUrl:'http://www.syyj.tglfair.com/res/alibabalogo.jpg', // 分享图片的地址
	                success: function () {
      
      
	                    alert('分享测试成功')
	                }
	            }
				wx.onMenuShareTimeline(config)
				wx.onMenuShareAppMessage(config)
	        })
	    })()
	
	</script>
</head>

<body>
    <h1>微信分享H5,前提条件是要有备案的域名,非个人主体的公众号。</h1>
</body>

</html>



2-9 在公众号JS接口安全域名页面下载MP_verify_WM4J2b96xJcFpeHe.txt 然后复制到www文件夹
在这里插入图片描述
在这里插入图片描述

3. 运行服务

在当前项目打开cmd 运行服务 node server.js
在这里插入图片描述

4.测试服务

访问密钥文件成功
在这里插入图片描述
测试配置成功
在这里插入图片描述
如果出现下图,要把ip填写到公众号白名单。
在这里插入图片描述

5.访问H5网页

以上步骤都没有问题的话,这里访问h5网页就能正确返回所有参数。
在这里插入图片描述
在这里插入图片描述

说明 :由于笔者没有非个人主体的公众号,分享出去的链接还是默认样式。
此文章转载于:https://segmentfault.com/a/1190000037552782?utm_source=tag-newest

猜你喜欢

转载自blog.csdn.net/weixin_38946164/article/details/117623017