概览
key | value |
---|---|
项目名称 | node 微信公众号开发 |
项目描述 | 使用 node 编写接口,前后端分离获取签名数据 |
开发者 | leinov |
发布日期 | 2018-11-07 |
仓库 | github 地址 https://github.com/leinov/node-weixin-api |
安装 & 使用
下载
- Git clone Git@GitHub.com:leinov/node-weixin-API.Git
- NPM install
开发
在微信公众号后台配置域名白名单
在 server/weixin/wx.JS 里添加自己的 appid secret
在 src/index/index.JS 里 wxShare 里添加自己的分享内容
NPM run dev
打开微信开发者工具调试
NPM run build
将域名配置时下载的 txt 文件放到 dist 文件夹下
上传到服务器
pm2 start www.JS 启动服务
在微信里打开连接分享给好友测试
扩展: 修改 / src/component/wxconfig.JS 中的 jsApiList 数组, 添加想要使用的微信 API
WIKI
我们在微信网页开发的时候需要通过后端返回的微信签名数据加以前端的配置才能使用微信提供的分享, 图像, 音频等 API 接口. 这里我们就用前后端分离的思想, 拿分享到朋友圈为例, 使用 node 来完成这一过程
下图没有使用 JS-sdk 开发的页面在微信里分享样式
接下来我们一步步来实现
步骤一: 绑定域名
先登录微信公众平台进入 "公众号设置" 的 "功能设置" 里填写 "JS 接口安全域名".
在添加域名时需要下载一个 txt 文件放到服务器 web 可访问的根目录 比如 http://www.leinov.com/xxx.txt 可访问的静态根目录, 比如 node 的静态文件设置的是 public 文件, 就放 public 下
备注: 登录后可在 "开发者中心" 查看对应的接口权限, 看是否有分享朋友圈等权限
步骤二: 引入微信 JS 文件
在需要调用 JS 接口的页面引入如下 JS 文件,(支持 https):http://res.wx.qq.com/open/js/jweixin-1.4.0.js 也可以直接下载到本地目录引入
步骤三: 通过 config 接口注入权限验证配置 (第六步详解)
所有需要使用 JS-SDK 的页面必须先注入配置信息, 否则将无法调用 (同一个 url 仅需调用一次, 对于变化 url 的 SPA 的 Web App 可在每次 url 变化时进行调用, 目前 Android 微信客户端不支持 pushState 的 H5 新特性, 所以使用 pushState 来实现 Web
- wx.config({
- debug: true, // 开启调试模式, 调用的所有 API 的返回值会在客户端 alert 出来, 若要查看传入的参数, 可以在 pc 端打开, 参数信息会通过 log 打出, 仅在 pc 端时才会打印.
- appId: '', // 必填, 公众号的唯一标识
- timestamp: , // 必填, 生成签名的时间戳
- nonceStr: '', // 必填, 生成签名的随机串
- signature: '',// 必填, 签名
- jsApiList: [] // 必填, 需要使用的 JS 接口列表
- });
我们使用微信的所有接口都需要有在引入 wx JS-sdk http://res.wx.qq.com/open/js/jweixin-1.4.0.js 和配置 config 的前提下
下面我们主要讲解如何通过 node 来获取微信签名的 config 的数据.
步骤四: 生成签名 config 数据
步骤三所需要的数据需要通过签名算来生成, 下面是生成签名数据的步骤
1, 通过公众号的 appid 和 secret 获取 access_token
2. 根据 access_token 获取 ticket 票据
3. 根据微信提供 node 生成签名算法 http://demo.open.weixin.qq.com/jssdk (需要 ticket,url 参数来返回 config 数据
这里要强调是 secret 一定要写在后端, 决不能暴露在前端, 这也是为什么需要用接口返回数据的原因.
获取签名 config 数据完整代码 server/wx.JS
- /*********************************************************************************
- * @file: 返回微信开发需要的 config 数据
- * @desc:
- * 1, 通过 appid 和 secret 获取 access_token
- * 2. 根据 access_token 获取 ticket
- * 3. 根据 ticket 和 url(访问的页面地址由接口传过来 ) 通过 sgin 加密返回前度需要用到的 config 数据
- * @ahthor: leinov
- * @usedate:2018-11-07
- **********************************************************************************/
- const request = require("request");
- const Base64 = require("js-base64").Base64;
- const sign = require("./sign.js"); // 微信提供在开发文档可以找到下载到本地
- const base={
- appid:"****",// 公众号 appid
- secret:"****", // 公众号 secret (重要不要暴露在前端)
- wxapi:"https://api.weixin.qq.com/cgi-bin"
- };
- /**
- * 根据 appid,secret 获取 access_token
- */
- function getAccessToken(){
- return new Promise((resolve, reject)=>{
- request.get(`${base.wxapi}/token?grant_type=client_credential&appid=${base.appid}&secret=${base.secret}`, function (error, response, body) {
- if(error!==null){
- reject("获取 access_token 失败 检查 getAccessToken 函数");
- }
- resolve(JSON.parse(body));
- });
- });
- }
- /**
- * 根据 access_token 获取 api_ticket
- *
- * @param {String} access_token
- * @return {Promise}
- */
- function getTicket(access_token){
- return new Promise((resolve,reject)=>{
- request.get(`${base.wxapi}/ticket/getticket?access_token=${access_token}&type=jsapi`, function (error, response, body) {
- if(error!==null){
- reject("获取 api_ticket 失败 检查 getTicket 函数");
- }
- resolve(JSON.parse(body));
- });
- });
- }
- /**
- * 根据 api_ticket 和 url 通过加密返回所有 config 数据
- *
- * @param {String} href
- * @return {Object} configdata
- */
- async function getConfigData(href){
- let configData;
- try{
- const accessTokenData = await getAccessToken();
- const ticketData = await getTicket(accessTokenData.access_token);
- const decodeHref = Base64.decode(href);
- configData = sign(ticketData.ticket,decodeHref);
- configData.appid = base.appid;
- }catch(err){
- // 打印错误日志
- console.log(err);
- configData = {};
- }
- return configData;
- }
- module.exports = getConfigData;
这里使用到了 request 来请求微信接口, sign.JS 是微信提供的 node 签名算法, 自己可以下载, 通过微信接口请求以及 node 签名算法就可以获取到如下签名数据.
- timestamp: , // 生成签名的时间戳
- nonceStr: '', // 生成签名的随机串
- signature: '',// 签名
第五步: 编写接口返回 config 数据
上面 wx.JS 已经获得数据, 接下来我们用 node 编写接口返回数据. 注意下面的 href,href 是前端传回的用来生成签名的, 而且这个网页地址的域名一定是在设置里加入白名单了的.
- var express = require("express");
- var App = express();
- var getConfigData = require("./server/wx.js");
- var port = "3000";
- // 获取微信配置数据接口
- App.get("/wxconfigdata", function(req, res){ // 获取配置
- let href = req.query.href;//get 获取前端传来的 base64 网页地址
- getConfigData(href).then((data)=>{
- res.send(JSON.stringify(data));
- });
- });
- var server = http.createServer(App);
- server.listen(port);
- server.on("listening", onListening);
这样就启动了一个 3000 端口的服务
我们通过访问 "http://localhost:3000/wxconfigdata" 就可以拿到数据, 但这个数据是不正确的, 因为 locahost 跟在设置里的白名单域名不匹配, 所以在开发时我们要放到测试服务器里测试.
步骤六: 前端请求获取签名数据
- /*********************************************************************************
- * @file: src/wxconfig.JS 通过接口获取微信 config 数据
- * @ahthor: leinov
- * @usedate:2018-11-07
- **********************************************************************************/
- import { Base64 } from "js-base64";
- const axios = require("axios");
- /**
- * 页面调用微信分享方法
- *
- * @param {Object} obj 分享的标题, 描述, 图片等
- * @param {type} callback
- * @return {type}
- */
- function wxShare(obj,callback){
- const href = Base64.encode(location.href);
- //base64 当前页面地址传给后端生成签名
- axios.get(`${location.origin}/wxconfigdata?href=${href}`).then((res)=>{
- wx.config({
- debug: false, // 开启调试模式, 调用的所有 API 的返回值会在客户端 alert 出来, 若要查看传入的参数, 可以在 pc 端打开, 参数信息会通过 log 打出, 仅在 pc 端时才会打印.
- appId: res.data.appid, // 必填, 公众号的唯一标识
- timestamp: res.data.timestamp, // 必填, 生成签名的时间戳
- nonceStr: res.data.nonceStr, // 必填, 生成签名的随机串
- signature: res.data.signature,// 必填, 签名, 见附录 1
- jsApiList: ["onMenuShareTimeline","onMenuShareAppMessage"] // 必填, 需要使用的 JS 接口列表, 所有 JS 接口列表见文档
- });
- shareConfig(obj,callback);
- }).catch((err)=>{
- shareConfig({},callback);
- });
- }
- function shareConfig(obj,callback){
- wx.ready(function(){
- // 分享到朋友圈
- wx.onMenuShareTimeline({
- title: obj.timelinetitle ? obj.timelinetitle : obj.title , // 分享标题
- link: obj.link, // 分享链接
- imgUrl: obj.imgUrl ? obj.imgUrl :"" , // 分享图标
- success: function () {
- if (typeof callback === "function"){
- callback();
- }
- },
- cancel: function () {
- // 用户取消分享后执行的回调函数
- }
- });
- // 分享给微信好友
- wx.onMenuShareAppMessage({
- title: obj.title, // 分享标题
- desc: obj.desc, // 分享描述
- link: obj.link, // 分享链接
- imgUrl: obj.imgUrl ? obj.imgUrl:"",
- success: function () {
- if (typeof callback === "function"){
- callback();
- }
- },
- cancel: function () {
- // 用户取消分享后执行的回调函数
- }
- });
- });
- }
- export default wxShare;
步骤七: 页面使用
假设我们使用的是 react 在 react 打包入口 JS 文件里调用配置即可
- import wxShare from "../component/wxconfig.js";
- wxShare({
- title: "驾多多 - 小程序时代的驾校管理系统", // 分享标题
- desc:"驾多多驾校管理系统. 帮助驾校在互联网时代, 零门槛使用小程序工具, 提升招生量, 提升服务能力, 降低运营成本, 是为驾校提供人, 财, 物及业务办理的综合管理系统.", // 分享描述
- link: location.href, // 分享链接
- imgUrl:"https://***/jiaddwxicon.png" , // 分享图标
- });
在配置正确的情况下就可以实现配置分享标题描述和图片了, 并且微信提供的可用接口都可以实现.
tips
在微信开发者工具中调试
appid 和 secret 一定要正确
域名一定是备案的
绑定域名需要的放在服务器上的 txt 位置一定要正确
参考
微信公众号开发文档
来源: https://www.cnblogs.com/leinov/p/9944994.html