Nodejs微信公眾號開發

frontman發表於2018-11-12

概覽

key value
專案名稱 node微信公眾號開發
專案描述 使用node編寫介面,前後端分離獲取簽名資料
開發者 leinov
釋出日期 2018-11-07
倉庫 github地址

安裝&使用

下載
git clone git@github.com:leinov/node-weixin-api.git

npm install
開發
  • 在微信公眾號後臺配置域名白名單
  • server/weixin/wx.js裡新增自己的appid secret
  • src/index/index.jswxShare裡新增自己的分享內容
  • npm run dev
  • 開啟微信開發者工具除錯
  • npm run build
  • 將域名配置時下載的txt檔案放到dist資料夾下
  • 上傳到伺服器
  • pm2 start www.js啟動服務
  • 在微信裡開啟連線分享給好友測試
  • 擴充套件:修改/src/component/wxconfig.js中的jsApiList陣列,新增想要使用的微信api

WIKI

我們在微信網頁開發的時候需要通過後端返回的微信簽名資料加以前端的配置才能使用微信提供的分享,影像,音訊等api介面。這裡我們就用前後端分離的思想,拿分享到朋友圈為例,使用node來完成這一過程

下圖沒有使用js-sdk開發的頁面在微信裡分享樣式

image

接下來我們一步步來實現

步驟一:繫結域名

先登入微信公眾平臺進入“公眾號設定”的“功能設定”裡填寫“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和配置config的前提下
下面我們主要講解如何通過node來獲取微信簽名的config的資料。

步驟四:生成簽名config資料

步驟三所需要的資料需要通過簽名算來生成,下面是生成簽名資料的步驟

  • 1,通過公眾號的appid和secret獲取access_token
  • 2.根據access_token獲取ticket票據
  • 3.根據微信提供node生成簽名演算法(需要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" , // 分享圖示
});
在配置正確的情況下就可以實現配置分享標題描述和圖片了,並且微信提供的可用介面都可以實現。

image

tips

  • 在微信開發者工具中除錯
  • appid和secret一定要正確
  • 域名一定是備案的
  • 繫結域名需要的放在伺服器上的txt位置一定要正確

參考


相關文章