这篇文章主要来说说微信JSSDK的一些配置和微信分享的使用,包括从前端sdk文件引入到服务器端和微信服务器的交互。另外Tangide已经把一些工作做好了,我会简要说一说怎么把它用起来。在开发的过程中主要参考了微信官方开发文档,由于微信提供的功能略多,我会定期更新文档,如果你已经熟悉了微信JSSDK的开发流程可以直接跳过前面的步骤,直接跳转到Tangide与微信JSSDK的使用结合 :)。
1. 首先得有个公众号
微信把公众号细分为服务号和订阅号。接口权限各不相同,如果你记不住你的公众号有没有对应功能的权限,可以到开发者中心->接口权限表对应查看。
2. 配置JS接口安全域名
微信限制了JS接口使用的域名,具体在:公众号设置->功能设置页面。好在可以同时配置3个,而且可以修改:
这意味着配置可以复用了,重复劳动减少了:)。
3. 引入JS文件
http://res.wx.qq.com/open/js/jweixin-1.0.0.js
这个是微信官方提供的sdk。可以在h5页面放个<script>
标签把它引入进来。
4. 注入权限验证配置
微信为了验证调用SDK
的合法性,需要我们的服务器与微信服务器交互获取配置信息。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
一般来说只有是否开启调式模式由客户端决定,其他的都是通过http请求服务器获得,下面我们就来看看如何从服务获取配置信息。
5. 服务端获取配置信息
这是整个过程相对关键的一步,你必须要缓存好两个token: jsapi_ticket
以及access_token
。access_token
有效时间为2个小时。向微信服务器请求频率限制为:每天2000次。微信还有其他一些参数的频率限制,你可以看这里。
下面来说说获取配置信息的具体步骤:
来看看服务器端是怎么处理的:
nodejs
服务器端:
var fs = require('fs');
var path = require('path');
var urlParser = require('url');
var TokenManager = require('./token_manager');
var Handler = function() {
};
Handler.doit = function(req, res) {
try {
var query = urlParser.parse(req.url, true).query;
if(!query || !query.url) {
throw new Error('invalid params');
}
var realUrl= atob(decodeURI(query.url));
}
catch(e) {
res.status(401).json({code: -1, message: e});
res.end();
return;
}
Handler.tokens.getJsApiTicket(realUrl, function(err, config) {
if(!!err) {
res.status(500).json({code: -1, message: err});
}
else {
res.status(200).json({code: 0, message: 'success', data: config});
}
res.end();
});
};
Handler.init = function(app, express, config) {
Handler.opts = {
appid: config.appid,
secret:config.secret
};
Handler.tokens = TokenManager.create(opts);
app.post('/weixin/get-config.php', Handler.doit);
};
module.exports = Handler;
//
//token manager
var TokenManager = function(opts) {
this.opts = opts;
if(!opts.appid || !opts.secret) {
thow new Error('appid and secret should not be empty!!!');
}
var tokenPath = path.join(__dirname, 'tokens.json');
this.loadToken = opts.loadToken || function(type, cb) {
fs.readFile(tokenPath, 'utf8', function(err, data) {
if(!!err) {
return cb(err);
}
try {
data = data || JSON.stringify({});
data = JSON.parse(data);
}
catch(e) {
return cb(e);
}
cb(null, data[type] || {});
});
};
this.saveToken = opts.saveToken || function(token, cb) {
fs.readFile(tokenPath, 'utf8', function(err, data) {
if(!!err) {
return cb(err);
}
data = data || {};
var type = Object.keys(token)[0];
data[type] = token[type];
fs.writeFile(tokenPath, JSON.stringify(data), cb);
});
};
};
var isValid = function() {
return !!this.token && (new Date().getTime()) < this.expireTime;
};
var load = function(stream, cb) {
var chunks = [];
stream.on('data', function(chunk) {
chunks.push(chunk);
});
stream.on('error', function(err) {
cb(err);
});
stream.on('end', function() {
cb(null, Buffer.concat(chunks));
});
};
var request = function