q-koa 10.6.7 → 10.7.1

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
@@ -1987,6 +1987,10 @@ APP.getClientTypeByCtx = (ctx) => {
1987
1987
 
1988
1988
  APP.getConfig = (app) => ({
1989
1989
  async getObject(type) {
1990
+ if (!type) {
1991
+ console.error(`getObject type : ${type}`)
1992
+ return {}
1993
+ }
1990
1994
  let configList = app.cache.get('configList')
1991
1995
  if (!configList) {
1992
1996
  configList = await app.model.setting.findAll({
@@ -5,8 +5,7 @@ const axios = require('axios')
5
5
  const qr = require('qr-image')
6
6
  const path = require('path')
7
7
  const TOUTIAO = getService('toutiao')
8
-
9
- const utils = require('../../utils')
8
+ const { signResult, hashFn } = require('../../utils')
10
9
 
11
10
  exports.initData = async (ctx) => {
12
11
  const { app, appName } = getAppByCtx(ctx)
@@ -36,7 +35,7 @@ exports.qr_code = async (ctx) => {
36
35
  const result = await toutiaoService.createQR({
37
36
  path: encodeURIComponent(page),
38
37
  appname: type,
39
- filename: utils.hashFn(item.key + page + type),
38
+ filename: hashFn(item.key + page + type),
40
39
  })
41
40
  console.log(`qr,${item.key},${page},${type}`)
42
41
  const qr_image = `https://${site_host || 'api.kuashou.com'}/upload/${result}`
@@ -194,3 +193,192 @@ exports.login = async (ctx) => {
194
193
  user: result,
195
194
  })
196
195
  }
196
+
197
+ exports.pay = async (ctx) => {
198
+ const { app, appName } = getAppByCtx(ctx)
199
+ const appConfig = getConfig(app)
200
+ const { is_dev, site_host } = await appConfig.getObject('base')
201
+ const { app_id, salt, key, is_sandbox, ...rest } = await appConfig.getObject(
202
+ 'toutiao'
203
+ )
204
+
205
+ const {
206
+ name,
207
+ out_trade_no: _out_trade_no,
208
+ prefix = '',
209
+ order_id,
210
+ type = 'TOUTIAO-WEIXIN',
211
+ price,
212
+ is_admin = false,
213
+ valid_time = 900,
214
+ } = ctx.request.body
215
+
216
+ const url = `https://${
217
+ is_sandbox ? 'open-sandbox.douyin.com' : 'developer.toutiao.com'
218
+ }/api/apps/ecpay/v1/create_order`
219
+
220
+ const out_order_no = _out_trade_no
221
+ ? _out_trade_no
222
+ : prefix
223
+ ? `${key.length > 10 ? appName : key}_${prefix}-${order_id}_${type}`
224
+ : `${key.length > 10 ? appName : key}_${order_id}_${type}`
225
+
226
+ const notify_url = `https://${
227
+ site_host || 'api.kuashou.com'
228
+ }/${appName}/toutiao/notify`
229
+
230
+ const data = {
231
+ app_id,
232
+ out_order_no,
233
+ total_amount: is_admin || is_dev ? 1 : Math.round(price * 100),
234
+ subject: name,
235
+ body: `订单【${out_order_no}】`,
236
+ valid_time,
237
+ notify_url,
238
+ }
239
+
240
+ const res = await axios
241
+ .post(url, {
242
+ ...data,
243
+ sign: signResult(data, salt),
244
+ })
245
+ .then((res) => res.data)
246
+
247
+ if (res.err_no) {
248
+ throw new Error(res.err_tips)
249
+ }
250
+ ctx.SUCCESS(res.data)
251
+ }
252
+
253
+ exports.notify = async (ctx) => {
254
+ const { app } = getAppByCtx(ctx)
255
+ const { type, msg, nonce, msg_signature, timestamp } = ctx.request.body
256
+
257
+ const {
258
+ appid,
259
+ cp_orderno: out_trade_no,
260
+ cp_extra,
261
+ way,
262
+ channel_no,
263
+ payment_order_no,
264
+ total_amount,
265
+ status,
266
+ item_id,
267
+ seller_uid,
268
+ paid_at,
269
+ order_id: transactionid,
270
+ } = JSON.parse(msg)
271
+
272
+ let order_id = out_trade_no.split('_')[1]
273
+ const order_price = Number(total_amount) / 100
274
+ let prefix = ''
275
+ if (order_id.includes('-')) {
276
+ const arr = order_id.split('-')
277
+ order_id = Number(arr[1])
278
+ ;[prefix] = arr
279
+ } else {
280
+ order_id = Number(order_id)
281
+ }
282
+ const model = prefix ? `${prefix}_order` : 'order'
283
+ let openid = ''
284
+
285
+ console.log(order_id, '微信支付回调-----', model, order_price, transactionid)
286
+ if (app.service[model] && app.service[model].notify) {
287
+ await app.service[model].notify({
288
+ app,
289
+ order_id,
290
+ order: model,
291
+ order_price,
292
+ transactionid,
293
+ out_trade_no,
294
+ openid,
295
+ })
296
+ }
297
+
298
+ ctx.status = 200
299
+ ctx.body = {
300
+ err_no: 0,
301
+ err_tips: 'success',
302
+ }
303
+ }
304
+
305
+ exports.checkPay = async (ctx) => {
306
+ const { app, appName } = getAppByCtx(ctx)
307
+
308
+ const {
309
+ id,
310
+ prefix,
311
+ type = 'TOUTIAO-DOUYIN',
312
+ out_trade_no: _out_trade_no,
313
+ } = ctx.request.body
314
+
315
+ const orderModel = prefix ? `${prefix}_order` : 'order'
316
+ const result = await app.model[orderModel].findOne({
317
+ where: {
318
+ id,
319
+ },
320
+ })
321
+ if (!result) return ctx.SUCCESS('找不到')
322
+
323
+ const appConfig = getConfig(app)
324
+ const { is_dev, site_host } = await appConfig.getObject('base')
325
+ const { app_id, salt, key, is_sandbox, ...rest } = await appConfig.getObject(
326
+ 'toutiao'
327
+ )
328
+
329
+ const orderPrefix = prefix ? `${prefix}-` : ''
330
+ const out_trade_no = _out_trade_no
331
+ ? _out_trade_no
332
+ : `${key}_${orderPrefix}${id}_${type}`
333
+
334
+ const url = `https://${
335
+ is_sandbox ? 'open-sandbox.douyin.com' : 'developer.toutiao.com'
336
+ }/api/apps/ecpay/v1/query_order`
337
+
338
+ const data = {
339
+ app_id,
340
+ out_order_no: out_trade_no,
341
+ }
342
+
343
+ const res = await axios
344
+ .post(url, {
345
+ ...data,
346
+ sign: signResult(data, salt),
347
+ })
348
+ .then((res) => res.data)
349
+
350
+ if (res.err_no) {
351
+ throw new Error(res.err_tips)
352
+ }
353
+
354
+ const order_price = Number(res.payment_info.total_fee) / 100
355
+ await app.service[orderModel].notify({
356
+ app,
357
+ order: orderModel,
358
+ order_id: id,
359
+ order_price,
360
+ transactionid: res.order_id,
361
+ out_trade_no: res.out_trade_no,
362
+ })
363
+ ctx.SUCCESS({
364
+ ...res.payment_info,
365
+ order_id: res.order_id,
366
+ })
367
+ }
368
+
369
+ exports.refund = async (ctx) => {
370
+ const { app, appName } = getAppByCtx(ctx)
371
+ const appConfig = getConfig(app)
372
+ const { id, prefix = '', price, out_trade_no, type } = ctx.request.body
373
+
374
+ if (!app.service.toutiao) throw new Error(`toutiao可能没有service.js`)
375
+ const res = await app.service.toutiao.refund({
376
+ ctx,
377
+ id,
378
+ prefix,
379
+ price,
380
+ out_trade_no,
381
+ type,
382
+ })
383
+ ctx.SUCCESS(res)
384
+ }
@@ -0,0 +1,78 @@
1
+ const { getAppByCtx, getUserByCtx, getConfig } = require('q-koa')
2
+ const axios = require('axios')
3
+ const { signResult } = require('../../utils')
4
+
5
+ exports.refund = async ({
6
+ ctx,
7
+ id,
8
+ prefix = '',
9
+ total_fee,
10
+ refund_fee,
11
+ price,
12
+ out_trade_no: _out_trade_no,
13
+ type = 'TOUTIAO-DOUYIN',
14
+ ...rest
15
+ }) => {
16
+ if (!ctx) throw new Error('?ctx')
17
+ const { app, appName } = getAppByCtx(ctx)
18
+ const appConfig = getConfig(app)
19
+ const { app_id, salt, key, is_sandbox } = await appConfig.getObject('toutiao')
20
+ const { site_host } = await appConfig.getObject('base')
21
+
22
+ const orderModel = prefix ? `${prefix}_order` : 'order'
23
+ const out_trade_no = _out_trade_no
24
+ ? _out_trade_no
25
+ : prefix
26
+ ? `${key}_${prefix}-${id}_${type}`
27
+ : `${key}_${id}_${type}`
28
+ const orderDetail = await app.model[orderModel].findOne({
29
+ where: {
30
+ id,
31
+ },
32
+ })
33
+ if (!orderDetail) throw new Error('不存在该订单')
34
+
35
+ const url = `https://${
36
+ is_sandbox ? 'open-sandbox.douyin.com' : 'developer.toutiao.com'
37
+ }/api/apps/ecpay/v1/create_refund`
38
+
39
+ const data = {
40
+ app_id,
41
+ out_order_no: out_trade_no,
42
+ out_refund_no: `${prefix}-${id}_${type}`,
43
+ reason: rest.remark || '退款',
44
+ refund_amount: Math.round((refund_fee || price) * 100),
45
+ notify_url: `https://${
46
+ site_host || 'api.kuashou.com'
47
+ }/${appName}/toutiao/refund_notify`,
48
+ }
49
+
50
+ const signResult = (params, salt) => {
51
+ var skip_arr = ['thirdparty_id', 'app_id', 'sign']
52
+ var paramArray = new Array()
53
+ for (var k in params) {
54
+ if (skip_arr.indexOf(k) != -1) {
55
+ continue
56
+ }
57
+ if (params[k] == '') {
58
+ continue
59
+ }
60
+ paramArray.push(params[k])
61
+ }
62
+ paramArray.push(salt)
63
+ paramArray.sort()
64
+ var signStr = paramArray.join('&')
65
+ return md5(signStr)
66
+ }
67
+ const res = await axios
68
+ .post(url, {
69
+ ...data,
70
+ sign: signResult(data, salt),
71
+ })
72
+ .then((res) => res.data)
73
+ if (res.err_no) {
74
+ throw new Error(res.err_tips)
75
+ }
76
+
77
+ return res
78
+ }
@@ -7,8 +7,6 @@ exports.login = async (ctx) => {
7
7
  const { mobile, password, config: _config, ...rest } = ctx.request.body
8
8
 
9
9
  const config = _config || ctx.request.header.config || 'weixin_mp'
10
- const appConfig = getConfig(app)
11
- const { app_id } = await appConfig.getObject(config)
12
10
 
13
11
  const where =
14
12
  process.env.NODE_ENV !== 'production'
@@ -36,6 +34,22 @@ exports.login = async (ctx) => {
36
34
  where,
37
35
  })
38
36
  if (!result) throw new Error('账号密码错误')
37
+ if (_config === 'none') {
38
+ const tokenResult = {
39
+ id: result.id,
40
+ name: result.name,
41
+ mobile: result.mobile,
42
+ }
43
+ const token = await app.sign({
44
+ user: tokenResult,
45
+ })
46
+ return ctx.SUCCESS({
47
+ token,
48
+ user: app.appConfig.loginData
49
+ ? lodash.omit(result.toJSON(), app.appConfig.loginData.omit)
50
+ : result,
51
+ })
52
+ }
39
53
  if (
40
54
  ctx.request[`${appName}-user`] &&
41
55
  ctx.request[`${appName}-user`].mp_user
@@ -89,6 +103,8 @@ exports.login = async (ctx) => {
89
103
  }
90
104
  )
91
105
  }
106
+ const appConfig = getConfig(app)
107
+ const { app_id } = await appConfig.getObject(config)
92
108
  /**
93
109
  * 查出最新用户,存token并返回
94
110
  */
@@ -115,18 +131,20 @@ exports.login = async (ctx) => {
115
131
  : {
116
132
  model: app.model.mp_user,
117
133
  }
118
- const includeDefault = [
119
- {
120
- model: app.model.github_user,
121
- },
122
- h5_user_include,
123
- mp_user_include,
124
- {
125
- model: app.model.toutiao_user,
126
- },
127
- ...app.include.user,
128
- ].filter((item) => item.model)
129
-
134
+ const includeDefault =
135
+ config !== 'none'
136
+ ? [
137
+ {
138
+ model: app.model.github_user,
139
+ },
140
+ h5_user_include,
141
+ mp_user_include,
142
+ {
143
+ model: app.model.toutiao_user,
144
+ },
145
+ ...app.include.user,
146
+ ].filter((item) => item.model)
147
+ : []
130
148
  if (app.appConfig.loginData) {
131
149
  const include = includeDefault.filter((i) => {
132
150
  return app.appConfig.loginData.excludeInclude.every((m) => {
@@ -51,29 +51,21 @@ exports.refund = async ({
51
51
  })
52
52
  if (!orderDetail) throw new Error('不存在该订单')
53
53
  try {
54
- const { result_code, err_code_des } = await payObj.refund({
54
+ const data = {
55
55
  ...rest,
56
56
  out_trade_no,
57
- out_refund_no: id + '_' + type,
57
+ out_refund_no: `${prefix}-${id}_${type}`,
58
58
  total_fee: Math.round((total_fee || refund_fee || price) * 100),
59
59
  refund_fee: Math.round((refund_fee || price) * 100),
60
60
  notify_url: `https://${
61
61
  site_host || 'api.kuashou.com'
62
62
  }/${appName}/weixin/refund_notify/${pay_config}`,
63
- })
63
+ }
64
+ const { result_code, err_code_des } = await payObj.refund(data)
64
65
  if (result_code === 'SUCCESS') {
65
66
  return true
66
67
  } else {
67
- console.error({
68
- ...rest,
69
- out_trade_no,
70
- out_refund_no: id + '_' + type,
71
- total_fee: Math.round((total_fee || refund_fee || price) * 100),
72
- refund_fee: Math.round((refund_fee || price) * 100),
73
- notify_url: `https://${
74
- site_host || 'api.kuashou.com'
75
- }/${appName}/weixin/refund_notify/${pay_config}`,
76
- })
68
+ console.error(data)
77
69
  throw new Error(err_code_des)
78
70
  }
79
71
  } catch (e) {
@@ -1,4 +1,5 @@
1
1
  const { lodash } = require('q-koa')
2
+ const md5 = require('md5')
2
3
 
3
4
  const findConfig = (type) => (item) =>
4
5
  item.key === type ||
@@ -169,3 +170,21 @@ exports.getAppConfig = async ({ app, config, key, app_id }) => {
169
170
 
170
171
  return target || null
171
172
  }
173
+
174
+ exports.signResult = (params, salt) => {
175
+ var skip_arr = ['thirdparty_id', 'app_id', 'sign']
176
+ var paramArray = new Array()
177
+ for (var k in params) {
178
+ if (skip_arr.indexOf(k) != -1) {
179
+ continue
180
+ }
181
+ if (params[k] == '') {
182
+ continue
183
+ }
184
+ paramArray.push(params[k])
185
+ }
186
+ paramArray.push(salt)
187
+ paramArray.sort()
188
+ var signStr = paramArray.join('&')
189
+ return md5(signStr)
190
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q-koa",
3
- "version": "10.6.7",
3
+ "version": "10.7.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {