我们在微信分享网页链接时,希望分享出去的不仅仅是url链接的形式,而是可以自定义分享形式,如标题+链接+描述+缩略图的形式:
下面我把自定义微信分享网页的实现分享给大家:
一、仔细阅读微信官方开发文档
地址:微信开发文档
几个关键点注意一下
1.快速定位到我们开发的分享功能的文档
2.了解需要我们做哪些前期准备(写代码之前)
3.有哪些用到的接口先大致浏览一遍,写代码时方便快速查阅
二、前期准备
1.注册微信公众平台账号(已有账号直接登录)
地址:微信公众平台注册页
个人开发者可以注册订阅号,企业可以选择注册服务号,服务号相对于订阅号权限大一些,如果只开发微信分享功能,订阅号有微信分享的接口权限。
2.注册成功后登录查看权限接口
登录公众号在设置与开发的接口权限中查看,如果有基础接口的权限和分享接口的权限就可以进行下一步了。
3.绑定域名
在“公众号设置”的“功能设置”里填写“JS接口安全域名”。(根据提示绑定域名,域名必须是通过icp备案的)
4.获取公众号开发信息
在“基本设置”中获取开发者ID(AppID),开发者密码(AppSecret),并设置IP白名单(ip为绑定服务器的ip)
三、代码实现
1.创建服务
-
npm init 来初始化 package.json
-
新建public文件夹放入前端页面和校验文件
-
<!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', 'https://www.dikaer.tech/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: '',// 必填,公众号的唯一标识
timestamp, // 必填,生成签名的时间戳
nonceStr, // 必填,生成签名的随机串
signature,// 必填,签名
jsApiList: ['chooseImage','onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareQZone'] // 必填,需要使用的JS接口列表
}
wx.config(config);
console.log(location.href)
wx.ready(function(){
wx.checkJsApi({
jsApiList: ['chooseImage','onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareQZone'],
success(res) {
console.log("checkJsApi: " + JSON.stringify(res));
}
})
let shareAppMessage ={
title: '测试分享', // 分享标题
desc: '笛卡尔官网分享', // 分享描述
link: location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
type: 'link',//分享类型,music、video或link,不填默认为link,
imgUrl:'',
success: function () {
alert('分享测试成功')
}
}
wx.onMenuShareTimeline(shareAppMessage )
wx.onMenuShareAppMessage(shareAppMessage )
wx.onMenuShareQQ(shareAppMessage )
wx.onMenuShareQZone(shareAppMessage )
})
})()
</script>
- node后端接口提供timestamp,nonceStr,signature参数,新建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;
}
access_token.js 调用官方api获取Access token
地址:获取Access token
//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();
}
jsapi_ticket.js 用access_token换取jsapi_ticket
//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();
}
signature.js 组装签名,将所有参数字符串拼接成一个字符串进行sha1加密,得到signature
//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();
}
wx_config.js 给前端提供接口,传递所需的timestamp,nonceStr,signature参数。
//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();
}
- 新建config文件夹,添加配置文件
//config/index.js
module.exports = {
grant_type:'client_credential',
appid:'',//绑定域名的开发者id
secret:'',//开发者密钥
timestamp:new Date().getTime().toString().slice(0,10),//时间戳
nonceStr:'',//随机字符串,也可固定
localPath:'',//绑定的域名
}
- 引入 express, 启一个服务
//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(8081,function(){
console.log('server run at http://localhost:8081');
})
}
bootstrap();
四、把服务放到自己的服务器上
1.用nginx配置一下把8081端口配置到80端口
2. 启动服务进行测试
注意:微信新修改了自定义分享规则,通过链接点进来的分享只能分享链接;通过分享和扫码进来的可以分享链接+标题+缩略图。更多细节注意留意官方文档
需要demo源码的可以在帖子下面留言私发