The signature algorithm that WeChat shares is also written in Wechat. The main reason is that the calling interface needs to use the server (as the official Wechat document says, even if you try the lower front end). However, access_token and jsapi_ticket of Wechat are limited in usage, so they can be obtained by the server and saved later. Then they can be retrieved after the next usage timeout.That's enough, or you'll end up with an embarrassing situation where the number of interface calls exceeds the limit.
If you need to use a custom shared copy, the service number or subscription number must be authenticated (I am a human subscription number and can't authenticate, so I can't use the sharing function)
I'm using the background that node does here, so the code is using js code, of course other can, the logic is the same, the code is written differently.
1. First of all, the setting of the public number
I'm applying for a subscription number
First, to obtain your own developer id (appid) and developer password (AppSecret) in the development->basic configuration, these two are required
Then set the server's ip in the ip whitelist option under the same directory
This way, the basic server setup is complete.
2. And that's what we're best at - writing code
According to the official WeChat documentation, the first step is to get access_token, which has a validity period of 7200 seconds, so there will be local access_token (file storage or database storage is fine, if you save it anyway)
The implementation code is as follows
First, I need to import the module corresponding to node (mongodb database needs to be started every time I use it, so I use file storage here)
1 var express=require('express'); 2 var https=require('https');5 var fs = require("fs"); 6 var crypto = require('crypto');
From top to bottom is
The express ion module is used to create a server to interface with the front end and WeChat separately (which may not seem useful here, but can be replaced by the http module)
) A module used by the https module to send https requests (WeChat requests require https requests, not http requests)
fs module file operation module, if the database used needs to be replaced with the corresponding module
crypto module encryption module, the WeChat signature algorithm needs to use the sha1 algorithm encryption, as mentioned below
Introduction of all modules, and then define some easy-to-use methods
First, to start a server:
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);
Then define how to read and write files
1 //write file 2 function whiteFile(obj,callback){ 3 fs.writeFile(obj.fileName,obj.data,{flag:"w"},function (err) { 4 if(err){ 5 console.error(obj.name+"File Write Error"); 6 console.log(err); 7 return; 8 } 9 console.log('File Write Successfully'); 10 callback(obj.data); 11 }); 12 } 13 //Read file information 14 function readFile(obj,callback,errback){ 15 fs.readFile(obj.fileName,"utf-8",function (err,data) { 16 if(err){ 17 console.error(obj.name+"Read error"); 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 }
Then use a method that defines how to send an https request
1 //Send one http get request 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("Interface call failed"); 11 }); 12 httpReq.end(); 13 }
With the basic methods available, you can request the WeChat interface below.
1 //Obtain 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=Your appid&secret=Your appid Corresponding Password", 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("File Write Failure"); 25 console.log("access_token:"+res); 26 cb(res); 27 } 28 }); 29 }); 30 }
The above method is to get the WeChat token, which I read from the local file first, but I can't read the interface anymore (I'm just testing, I don't make a judgment, I need to judge the timestamp in practice, if the access_token expires, I need to delete the contents of the file and request a new access_token again)
With access_token, get jsapi_ticket below:
1 //Obtain 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("File Write Failure"); 33 console.log("ticket:"+res); 34 callback(res); 35 } 36 } else { 37 callback(res); 38 } 39 40 }); 41 }); 42 }); 43 }
The jsapi_ticket and token acquisition and storage logic are the same
Next comes signature generation
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 });
After generating the signature, pass the signature and random string together with the appid and timestamp to the front end via 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 });
The front end receives the data and then calls wx.config(), passing in the parameters of the drink to get the corresponding WeChat js rights (the front end implements logic as described in the last article).