q-koa 12.8.4 → 12.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,13 @@ module.exports = {
3
3
  belongs: 'page',
4
4
  multiple: false,
5
5
  availableSort: false,
6
- order: ['created_at'],
7
- select: [{ key: 'user_id' }, { key: 'nick_name' }],
6
+ order: ['user_id', 'unionid'],
7
+ select: [
8
+ { key: 'user_id' },
9
+ { key: 'openid' },
10
+ { key: 'appid' },
11
+ { key: 'unionid' },
12
+ ],
8
13
  excludes: [],
9
14
  limit: 20,
10
15
  defaultOrder: [{ sort: 'descending', type: 'id' }],
@@ -19,5 +24,6 @@ module.exports = {
19
24
  fields: ['openid'],
20
25
  },
21
26
  { fields: ['user_id'] },
27
+ { fields: ['unionid', 'appid'] },
22
28
  ],
23
29
  }
@@ -57,3 +57,13 @@ exports.unionid = {
57
57
  sortOrder: 11,
58
58
  mock: () => Random.ctitle(),
59
59
  }
60
+
61
+ exports.is_subscribe = {
62
+ type: Sequelize.BOOLEAN,
63
+ comment: '是否关注',
64
+ allowNull: false,
65
+ is_mock: true,
66
+ defaultValue: true,
67
+ sortOrder: 12,
68
+ mock: () => Random.boolean(),
69
+ }
@@ -1705,13 +1705,22 @@ exports.messagePush = async (ctx) => {
1705
1705
  if (ctx.request.method === 'GET') {
1706
1706
  ctx.body = echostr
1707
1707
  } else {
1708
- const result = ctx.request.body
1708
+ const result =
1709
+ ctx.request.xmlBody && ctx.request.xmlBody.xml
1710
+ ? ctx.request.xmlBody.xml
1711
+ : ctx.request.body
1709
1712
  if (!lodash.isEmpty(result)) {
1710
1713
  const event = result.Event
1711
1714
  if (!app.service.weixin) throw new Error(`weixin可能没有service.js`)
1712
1715
  if (event) {
1713
1716
  if (app.service.weixin[event]) {
1714
1717
  await app.service.weixin[event]({ ctx, app, result })
1718
+ } else {
1719
+ app.service.log.push({
1720
+ app,
1721
+ url: 'weixin/messagePush',
1722
+ message: `没有${event}方法 ${JSON.stringify(result)}`,
1723
+ })
1715
1724
  }
1716
1725
  } else {
1717
1726
  await app.service.weixin.handleUserMessage({
@@ -0,0 +1,164 @@
1
+ const util = require('util')
2
+ const axios = require('axios')
3
+
4
+ const { lodash } = require('q-koa')
5
+ const getAccessTokenUrl =
6
+ 'https://api.weixin.qq.com/cgi-bin/token?grant_type=%s&appid=%s&secret=%s'
7
+
8
+ const getOpenListUrl =
9
+ 'https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s'
10
+
11
+ const getUserInfoUrl =
12
+ 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN'
13
+
14
+ const getUserInfoListUrl =
15
+ 'https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=%s'
16
+
17
+ const sendMessageUrl =
18
+ 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s'
19
+
20
+ const getTemplateUrl =
21
+ 'https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=%s'
22
+
23
+ const LRU = require('lru-cache')
24
+ const cache = new LRU({
25
+ max: 100,
26
+ maxAge: 1000 * 60 * 60,
27
+ })
28
+
29
+ module.exports = class Singleton {
30
+ constructor(config) {
31
+ this.config = {
32
+ ...config,
33
+ grant_type: 'client_credential',
34
+ }
35
+ /**
36
+ * 单例模式
37
+ */
38
+ if (!Singleton.instance) {
39
+ Singleton.instance = this
40
+ }
41
+ const previous = Singleton.instance.getConfig()
42
+ if (!lodash.isEqual(previous, config)) {
43
+ Singleton.instance = this
44
+ }
45
+ return Singleton.instance
46
+ }
47
+
48
+ init() {
49
+ if (!this.config.appid || !this.config.secrect) {
50
+ throw new Error('没有配置appid或secrect')
51
+ }
52
+ }
53
+
54
+ async getAccessToken() {
55
+ const { appid, secrect, grant_type } = this.config
56
+ if (cache.get(appid)) {
57
+ return cache.get(appid)
58
+ }
59
+ const url = util.format(getAccessTokenUrl, grant_type, appid, secrect)
60
+
61
+ const result = await axios.get(url).then((res) => res.data)
62
+ const { errcode, errmsg, access_token } = result
63
+
64
+ if (errcode) {
65
+ throw new Error(errmsg)
66
+ }
67
+
68
+ cache.set(appid, access_token)
69
+ return access_token
70
+ }
71
+
72
+ async getOpenList() {
73
+ const access_token = await this.getAccessToken()
74
+ const url = util.format(getOpenListUrl, access_token)
75
+ const result = await axios.post(url).then((res) => res.data)
76
+ if (result.errcode) {
77
+ if (result.errcode === 40001) {
78
+ cache.reset()
79
+ return await this.getOpenList()
80
+ }
81
+ throw new Error(`${result.errcode};${result.errmsg}`)
82
+ }
83
+ return result
84
+ }
85
+
86
+ async getUserInfo(openid) {
87
+ const access_token = await this.getAccessToken()
88
+ const url = util.format(getUserInfoUrl, access_token, openid)
89
+ const result = await axios.post(url).then((res) => res.data)
90
+ if (result.errcode) {
91
+ if (result.errcode === 40001) {
92
+ cache.reset()
93
+ return await this.getUserInfo(openid)
94
+ }
95
+ throw new Error(`${result.errcode};${result.errmsg}`)
96
+ }
97
+ return result
98
+ }
99
+
100
+ async getUserInfoList(list = []) {
101
+ const user_list = list.map((openid) => {
102
+ return {
103
+ openid,
104
+ lang: 'zh_CN',
105
+ }
106
+ })
107
+ const access_token = await this.getAccessToken()
108
+ const url = util.format(getUserInfoListUrl, access_token)
109
+ const result = await axios
110
+ .post(url, {
111
+ user_list,
112
+ })
113
+ .then((res) => res.data)
114
+ if (result.errcode) {
115
+ if (result.errcode === 40001) {
116
+ cache.reset()
117
+ return await this.getUserInfoList(list)
118
+ }
119
+ throw new Error(`${result.errcode};${result.errmsg}`)
120
+ }
121
+ return result.user_info_list
122
+ }
123
+
124
+ async sendMessage(options) {
125
+ const access_token = await this.getAccessToken()
126
+ const url = util.format(sendMessageUrl, access_token)
127
+ const formatOptions = {
128
+ ...options,
129
+ data: lodash.mapValues(options.data, (item) => {
130
+ return {
131
+ value: item,
132
+ }
133
+ }),
134
+ }
135
+
136
+ const result = await axios.post(url, formatOptions).then((res) => res.data)
137
+ if (result.errcode) {
138
+ if (result.errcode === 40001) {
139
+ cache.reset()
140
+ return await this.sendMessage(options)
141
+ }
142
+ throw new Error(`${result.errcode};${result.errmsg}`)
143
+ }
144
+ return result
145
+ }
146
+
147
+ async getTemplate() {
148
+ const access_token = await this.getAccessToken()
149
+ const url = util.format(getTemplateUrl, access_token)
150
+ const result = await axios.post(url).then((res) => res.data)
151
+ if (result.errcode) {
152
+ if (result.errcode === 40001) {
153
+ cache.reset()
154
+ return await this.getTemplate()
155
+ }
156
+ throw new Error(`${result.errcode};${result.errmsg}`)
157
+ }
158
+ return result
159
+ }
160
+
161
+ getConfig() {
162
+ return this.config
163
+ }
164
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q-koa",
3
- "version": "12.8.4",
3
+ "version": "12.9.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {