根据微信官方文档,需要拿到access_token,(access_token有7200秒的有效期,所以拿到access_token以后要存在本地)
具体实现代码如下
首先需要引入node对应的模块(mongodb数据库每次使用还要启动,用的是文件存储)
1 var express=require('express');
2 var https=require('https');5 var fs = require("fs");
6 var crypto = require('crypto');
express模块 用来创建一个服务器,分别和前端、微信进行接口对接(可以使用http模块代替)
https模块 用来发送https请求的一个模块(微信请求需要使用https请求,http不行)
fs模块 文件操作模块,如果是用的数据库就需要换成对应的模块
crypto模块 加密模块,微信签名算法需要使用sha1算法加密
模块全部引入。
然后,要开启一个服务器:
1 app.get("/getconfig",function (req,res) {
2 res.header("Access-Control-Allow-Origin", "*");
3 res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
4 res.header("Access-Control-Allow-Headers", "X-Requested-With");
5 res.header('Access-Control-Allow-Headers', 'Content-Type');
6 res.send({
7 code:"200",
8 data:{},
9 result:true
10 });
11 res.end("");
12 });
13 app.listen(8000);
再然后定义阅读和写入文件的方法
1 //写入文件
2 function whiteFile(obj,callback){
3 fs.writeFile(obj.fileName,obj.data,{flag:"w"},function (err) {
4 if(err){
5 console.error(obj.name+"文件写入错误");
6 console.log(err);
7 return;
8 }
9 console.log('文件写入成功');
10 callback(obj.data);
11 });
12 }
13 //读取文件信息
14 function readFile(obj,callback,errback){
15 fs.readFile(obj.fileName,"utf-8",function (err,data) {
16 if(err){
17 console.error(obj.name+"读取错误");
18 return errback(callback);
19 }
20 //console.log(data);
21 if(!data){
22 errback(callback);
23 }else{
24 console.log(data);
25 callback(data);
26 }
27 });
28 }
然后是使用定义一个发送https请求的方法
1 //发送一个http get请求
2 function sendGetRequest(options,callback){
3 var httpReq=https.request(options, function(httpRes) {
4 httpRes.on('data',function(chun){
5 callback(chun);
6 });
7 httpRes.on('end',function(){});
8 });
9 httpReq.on('error',function(err){
10 console.log("接口调用失败");
11 });
12 httpReq.end();
13 }
下边就可以请求微信接口了
1 //获取access_token
2 function getToken(callback){
3 readFile({
4 fileName:"./access_token.txt",
5 name:"access_token"
6 },callback,function(cb){
7 var options={
8 hostname:"api.weixin.qq.com",
9 path:"/cgi-bin/token?grant_type=client_credential&appid=您的appid&secret=你的appid对应的密码",
10 method:'GET'
11 };
12 sendGetRequest(options,function(chun){
13 var resObj = JSON.parse(chun.toString());
14 resObj.timestamp = Math.floor((new Date().getTime())/1000);
15 var res = JSON.stringify(resObj);
16 //console.log(res);
17 try {
18 whiteFile({
19 fileName:"./access_token.txt",
20 data:res,
21 name:"access_token"
22 },cb);
23 }catch(err){
24 console.log("文件写入失败");
25 console.log("access_token:"+res);
26 cb(res);
27 }
28 });
29 });
30 }
上边这个方法是获取微信token的方法,首先从本地文件中读取,读取不到再调用接口(实际操作中需要判断时间戳,如果access_token过期需要删掉文件里的内容重新请求新的access_token)
access_token有了,下边就是获取jsapi_ticket:
1 //获取ticket
2 function getTicket(callback){
3 readFile({
4 fileName:"./ticket.txt",
5 name:"ticket"
6 },callback,function(cb) {
7 getToken(function(tokenData){
8 var token = JSON.parse(tokenData);
9 //console.log("token:"+JSON.stringify(token));
10 //callback({code:"200",data:{"data":token},result:true});
11 var options = {
12 hostname: "api.weixin.qq.com",
13 path: "/cgi-bin/ticket/getticket?access_token=" + token.access_token + "&type=jsapi",
14 method: 'GET'
15 };
16 sendGetRequest(options, function (chun) {
17 var resObj = JSON.parse(chun.toString());
18 resObj.timestamp = Math.floor((new Date().getTime())/1000);
19 var res = JSON.stringify(resObj);
20 if (resObj.errcode == 42001) {
21 getToken(function(){
22 getTicket(callback);
23 });
24 } else if (resObj.ticket) {
25 try {
26 whiteFile({
27 fileName:"./ticket.txt",
28 data:res,
29 name:"ticket"
30 },callback);
31 }catch(err){
32 console.log("文件写入失败");
33 console.log("ticket:"+res);
34 callback(res);
35 }
36 } else {
37 callback(res);
38 }
39
40 });
41 });
42 });
43 }
jsapi_ticket和token获取和存储逻辑是一样的
接下来就是签名的生成
1 getTicket(function(data){
2 var dataObj = JSON.parse(data);
3 var noncestr = "zhangchenguang";
4 var timestamp = Math.floor((new Date().getTime())/1000);
5 var url = "http://api-loan.zhmf.com/html/test/testshare.html";
6 var obj = {
7 noncestr,timestamp,url,jsapi_ticket:dataObj.ticket
8 };
9 var arr = ["noncestr","jsapi_ticket","timestamp","url"].sort();
10 var string1 = "";
11 for(var i = 0; i < arr.length; i++){
12 string1 += (arr[i]+"="+obj[arr[i]])+"&";
13 }
14 string1 = string1.slice(0,string1.length-1);
15 console.log(string1);
16 var shasum = crypto.createHash('sha1');
17 shasum.update(string1);
18 var signature = shasum.digest("hex");
19 console.log(signature);
20 });
生成签名以后,把签名和随机串和appid和时间戳同时通过res.send传给前端:
1 app.get("/getconfig",function (req,res) {
2 res.header("Access-Control-Allow-Origin", "*");
3 res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
4 res.header("Access-Control-Allow-Headers", "X-Requested-With");
5 res.header('Access-Control-Allow-Headers', 'Content-Type');
6 getTicket(function(data){
7 var dataObj = JSON.parse(data);
8 var noncestr = "zhangchenguang";
9 var timestamp = Math.floor((new Date().getTime())/1000);
10 var url = "http://api-loan.zhmf.com/html/test/testshare.html";
11 var obj = {
12 noncestr,timestamp,url,jsapi_ticket:dataObj.ticket
13 };
14 var arr = ["noncestr","jsapi_ticket","timestamp","url"].sort();
15 var string1 = "";
16 for(var i = 0; i < arr.length; i++){
17 string1 += (arr[i]+"="+obj[arr[i]])+"&";
18 }
19 string1 = string1.slice(0,string1.length-1);
20 console.log(string1);
21 var shasum = crypto.createHash('sha1');
22 shasum.update(string1);
23 var signature = shasum.digest("hex");
24 console.log(signature);
25 res.send({
26 code:"200",
27 data:{
28 noncestr:noncestr,
29 timestamp:timestamp,
30 appId:"wx23599cdec409383c",
31 signature:signature
32 },
33 result:true
34 });
35 res.end("");
36 });
37 });