|
@@ -0,0 +1,73 @@
|
|
|
+'use strict';
|
|
|
+const { CrudService } = require('naf-framework-mongoose-free/lib/service');
|
|
|
+const { BusinessError, ErrorCode } = require('naf-core').Error;
|
|
|
+const _ = require('lodash');
|
|
|
+const assert = require('assert');
|
|
|
+const moment = require('moment');
|
|
|
+
|
|
|
+// 微信相关
|
|
|
+class WeixinService extends CrudService {
|
|
|
+ constructor(ctx) {
|
|
|
+ super(ctx, 'weixin');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 小程序登录(换取openid)
|
|
|
+ * @param {Object} body js_code 临时登陆码
|
|
|
+ * @param {String} tenant 分站
|
|
|
+ */
|
|
|
+ async appAuth({ js_code }, tenant) {
|
|
|
+ if (!tenant) throw new BusinessError(ErrorCode.ACCESS_DENIED, '未找到分站');
|
|
|
+ const { wxApp } = this.app.config;
|
|
|
+ if (!wxApp) throw new BusinessError(ErrorCode.SERVICE_FAULT, '系统未启动小程序登录!');
|
|
|
+ if (!wxApp[tenant]) throw new BusinessError(ErrorCode.SERVICE_FAULT, '未设置该小程序相关信息!');
|
|
|
+ const { appid, secret } = wxApp[tenant];
|
|
|
+ const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${js_code}&grant_type=authorization_code`;
|
|
|
+ const res = await this.ctx.curl(url, {
|
|
|
+ method: 'get',
|
|
|
+ headers: {
|
|
|
+ 'content-type': 'application/json',
|
|
|
+ },
|
|
|
+ dataType: 'json',
|
|
|
+ });
|
|
|
+ const { openid } = res.data;
|
|
|
+ if (!openid) throw new BusinessError(ErrorCode.BUSINESS, '未获取到openid', '未获取到openid');
|
|
|
+ return res.data;
|
|
|
+ }
|
|
|
+
|
|
|
+ async getSecret({ encryptedData, iv, session_key }) {
|
|
|
+ assert(encryptedData, '缺少参数-encryptedData');
|
|
|
+ assert(iv, '缺少参数-iv');
|
|
|
+ assert(session_key, '缺少参数-session_key');
|
|
|
+ // 找到小程序设置,最后解密完,需要检验appid是不是对的
|
|
|
+ const { wxApp } = this.app.config;
|
|
|
+ const wxInfo = wxApp[this.ctx.tenant];
|
|
|
+ const crypto = require('crypto');
|
|
|
+ session_key = new Buffer(session_key, 'base64');
|
|
|
+ encryptedData = new Buffer(encryptedData, 'base64');
|
|
|
+ iv = new Buffer(iv, 'base64');
|
|
|
+ let decoded;
|
|
|
+ try {
|
|
|
+ const decipher = crypto.createDecipheriv('aes-128-cbc', session_key, iv);
|
|
|
+ decipher.setAutoPadding(true);
|
|
|
+ decoded = decipher.update(encryptedData, 'binary', 'utf8');
|
|
|
+ decoded += decipher.final('utf8');
|
|
|
+ decoded = JSON.parse(decoded);
|
|
|
+ } catch (error) {
|
|
|
+ throw new BusinessError(ErrorCode.DATA_INVALID, '密文不正确!');
|
|
|
+ }
|
|
|
+ if (decoded.watermark.appid !== wxInfo.appid) {
|
|
|
+ throw new BusinessError(ErrorCode.VERIFYCODE_INVALID, '未通过校验!');
|
|
|
+ }
|
|
|
+
|
|
|
+ decoded.stepInfoList = decoded.stepInfoList.map(i => {
|
|
|
+ i.date = moment.unix(i.timestamp).format('YYYY-MM-DD');
|
|
|
+ return i;
|
|
|
+ });
|
|
|
+ decoded.stepInfo = decoded.stepInfoList.find(f => f.date === moment().format('YYYY-MM-DD'));
|
|
|
+ delete decoded.stepInfoList;
|
|
|
+ return decoded;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+module.exports = WeixinService;
|