README
示例文件
微信服务端代码链接: https://pan.baidu.com/s/1aFebiga-8Q3rSNhEMadJYg 提取码: reql
- 官方文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
- DEMO 页面和示例代码:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#67
JSSDK 使用步骤
步骤一: 绑定 JS 接口安全域名
先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS 接口安全域名”。
备注:登录后可在“开发者中心”查看对应的接口权限。
文档地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
步骤二:引入 JS 文件
- 在需要调用 JS 接口的页面引入如下 JS 文件,(支持 https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js`(使用这个)`
- 如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持 https)。
备注:支持使用 AMD/CMD 标准模块加载方法加载
<!DOCTYPE html>
<html>
<head>
<title>2021,送你一张船票</title>
<meta charset="utf-8" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<meta name="laya" screenorientation="landscape" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<!-- 引擎jQuery库 -->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js" />
<!-- 第一步:根据 appid和sercet 换取code (前端) -->
<script>
...
</script>
<!-- 引入JS文件 -->
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
...
</body>
</html>
步骤三:通过 config 接口注入权限验证配置
所有需要使用 JS-SDK 的页面必须先注入配置信息,否则将无法调用(同一个 url 仅需调用一次,对于变化 url 的 SPA 的 web app 可在每次 url 变化时进行调用)。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});
签名算法见文末的附录 1,所有 JS 接口列表见文末的附录 2
注意:如果使用的是小程序云开发静态网站托管的域名的网页,可以免鉴权直接跳任意合法合规小程序,调用 wx.config 时 appId 需填入非个人主体的已认证小程序,不需计算签名,timestamp、nonceStr、signature 填入非空任意值即可。
- 前端
<!DOCTYPE html>
<html>
<head>
<title>2021,送你一张船票</title>
<meta charset="utf-8" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<meta name="laya" screenorientation="landscape" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<!-- 引擎jQuery库 -->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js" />
<!-- 第一步:根据 appid和sercet 换取code (前端) -->
<script>
...
</script>
<!-- 引入JS文件 -->
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
//发起签名时的请求url中不能带其他参数(例如code等):通过window.location.href.split('?')[0]过滤删除发起url中code等参数
console.log(window.location.href.split("?")[0]);
//调用服务器配置接口(传递参数):// 根据 请求 换取 签名等数据
$.get(
"/api/get/jsapi/signature?url=" + window.location.href.split("?")[0],
function (data, status) {
console.log(data);
/* 签名等数据格式
{
code: 0 //状态码
data:{
appid: "wx381145d57357ff23"
noncestr: "5d7d39a35ba943178de5f43cbd68a8cd"
signature: "1b74b3d3628bd135a7878c7c66d4898e836ac027"
timestamp: 1634709957
url: "http://172.30.21.29:3000/"
}
message: "成功"
}
*/
// 根据 签名等数据 进行初始化 wx.config
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.data.appid, // 必填,公众号的唯一标识
timestamp: data.data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.data.noncestr, // 必填,生成签名的随机串
signature: data.data.signature, // 必填,签名
jsApiList: [
// 必填,需要使用的JS接口列表,声明后才能调用
"onMenuShareTimeline",
"updateAppMessageShareData",
],
});
}
);
</script>
</head>
<body>
...
</body>
</html>
- 后端
const moment = require("moment");
const request = require("../../common/request");
const wxService = require("../../services/wechat/wechat");
//后端用户信息接口
exports.userinfo = {
path: "/api/wx/userinfo",
method: "get",
online: true,
handler: async (ctx) => {
let code = ctx.query.code;
var url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx381145d57357ff23&secret=cbed33d90bc25be44bd219188c4a94c4&code=${code}&grant_type=authorization_code`;
let tokenData = await request.get({ url, json: true });
let qs = {
access_token: tokenData.access_token,
openid: tokenData.openid,
lang: "zh_CN",
};
var url2 = `https://api.weixin.qq.com/sns/userinfo`;
const userinfo = await request.get({ url: url2, qs, json: true }); //qs自动拼接到url后
ctx.json(userinfo);
},
};
//后端生成签名接口:根据当前url 生成 签名信息
exports.signature = {
path: "/api/get/jsapi/signature",
method: "get",
online: true,
handler: async (ctx) => {
//获取url
const url = ctx.query.url;
//调用封装生成签名接口
let result = await wxService.get_jsapi_signature(url);
//返回数据
ctx.json(result);
},
};
步骤四:通过 ready 接口处理成功验证
wx.ready(function () {
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
- 前端
<!DOCTYPE html>
<html>
<head>
<title>2021,送你一张船票</title>
<meta charset="utf-8" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<meta name="laya" screenorientation="landscape" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<!-- 引擎jQuery库 -->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js" />
<!-- 第一步:根据 appid和sercet 换取code (前端) -->
<script>
...
</script>
<!-- 引入JS文件 -->
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
//发起签名时的请求url中不能带其他参数(例如code等):通过window.location.href.split('?')[0]过滤删除发起url中code等参数
console.log(window.location.href.split("?")[0]);
//调用服务器配置接口(传递参数):// 根据 请求 换取 签名等数据
$.get(
"/api/get/jsapi/signature?url=" + window.location.href.split("?")[0],
function (data, status) {
console.log(data);
/* 签名等数据格式
{
code: 0 //状态码
data:{
appid: "wx381145d57357ff23"
noncestr: "5d7d39a35ba943178de5f43cbd68a8cd"
signature: "1b74b3d3628bd135a7878c7c66d4898e836ac027"
timestamp: 1634709957
url: "http://172.30.21.29:3000/"
}
message: "成功"
}
*/
// 根据 签名等数据 进行初始化 wx.config
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.data.appid, // 必填,公众号的唯一标识
timestamp: data.data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.data.noncestr, // 必填,生成签名的随机串
signature: data.data.signature, // 必填,签名
jsApiList: [
// 必填,需要使用的JS接口列表,声明后才能调用
"onMenuShareTimeline",
"updateAppMessageShareData",
],
});
}
);
//第二步:初始化完毕调用接口
wx.ready(function () {
//需在用户可能点击分享按钮前就先调用
//调用分享给朋友/分享到QQ接口
wx.updateAppMessageShareData({
title: "xxx", // 分享标题
desc: "xxx", // 分享描述
link: "http://172.30.21.29:3000", // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: "https://p0.ifengimg.com/ifeng/index/20150921/ifengLogo.png", // 分享图标
success: function (data) {
// 设置成功
alert("分享成功");
console.log("data", data);
},
error: function () {
// 设置失败
alert("分享error");
},
});
});
</script>
</head>
<body>
...
</body>
</html>
###步骤五:通过 error 接口处理失败验证
wx.error(function (res) {
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
需求文档:
完整代码:
- 前端
<!DOCTYPE html>
<html>
<head>
<title>2021,送你一张船票</title>
<meta charset="utf-8" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="full-screen" content="true" />
<meta name="x5-fullscreen" content="true" />
<meta name="360-fullscreen" content="true" />
<meta name="laya" screenorientation="landscape" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<!-- 引擎jQuery库 -->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js" />
<!-- 第一步:根据 appid和sercet 换取code (前端) -->
<script>
//获取url路径中指定key的value值
//例如url路径: http://172.30.21.29:3000/?code=001XQh0006bLCM1RLx100TAmgB2XQh0D&state=STATE
//获取code的值 001XQh0006bLCM1RLx100TAmgB2XQh0D
function getQueryString(name) {
let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
let r = window.location.search.substr(1).match(reg);
if (r != null) {
return decodeURIComponent(r[2]);
}
return null;
}
//声明code
var code;
//设置code
if (localStorage.getItem("code")) {
// 如果本地缓存已经存有code 说明是回退到了获取code的起始页面
code = localStorage.getItem("code");
console.log("code", code);
alert("我是从本地缓存取的code:" + code);
} else if (getQueryString("code")) {
// 本地无code,查询URL链接上是否存在code,存在说明是获取code的当前页面
code = getQueryString("code");
localStorage.setItem("code", code);
alert("我是获取code的页面从url取的code: ", code);
} else {
// 都不没有code,跳转页面发起请求(要去微信指定链接获取)
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx381145d57357ff23&redirect_uri=${encodeURIComponent(
window.location.href
)}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`;
}
//调用后台接口请求页面(传递参数)获取用户数据(后两步在服务器完成)
if (code) {
console.log("/api/wx/userinfo?code=" + code);
//发起后台请求
$.get("/api/wx/userinfo?code=" + code, function (data, status) {
// alert("数据:" + data + "\n状态:" + status);
console.log(data);
});
}
</script>
<!-- 引入JS文件 -->
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
//发起签名时的请求url中不能带其他参数(例如code等):通过window.location.href.split('?')[0]过滤删除发起url中code等参数
console.log(window.location.href.split("?")[0]);
//调用服务器配置接口(传递参数):// 根据 请求 换取 签名等数据
$.get(
"/api/get/jsapi/signature?url=" + window.location.href.split("?")[0],
function (data, status) {
console.log(data);
/* 签名等数据格式
{
code: 0 //状态码
data:{
appid: "wx381145d57357ff23"
noncestr: "5d7d39a35ba943178de5f43cbd68a8cd"
signature: "1b74b3d3628bd135a7878c7c66d4898e836ac027"
timestamp: 1634709957
url: "http://172.30.21.29:3000/"
}
message: "成功"
}
*/
// 根据 签名等数据 进行初始化 wx.config
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.data.appid, // 必填,公众号的唯一标识
timestamp: data.data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.data.noncestr, // 必填,生成签名的随机串
signature: data.data.signature, // 必填,签名
jsApiList: [
// 必填,需要使用的JS接口列表,声明后才能调用
"onMenuShareTimeline",
"updateAppMessageShareData",
],
});
}
);
//第二步:初始化完毕调用接口
wx.ready(function () {
//需在用户可能点击分享按钮前就先调用
//调用分享给朋友/分享到QQ接口
wx.updateAppMessageShareData({
title: "xxx", // 分享标题
desc: "xxx", // 分享描述
link: "http://172.30.21.29:3000", // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: "https://p0.ifengimg.com/ifeng/index/20150921/ifengLogo.png", // 分享图标
success: function (data) {
// 设置成功
alert("分享成功");
console.log("data", data);
},
error: function () {
// 设置失败
alert("分享error");
},
});
});
</script>
</head>
<body>
...
</body>
</html>
- 服务端
const moment = require("moment");
const request = require("../../common/request");
const wxService = require("../../services/wechat/wechat");
//后端用户信息接口
exports.userinfo = {
path: "/api/wx/userinfo",
method: "get",
online: true,
handler: async (ctx) => {
let code = ctx.query.code;
var url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx381145d57357ff23&secret=cbed33d90bc25be44bd219188c4a94c4&code=${code}&grant_type=authorization_code`;
let tokenData = await request.get({ url, json: true });
let qs = {
access_token: tokenData.access_token,
openid: tokenData.openid,
lang: "zh_CN",
};
var url2 = `https://api.weixin.qq.com/sns/userinfo`;
const userinfo = await request.get({ url: url2, qs, json: true }); //qs自动拼接到url后
ctx.json(userinfo);
},
};
//后端生成签名接口:根据当前url 生成 签名信息
exports.signature = {
path: "/api/get/jsapi/signature",
method: "get",
online: true,
handler: async (ctx) => {
//获取url
const url = ctx.query.url;
//调用封装生成签名接口
let result = await wxService.get_jsapi_signature(url);
//返回数据
ctx.json(result);
},
};
FAQ
微信公众号 H5 可以通过页面自定义按钮分享或者唤起微信分享弹窗吗? 解决方法:只能通过右上角。
自定义卡片分享的动态图片无法显示或者始终为默认图片 不要使用
&&
进行判断,需要使用三元表达式进行判断,并且测试只能在生产(https)环境下查看。
链接
手把手教你如何自定义微信分享卡片内容 >微信 H5 自定义分享在 IOS 下失效的问题 >解决微信页面中 ios 音乐不能自动播放问题 >微信中音乐播放在 ios 不能自动播放解决 >微信公众号-- 微信分享功能(分享到朋友和朋友圈显示图片和简介 >手把手教你如何自定义微信分享卡片内容 >如何在微信自定义链接分享制作图文卡片生成代码实现自定义标题描述缩列图以供转发