微信真坑,鼓捣了一天,眼睛都瞎了,最后发现个人微信公众账号没有权限,尼玛。。。
1. 注册微信公众平台
为了能够使用微信的接口,需要注册开发者账号身份, 这个自行百度
2.搭建一个服务器
我们需要一个服务器,来获取访问微信API的签名,这里使用NodeJS服务器:
const request = require('request')
var express = require('express');
var app = express();
const sha1 = require('sha1')
const waterfall = require('async/waterfall')
const NodeCache = require('node-cache')
const cache = new NodeCache({stdTTL: 3600, checkperiod: 3600})
// app.get('/wxJssdk', function (req, res) {
// let wx = req.query
// // 1)将token、timestamp、nonce三个参数进行字典序排序
// let token = 'jegfjaeghfuyawegfgjdbh'
// let timestamp = wx.timestamp
// let nonce = wx.nonce
// // 2)将三个参数字符串拼接成一个字符串进行sha1加密
// let list = [token, timestamp, nonce]
// let result = sha1(list.sort().join(''))
// // 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
// if (result === wx.signature) {
// res.send(wx.echostr)
// } else {
// res.send(false)
// }
// })
app.get('/wxJssdk/getJssdk', function (req, res) {
let grant_type = 'client_credential'
let appid = 'xxxx'
let secret = 'xxxx' // appscret
let steps = []
// 第一步,获取access_token
steps.push((cb) => {
let steps1 = []
// 第1.1步,从缓存中读取access_token
steps1.push((cb1) => {
let access_token = cache.get('access_token', (err, access_token) => {
cb1(err, access_token)
})
})
// 第1.2步,缓存中有access_token则直接返回,如果没有,则从服务器中读取access_token
steps1.push((access_token, cb1) => {
if (access_token) {
cb1(null, access_token, 'from_cache')
} else {
request('https://api.weixin.qq.com/cgi-bin/token?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret, (err, response, body) => {
cb1(err, JSON.parse(body).access_token, 'from_server')
})
}
})
// 第1.3步,如果是新从服务器取的access_token,则缓存起来,否则直接返回
steps1.push((access_token, from_where, cb1) => {
if (from_where === 'from_cache') {
console.log(' === 成功从缓存中读取access_token: ' + access_token + ' ===')
cb1(null, access_token)
} else if (from_where === 'from_server') {
cache.set('access_token', access_token, (err, success) => {
if (!err && success) {
console.log(' === 缓存已过期,从服务器中读取access_token: ' + access_token + ' ===')
cb1(null, access_token)
} else {
cb1(err || 'cache设置access_token时,出现未知错误')
}
})
} else {
cb1('1.3获取from_where时,from_where值为空')
}
})
waterfall(steps1, (err, access_token) => {
cb(err, access_token)
})
})
// 第二步,获取ticket
steps.push((access_token, cb) => {
let steps1 = []
// 第2.1步,从缓存中读取ticket
steps1.push((cb1) => {
let ticket = cache.get('ticket', (err, ticket) => {
cb1(err, ticket)
})
})
// 第2.2步,缓存中有ticket则直接返回,如果没有,则从服务器中读取ticket
steps1.push((ticket, cb1) => {
if (ticket) {
cb1(null, ticket, 'from_cache')
} else {
request('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi', (err, response, body) => {
cb1(err, JSON.parse(body).ticket, 'from_server')
})
}
})
// 第2.3步,如果新从服务器取的ticket,则缓存起来,否则直接返回
steps1.push((ticket, from_where, cb1) => {
if (from_where === 'from_cache') {
console.log(' === 成功从缓存中读取ticket: ' + ticket + ' ===')
cb1(null, ticket)
} else if (from_where === 'from_server') {
cache.set('ticket', ticket, (err, success) => {
if (!err && success) {
console.log(' === 缓存已过期,从服务器中读取ticket: ' + ticket + ' ===');
cb1(null, ticket)
} else {
cb1(err || 'cache设置ticket时,出现未知错误')
}
})
} else {
cb1('2.3获取from_where时,from_where值为空')
}
})
waterfall(steps1, (err, ticket) => {
cb(err, ticket)
})
})
// 第三步,生成签名
steps.push((ticket, cb) => {
let jsapi_ticket = ticket
let nonce_str = '123456'
let timestamp = Math.floor((new Date().getTime())/1000)
let url = req.query.url
let str = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + nonce_str + '×tamp=' + timestamp + '&url=' + url
console.log('signature ' + str)
let signature = sha1(str)
console.log('==> ' + signature)
cb(null, {
appId: appid,
timestamp: timestamp,
nonceStr: nonce_str,
signature: signature,
ticket: ticket
})
})
waterfall(steps, (err, data) => {
res.setHeader("Content-Type", "text/json");
res.setHeader("Access-Control-Allow-Origin", "*");
if (err) {
res.send({status: 'error', data: err})
} else {
res.send({status: 'success', data: data})
}
})
})
app.use('/wxJssdk/public', express.static('public'))
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
})
出处是:https://www.jb51.net/article/118729.htm
一定要注意,生成签名的部分打log,然后和微信公众平台上的签名验证工具对比一下,比如时间戳位数,url对不对等
3. 在H5中导入
这里使用的是ajax请求的,请求签名的时候,需要加上一个url参数,取当前url一定要使用encodeURIComponent(location.href.split('#')[0])方法啊,忘记从哪个网站上看到的了,试了好几个小时,因为这个大哥茅塞顿开,好人啊
然后在微信web开发者工具中测试就能通过,但是真机没法通过,因为个人微信公众号没有权限!!!