/** * @Author HonorLee (dev@honorlee.me) * @Version 2.0 (2019-10-08) */ // 'use strict' //基础配置项 import { RedisClientType } from '@redis/client'; import sha1 from 'sha1' import wxerr from '../errcodes' // eslint-disable-next-line @typescript-eslint/no-var-requires // const random = require('string-random') const errMsg:AnyKeyString = wxerr; const randomStr = (length?:number,nonum?:boolean)=>{ let arr = '1234567890abcdefghijklmnopqrstuvwxyz'; if(nonum) arr = 'abcdefghijklmnopqrstuvwxyz'; let str = ''; length = length?length:3; for(let i = 0;i{ const token = await this._redisClient.get(`WECHAT_${this._appId}_ACCESSTOKEN`); console.log(!!token) if(token) return resolve({token}); //请求新的Token LOGGER.debug('[Wechat] Get new token') REQUEST({url:this._wechatApiURL.getAccessToken,encoding:'UTF-8',json:true},async (err:any,response:any,body:any)=>{ if(err || !body){ LOGGER.error('Wechat getAccessToken error!'); LOGGER.error(err.stack); return resolve({err:new Error('Wechat getAccessToken error!')}); } if(body.errcode){ LOGGER.debug(body.errmsg||'body.errcode'); return resolve({err:new Error(`ERROR_CODE:${errMsg[body.errcode]}`)}); } const _token = body.access_token; const expires = body.expires_in - 5 * 60; await this._redisClient.set(`WECHAT_${this._appId}_ACCESSTOKEN`,_token,{EX:expires}); resolve({token:_token}); }); }); } public async getJsApiTicket(){ const token:any = await this.getAccessToken(); if(token.err) return token; return new Promise(async (resolve,reject)=>{ const ticket = await this._redisClient.get(`WECHAT_${this._appId}_JSAPITICKET`); if(ticket) return resolve({ticket}); REQUEST({url:`${this._wechatApiURL.getJsApiTicket}${token.token}`,encoding:'UTF-8',json:true},(err:any,response:any,body:any)=>{ if(err || !body){ LOGGER.error('Wechat getJsApiTicket error!'); LOGGER.error(err.stack); return resolve({err:new Error('Wechat getJsApiTicket error!')}); } if(body.errcode){ return resolve({err:new Error(`ERROR_CODE:${errMsg[body.errcode]}`)}); } const _ticket = body.ticket; const expires = body.expires_in - 5; this._redisClient.set(`WECHAT_${this._appId}_JSAPITICKET`,_ticket,{EX:expires}); resolve({ticket:_ticket}); }) }); } public async getSignature(url:string){ if(!url) return {err:new Error('URL is empty!')}; const noncestr = randomStr(16); const timestamp = Math.floor(new Date().getTime()); const ticket = await this.getJsApiTicket(); const combineStr = `jsapi_ticket=${ticket.ticket}&noncestr=${noncestr}×tamp=${timestamp}&url=${url}`; const signature = sha1(combineStr); return {nonceStr:noncestr,timestamp:timestamp,signature:signature,appId:this._appId}; } public getJsOauthCodeURL(redirectURL:string,Scope:string,State?:string){ if(!redirectURL || !redirectURL.match(/(https?):\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/gi)){ return {err:new Error('redirectURL Error')}; } if(Scope!='snsapi_base' && Scope!='snsapi_userinfo'){ return {err:new Error('Scope must be snsapi_base or snsapi_userinfo')}; } if(!State) State = 'null'; redirectURL = encodeURI(redirectURL); const urlString = `${this._wechatApiURL.getJsOauthCode}&redirect_uri=${redirectURL}&response_type=code&scope=${Scope}&state=${State}#wechat_redirect`; return {url:urlString}; } public async getOauthToken(code:string){ if(!code) return {err:new Error('Code is empty!')}; return new Promise((resolve,reject)=>{ REQUEST({url:`${this._wechatApiURL.getOauthToken}&code=${code}`,encoding:'UTF-8',json:true},(err:any,response:any,body:any)=>{ if(err || !body){ LOGGER.error('Wechat getOauthToken error!'); LOGGER.error(err.stack); return resolve({err:new Error('Wechat getOauthToken error!')}); } if(body.errcode){ return resolve({err:new Error(`ERROR_CODE:${errMsg[body.errcode]}`)}); } resolve({token:body.access_token,openid:body.openid}); }); }) } public getOauthUserinfo(oAuthToken:string,openid:string){ return new Promise((resolve,reject)=>{ REQUEST({url:`${this._wechatApiURL.getOauthUserinfo}&access_token=${oAuthToken}&openid=${openid}`,encoding:'UTF-8',json:true},(err:any,response:any,body:any)=>{ if(err || !body){ LOGGER.error('Wechat getOauthUserinfo error!'); LOGGER.error(err.stack); return resolve({err:new Error('Wechat getOauthUserinfo error!')}); } if(body.errcode){ return resolve({err:new Error(`ERROR_CODE:${errMsg[body.errcode]}`)}); } resolve({userinfo:body}); }); }) } public async getOauthUserinfoByCode(code:string){ const _authToken = await this.getOauthToken(code) as AnyKeyString; if(_authToken && !_authToken.err){ const _userInfo = await this.getOauthUserinfo(_authToken.access_token,_authToken.openid); return _userInfo; }else{ return null; } } public getCodeSession(code:string){ return new Promise((resolve,reject)=>{ REQUEST({url:`${this._wechatApiURL.getCode2Session}${code}`,encoding:'UTF-8',json:true},(err:any,response:any,body:any)=>{ // console.log(1,err,response,body) if(err || !body){ LOGGER.error('Wechat getCode2Session error!'); LOGGER.error(err.stack); return resolve({err:new Error('Wechat getCode2Session error!')}); } if(body.errcode){ return resolve({err:new Error(`ERROR_CODE:${body.errcode} - ${errMsg[body.errcode]}`)}); } resolve({openid:body.openid,unionid:body.unionid,session_key:body.session_key}); }); }) } } module.exports = WechatSDK;