写了两个微信页面,遇到了很多不知道的问题。收拾东西。不同于普通的手机页面,微信页面为您提供了调用微信APP内置函数的接口,可以实现更复杂的功能。jssdk前端使用前端页面调用jssdk。首先在绑定“公众号设置”的“功能设置”中填写“JS接口安全域名”,然后在页面/js/中导入http://res.wx.qq.com/open...调用wx.config({...})验证权限配置,然后根据需要调用微信提供的接口。前端调用时后端返回wx.config({...})中的接口需要的参数需要我们自己返回。wx.config({debug:true,//开启debug模式,客户端会提示所有API调用的返回值。查看传入的参数可以在PC端打开,参数信息会通过日志打印出来,只会在PC端打印appId:'',//必填,公众号的唯一标识timestamp:,//必填,生成签名的时间戳nonceStr:'',//必填,生成签名的随机字符串signature:'',//必填,签名jsApiList:[]//必填,需要使用的JS接口列表});其中需要timestamp、nonceStr、signature由结束计算返回。签名获取方式签名生成规则如下:签名涉及的字段包括noncestr(随机字符串)、validjsapi_ticket、timestamp(时间戳)、url(当前网页的URL,不包括#及其后续部分).将所有待签名参数按照字段名的ASCII码从小到大(字典序)排序后,使用URL键值对格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是,所有的参数名称都是小写字符。对string1进行SHA1加密,字段名和字段值采用原值,不做URL转义。jsapi_ticket是通过access_token获取的,两者都有过期时间(7200秒)。其中jsapi_ticket限制了获取的数量。所以为了两者都保存,使用redis数据库保存在内存中是一个不错的选择(读取速度快,并设置过期时间)。token获取方法:/***获取token*@return{promise}res值为token*/functiongetToken(){returnredis.getVal('token')//先读取redis看token是否存在.then(function(res){if(res===null){//如果不存在,则返回savetoken()Get//console.log('Notokenexists,callsaveToken')returnsaveToken()}else{//如果存在,则直接返回//console.log('Token存在,直接返回')returnres}}).catch(function(err){//catcherrorconsole.log(err)})}/***从服务器获取token并保存到redis*@return{promise}valuetoken*/functionsaveToken(){returnnewPromise((resolve,reject)=>{letreqUrl=config.gettoken_url//https://api.weixin.qq.com/cgi-bin/token?letparams={grant_type:'client_credential',appid:config.appid,secret:config.appsecret}letoptions={method:'get',url:reqUrl+qs.stringify(params)}request(options,function(err,res,body){if(res){letbodies=JSON.parse(body)letexpires=bodys.expires_inlettoken=bodys.access_tokenredis.setKey('token',token,expires)//保存token到redis.catch(function(err){console.log(err)})resolve(token)}else{reject(err)}})})}在配置文件中配置需要的appid和appsecret,首先检查redis中是否存在,存在则直接返回,不存在则调用saveToken获取并保存在redis中jsapi_ticket获取方法相同,同样获取jsapi_ticket/***获取ticket*@return{promise}res值为ticket*/functiongetJsTicket(){//获取tokenreturnredis.getVal('ticket')//先读取redis中是否有ticket.then(function(res){if(res===null){//如果没有,返回saveJsTicket()get//console.log('没有票,调用saveJsTicket')returnsaveJsTicket()}else{//存在则直接返回//console.log('票存在,直接返回')returnres}}).catch(function(err){//捕获错误console.log(err)})}/***从服务器获取ticket并保存在redis*@r返回{promise}值是ticket*/functionsaveJsTicket(){returnnewPromise((resolve,reject)=>{getToken().then(function(token){letreqUrl=config.ticket_start+token+config.ticket_endletoptions={method:'get',url:reqUrl}request(options,function(err,res,body){if(res){letbodys=JSON.parse(body)//解析微信服务器返回的letticket=bodies.ticket//获取ticketletexpires=bodys.expires_in//获取过期时间redis.setKey('ticket',ticket,expires)//保存ticket到redis.catch(function(err){console.log(err)})resolve(ticket)}else{reject(err)}})}).catch(function(err){console.log(err)})})}签名算法得到jsapi_ticket后可以生成JS-SDK授权验证signed/***1.appId为必填,公众号的唯一标识*2.timestamp为必填,签名生成的时间戳*3.nonceStr为必填,签名生成的随机串*4.signature为需要填写,签名*/constcrypto=require('crypto')constgetJsTicket=require('./getJsTicket')constconfig=require('../../config')//微信设置//sha1加密函数sha1(str){letshasum=crypto.createHash("sha1")shasum.update(str)str=shasum.digest("hex")returnstr}/***生成签名的时间戳*@return{string}*/functioncreateTimestamp(){returnparseInt(newDate().getTime()/1000)+''}/***生成带符号的随机字符串*@return{string}*/functioncreateNonceStr(){returnMath.random().toString(36).substr(2,15)}/***参数对象字典排序*@param{object}argssignaturerequiredparameterobject*@return{string}排序后生成字符串*/functionraw(args){varkeys=Object.键(参数)键=键。排序()varnewArgs={}键。forEach(function(key){newArgs[key.toLowerCase()]=args[key]})varstring=''for(varkinnewArgs){string+='&'+k+'='+newArgs[k]}string=string.substr(1)returnstring}/***@synopsissignaturealgorithm**@paramjsapi_ticketjsapi_ticketforsignature*@paramurl签名url,注意一定要动态获取,不能hardcode**@returns{object}返回微信jssdk需要的参数对象*/functionsign(jsapi_ticket,url){varret={jsapi_ticket:jsapi_ticket,nonceStr:createNonceStr(),timestamp:createTimestamp(),url:url}varstring=raw(ret)ret.signature=sha1(string)ret.appId=config.appidreturnret}/***返回微信需要的参数对象jssdk*@param{string}url当前访问URL*@return{promise}返回promise类val作为一个object*/functionjsSdk(url){returngetJsTicket().then(function(ticket){returnsign(ticket,url)}).catch(function(err){console.log(err)})}functionrouterSdk(req,res,next){letclientUrl=req.body.urlif(clientUrl){jsSdk(clientUrl).then(function(obj){res.json(obj)})}else{res.end('nourl')}}module.exports=routerSdk后端返回签名的过程基本完成(省略redis部分)。具体可以参考我当时实践项目中的代码。此时前端就可以使用jssdk来完成函数调用了。ps:有一次用录音接口做了一个功能,发现微信服务器只会保存3天的数据,需要自己下载到自己的服务器上。不知道大家有没有做过类似的需求。请提供以下指导么么哒,万分感谢~后记后面自己写了一个获取用户信息的页面,感觉还是挺常用的,写个demo看看(access_token没有保存,似乎没有获得次数的限制)。router.get('/',function(req,res,next){console.log("oauth-login")//第一步:用户同意授权,获取codeletrouter='get_wx_access_token'//这是代码地址letreturn_uri=encodeURIComponent(base_url+router)console.log('回调地址:'+return_uri)letscope='snsapi_userinfo'res.redirect('https://open.weixin.qq.com/connect/oauth2/authorize?appid='+appid+'&redirect_uri='+return_uri+'&response_type=code&scope='+scope+'&state=STATE#wechat_redirect')})//第二步:交换网页授权codeaccess_tokenrouter.get('/get_wx_access_token',function(req,res,next){console.log("get_wx_access_token")console.log("code_return:"+req.query.code)letcode=req.query.coderequest.get({url:'https://api.weixin.qq.com/sns/oauth2/access_token?appid='+appid+'&secret='+appsecret+'&code='+code+'&grant_type=authorization_code',},function(error,response,body){if(response.statusCode===200){//第三步:拉取用户信息(需要scope为snsapi_userinfo)//console.log(JSON.parse(body))letdata=JSON.parse(body)letaccess_token=data.access_tokenletopenid=data.openidrequest.get({url:'https://api.weixin.qq.com/sns/userinfo?access_token='+access_token+'&openid='+openid+'&lang=zh_CN',},function(error,response,body){if(response.statusCode==200){//第四步:根据获取到的用户信息进行相应的操作letuserinfo=JSON.parse(body)console.log(JSON.parse(body))console.log('获取微信信息成功!'),你可以创建一个账号res.send("\
"+userinfo.nickname+"个人信息
\"+userinfo.city+","+userinfo.province+","+userinfo.country+"
\")}else{console.log(response.statusCode)}})}else{console.log(response.statusCode)}})})