About WeChat signature Signature Acquisition

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).

Keywords: Javascript JSON Database SHA1 MongoDB

Added by monkeyx on Sat, 25 May 2019 20:25:41 +0300