准备工作
1. 阅读 微信开放文档 JS-SDK 使用权限签名算法,根据文档提供接口,返回 jsapi_ticket。
2. 阅读 高清语音素材获取接口文档,根据文档提供接口,返回音频数据。
3. 登录公众号后台,在开发 > 开发管理 > 开发设置 > 开发者 ID 中获取公众号 appid 及 appsecret。
注意:
接口需保证下载表现和直接在浏览器调用微信侧接口 https://api.weixin.qq.com/cgi-bin/media/get/jssdk?access_token=ACCESS_TOKEN&media_id=MEDIA_ID 一致,即在浏览器调用接口后下载二进制文件,文件内容需与直接调用微信接口内容一致,否则 SDK 内部无法正常下载及解析音频内容。
获取 access_token
let request = require('request-promise')async function get_token() {return new Promise((resolve) => {const appid = ''const secret = ''request.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`, (err, res, body) => {resolve(JSON.parse(body).access_token);});})}
注意:
access_token 日调用上限为2000次,需业务侧做好缓存和更新逻辑。
let request = require('request-promise')// 用redis来做缓存let redis = require('redis')let redisClient = redis.createClient();redisClient.on('error', err => {console.log(err)})redisClient.connect() // 连接async function token_cache() {return new Promise(async (resolve) => {let token = await redisClient.get("access_token")if (token == null) {let access_token = await get_token()await redisClient.set("access_token", access_token);await redisClient.expire("access_token", 7000)resolve(access_token)} else {resolve(token)}})}
jsapi_ticket 接口
let request = require('request-promise')let express = require('express')let server = express();const cors = require('cors'); // 跨域server.use(cors());let redis = require('redis')let redisClient = redis.createClient();redisClient.on('error', err => {console.log(err)})redisClient.connect() // 连接server.get('/getTicket', async (req, resp) => {let jsapi_ticket = await redisClient.get("jsapi_ticket")if (jsapi_ticket ==null){const token = await token_cache()const ticket_url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`request.get(ticket_url, async (err, res, body) => {await redisClient.set("jsapi_ticket", JSON.parse(body).ticket);await redisClient.expire("jsapi_ticket", 7000)resp.send(JSON.parse(body).ticket)});}else{resp.send(jsapi_ticket)}})server.listen(5050, () => {console.log('服务器已就绪')})module.exports = server;
mediaUrl 接口
let request = require('request-promise')let express = require('express')let server = express();const cors = require('cors');server.use(cors());server.get('/getMedia', async (req, resp) => {const token = await token_cache()let id = req.query.mediaId;const mediaUrl = `https://api.weixin.qq.com/cgi-bin/media/get/jssdk?access_token=${token}&media_id=${id}`;request.get(mediaUrl).pipe(resp);})server.listen(5050, () => {console.log('服务器已就绪')})module.exports = server;
Node.js 完整示例
使用 express 框架,需要 npm 安装如下依赖。
npm install request-promise express cors redis
示例代码
let request = require('request-promise')let express = require('express')let server = express();const cors = require('cors');server.use(cors());let redis = require('redis')let redisClient = redis.createClient();redisClient.on('error', err => {console.log(err)})redisClient.connect() // 连接async function get_token() {return new Promise((resolve) => {const appid = ''const secret = ''request.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`, (err, res, body) => {resolve(JSON.parse(body).access_token);});})}async function token_cache() {return new Promise(async (resolve) => {let token = await redisClient.get("access_token")if (token == null) {let access_token = await get_token()await redisClient.set("access_token", access_token);await redisClient.expire("access_token", 7000)resolve(access_token)} else {resolve(token)}})}server.get('/getTicket', async (req, resp) => {let jsapi_ticket = await redisClient.get("jsapi_ticket")if (jsapi_ticket ==null){const token = await token_cache()const ticket_url = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${token}&type=jsapi`request.get(ticket_url, async (err, res, body) => {await redisClient.set("jsapi_ticket", JSON.parse(body).ticket);await redisClient.expire("jsapi_ticket", 7000)resp.send(JSON.parse(body).ticket)});}else{resp.send(jsapi_ticket)}})server.get('/getMedia', async (req, resp) => {const token = await token_cache()let id = req.query.mediaId;const mediaUrl = `https://api.weixin.qq.com/cgi-bin/media/get/jssdk?access_token=${token}&media_id=${id}`;request.get(mediaUrl).pipe(resp);})server.listen(5050, () => {console.log('服务器已就绪')})module.exports = server;