h5微信分享实现(node+express);

前言

(^o^)/~
h5页面在微信中使用微信分享功能,实现个性化分享模版。
从默认样式:
h5微信分享实现(node+express);_第1张图片

到自定义样式:
h5微信分享实现(node+express);_第2张图片

第一步:注册微信公众平台账号(已有略过此步)

https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN&token=
h5微信分享实现(node+express);_第3张图片

个人只能注册订阅号类型,服务号就需要企业认证了。企业权限大一些,能用的接口比较全,分享的话个人的就行。

目前网页端能使用的微信功能(支付除外)都属于公众号的范畴,隶属于微信公众平台,和微信开放平台无关;

注册完登录后可以查看自己的权限,能用那些功能。
h5微信分享实现(node+express);_第4张图片

第二步:接入sdk

这一步容易卡关,应为首先需要一台能用的服务器和备案的域名;没办法,微信对接要求很苛刻,本地无法实现对接
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#1

h5微信分享实现(node+express);_第5张图片

安全域名这里要求将某个密钥文件放在服务器根目录。
h5微信分享实现(node+express);_第6张图片

下面就要开始写代码了。

第三步:创建服务,放置指定文件(有现成服务的放下文件,这一步跳过)

文件结构如下:
h5微信分享实现(node+express);_第7张图片

//server.js
const express = require('express');
const { resolve } = require('path');
const publicPath = resolve('./public');

const server = express();

async function bootstrap(){
    server.use(express.static(publicPath));//托管静态文件
    server.listen(9222,function(){
        console.log('server run at:http://localhost:9222')
    })
}
bootstrap();

启动服务试一下:
image.png

查看文件是否正常查看:
http://localhost:9222/MP_verify_kuKy0AHjAhdrFeBO.txt
h5微信分享实现(node+express);_第8张图片
假定服务器上已经安装好了node,npm,yarn.pm2等工具。
我这里使用yarn安装,用npm也是一样的。

用pm2托管服务:
输入命令pm2 start server.js
h5微信分享实现(node+express);_第9张图片
服务启动成功就可以试一下MP_verify_kuKy0AHjAhdrFeBO.txt能否访问。
http://www.liubingyang.top:9222/MP_verify_kuKy0AHjAhdrFeBO.txt
提示:我的是ubuntu系统,默认9222端口不可访问,需打开防火墙限制:

ufw allow xxx//开放接口
ufw status  查看接口放开状态

h5微信分享实现(node+express);_第10张图片

h5微信分享实现(node+express);_第11张图片
只需要如下代码就够了,那两个add_header是用来处理接口跨域请求的,也可以不要。

server {
        listen 80;
        server_name www.liubingyang.top;

        location / {
            add_header 'Access-Control-Allow-Origin' '$http_origin';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
            proxy_pass http://127.0.0.1:9222;
        }
}

在线编辑,或者本地编辑完用xftp传上去也可以。
编辑完保存后(编辑输入i命令,编辑完输入ESC->:wq->回车),开启(或重启nginx)

ngixn -s reload

image.png
文件放置正常;

第三步:页面接入sdk

看文档,页面引入js,并配置初始项。
新建html
h5微信分享实现(node+express);_第12张图片

//inde.html



    
    
    Document


    测试分享




前端做的事情就是把appId,timestamp,nonceStr,signature这4个参数填下就行了,都是必填项。
appId在平台的基本配置中找到(页面拉到最下面);
https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=1496518416&lang=zh_CN
h5微信分享实现(node+express);_第13张图片

h5微信分享实现(node+express);_第14张图片

jsApiList不能为空,就先把分享有关的几个接口先写进去:

jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareQZone'] // 必填,需要使用的JS接口列表

timestamp,nonceStr,signature三个参数由服务端对接提供(appId也可以由服务端提供)。
接下来就开始做服务端对接,解决这三个参数的获取。

第四步:服务端获取signature

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#1

h5微信分享实现(node+express);_第15张图片
根据文档的附录(上面这个页面往下翻)描述,可以判断出我们需要的三个参数构成:
timestamp:时间戳(特别提示:就是个随机数字,new Date().getTime()可以获取,但是12位的,这里只要10位,截取一下就行了);
nonceStr:随机码,也是自定义的,这里写死也行。
signature:最重要的签名字段,是由上面两个加上url和jsapi_ticket拼成的字符串,再进行sha1加密得到。
例如:

jsapi_ticket=xx&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value

加密后会得到一个简短的密文:
h5微信分享实现(node+express);_第16张图片

下面就看怎么获取jsapi_ticket:
h5微信分享实现(node+express);_第17张图片
新建controller文件夹和config文件夹,新增获取access_token的controller和config文件:

 //config/index.js
 module.exports = {
    grant_type:'client_credential',
    appid:'wx9c48ee416a064a99',//换成自己的,和域名绑定的
    secret:'030fa057e50a2e3eedd42cc2e605edb6',//换成自己的,和域名绑定的

    timestamp:new Date().getTime().toString().slice(0,10),
    nonceStr:'Wm3WZYTPz0wzccnW',

    localPath:'http://www.liubingyang.top',
}

//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();
}

controller文件入口:

//contriller/index.js
const { Router } = require('express');
const access_tokenController = require('./access_token.js');

module.exports = async function(){
    const router = Router();
    router.use('/access_token', await access_tokenController());
    return router;
}

server.js同样做下修改:

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

const publucPath = resolve('./public');

const initControllers = require('./controller');
const bootstrap = async function(){
    server.use(bodyParser.urlencoded({ extended: false }));//处理表单入参
    server.use(bodyParser.json({ extended: false }));//处理json入参
    server.use(express.static(publucPath));
    server.use(await initControllers());
    server.listen(9222,function(){
        console.log('server run at http://localhost:9222');
    })
}
bootstrap();

将修改后的代码放到服务器上:
h5微信分享实现(node+express);_第18张图片

安装axios插件,重启pm2:
h5微信分享实现(node+express);_第19张图片

//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();
}

controller/index.js别忘注册下接口:
h5微信分享实现(node+express);_第20张图片

//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}×tamp=${config.timestamp}&url=${params.url}`;
            console.log('signature:'+signature);
            res.json({signature});

        }


    }
}

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

应为是在服务器上调试,多写几个console便于查看问题,
controller/index.js注册接口
h5微信分享实现(node+express);_第21张图片

上传文件重启pm2:
h5微信分享实现(node+express);_第22张图片
日志也出来了,接口也正常。

最后一步 前端获取参数

最后就是提供前端开接口获前端所有需要的参数:
h5微信分享实现(node+express);_第23张图片

//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({
            timestamp : config.timestamp,
            nonceStr : config.nonceStr,
            signature:sha1(signature),
        })
    }
}

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

最后更新下controller/index.js
h5微信分享实现(node+express);_第24张图片
修改下index.html,这里就不啰嗦了,把需要的都放进去:

//index.html



    
    
    Document


    测试分享





文件更新到服务器上,安装node-sha1插件并重启pm2:
h5微信分享实现(node+express);_第25张图片

总结

在微信的条条框框中探索探索某个功能的实现是比较困难的,尤其是新手,文档像说明书一样,几乎没有逻辑可寻,而且有很多地方更新的太快,而手册又比较老。
比如这两个接口,实际上个人是没有权限的,文档里并没有说明。个人只能用比较老的快废弃的接口
h5微信分享实现(node+express);_第26张图片

上面有很多我踩过的坑就不一一说明了,也许你遇不到,也许你遇到的我没遇到过,慢慢探索吧。微信功能实现其实主要由服务端完成,前端做的很少,熟悉对接流程会使前端同学对微信体系有更深的理解,出了问题也能从容的应对。

你可能感兴趣的:(javascript,前端,node.js,html)