q-koa 13.4.2 → 13.4.5

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.
package/core/app.js CHANGED
@@ -222,6 +222,7 @@ class APP {
222
222
  this.app[appName].sign = async (user) => {
223
223
  const result = await jwt.sign(user, secret, {
224
224
  expiresIn,
225
+ algorithm: 'HS256',
225
226
  })
226
227
  return result
227
228
  }
@@ -248,7 +249,9 @@ class APP {
248
249
  }
249
250
 
250
251
  try {
251
- const { user } = await verify(token, secret)
252
+ const { user } = await verify(token, secret, {
253
+ algorithms: ['HS256'],
254
+ })
252
255
  if (user) {
253
256
  if (this.config.log.request) {
254
257
  console.log('user id ---> ', appName, '--->', user.id, user.name)
@@ -893,15 +896,11 @@ class APP {
893
896
  const modelService = cloneTarget[b]
894
897
  const newB = Object.keys(modelService).reduce((_a, _b) => {
895
898
  const bindFn = modelService[_b].bind(this.app[appName])
896
- return {
897
- ..._a,
898
- [_b]: bindFn,
899
- }
899
+ _a[_b] = bindFn
900
+ return _a
900
901
  }, {})
901
- return {
902
- ...a,
903
- [b]: newB,
904
- }
902
+ a[b] = newB
903
+ return a
905
904
  }, {})
906
905
  }
907
906
 
@@ -914,10 +913,8 @@ class APP {
914
913
  const modelList = Object.keys(this.app[appName].model)
915
914
 
916
915
  const include = modelList.reduce((a, b) => {
917
- return {
918
- ...a,
919
- [b]: [],
920
- }
916
+ a[b] = []
917
+ return a
921
918
  }, {})
922
919
  this.app[appName] = _.defaultsDeep(
923
920
  {
@@ -1308,10 +1305,18 @@ class APP {
1308
1305
  typeof where.id === 'string' &&
1309
1306
  where.id.includes('/')
1310
1307
  ) {
1308
+ const arr = where.id.split('?')
1309
+
1310
+ let obj = {}
1311
+ if (arr[1] && arr[1].includes('id=')) {
1312
+ obj = {
1313
+ id: JSON.parse(arr[1].split('=')[1]),
1314
+ }
1315
+ }
1311
1316
  const _result = await _.get(
1312
1317
  app[appName].controller,
1313
- where.id.replace('/', '.')
1314
- )(ctx)
1318
+ arr[0].replace('/', '.')
1319
+ )(ctx, obj)
1315
1320
  where.id = _result
1316
1321
  }
1317
1322
 
package/core/config.js CHANGED
@@ -7,6 +7,7 @@ module.exports = {
7
7
  dir: 'public',
8
8
  },
9
9
  is_check_admin: false,
10
+ is_token_name: true,
10
11
  log: {
11
12
  request: true,
12
13
  },
@@ -67,6 +68,7 @@ module.exports = {
67
68
  'log/create',
68
69
  'log/upsert',
69
70
  'auto/minute',
71
+ 'auto/second',
70
72
  ].every((item) => {
71
73
  return !ctx.request.url.includes(item)
72
74
  })
@@ -3,7 +3,7 @@ module.exports = {
3
3
  belongs: 'auth',
4
4
  multiple: false,
5
5
  order: [],
6
- select: [],
6
+ select: ['name'],
7
7
  excludes: ['query', 'post'],
8
8
  reference: [
9
9
  {
@@ -24,9 +24,15 @@ exports.login = async (ctx) => {
24
24
  result = hasUser
25
25
  }
26
26
 
27
+ const is_token_name = app.appConfig.is_token_name
28
+
27
29
  const tokenResult = {
28
30
  id: result.id,
29
- name: result.name,
31
+ ...(is_token_name
32
+ ? {
33
+ name: result.name,
34
+ }
35
+ : {}),
30
36
  mp_user: result.mp_user
31
37
  ? {
32
38
  openid: result.mp_user && result.mp_user.openid,
@@ -431,20 +431,28 @@ exports.syncModel = async (ctx) => {
431
431
  ctx.SUCCESS('ok')
432
432
  }
433
433
 
434
- exports.verify = async (ctx) => {
434
+ exports.verify = async (ctx, _data) => {
435
435
  const { app, appName } = getAppByCtx(ctx)
436
- const { code } = ctx.request.body
436
+ const { code } = _data || ctx.request.body
437
+ if (!code) {
438
+ ctx.SUCCESS(null)
439
+ return null
440
+ }
437
441
  const verify = util.promisify(jwt.verify)
438
442
  const result = await verify(code, 'token')
439
443
  ctx.SUCCESS(result)
444
+ return result
440
445
  }
441
446
 
442
- const expressFn = async ({ app, express_number: _express_number }) => {
447
+ const expressFn = async ({ app, express_number: _express_number, mobile }) => {
443
448
  const appConfig = getConfig(app)
444
- const { app_code, express_mobile } = await appConfig.getObject('express')
449
+ const { app_code, express_mobile: default_express_mobile } =
450
+ await appConfig.getObject('express')
445
451
 
446
452
  const express_number = _express_number.replace(/\t/, '').trim()
447
453
 
454
+ const express_mobile = mobile || default_express_mobile
455
+
448
456
  const lastFour = express_mobile
449
457
  .split('')
450
458
  .slice(express_mobile.length - 4, express_mobile.length)
@@ -501,7 +509,7 @@ const expressFn = async ({ app, express_number: _express_number }) => {
501
509
  exports.express = async (ctx) => {
502
510
  const { app } = getAppByCtx(ctx)
503
511
 
504
- const { express_number } = ctx.request.body
512
+ const { express_number, mobile } = ctx.request.body
505
513
 
506
514
  if (Array.isArray(express_number)) {
507
515
  const result = await Promise.all(
@@ -518,6 +526,7 @@ exports.express = async (ctx) => {
518
526
  const result = await expressFn({
519
527
  app,
520
528
  express_number,
529
+ mobile,
521
530
  })
522
531
 
523
532
  return ctx.SUCCESS(result)
@@ -674,3 +683,66 @@ exports.gpt = async (ctx) => {
674
683
  })
675
684
  await sleep(1000000)
676
685
  }
686
+
687
+ exports.copyDB = async (ctx) => {
688
+ const { app, appName: currentAppName } = getAppByCtx(ctx)
689
+ const {
690
+ host = '',
691
+ ori_appname = '',
692
+ break_list = [],
693
+ limit = 3000,
694
+ } = ctx.request.body
695
+ if (!host) {
696
+ throw new Error(`?host`)
697
+ }
698
+ const list = Object.keys(app.model)
699
+ const appName = ori_appname || currentAppName
700
+
701
+ for (const model of list) {
702
+ if (break_list.includes(model)) {
703
+ console.log(`跳过`)
704
+ continue
705
+ }
706
+ const count = await app.model[model].count()
707
+ if (count > 0) {
708
+ console.log(`有数据,跳过`)
709
+ continue
710
+ }
711
+ await app.model[model].sync({
712
+ force: true,
713
+ })
714
+ const url = `${host}/${appName}/${model}/findAll`
715
+ for (let i = 0; i < 10000; i++) {
716
+ console.log(`page-${i}`)
717
+ const { code, data } = await axios
718
+ .post(url, {
719
+ offset: i * limit,
720
+ limit,
721
+ where: {
722
+ id: {
723
+ $gt: 0,
724
+ },
725
+ },
726
+ ...(model === 'setting'
727
+ ? {
728
+ raw: true,
729
+ }
730
+ : {}),
731
+ autoInclude: false,
732
+ })
733
+ .then((res) => res.data)
734
+
735
+ if (code !== 200) {
736
+ break
737
+ }
738
+ await app.model[model].bulkCreate(data)
739
+ if (data.length < limit) {
740
+ break
741
+ }
742
+ }
743
+
744
+ console.log(`${model}结束`)
745
+ }
746
+
747
+ ctx.SUCCESS('ok')
748
+ }
@@ -147,9 +147,15 @@ exports.login_callback = async (ctx) => {
147
147
  ],
148
148
  })
149
149
 
150
+ const is_token_name = app.appConfig.is_token_name
151
+
150
152
  const tokenResult = {
151
153
  id: result.id,
152
- name: result.name,
154
+ ...(is_token_name
155
+ ? {
156
+ name: result.name,
157
+ }
158
+ : {}),
153
159
  h5_user: result.h5_user
154
160
  ? {
155
161
  openid: result.h5_user && result.h5_user.openid,
@@ -33,11 +33,12 @@ exports.clearWeixin = async (ctx) => {
33
33
  exports.push = async (ctx) => {
34
34
  const { app, appName } = getAppByCtx(ctx)
35
35
 
36
- const { message = '测试通知' } = ctx.request.body
36
+ const { message = '测试通知', url } = ctx.request.body
37
37
 
38
38
  await app.service.log.push({
39
39
  app,
40
40
  message,
41
+ url,
41
42
  })
42
43
 
43
44
  ctx.SUCCESS('ok')
@@ -222,7 +222,7 @@ exports.alias = {
222
222
 
223
223
  exports.hookList = {
224
224
  type: Sequelize.JSON,
225
- comment: 'hookd',
225
+ comment: 'hook',
226
226
  allowNull: false,
227
227
  defaultValue: [],
228
228
  }
@@ -3,7 +3,14 @@ module.exports = {
3
3
  belongs: 'auth',
4
4
  multiple: false,
5
5
  order: [],
6
- select: [],
6
+ select: [
7
+ {
8
+ key: 'model_id',
9
+ },
10
+ {
11
+ key: 'name',
12
+ },
13
+ ],
7
14
  excludes: [],
8
15
  defaultOrder: [],
9
16
  comment: {},
@@ -4,7 +4,11 @@ module.exports = {
4
4
  multiple: false,
5
5
  availableSort: false,
6
6
  order: [],
7
- select: [],
7
+ select: [
8
+ {
9
+ key: 'controller',
10
+ },
11
+ ],
8
12
  excludes: [],
9
13
  limit: 20,
10
14
  defaultOrder: [],
@@ -12,4 +16,4 @@ module.exports = {
12
16
  sortOrder: 1,
13
17
  reference: [],
14
18
  excludeAuth: [],
15
- };
19
+ }
@@ -157,3 +157,47 @@ exports.html = async (ctx) => {
157
157
  </body>
158
158
  </html>`
159
159
  }
160
+
161
+ exports.getList = async (ctx, _data) => {
162
+ const { app, appName } = getAppByCtx(ctx)
163
+
164
+ const { type = 'is_custom' } = _data || ctx.request.body
165
+
166
+ const settingList = await app.model.setting.findAll({
167
+ where: {
168
+ $or: [
169
+ {
170
+ is_front: true,
171
+ },
172
+ type
173
+ ? {
174
+ extra: {
175
+ [type]: true,
176
+ },
177
+ }
178
+ : null,
179
+ ].filter(Boolean),
180
+ },
181
+ attributes: {
182
+ exclude: [
183
+ 'name',
184
+ 'created_at',
185
+ 'updated_at',
186
+ 'createdid',
187
+ 'is_cache',
188
+ 'is_front',
189
+ 'is_control',
190
+ 'extra',
191
+ ],
192
+ },
193
+ })
194
+
195
+ const payLoad = settingList.map((item) => {
196
+ return lodash.omit(item.toJSON(), [
197
+ 'type',
198
+ item.parent_id === 0 ? '' : 'id',
199
+ ])
200
+ })
201
+ ctx.SUCCESS(payLoad)
202
+ return payLoad
203
+ }
@@ -141,7 +141,13 @@ exports.extra = {
141
141
  sortOrder: 9,
142
142
  set: function (value) {
143
143
  try {
144
- const dataValue = typeof value === 'object' ? value : JSON.parse(value)
144
+ const dataValue =
145
+ value === null
146
+ ? {}
147
+ : typeof value === 'object'
148
+ ? value
149
+ : JSON.parse(value)
150
+
145
151
  this.setDataValue('extra', dataValue)
146
152
  } catch {
147
153
  throw new Error('extra值不合法')
@@ -78,13 +78,13 @@ exports.countAndMaxId = async (ctx, _data) => {
78
78
  ctx.SUCCESS(null)
79
79
  return null
80
80
  }
81
- const count = await app.model[model].count()
82
- const current = await app.model[model].findOne({
83
- attributes: ['id', 'created_at'],
84
- order: [['id', 'DESC']],
85
- })
86
81
 
87
- const current_max_id = current ? current.id : 0
82
+ const result = await app.sequelize.query(
83
+ `select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = '${app.sequelize.config.database}' and TABLE_NAME = '${model}'`
84
+ )
85
+ const count = result[0][0].TABLE_ROWS
86
+
87
+ const current_max_id = result[0][0].AUTO_INCREMENT
88
88
 
89
89
  const lastMonth = await app.model[model].findOne({
90
90
  attributes: ['id'],
@@ -933,6 +933,40 @@ exports.checkIndex = async (ctx) => {
933
933
  }
934
934
  }
935
935
 
936
+ exports.checkAttribute = async (ctx) => {
937
+ const { app, appName } = getAppByCtx(ctx)
938
+ const { model } = ctx.request.body
939
+
940
+ if (!model) return ctx.ERROR('model不能为空')
941
+
942
+ const result = await app.sequelize.getQueryInterface().describeTable(model)
943
+
944
+ const attributeList = Object.keys(result).filter(
945
+ (item) => !['id', 'created_at', 'createdid', 'updated_at'].includes(item)
946
+ )
947
+
948
+ const currentAttributeList = Object.keys(app.attributes[model]).filter(
949
+ (item) => {
950
+ return app.attributes[model][item].type !== Sequelize.VIRTUAL
951
+ }
952
+ )
953
+
954
+ let flag = true
955
+ if (attributeList.length !== currentAttributeList.length) {
956
+ flag = false
957
+ }
958
+
959
+ const current = attributeList.filter(
960
+ (item) => !currentAttributeList.includes(item)
961
+ )
962
+
963
+ ctx.SUCCESS({
964
+ isSame: flag,
965
+ current,
966
+ remote: [],
967
+ })
968
+ }
969
+
936
970
  exports.dropIndex = async (ctx) => {
937
971
  const { app, appName } = getAppByCtx(ctx)
938
972
  const { model, key } = ctx.request.body
@@ -80,6 +80,7 @@ exports.initData = async ({ includes, excludes, app, ctx }) => {
80
80
  const omit = data && data.omit ? data.omit : []
81
81
  const pick = data && data.pick ? data.pick : []
82
82
  const cacheData = app.cache.get(`${model}`) || []
83
+
83
84
  const cacheList = cacheData
84
85
  .map((i) => (i.toJSON ? i.toJSON() : i))
85
86
  .filter((c) => {
@@ -160,10 +160,15 @@ exports.login = async (ctx) => {
160
160
  ...app.include.user,
161
161
  ],
162
162
  })
163
+ const is_token_name = app.appConfig.is_token_name
163
164
 
164
165
  const tokenResult = {
165
166
  id: result.id,
166
- name: result.name,
167
+ ...(is_token_name
168
+ ? {
169
+ name: result.name,
170
+ }
171
+ : {}),
167
172
  mp_user: result.mp_user
168
173
  ? {
169
174
  openid: result.mp_user && result.mp_user.openid,
@@ -8,6 +8,8 @@ exports.login = async (ctx) => {
8
8
 
9
9
  const config = _config || ctx.request.header.config || 'weixin_mp'
10
10
 
11
+ const is_token_name = app.appConfig.is_token_name
12
+
11
13
  const where =
12
14
  process.env.NODE_ENV !== 'production'
13
15
  ? {
@@ -41,7 +43,11 @@ exports.login = async (ctx) => {
41
43
  if (_config === 'none') {
42
44
  const tokenResult = {
43
45
  id: result.id,
44
- name: result.name,
46
+ ...(is_token_name
47
+ ? {
48
+ name: result.name,
49
+ }
50
+ : {}),
45
51
  }
46
52
  const token = await app.sign({
47
53
  user: tokenResult,
@@ -192,7 +198,11 @@ exports.login = async (ctx) => {
192
198
 
193
199
  const tokenResult = {
194
200
  id: result.id,
195
- name: result.name,
201
+ ...(is_token_name
202
+ ? {
203
+ name: result.name,
204
+ }
205
+ : {}),
196
206
  mp_user: result.mp_user
197
207
  ? {
198
208
  openid: result.mp_user && result.mp_user.openid,
@@ -315,11 +325,12 @@ exports.checkLogin = async (ctx) => {
315
325
  const config = _config || 'weixin_mp'
316
326
  const appConfig = getConfig(app)
317
327
  if (ctx.request[`${appName}-user`] && ctx.request[`${appName}-user`].id) {
328
+ const { app_id: appid } = await appConfig.getObject(config)
318
329
  const h5_user_include = config.includes('h5')
319
330
  ? {
320
331
  model: app.model.h5_user,
321
332
  where: {
322
- appid: (await appConfig.getObject(config)).app_id,
333
+ appid,
323
334
  },
324
335
  attributes: {
325
336
  exclude: ['created_at', 'updated_at', 'createdid'],
@@ -331,14 +342,18 @@ exports.checkLogin = async (ctx) => {
331
342
  const mp_user_include = config.includes('mp')
332
343
  ? {
333
344
  model: app.model.mp_user,
345
+ attributes: ['openid', 'unionid'],
334
346
  where: {
335
- appid: (await appConfig.getObject(config)).app_id,
347
+ appid,
336
348
  },
337
349
  }
338
350
  : {
339
351
  model: app.model.mp_user,
352
+ attributes: ['openid', 'unionid'],
340
353
  }
354
+
341
355
  let result
356
+
342
357
  const includeDefault = [
343
358
  {
344
359
  model: app.model.github_user,
@@ -353,6 +368,7 @@ exports.checkLogin = async (ctx) => {
353
368
 
354
369
  if (app.appConfig.loginData) {
355
370
  const application = await getAppConfig({ app, config })
371
+
356
372
  const loginData = lodash.mergeWith(
357
373
  lodash.cloneDeep(app.appConfig.loginData),
358
374
  lodash.get(application, 'loginData', {}),
@@ -379,6 +395,7 @@ exports.checkLogin = async (ctx) => {
379
395
  ])
380
396
  ),
381
397
  }
398
+
382
399
  result = await app.model.user.findOne({
383
400
  where: {
384
401
  id: ctx.request[`${appName}-user`].id,
@@ -428,9 +445,15 @@ exports.checkLogin = async (ctx) => {
428
445
  }
429
446
  }
430
447
 
448
+ const is_token_name = app.appConfig.is_token_name
449
+
431
450
  const tokenResult = {
432
451
  id: result.id,
433
- name: result.name,
452
+ ...(is_token_name
453
+ ? {
454
+ name: result.name,
455
+ }
456
+ : {}),
434
457
  mp_user: result.mp_user
435
458
  ? {
436
459
  openid: result.mp_user && result.mp_user.openid,
@@ -451,6 +474,7 @@ exports.checkLogin = async (ctx) => {
451
474
  }
452
475
  : {}),
453
476
  }
477
+
454
478
  const token = await app.sign({
455
479
  user: tokenResult,
456
480
  })
@@ -94,8 +94,17 @@ exports.mp_getPhone = async (ctx) => {
94
94
  (!exist.mp_user.appid || exist.mp_user.appid === app_id)
95
95
 
96
96
  if (mobileExist) {
97
- app.service.log.push({ app, message: `系统已存在该手机号${phoneNumber}` })
98
- return ctx.ERROR('系统已存在该手机号')
97
+ const formatMobile = (mobile) => {
98
+ if (!mobile) return ''
99
+ return mobile.slice(0, 3) + '*****' + mobile.slice(8, mobile.length)
100
+ }
101
+
102
+ const user_id = getUserByCtx(ctx)
103
+ app.service.log.push({
104
+ app,
105
+ message: `系统已存在该手机号${phoneNumber};${user_id}`,
106
+ })
107
+ return ctx.ERROR(`系统已存在该手机号`)
99
108
  }
100
109
 
101
110
  const userResult = await app.model.mp_user.findOne({
@@ -130,9 +139,15 @@ exports.mp_getPhone = async (ctx) => {
130
139
  ].filter((item) => item.model),
131
140
  })
132
141
 
142
+ const is_token_name = app.appConfig.is_token_name
143
+
133
144
  const tokenResult = {
134
145
  id: result.id,
135
- name: result.name,
146
+ ...(is_token_name
147
+ ? {
148
+ name: result.name,
149
+ }
150
+ : {}),
136
151
  mp_user: result.mp_user
137
152
  ? {
138
153
  openid: result.mp_user && result.mp_user.openid,
@@ -251,9 +266,15 @@ exports.mp_getPhoneNew = async (ctx) => {
251
266
  ].filter((item) => item.model),
252
267
  })
253
268
 
269
+ const is_token_name = app.appConfig.is_token_name
270
+
254
271
  const tokenResult = {
255
272
  id: result.id,
256
- name: result.name,
273
+ ...(is_token_name
274
+ ? {
275
+ name: result.name,
276
+ }
277
+ : {}),
257
278
  mp_user: result.mp_user
258
279
  ? {
259
280
  openid: result.mp_user && result.mp_user.openid,
@@ -492,9 +513,15 @@ exports.mp_login = async (ctx) => {
492
513
 
493
514
  if (!(result && result.id)) throw new Error('登录失败')
494
515
 
516
+ const is_token_name = app.appConfig.is_token_name
517
+
495
518
  const tokenResult = {
496
519
  id: result.id,
497
- name: result.name,
520
+ ...(is_token_name
521
+ ? {
522
+ name: result.name,
523
+ }
524
+ : {}),
498
525
  mp_user: result.mp_user
499
526
  ? {
500
527
  openid: result.mp_user && result.mp_user.openid,
@@ -671,9 +698,15 @@ exports.h5_login_callback = async (ctx) => {
671
698
  ].filter((item) => item.model),
672
699
  })
673
700
 
701
+ const is_token_name = app.appConfig.is_token_name
702
+
674
703
  const tokenResult = {
675
704
  id: result.id,
676
- name: result.name,
705
+ ...(is_token_name
706
+ ? {
707
+ name: result.name,
708
+ }
709
+ : {}),
677
710
  mp_user: result.mp_user
678
711
  ? {
679
712
  openid: result.mp_user && result.mp_user.openid,
@@ -805,9 +838,15 @@ exports.h5_login_info_callback = async (ctx) => {
805
838
  ].filter((item) => item.model),
806
839
  })
807
840
 
841
+ const is_token_name = app.appConfig.is_token_name
842
+
808
843
  const tokenResult = {
809
844
  id: result.id,
810
- name: result.name,
845
+ ...(is_token_name
846
+ ? {
847
+ name: result.name,
848
+ }
849
+ : {}),
811
850
  mp_user: result.mp_user
812
851
  ? {
813
852
  openid: result.mp_user && result.mp_user.openid,
@@ -1013,6 +1052,7 @@ exports.mp_pay = async (ctx) => {
1013
1052
  config = 'weixin_mp',
1014
1053
  pay_config = 'weixin_pay',
1015
1054
  profit_sharing = 'N',
1055
+ mch_id = '',
1016
1056
  } = ctx.request.body
1017
1057
  if (price === 0) throw new Error('价格不能为0')
1018
1058
 
@@ -1036,7 +1076,7 @@ exports.mp_pay = async (ctx) => {
1036
1076
  key,
1037
1077
  pay_key: _pay_key,
1038
1078
  partner_key,
1039
- } = await appConfig.getObject(pay_config)
1079
+ } = await appConfig.getObject(mch_id || pay_config)
1040
1080
 
1041
1081
  const pay_key = _pay_key || key || appName
1042
1082
  const { is_dev, site_host } = await appConfig.getObject('base')
@@ -1048,7 +1088,7 @@ exports.mp_pay = async (ctx) => {
1048
1088
 
1049
1089
  const wxpay = WXPay({
1050
1090
  appid: app_id,
1051
- mch_id: mchId,
1091
+ mch_id: mchId || mch_id,
1052
1092
  partner_key, // 微信商户平台API密钥
1053
1093
  })
1054
1094
 
@@ -1645,6 +1685,7 @@ exports.checkPayOnly = async (ctx, _data) => {
1645
1685
  })
1646
1686
 
1647
1687
  ctx.SUCCESS({ prefix, out_trade_no, ...payResult })
1688
+ return { prefix, out_trade_no, ...payResult }
1648
1689
  }
1649
1690
 
1650
1691
  exports.checkRefund = async (ctx, _data) => {
@@ -2044,6 +2085,7 @@ exports.getCommentInfo = async (ctx, _data) => {
2044
2085
  const {
2045
2086
  content: {
2046
2087
  orderInfo: { busiOrderId },
2088
+ content,
2047
2089
  },
2048
2090
  } = info
2049
2091
 
@@ -2060,6 +2102,7 @@ exports.getCommentInfo = async (ctx, _data) => {
2060
2102
  const result = {
2061
2103
  prefix,
2062
2104
  order_id,
2105
+ content,
2063
2106
  }
2064
2107
  ctx.SUCCESS(result)
2065
2108
  return result
@@ -687,7 +687,7 @@ exports.pc_pay = async ({
687
687
  pay_config = 'weixin_pay',
688
688
  out_trade_no: _out_trade_no,
689
689
  is_admin = false,
690
- type = 'SCAN-WEIXIN',
690
+ type = 'PC-WEIXIN',
691
691
  prefix = '',
692
692
  }) => {
693
693
  if (!ctx) throw new Error('?ctx')
@@ -866,6 +866,60 @@ exports.removereceiver = async ({
866
866
  return res
867
867
  }
868
868
 
869
+ const handleBillData = (result) => {
870
+ const arr = result.split('\r\n')
871
+ const list = arr.slice(1, arr.length - 3)
872
+ return {
873
+ header: arr[0],
874
+ list,
875
+ result: list.map((item) => {
876
+ const array = item.split(',')
877
+ const orderdate = array[20].substring(1).slice(2, 10)
878
+ const orderPrefix = array[6].substring(1).split('_')[1]
879
+ let order_id = 0
880
+ let prefix = ''
881
+ if (orderPrefix.includes('-')) {
882
+ order_id = Number(orderPrefix.split('-')[1])
883
+ prefix = orderPrefix.split('-')[0]
884
+ } else {
885
+ order_id = Number(orderPrefix)
886
+ }
887
+ let order_date
888
+ if (prefix) {
889
+ order_date = moment(array[0].substring(1)).format('YYYY-MM-DD') + ''
890
+ } else {
891
+ order_date = moment(
892
+ `${orderdate.slice(0, 4)}-${orderdate.slice(4, 6)}-${orderdate.slice(
893
+ 6,
894
+ 8
895
+ )}`
896
+ ).format('YYYY-MM-DD')
897
+ }
898
+ return {
899
+ created_at: array[0].substring(1),
900
+ transactionid: array[5].substring(1),
901
+ [`${[prefix, 'order_id'].filter(Boolean).join('_')}`]: order_id,
902
+ openid: array[7].substring(1),
903
+ price: Number(array[12].substring(1)),
904
+ refund_price: Number(array[16].substring(1)),
905
+ remark: array[20].substring(1),
906
+ rate_price: Number(array[22].substring(1)),
907
+ type: array[9].substring(1),
908
+ order_date,
909
+ }
910
+ }),
911
+ totalHeader: arr[arr.length - 3],
912
+ total: arr[arr.length - 2],
913
+ totalResult: {
914
+ number: Number(arr[arr.length - 2].split(',')[0].substring(1)),
915
+ total_price: Number(arr[arr.length - 2].split(',')[1].substring(1)),
916
+ refund_price: Number(arr[arr.length - 2].split(',')[2].substring(1)),
917
+ rate_price: Number(arr[arr.length - 2].split(',')[4].substring(1)),
918
+ price: Number(arr[arr.length - 2].split(',')[5].substring(1)),
919
+ },
920
+ }
921
+ }
922
+
869
923
  exports.downloadBill = async ({ ctx, pay_config = 'weixin_pay', ...rest }) => {
870
924
  if (!ctx) throw new Error('?ctx')
871
925
  const { app, appName } = getAppByCtx(ctx)
@@ -887,58 +941,17 @@ exports.downloadBill = async ({ ctx, pay_config = 'weixin_pay', ...rest }) => {
887
941
 
888
942
  try {
889
943
  const result = await payObj.downloadBill(rest)
944
+ return handleBillData(result)
945
+ } catch {
946
+ return []
947
+ }
948
+ }
890
949
 
891
- const arr = result.split('\r\n')
892
- const list = arr.slice(1, arr.length - 3)
893
- return {
894
- header: arr[0],
895
- list,
896
- result: list.map((item) => {
897
- const array = item.split(',')
898
- const orderdate = array[20].substring(1).slice(2, 10)
899
- const orderPrefix = array[6].substring(1).split('_')[1]
900
- let order_id = 0
901
- let prefix = ''
902
- if (orderPrefix.includes('-')) {
903
- order_id = Number(orderPrefix.split('-')[1])
904
- prefix = orderPrefix.split('-')[0]
905
- } else {
906
- order_id = Number(orderPrefix)
907
- }
908
- let order_date
909
- if (prefix) {
910
- order_date = moment(array[0].substring(1)).format('YYYY-MM-DD') + ''
911
- } else {
912
- order_date = moment(
913
- `${orderdate.slice(0, 4)}-${orderdate.slice(
914
- 4,
915
- 6
916
- )}-${orderdate.slice(6, 8)}`
917
- ).format('YYYY-MM-DD')
918
- }
919
- return {
920
- created_at: array[0].substring(1),
921
- transactionid: array[5].substring(1),
922
- [`${[prefix, 'order_id'].filter(Boolean).join('_')}`]: order_id,
923
- openid: array[7].substring(1),
924
- price: Number(array[12].substring(1)),
925
- refund_price: Number(array[16].substring(1)),
926
- remark: array[20].substring(1),
927
- rate_price: Number(array[22].substring(1)),
928
- type: array[9].substring(1),
929
- order_date,
930
- }
931
- }),
932
- totalHeader: arr[arr.length - 3],
933
- total: arr[arr.length - 2],
934
- totalResult: {
935
- number: Number(arr[arr.length - 2].split(',')[0].substring(1)),
936
- total_price: Number(arr[arr.length - 2].split(',')[1].substring(1)),
937
- refund_price: Number(arr[arr.length - 2].split(',')[2].substring(1)),
938
- rate_price: Number(arr[arr.length - 2].split(',')[4].substring(1)),
939
- price: Number(arr[arr.length - 2].split(',')[5].substring(1)),
940
- },
941
- }
950
+ exports.uploadBill = async ({ ctx, content }) => {
951
+ if (!ctx) throw new Error('?ctx')
952
+ if (!content) return []
953
+ try {
954
+ return handleBillData(content)
942
955
  } catch {
943
956
  return []
944
957
  }
@@ -65,6 +65,12 @@ const getShipTemplateUrl =
65
65
  const uploadShipUrl =
66
66
  'https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=%s'
67
67
 
68
+ const uploadPreShipUrl =
69
+ 'https://api.weixin.qq.com/wxa/sec/order/opspecialorder?access_token=%s'
70
+
71
+ const getShipOrderListUrl =
72
+ 'https://api.weixin.qq.com/wxa/sec/order/get_order_list?access_token=%s'
73
+
68
74
  const setMsgJumpPathUrl =
69
75
  'https://api.weixin.qq.com/wxa/sec/order/set_msg_jump_path?access_token=%s'
70
76
 
@@ -117,6 +123,20 @@ const uploadPromise = (options) => {
117
123
  })
118
124
  }
119
125
 
126
+ const https = require('https')
127
+
128
+ // 1. 全局 HTTPS 连接池(微信专用)
129
+ const wxHttpsAgent = new https.Agent({
130
+ keepAlive: true, // 开启长连接
131
+ keepAliveMsecs: 60000, // 空闲连接保留 60 秒
132
+ maxSockets: 30, // 最大并发连接(适配微信QPS,不超限)
133
+ maxFreeSockets: 10, // 保留空闲连接数
134
+ timeout: 8000, // 底层套接字超时
135
+ rejectUnauthorized: true,
136
+ })
137
+
138
+ axios.defaults.httpsAgent = wxHttpsAgent
139
+
120
140
  module.exports = class Singleton {
121
141
  constructor(config) {
122
142
  this.config = {
@@ -786,6 +806,44 @@ module.exports = class Singleton {
786
806
  return result
787
807
  }
788
808
 
809
+ async uploadPreShip(payLoad) {
810
+ const access_token = await this.getAccessToken()
811
+ const url = util.format(uploadPreShipUrl, access_token)
812
+
813
+ const result = await axios
814
+ .post(url, {
815
+ ...payLoad,
816
+ })
817
+ .then((res) => res.data)
818
+ if (result.errcode) {
819
+ if (result.errcode === 40001) {
820
+ cache.reset()
821
+ return await this.uploadPreShip(payLoad)
822
+ }
823
+ throw new Error(`${result.errcode};${result.errmsg}`)
824
+ }
825
+ return result
826
+ }
827
+
828
+ async getShipOrderList(payLoad) {
829
+ const access_token = await this.getAccessToken()
830
+ const url = util.format(getShipOrderListUrl, access_token)
831
+
832
+ const result = await axios
833
+ .post(url, {
834
+ ...payLoad,
835
+ })
836
+ .then((res) => res.data)
837
+ if (result.errcode) {
838
+ if (result.errcode === 40001) {
839
+ cache.reset()
840
+ return await this.getShipOrderList(payLoad)
841
+ }
842
+ throw new Error(`${result.errcode};${result.errmsg}`)
843
+ }
844
+ return result
845
+ }
846
+
789
847
  async uploadImage(payLoad) {
790
848
  const access_token = await this.getAccessToken()
791
849
  const { upload_type, resp_type, ...rest } = payLoad
@@ -1,6 +1,17 @@
1
1
  const util = require('util')
2
2
  const axios = require('axios')
3
+ const https = require('https')
4
+ // 1. 全局 HTTPS 连接池(微信专用)
5
+ const wxHttpsAgent = new https.Agent({
6
+ keepAlive: true, // 开启长连接
7
+ keepAliveMsecs: 60000, // 空闲连接保留 60 秒
8
+ maxSockets: 30, // 最大并发连接(适配微信QPS,不超限)
9
+ maxFreeSockets: 10, // 保留空闲连接数
10
+ timeout: 8000, // 底层套接字超时
11
+ rejectUnauthorized: true,
12
+ })
3
13
 
14
+ axios.defaults.httpsAgent = wxHttpsAgent
4
15
  const { lodash } = require('q-koa')
5
16
  const getAccessTokenUrl =
6
17
  'https://api.weixin.qq.com/cgi-bin/token?grant_type=%s&appid=%s&secret=%s'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q-koa",
3
- "version": "13.4.2",
3
+ "version": "13.4.5",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {