node挪用微信JS SDK碰到的坑

这几天要做一个H5的页面,之前没做。对我来讲也是一次对新领域的打仗。空话不多说来讲说用node做服务端挪用微信JS SDK碰到的坑。
起首讲一下思绪:

微信JS-SDK申明文档

  1. 绑定域名

  2. 引入JS文件

  3. 经由过程config接口注入权限考证设置

    wx.config({
        debug: true,
        appId: '', // 必填,民众号的唯一标识
        timestamp: , // 必填,天生署名的时候戳
        nonceStr: '', // 必填,天生署名的随机串
        signature: '',// 必填,署名,见附录1
        jsApiList: [] // 必填,须要运用的JS接口列表,一切JS接口列表见附录2
    });

今后就是经由过程ready接口处置惩罚胜利考证、经由过程error接口处置惩罚失利考证。微信JS-SDK都有申明不做赘述。

Node挪用微信JS-SDK实践

须要装置一下模块供我们运用:

npm install sha1

这个哈希1模块是处置惩罚对字符的哈希加密,天生signature

npm install redis

这个人人都懂,用来做对access_token、jsapi_ticket的存储而且设定存在时候7200s。(由于7200s今后微信返回的值才会转变,而且微信划定天天限定2000的接见次数);

假如运用co库的话

npm install co
  • 上风

能够削减对微信sdk服务器接见的次数,提拔机能。同时对接见的次数限定做了最大的优化处置惩罚。

起首建一个wechatConfig.js用来寄存appid,appsecret

    module.exports = {
        appid : '',//民众号的appId,能够在民众平台上找到,-。-本身找。
        appsecret : ''//民众号的appsecret 
    };

竖立getWebToken.js 用来返回access_token,由于这个是异步返回一个promise

'use strict';
const request = require('request');
const qs = require('querystring');
const config = require('./../wechatConfig');

function getToken() {
    
    let reqUrl = 'https://api.weixin.qq.com/cgi-bin/token?';
    let params = {
        grant_type: 'client_credential',
        appid: config.appid,
        secret: config.appsecret
    };

    let options = {
        method: 'get',
        url: reqUrl+qs.stringify(params)
    };
    console.log(options.url);

    return new Promise((resolve, reject) => {
        request(options, function (err, res, body) {
            if (res) {
                console.log(body)
                resolve(body);
            } else {
                
                reject(err);
            }
        })
    })
}

module.exports = getToken;

param的递次肯定不能错!!!这个很重要不然会证书会认证失利!这个坑我整了1天赋爬出来。

竖立一个getJsApiData.js 文件用来做为重要的controller返回效果返回给client

/**
 * Created by caozheng on 2016/11/24.
 */
'use strict';
const fs = require('fs');
const request = require('request');
const getToken = require('./getWebToken');
const sha1 = require('sha1');


function getJsApiTicket() {  
    return new Promise((resolve, reject) => {
                getToken().then(function (body) {
                    body = JSON.parse(body);
                    var token = body.access_token;
                    var reqUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + token + '&type=jsapi';
                    let options = {
                        method: 'get',
                        url: reqUrl
                    };
                    request(options, function (err, res, body) {
                        if (res) {
                            resolve(body);
                        } else {
                            reject(err);
                        }
                    })
                }).catch(function (err) {
                    throw (err)
                });
    })
}
//noncestr
function getNonceStr () {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for(var i = 0; i < 16; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}
//timestamp
function getTimestamp() {
    var time = String(new Date().valueOf());
    return time.substr(0, time.length-3);
}

function getSign(jsApiTicket, noncestr, timestamp, url) {
    console.log("******************");
    console.log(jsApiTicket);
    var sortData = "jsapi_ticket=" + jsApiTicket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;

    return sha1(sortData);
}

//返回数据分别为sign, timestamp, noncestr
function getJsApiData(clientUrl) {
    let noncestr = getNonceStr();
    let timestamp = getTimestamp();
    return getJsApiTicket().then(data => {
        return [getSign(JSON.parse(data).ticket, noncestr, timestamp, clientUrl), timestamp, noncestr];
    })
}

module.exports = getJsApiData;

在路由处增加进口

/*微信返回sdk参数*/
router.post('/wechat',function (req, res) {
    var clientUrl = req.body.url;

    getJsApiData(clientUrl).then(data => {
        res.send({signature: data[0], timestamp: data[1], nonceStr: data[2]});
    });

});

注重:这里从client传过来的url肯定是动态猎取的location.href.split(‘#’)[0],而且不能带有#号,由于分享一篇文章今后微信会在链接后加参数。

  • 运用redis缓存access_token、jsapi_ticket

竖立一个redis.js文件,由于这里只须要存储功用。

/**
 * Created by caozheng on 2016/11/24.
 */
var db = {};
var redis = require('redis');
var options = {
    host : '', // 这里不须要诠释吧
    port : '6379', // 这里也不须要
    password : '', // 这个论英文的重要性
    db : 2 //db存储的位置
};

var client = redis.createClient(options);

client.on('ready',function(err){
    console.log('ready');
});

client.on("error", function (err) {
    console.log("Error :" , err);
});

client.on('connect', function(){
    console.log('Redis衔接胜利.');
});

/**
 * 增加string范例的数据
 * @param key 键
 * @params value 值
 * @params expire (逾期时候,单元秒;可为空,为空示意不逾期)
 * @param callBack(err,result)
 */
db.set = function(key, value, expire, callback){
    client.set(key, value, function(err, result){
        console.log(key);
        console.log(value);
        if (err) {
            console.log(err);
            callback(err,null);
            return;
        }

        if (!isNaN(expire) && expire > 0) {
            client.expire(key, parseInt(expire));
        }

        callback(null,result)
    })
};

/**
 * 查询string范例的数据
 * @param key 键
 * @param callBack(err,result)
 */
db.get = function(key, callback){

    client.get(key, function(err,result){
        if (err) {
            console.log(err);
            callback(err,null);
            return;
        }

        callback(null,result);
    });
};

module.exports = db;

总结:这里也能够写成异步! express能够运用co库,KOA的话那就不必看我写的了…

在getJsApiData.js中的getJsApiTicket函数中增加redis存储,读取。同时须要引入redis.js

const db = require('./../../db/radis');
var res = {
    access_token :'',
    ticket : ''
}    // 这里为了和大众接口同步把数
co(function* (){
    // 援用co库
    var result = yield {
        access_token : db.get("access_token"),
        ticket : db.get("ticket")
    }
    // 推断redis中是不是存在access_token、ticket
    if(result.access_token && result.ticket){
        return result // 返回存储中的ticket的值
    }else{
        // 这里是之前代码 -> getJsApiTicket 中返回promise的要领
       
    }
})

总结 : 这只是个示例代码的详细完成照样看场景。

    原文作者:caozheng550
    原文地址: https://segmentfault.com/a/1190000007602617
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞