资讯专栏INFORMATION COLUMN

node调用微信JS SDK遇到的坑

Godtoy / 1328人阅读

摘要:废话不多说来说说用做服务端调用微信遇到的坑。微信都有说明不做赘述。因为以后微信返回的值才会改变,并且微信规定每天限定的访问次数如果使用库的话优势可以减少对微信服务器访问的次数提升性能。

这几天要做一个H5的页面,之前没做。对我来说也是一次对新领域的接触。废话不多说来说说用node做服务端调用微信JS SDK遇到的坑。
首先讲一下思路:

微信JS-SDK说明文档

绑定域名

引入JS文件

通过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 + "×tamp=" + 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的方法
       
    }
})

总结 : 这只是个示例代码的具体实现还是看场景。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81047.html

相关文章

  • 微信JS-SDK选择图片遇到的坑

    摘要:微信选择图片遇到的坑有个需求要在微信企业号里面做开发,有个功能是选择图片,使用标签肯定是不管用了,手机上不能多选,所以使用了微信的提供的相关,这个地方真的是有坑,记录一下。 微信JS-SDK选择图片遇到的坑 有个需求要在微信企业号里面做开发,有个功能是选择图片,使用input标签肯定是不管用了,Android手机上不能多选,所以使用了微信的JS-SDK提供的相关API,这个地方真的是有...

    explorer_ddf 评论0 收藏0
  • vue项目接入微信JSSDK的坑

    摘要:微信说明文档分享的坑根据的文档,很多人都是在初始化的配置的时候,传入的当前的地址不正确。同样的,给微信初始化的加入对应的参数。 date: 2018-12-13 15:23:09 用于记录接入微信JS-SDK的坑,以后方便查询第一次接入公众号微信支付、分享、定位等等的坑的时候,心里是迷茫而又恐惧。因为,听说坑特别多,后来发现自己的亲身体验到了这一点。 支付的坑 1、当前URL未注册 ...

    lieeps 评论0 收藏0
  • vue项目接入微信JSSDK的坑

    摘要:微信说明文档分享的坑根据的文档,很多人都是在初始化的配置的时候,传入的当前的地址不正确。同样的,给微信初始化的加入对应的参数。 date: 2018-12-13 15:23:09 用于记录接入微信JS-SDK的坑,以后方便查询第一次接入公众号微信支付、分享、定位等等的坑的时候,心里是迷茫而又恐惧。因为,听说坑特别多,后来发现自己的亲身体验到了这一点。 支付的坑 1、当前URL未注册 ...

    jsdt 评论0 收藏0
  • vue项目接入微信JSSDK的坑

    摘要:微信说明文档分享的坑根据的文档,很多人都是在初始化的配置的时候,传入的当前的地址不正确。同样的,给微信初始化的加入对应的参数。 date: 2018-12-13 15:23:09 用于记录接入微信JS-SDK的坑,以后方便查询第一次接入公众号微信支付、分享、定位等等的坑的时候,心里是迷茫而又恐惧。因为,听说坑特别多,后来发现自己的亲身体验到了这一点。 支付的坑 1、当前URL未注册 ...

    nodejh 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<