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}×tamp=${
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