前言
(^o^)/~
h5页面在微信中应用微信分享性能,实现个性化分享模版。
从默认款式:
到自定义款式:
第一步:注册微信公众平台账号(已有略过此步)
https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN&token=
集体只能注册订阅号类型,服务号就须要企业认证了。企业权限大一些,能用的接口比拟全,分享的话集体的就行。
目前网页端能应用的微信性能(领取除外)都属于公众号的领域,隶属于微信公众平台,和微信开放平台无关;
注册完登录后能够查看本人的权限,能用那些性能。
第二步:接入sdk
这一步容易卡关,应为首先须要一台能用的服务器和备案的域名;没方法,微信对接要求很刻薄,本地无奈实现对接
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#1
平安域名这里要求将某个密钥文件放在服务器根目录。
上面就要开始写代码了。
第三步:创立服务,搁置指定文件(有现成服务的放下文件,这一步跳过)
文件构造如下:
//server.jsconst 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();
启动服务试一下:
查看文件是否失常查看:
http://localhost:9222/MP_verify_kuKy0AHjAhdrFeBO.txt
这样就能够放到服务器下来了。
个别用这两个工具操作服务器就够了。
将动态资源传上去,node_modules手动装置比拟好:
假设服务器上曾经装置好了node,npm,yarn.pm2等工具。
我这里应用yarn装置,用npm也是一样的。
用pm2托管服务:
输出命令pm2 start server.js
服务启动胜利就能够试一下MP_verify_kuKy0AHjAhdrFeBO.txt是否拜访。
http://www.liubingyang.top:9222/MP_verify_kuKy0AHjAhdrFeBO.txt
提醒:我的是ubuntu零碎,默认9222端口不可拜访,需关上防火墙限度:
ufw allow xxx//凋谢接口ufw status 查看接口放开状态
尽管能够拜访,但要求是间接拜访,不能带端口号,用nginx简略配置下就行:(默认曾经装置了nginx)
找到nginx配置文件夹 nginx.conf(每个零碎不统一,应用whereis nginx能够粗略查找)
我的是在 /etc/nginx下,进入nginx.conf文件夹下用vim间接创立编辑一个test.conf文件。
只须要如下代码就够了,那两个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
失常(在linux零碎中,没有音讯就是最好的音讯)
再试试:
http://www.liubingyang.top/MP_verify_kuKy0AHjAhdrFeBO.txt
文件搁置失常;
第三步:页面接入sdk
看文档,页面引入js,并配置初始项。
新建html
//inde.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> 测试分享</body></html><script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script><script> wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert进去,若要查看传入的参数,能够在pc端关上,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的惟一标识 timestamp: '', // 必填,生成签名的工夫戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名 jsApiList: [] // 必填,须要应用的JS接口列表 });</script>
前端做的事件就是把appId,timestamp,nonceStr,signature这4个参数填下就行了,都是必填项。
appId在平台的根本配置中找到(页面拉到最上面);
https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=1496518416&lang=zh_CN
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
依据文档的附录(下面这个页面往下翻)形容,能够判断出咱们须要的三个参数形成:
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
加密后会失去一个简短的密文:
上面就看怎么获取jsapi_ticket:
分两步,先获取access_token:
https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
介绍有趣味缓缓看吧,我只管接口,参数,返回就行了。
grant_type固定值client_credential,secret和appid在一个中央查看。
新建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.jsconst { 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.jsconst { 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.jsconst 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();
将批改后的代码放到服务器上:
装置axios插件,重启pm2:
在浏览器中试一下接口
http://www.liubingyang.top/access_token
能够失常返回,上面用access_token换取jsapi_ticket:
用get办法申请这个接口就能够了。新建jsapi_ticket的controller:
//jsapi_ticket.jsconst { 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别忘注册下接口:
文件放到服务器上,装置url插件,重启pm2:
启动胜利能够用pm2 logs查看日志,pm2 flush能够清空所有日志。
试一下Jsapi_ticket接口:(access_token有时效性,得用本人刚获取的)
[http://www.liubingyang.top/js...
这里也正确的拿到了ticket。
接下来开始组装签名signature:
//signature.jsconst { 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注册接口
上传文件重启pm2:
这个时候就开着pm2 logs查看下接口:
http://www.liubingyang.top/signature?url=http://www.liubingyang.top
日志也进去了,接口也失常。
最初一步 前端获取参数
最初就是提供前端开接口获前端所有须要的参数:
//wx_config.jsconst { 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
批改下index.html,这里就不啰嗦了,把须要的都放进去:
//index.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> 测试分享</body></html><script src="https://res.wx.qq.com/open/js/jweixin-1.6.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); } } xhr.open('post', 'http://www.liubingyang.top/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 { timestamp,nonceStr,signature } = JSON.parse(configs); let config = { debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert进去,若要查看传入的参数,能够在pc端关上,参数信息会通过log打出,仅在pc端时才会打印。 appId: 'wx9c48ee416a064a99',// 必填,公众号的惟一标识 timestamp, // 必填,生成签名的工夫戳 nonceStr, // 必填,生成签名的随机串 signature,// 必填,签名 jsApiList: ['chooseImage','onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareQZone'] // 必填,须要应用的JS接口列表 } wx.config(config); wx.ready(function(){ let config={ title: '测试用例', // 分享题目 desc: '你看这个行不行', // 分享形容 link: location.href, // 分享链接,该链接域名或门路必须与当前页面对应的公众号JS平安域名统一 type: 'link',//分享类型,music、video或link,不填默认为link, imgUrl:'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603186815698&di=7ec300630a404299c855c73a99773e17&imgtype=0&src=http%3A%2F%2Fcdn.duitang.com%2Fuploads%2Fitem%2F201411%2F04%2F20141104225457_f8mrM.thumb.700_0.jpeg', success: function () { alert('分享测试胜利') } } wx.onMenuShareTimeline(config) wx.onMenuShareAppMessage(config) wx.onMenuShareQQ(config) wx.onMenuShareQZone(config) }) })()</script>
文件更新到服务器上,装置node-sha1插件并重启pm2:
记得先清空日志
查看页面状况
http://www.liubingyang.top/
开的是debug模式,各个参数都能看到。参数失常,就能够用手机微信测试了:
示意配置胜利,这里最容易呈现的谬误是invalid signature,签名不正确,解决办法照着这个查就行了
调用分享给敌人:
这样就没有问题了。
出现的后果
总结
在微信的条条框框中摸索摸索某个性能的实现是比拟艰难的,尤其是老手,文档像说明书一样,简直没有逻辑可寻,而且有很多中央更新的太快,而手册又比拟老。
比方这两个接口,实际上集体是没有权限的,文档里并没有阐明。集体只能用比拟老的快废除的接口
下面有很多我踩过的坑就不一一阐明了,兴许你遇不到,兴许你遇到的我没遇到过,缓缓摸索吧。微信性能实现其实次要由服务端实现,前端做的很少,相熟对接流程会使前端同学对微信体系有更深的了解,出了问题也能从容的应答。