lrf402788946 4 years ago
parent
commit
ba367991c0
3 changed files with 51 additions and 131 deletions
  1. 3 112
      app/controller/weixin.js
  2. 1 0
      app/router.js
  3. 47 19
      app/service/weixin.js

+ 3 - 112
app/controller/weixin.js

@@ -21,120 +21,11 @@ class WeixinController extends Controller {
   // GET 请求认证
   // response_type:
   //       code - url带上code参数重定向到原始地址
-  //       store - 默认,认证结果写入sessionStore,然后重定向回请求页面(要求请求页面和认证服务在同一域名下)
-  //       token - url带上token参数重定向到原始地址
   async auth() {
-    const { redirect_uri, code, test, type, response_type = 'store', groupid, doctorid } = this.ctx.query;
-    if (test) {
-      return await this.authTest();
-    }
-    if (code) {
-      return await this.authBack(this.ctx.query);
-    }
-
-    this.ctx.logger.debug(`[auth] reditect_uri - ${redirect_uri}`);
-    // assert(redirect_uri, '回调地址不能为空');
-
-    // TODO: 保存原始请求地址
-    // const { config } = this.app;
-    // console.log('ctx.host: ', this.ctx.host);
-    // console.log('config.hostHeaders: ', config.hostHeaders);
-    // TODO: 保存原始请求地址
-    const state = uuid();
-    const key = `visit:auth:state:${state}`;
-    const val = JSON.stringify({ redirect_uri, type, groupid, doctorid });
-    await this.app.redis.set(key, val, 'EX', 600);
-
-    // TODO: 生成回调地址
-    const { wxapi, authUrl = this.ctx.path } = this.app.config;
-    const backUrl = encodeURI(`${this.app.config.baseUrl}${this.config.authUrl}?state=${state}`);
-    // const to_uri = `${wxapi.baseUrl}/api/auth?appid=${wxapi.appid}&response_type=code&redirect_uri=${backUrl}&connect_redirect=1#wechat`;
-    // console.log('url-->' + to_uri);
-    // this.ctx.redirect(to_uri);
-    const to_uri = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${wxapi.appid}&redirect_uri=${backUrl}&response_type=code&scope=snsapi_base&state=${state}#wechat_redirect`;
-    console.log('url-->' + to_uri);
-    this.ctx.redirect(to_uri);
+    await this.ctx.service.auth(this.ctx.query);
   }
-
-  // GET 认证回调
-  async authBack({ code, state }) {
-    // const { code, state, type, redirecturi } = this.ctx.query;
-    this.ctx.logger.debug(`[auth-back] code - ${code}, state - ${state}`);
-    assert(code, 'code不能为空');
-    assert(state, 'state不能为空');
-    console.log('code-->' + code);
-
-    const { weixin } = this.ctx.service;
-    let openid;
-    try {
-      ({ openid } = await weixin.fetch(code));
-    } catch (err) {
-      await this.ctx.render('error.njk', { title: err.message, message: err.details });
-      return;
-    }
-    console.log('openid--->' + openid);
-    if (openid) {
-      const key = `visit:auth:state:${state}`;
-      const val = await this.app.redis.get(key);
-      const { redirect_uri, type, groupid, doctorid } = JSON.parse(val);
-      console.log('type-->' + type);
-      if (type === 'group') {
-        const to_uri = urljoin(redirect_uri, `?openid=${openid}&groupid=${groupid}`);
-        // TODO: 重定性页面
-        console.log('to_uri222-->' + to_uri);
-        this.ctx.redirect(to_uri);
-      } else if (type === 'login') {
-        console.log('to_uri333-->' + redirect_uri);
-        const to_uri = urljoin(redirect_uri, `?openid=${openid}`);
-        console.log('to_uri333-->' + to_uri);
-        // TODO: 重定性页面
-        this.ctx.redirect(to_uri);
-      } else if (type === 'doctor') {
-        console.log('to_uridoctor-->' + redirect_uri);
-        const to_uri = urljoin(redirect_uri, `?openid=${openid}&doctorid=${doctorid}`);
-        // TODO: 重定性页面
-        this.ctx.redirect(to_uri);
-      } else {
-        console.log('rrr--->' + redirect_uri);
-        const to_uri = urljoin(redirect_uri, `?openid=${openid}`);
-
-        // TODO: 重定性页面
-        this.ctx.redirect(to_uri);
-      }
-    }
-
-  }
-
-  // GET 用户授权内部测试接口
-  async authTest() {
-    const { redirect_uri, type, groupid, doctorid } = this.ctx.query;
-    const openid = '1234567';
-    this.ctx.logger.debug(`[auth-test] reditect_uri - ${redirect_uri}, openid - ${openid}`);
-    assert(redirect_uri, '回调地址不能为空');
-    assert(openid, 'openid不能为空');
-
-    if (type === 'group') {
-      const to_uri = urljoin(redirect_uri, `?openid=${openid}&groupid=${groupid}`);
-      // TODO: 重定性页面
-      console.log('to_uri222-->' + to_uri);
-      this.ctx.redirect(to_uri);
-    } else if (type === 'login') {
-      console.log('to_uri333-->' + redirect_uri);
-      const to_uri = urljoin(redirect_uri, `?openid=${openid}`);
-      console.log('to_uri333-->' + to_uri);
-      // TODO: 重定性页面
-      this.ctx.redirect(to_uri);
-    } else if (type === 'doctor') {
-      const to_uri = urljoin(redirect_uri, `?openid=${openid}&doctorid=${doctorid}`);
-      // TODO: 重定性页面
-      this.ctx.redirect(to_uri);
-    } else {
-      console.log('rrr--->' + redirect_uri);
-      const to_uri = urljoin(redirect_uri, `?openid=${openid}`);
-
-      // TODO: 重定性页面
-      this.ctx.redirect(to_uri);
-    }
+  async authBack() {
+    await this.ctx.service.authBack(this.ctx.query);
   }
 }
 

+ 1 - 0
app/router.js

@@ -55,6 +55,7 @@ module.exports = app => {
 
   // 微信认证,生成包含微信用户信息的token写入cookie
   router.get('/api/visit/auth', controller.weixin.auth);
+  router.get('/api/visit/authBack', controller.weixin.authBack);
   router.post('/api/visit/wxpaysign', controller.wxpay.wxpaysign); // 取得支付签名
   router.post('/api/visit/wxpayback', controller.wxpay.wxpaysignback); // 取得支付签名
   // 打赏管理

+ 47 - 19
app/service/weixin.js

@@ -10,30 +10,58 @@ const { AxiosService } = require('naf-framework-mongoose/lib/service');
 class WeixinAuthService extends AxiosService {
   constructor(ctx) {
     super(ctx, {}, _.get(ctx.app.config, 'wxapi'));
+    this.prefix = 'visit-auth:';
+    this.wxInfo = ctx.app.config.wxapi;
+  }
+  /**
+   * 网页授权
+   * @param {Object} query 参数
+   */
+  async auth(query) {
+    let { redirect_uri, ...others } = query;
+    if (!redirect_uri) {
+      redirect_uri = `${this.ctx.app.config.baseUrl}/api/visit/authBack`;
+    }
+    const { appid } = this.wxInfo;
+    if (!appid) {
+      throw new BusinessError(ErrorCode.SERVICE_FAULT, '缺少公众号设置');
+    }
+    // 用于redis
+    const state = uuid.v4();
+    const key = `${this.prefix}${state}`;
+    const val = JSON.stringify({ ...others, redirect_uri });
+    await this.app.redis.set(key, val, 'EX', 600);
+    const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_base&state=${state}#wechat_redirect`;
+    this.ctx.redirect(url);
   }
 
-  // 通过认证码获得用户信息
-  async fetch(code) {
-    // TODO:参数检查和默认参数处理
-    assert(code);
-    const { wxapi } = this.app.config;
-    const reqUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token';
-    const params = {
-      appid: wxapi.appid,
-      secret: wxapi.appSecret,
-      code,
-      grant_type: 'authorization_code',
-    };
-    const res = await this.httpGet(reqUrl, params);
-    console.log(res);
-    if (res.errcode && res.errcode !== 0) {
-      this.ctx.logger.error(`[WeixinAuthService] fetch open by code fail, errcode: ${res.errcode}, errmsg: ${res.errmsg}`);
-      throw new BusinessError(ErrorCode.SERVICE_FAULT, '获得微信认证信息失败');
+  /**
+   * 网页授权回调,获取openid
+   * @param {Object} query 参数
+   */
+  async authBack(query) {
+    const { code, state } = query;
+    if (!code) throw new BusinessError(ErrorCode.SERVICE_FAULT, '授权未成功');
+    const { appid, appSecret } = this.wxInfo;
+    const url = ` https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appid}&secret=${appSecret}&code=${code}&grant_type=authorization_code`;
+    const req = this.ctx.curl(url, {
+      method: 'GET',
+    });
+    if (req.status !== 200) throw new BusinessError(ErrorCode.SERVICE_FAULT, 'access_token获取失败');
+    const openid = _.get(req, 'data.openid');
+    if (!openid) {
+      this.ctx.logger.error(JSON.stringify(req.data));
+      throw new BusinessError(ErrorCode.SERVICE_FAULT, '未获取到openid');
     }
-    // const { openid } = res;
-    return res;
+    // 验证获取openid结束,接下来应该返回前端
+    const key = `${this.prefix}${state}`;
+    let fqueries = await this.app.redis.get(key);
+    if (fqueries)fqueries = JSON.parse(fqueries);
+    const { redirect_uri } = fqueries;
+    this.ctx.redirect(redirect_uri);
   }
 
+
   async createJwt({ openid, nickname, subscribe }) {
     const { secret, expiresIn = '1d', issuer = 'weixin' } = this.config.jwt;
     const subject = openid;