我们项目是使用Vue 和 Node.js的组合,所以文中的所以代码均是Js代码。
本文介绍的是验证服务器,以及获取网页授权的初步过程遇到的代理问题,其他接口大同小异,就不过多介绍了。
这是做公众号开发必备的第一部,它要求开发者准备好自己的服务器和域名,并且有一个指定的接口可以返回指定信息:
下面我来介绍一下这个功能点的实现,其实就是Nginx
中配置好路径,比如/my_path
跳转到我们的服务上,后台服务中已经实现我我们的 /api/validateAccessToken
接口,具体如下:
const { WECHAT_TOKEN, WECHAT_CONFIG } = require('../config');
const crypto = require('crypto');
const request = require('request');
const { getLog } = require("../utils/log");
const logger = getLog('wechat_service');
/**
* 参数 描述
* signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
* timestamp 时间戳
* nonce 随机数
* echostr 随机字符串
* @param {*} signature
* @param {*} timestamp
* @param {*} nonce
* @param {*} echostr
*/
async createAccessToken(signature, timestamp, nonce, echostr) {
try {
//1.将token、timestamp、nonce三个参数进行字典序排序
let array = [WECHAT_TOKEN, timestamp, nonce];
array.sort();
//2.将三个参数字符串拼接成一个字符串进行sha1加密
let tempStr = array.join('');
const hashCode = crypto.createHash('sha1');
let resultCode = hashCode.update(tempStr, 'utf8').digest('hex');
logger.info(`resultcode is : ${resultCode}`);
//3.开发者获得加密后的字符串可与signature对比,确认该请求来源于微信
if (resultCode === signature) {
logger.info(`createAccessToken resultCode is equql to signature`);
return echostr;
} else {
logger.info(`createAccessToken resultCode is not equql to signature`);
return 'mismatch';
}
} catch (err) {
logger.error(`createAccessToken error is : ${err && err.message || ''}`);
return 'mismatch_error';
}
}
这里需要注意的是字典序排序,其实在Js里就是Sort一下就行了。如果相等就返回echostr
, 不相等就返回mismatch
。
配置好服务器之后 ,在测试号上配置好我们自己 的菜单,直接通过链接跳转回调获取 Code,具体参考如下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
这里的REDIRECT_URI
就是直接配置到你的服务器前端路径,这样拿到Code就会直接带到你的项目上去了。
测试号配置菜单可以参考: 微信公众平台接口调试工具-配置菜单
好了,拿到Code
就可以开发下面的接口了,第一步没有什么问题。但是,在开发下面这个接口的时候,由于公司网络的原因,必须要加代理才能调用,下面不多说,直接上代码:
const { WECHAT_TOKEN, WECHAT_CONFIG } = require('../config');
const crypto = require('crypto');
const request = require('request');
const { getLog } = require("../utils/log");
const logger = getLog('wechat_service');
/**
* 根据Code获取 OpenId和网页授权Access_token,
* 这里的Access_token与基础支持中的Access_token不一样
* @param {*} code
*/
async getNetAccessToken(code) {
try {
logger.info(`come into getAccessToken Code is : ${code}`);
return new Promise((resolve, reject) => {
let pr = request.defaults({ 'proxy': WECHAT_CONFIG.proxy, rejectUnauthorized: false });
pr.get(
`https://api.weixin.qq.com/sns/oauth2/access_token?appid=${WECHAT_CONFIG.appid}&secret=${WECHAT_CONFIG.appsecret}&code=${code}&grant_type=authorization_code`,
(error, response, body) => {
if (response && response.statusCode == 200) {
var data = JSON.parse(body);
var access_token = data.access_token;
var openid = data.openid;
logger.info(`access_token ${access_token}, openid ${openid}`);
return resolve(access_token);
} else {
logger.info(`callback error ${error}`);
return reject('callback error');
}
})
})
} catch (err) {
logger.error(`getAccessToken error is : ${err && err.message || ''}`);
return;
}
}
这个方法,就是根据页面上拿到的Code
去获取网页授权的Access_token
和Openid
主要是下面这一句
let pr = request.defaults({ 'proxy': WECHAT_CONFIG.proxy, rejectUnauthorized: false });
这里的WECHAT_CONFIG.proxy
具体为: http://xx.xx.xx.xx:port
也就是说,必须带上http://
否则这个request的包不会识为它是个正确的代理地址。还有一点就是,rejectUnauthorized: false
因为微信的Api接口是https
的,所以这里还要把证书校验去掉。
至此,接口可以正常调通。
希望本文可以帮助到那些同样在公司内网开发的同学们。