q-koa 13.6.0 → 13.6.2

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.
@@ -8,7 +8,7 @@ exports.push = async ({ app, appName = '通知', url, message }) => {
8
8
  const log_push_url = lodash.get(
9
9
  app,
10
10
  'appConfig.log.url',
11
- 'https://api.day.app/xJXYwBCgBvxTjCdEC4CYf5'
11
+ 'https://api.day.app/4qcuxMTvSeTKWfy5tEQsf6'
12
12
  )
13
13
 
14
14
  const log_push_excludes = lodash.get(app, 'appConfig.log.excludes', {
@@ -85,32 +85,33 @@ exports.loadModel = async ({ app, appName }) => {
85
85
  model: result[i],
86
86
  name: config.name,
87
87
  belongs: config.belongs || 'page',
88
- order: config.order,
89
- multiple: config.multiple,
90
- availableSort: config.availableSort,
88
+ order: config.order || [],
89
+ multiple: config.multiple || false,
90
+ availableSort: config.availableSort || false,
91
91
  limit: config.limit || 20,
92
- select: config.select,
93
- excludes: config.excludes,
94
- initList: config.initList,
95
- initTableList: config.initTableList,
96
- defaultOrder: config.defaultOrder,
97
- excludeAuth: config.excludeAuth,
98
- comment: config.comment,
99
- reference: config.reference,
100
- include: config.include,
101
- sortOrder: config.sortOrder,
102
- personal: config.personal,
103
- autoData: config.autoData,
104
- is_split: config.is_split,
105
- is_split_count: config.is_split_count,
106
- show_virtual: config.show_virtual,
107
- modelQuery: config.modelQuery,
108
- modelUpsert: config.modelUpsert,
109
- modelDelete: config.modelDelete,
110
- editInline: config.editInline,
111
- deleteCheckList: config.deleteCheckList,
112
- bulkCreateList: config.bulkCreateList,
113
- indexList: config.indexList,
92
+ referenceSelect: config.referenceSelect || [],
93
+ select: config.select || [],
94
+ excludes: config.excludes || [],
95
+ initList: config.initList || [],
96
+ initTableList: config.initTableList || [],
97
+ defaultOrder: config.defaultOrder || [],
98
+ excludeAuth: config.excludeAuth || [],
99
+ comment: config.comment || {},
100
+ reference: config.reference || [],
101
+ include: config.include || '',
102
+ sortOrder: config.sortOrder || 1,
103
+ personal: config.personal || {},
104
+ autoData: config.autoData || {},
105
+ is_split: config.is_split || false,
106
+ is_split_count: config.is_split_count || false,
107
+ show_virtual: config.show_virtual || false,
108
+ modelQuery: config.modelQuery || {},
109
+ modelUpsert: config.modelUpsert || {},
110
+ modelDelete: config.modelDelete || {},
111
+ editInline: config.editInline || {},
112
+ deleteCheckList: config.deleteCheckList || [],
113
+ bulkCreateList: config.bulkCreateList || [],
114
+ indexList: config.indexList || [],
114
115
  hookList: config.hookList,
115
116
  list: attributes.map((attr, index) => {
116
117
  const name = attr.match(/exports.(.*)=/)[1].trim()
@@ -22,6 +22,8 @@ const path = require('path')
22
22
  const fsPromise = require('fs/promises')
23
23
  const { getAppConfig } = require('../../utils')
24
24
 
25
+ const AllinPay = require('../../services/allinpay')
26
+
25
27
  const check = ({ timestamp, nonce, signature, token }) => {
26
28
  const tmp = [token, timestamp, nonce].sort().join('')
27
29
  const currSign = crypto.createHash('sha1').update(tmp).digest('hex')
@@ -1106,16 +1108,27 @@ exports.mp_pay = async (ctx) => {
1106
1108
  const notify_url = `https://${
1107
1109
  site_host || 'api.kuashou.com'
1108
1110
  }/${appName}/weixin/notify`
1109
- const prePayResult = await wxpay.getBrandWCPayRequestParamsSync({
1110
- openid: userDetail.openid,
1111
- body: name,
1112
- detail: '公众号支付测试',
1113
- out_trade_no,
1114
- total_fee: is_admin || is_dev ? 1 : Math.round(price * 100),
1115
- spbill_create_ip: '192.168.2.210',
1116
- notify_url,
1117
- profit_sharing,
1118
- })
1111
+ let prePayResult
1112
+ try {
1113
+ prePayResult = await wxpay.getBrandWCPayRequestParamsSync({
1114
+ openid: userDetail.openid,
1115
+ body: name,
1116
+ detail: '公众号支付测试',
1117
+ out_trade_no,
1118
+ total_fee: is_admin || is_dev ? 1 : Math.round(price * 100),
1119
+ spbill_create_ip: '192.168.2.210',
1120
+ notify_url,
1121
+ profit_sharing,
1122
+ })
1123
+ } catch (e) {
1124
+ if (e.message.includes('此商家的收款功能已被限制')) {
1125
+ app.controller.weixin.changeMch &&
1126
+ app.controller.weixin.changeMch(ctx, {
1127
+ mchId: mchId || mch_id,
1128
+ })
1129
+ }
1130
+ return ctx.ERROR(e.message)
1131
+ }
1119
1132
 
1120
1133
  const checkOrder = (obj) => {
1121
1134
  return new Promise((resolve, reject) => {
@@ -1159,12 +1172,6 @@ exports.mp_pay = async (ctx) => {
1159
1172
  return ctx.SUCCESS('ok')
1160
1173
  }
1161
1174
  if (payResult.return_msg) {
1162
- console.error({
1163
- mchId,
1164
- key,
1165
- pay_key: _pay_key,
1166
- partner_key,
1167
- })
1168
1175
  throw new Error(
1169
1176
  payResult.return_msg === '签名错误,请检查后再试'
1170
1177
  ? payResult.return_msg + '(商户号/APIv2/关联)'
@@ -1190,16 +1197,30 @@ exports.b2b_pay = async (ctx) => {
1190
1197
  const { app, appName } = getAppByCtx(ctx)
1191
1198
  const appConfig = getConfig(app)
1192
1199
  const { is_dev } = await appConfig.getObject('base')
1193
- const { name, _out_trade_no, order_id, price, prefix, code, type, is_admin } =
1194
- ctx.request.body
1200
+ const {
1201
+ name,
1202
+ _out_trade_no,
1203
+ order_id,
1204
+ price,
1205
+ prefix,
1206
+ code,
1207
+ type,
1208
+ is_admin,
1209
+ mch_id = '',
1210
+ config = 'weixin_mp',
1211
+ pay_config = 'weixin_pay',
1212
+ } = ctx.request.body
1195
1213
 
1196
- const { app_id, app_secrect } = await appConfig.getObject('weixin_mp')
1214
+ const { app_id, app_secrect } = await appConfig.getObject(config)
1197
1215
  const {
1198
- mchId: mchid,
1216
+ mchId,
1217
+ b2b_mchId,
1199
1218
  app_key,
1200
1219
  key,
1201
1220
  pay_key: _pay_key,
1202
- } = await appConfig.getObject('weixin_pay')
1221
+ } = await appConfig.getObject(pay_config)
1222
+
1223
+ const mchid = mch_id || b2b_mchId || mchId
1203
1224
 
1204
1225
  if (!app_key) {
1205
1226
  throw new Error('缺少app_key')
@@ -1234,6 +1255,95 @@ exports.b2b_pay = async (ctx) => {
1234
1255
  ctx.SUCCESS(res)
1235
1256
  }
1236
1257
 
1258
+ exports.union_pay = async (ctx) => {
1259
+ const { app, appName } = getAppByCtx(ctx)
1260
+ const appConfig = getConfig(app)
1261
+ const { is_dev } = await appConfig.getObject('base')
1262
+ const {
1263
+ name,
1264
+ _out_trade_no,
1265
+ order_id,
1266
+ price,
1267
+ prefix,
1268
+ code,
1269
+ type,
1270
+ is_admin,
1271
+ mch_id = '',
1272
+ config = 'weixin_mp',
1273
+ pay_config = 'weixin_pay',
1274
+ } = ctx.request.body
1275
+
1276
+ const { app_id, app_secrect } = await appConfig.getObject(config)
1277
+
1278
+ const { site_host } = await appConfig.getObject('base')
1279
+ const {
1280
+ mchId,
1281
+ b2b_mchId,
1282
+ app_key,
1283
+ key,
1284
+ pay_key: _pay_key,
1285
+ union_mchId,
1286
+ union_appid,
1287
+ union_privateKey,
1288
+ union_publicKey,
1289
+ } = await appConfig.getObject(pay_config)
1290
+
1291
+ const mchid = mch_id || b2b_mchId || mchId
1292
+ const userDetail = ctx.request[`${appName}-user`].mp_user
1293
+ const pay_key = _pay_key || key || appName
1294
+
1295
+ const weixinMp = new WeixinMp({
1296
+ appid: app_id,
1297
+ secrect: app_secrect,
1298
+ })
1299
+ weixinMp.init()
1300
+ const out_trade_no = _out_trade_no
1301
+ ? _out_trade_no
1302
+ : prefix
1303
+ ? `${pay_key}_${prefix}-${order_id}_${type}`
1304
+ : `${pay_key}_${order_id}_${type}`
1305
+
1306
+ const order_amount = is_admin || is_dev ? 1 : Math.round(price * 100)
1307
+
1308
+ const notify_url = `https://${
1309
+ site_host || 'api.kuashou.com'
1310
+ }/${appName}/weixin/union_notify`
1311
+ const allinpay = new AllinPay({
1312
+ cusid: union_mchId,
1313
+ appid: union_appid,
1314
+ isTest: false,
1315
+ subAppid: app_id,
1316
+ privateKey: union_privateKey,
1317
+ publicKey: union_publicKey,
1318
+ notifyUrl: notify_url,
1319
+ })
1320
+
1321
+ const res = await allinpay.createOrder({
1322
+ reqsn: out_trade_no,
1323
+ trxamt: order_amount + '',
1324
+ body: name,
1325
+ paytype: 'W06',
1326
+ acct: userDetail.openid,
1327
+ })
1328
+
1329
+ const obj = {
1330
+ signData: JSON.stringify({
1331
+ requestPaymentInfo: {
1332
+ timeStamp: JSON.parse(res.payinfo).timeStamp,
1333
+ package: JSON.parse(res.payinfo).package,
1334
+ signType: JSON.parse(res.payinfo).signType,
1335
+ paySign: JSON.parse(res.payinfo).paySign,
1336
+ nonceStr: JSON.parse(res.payinfo).nonceStr,
1337
+ },
1338
+ }),
1339
+ mode: 'retail_pay_indirect_goods',
1340
+ }
1341
+
1342
+ // notify_url: `https://${site_host}/${appName}/weixin/uninon_notify`,
1343
+
1344
+ ctx.SUCCESS(obj)
1345
+ }
1346
+
1237
1347
  exports.mp_pay_new = async (ctx) => {
1238
1348
  const { app, appName } = getAppByCtx(ctx)
1239
1349
  const {
@@ -1294,9 +1404,108 @@ exports.mp_pay_new = async (ctx) => {
1294
1404
  return ctx.SUCCESS(prePayResult)
1295
1405
  }
1296
1406
 
1407
+ exports.union_notify = async (ctx) => {
1408
+ const { app, appName } = getAppByCtx(ctx)
1409
+
1410
+ try {
1411
+ const notifyData = ctx.request.body
1412
+
1413
+ app.service.log.push({
1414
+ app,
1415
+ message: JSON.stringify(notifyData),
1416
+ })
1417
+
1418
+ const {
1419
+ trxcode,
1420
+ trxstatus,
1421
+ cusorderid,
1422
+ cusid,
1423
+ acct,
1424
+ trxid,
1425
+ trxamt,
1426
+ srctrxid,
1427
+ trxreserved,
1428
+ } = notifyData
1429
+
1430
+ if (trxstatus === '0000') {
1431
+ if (trxcode === 'VSP501') {
1432
+ let prefix = ''
1433
+ const out_trade_no = cusorderid
1434
+ let order_id = out_trade_no.split('_')[1]
1435
+ let pay_type_key = out_trade_no.split('_')[2]
1436
+ const order_price = Number(trxamt) / 100
1437
+ if (order_id.includes('-')) {
1438
+ const arr = order_id.split('-')
1439
+ order_id = Number(arr[1])
1440
+ ;[prefix] = arr
1441
+ } else {
1442
+ order_id = Number(order_id)
1443
+ }
1444
+ const model = prefix ? `${prefix}_order` : 'order'
1445
+
1446
+ if (app.service[model] && app.service[model].notify) {
1447
+ await app.service[model].notify({
1448
+ ctx,
1449
+ app,
1450
+ order_id,
1451
+ order: model,
1452
+ order_price,
1453
+ transactionid: trxid,
1454
+ out_trade_no,
1455
+ openid: acct,
1456
+ pay_type_key,
1457
+ mch_id: cusid,
1458
+ refund_type: 'union_refund',
1459
+ })
1460
+ }
1461
+ } else if (trxcode === 'VSP503') {
1462
+ const payRecordTarget = await app.model.pay_record.findOne({
1463
+ where: {
1464
+ transactionid: srctrxid,
1465
+ },
1466
+ })
1467
+ const model =
1468
+ payRecordTarget && payRecordTarget.prefix
1469
+ ? `${payRecordTarget.prefix}_order`
1470
+ : 'order'
1471
+ const refund_price = Number(trxamt) / 100
1472
+ const out_refund_no = cusorderid
1473
+ const type = out_refund_no.includes('_')
1474
+ ? out_refund_no.split('_')[1]
1475
+ : ''
1476
+
1477
+ if (app.service[model] && app.service[model].refund_notify) {
1478
+ await app.service[model].refund_notify({
1479
+ app,
1480
+ order_id: payRecordTarget.order_id,
1481
+ order: model,
1482
+ refund_price,
1483
+ type,
1484
+ out_refund_no,
1485
+ remark: trxreserved,
1486
+ transactionid: srctrxid,
1487
+ refundid: trxid,
1488
+ })
1489
+ }
1490
+ }
1491
+ } else {
1492
+ app.service.log.push({
1493
+ app,
1494
+ message: `Order ${cusorderid} payment failed, status: ${trxstatus}`,
1495
+ })
1496
+ }
1497
+
1498
+ ctx.body = 'success'
1499
+ } catch (error) {
1500
+ console.error('Notify error:', error)
1501
+ ctx.body = 'FAIL'
1502
+ }
1503
+ }
1504
+
1297
1505
  exports.notify = async (ctx) => {
1298
1506
  const { app } = getAppByCtx(ctx)
1299
1507
  const result = ctx.request.xmlBody
1508
+
1300
1509
  let prefix = ''
1301
1510
  let order_id = result.xml.out_trade_no.split('_')[1]
1302
1511
  let pay_type_key = result.xml.out_trade_no.split('_')[2]
@@ -1705,6 +1914,7 @@ exports.checkRefund = async (ctx, _data) => {
1705
1914
  config = 'weixin_mp',
1706
1915
  pay_config = 'weixin_pay',
1707
1916
  out_trade_no: _out_trade_no,
1917
+ mch_id = '',
1708
1918
  } = _data || ctx.request.body
1709
1919
 
1710
1920
  const appConfig = getConfig(app)
@@ -1714,7 +1924,7 @@ exports.checkRefund = async (ctx, _data) => {
1714
1924
 
1715
1925
  const payObj = new WeixinPay({
1716
1926
  appId,
1717
- mchId,
1927
+ mchId: mch_id || mchId,
1718
1928
  key: key.length > 10 ? key : partner_key,
1719
1929
  })
1720
1930
 
@@ -1800,6 +2010,201 @@ exports.checkPayNew = async (ctx) => {
1800
2010
  ctx.SUCCESS({ prefix, out_trade_no, ...payResult })
1801
2011
  }
1802
2012
 
2013
+ exports.union_checkPay = async (ctx) => {
2014
+ const { app, appName, controller } = getAppByCtx(ctx)
2015
+
2016
+ const {
2017
+ id,
2018
+ prefix,
2019
+ config = 'weixin_mp',
2020
+ type = 'MP-WEIXIN',
2021
+ pay_config = 'weixin_pay',
2022
+ out_trade_no: _out_trade_no,
2023
+ mch_id = '',
2024
+ } = ctx.request.body
2025
+
2026
+ const orderModel = prefix ? `${prefix}_order` : 'order'
2027
+ const result = await app.model[orderModel].findOne({
2028
+ where: {
2029
+ id,
2030
+ },
2031
+ })
2032
+ if (!result) return ctx.SUCCESS('找不到')
2033
+
2034
+ const appConfig = getConfig(app)
2035
+ const { app_id, app_secrect } = await appConfig.getObject(config)
2036
+ const {
2037
+ mchId,
2038
+ union_mchId,
2039
+ union_appid,
2040
+ union_privateKey,
2041
+ union_publicKey,
2042
+ key,
2043
+ app_key,
2044
+ } = await appConfig.getObject(pay_config)
2045
+
2046
+ const weixinMp = new WeixinMp({
2047
+ appid: app_id,
2048
+ secrect: app_secrect,
2049
+ })
2050
+ weixinMp.init()
2051
+
2052
+ const orderPrefix = prefix ? `${prefix}-` : ''
2053
+ const out_trade_no = _out_trade_no
2054
+ ? _out_trade_no
2055
+ : `${key.length > 10 ? appName : key}_${orderPrefix}${id}_${type}`
2056
+
2057
+ const allinpay = new AllinPay({
2058
+ cusid: mch_id || union_mchId,
2059
+ appid: union_appid,
2060
+ isTest: false,
2061
+ subAppid: app_id,
2062
+ privateKey: union_privateKey,
2063
+ publicKey: union_publicKey,
2064
+ })
2065
+ const payResult = await allinpay.checkOrder(out_trade_no)
2066
+
2067
+ if (payResult) {
2068
+ if (payResult.trxstatus === '0000' && payResult.trxcode === 'VSP501') {
2069
+ const order_price = Number(payResult.trxamt) / 100
2070
+
2071
+ console.log({
2072
+ order: orderModel,
2073
+ order_id: id,
2074
+ order_price,
2075
+ transactionid: payResult.trxid,
2076
+ openid: payResult.acct,
2077
+ mch_id: payResult.cusid,
2078
+ out_trade_no: payResult.reqsn,
2079
+ })
2080
+ await app.service[orderModel].notify({
2081
+ app,
2082
+ order: orderModel,
2083
+ order_id: id,
2084
+ order_price,
2085
+ transactionid: payResult.trxid,
2086
+ openid: payResult.acct,
2087
+ mch_id: payResult.cusid,
2088
+ out_trade_no: payResult.reqsn,
2089
+ })
2090
+ }
2091
+ }
2092
+
2093
+ ctx.SUCCESS({ prefix, ...payResult })
2094
+ }
2095
+
2096
+ exports.b2b_checkPay = async (ctx) => {
2097
+ const { app, appName, controller } = getAppByCtx(ctx)
2098
+
2099
+ const {
2100
+ id,
2101
+ prefix,
2102
+ config = 'weixin_mp',
2103
+ type = 'MP-WEIXIN',
2104
+ pay_config = 'weixin_pay',
2105
+ out_trade_no: _out_trade_no,
2106
+ mch_id = '',
2107
+ } = ctx.request.body
2108
+
2109
+ const orderModel = prefix ? `${prefix}_order` : 'order'
2110
+ const result = await app.model[orderModel].findOne({
2111
+ where: {
2112
+ id,
2113
+ },
2114
+ })
2115
+ if (!result) return ctx.SUCCESS('找不到')
2116
+
2117
+ const appConfig = getConfig(app)
2118
+ const { app_id, app_secrect } = await appConfig.getObject(config)
2119
+ const { mchId, b2b_mchId, key, app_key } = await appConfig.getObject(
2120
+ pay_config
2121
+ )
2122
+
2123
+ const mchid = mch_id || b2b_mchId || mchId
2124
+
2125
+ const weixinMp = new WeixinMp({
2126
+ appid: app_id,
2127
+ secrect: app_secrect,
2128
+ })
2129
+ weixinMp.init()
2130
+
2131
+ const orderPrefix = prefix ? `${prefix}-` : ''
2132
+ const out_trade_no = _out_trade_no
2133
+ ? _out_trade_no
2134
+ : `${key.length > 10 ? appName : key}_${orderPrefix}${id}_${type}`
2135
+
2136
+ const payResult = await weixinMp.b2bCheckOrder({
2137
+ out_trade_no: out_trade_no,
2138
+ mchid,
2139
+ app_key,
2140
+ })
2141
+
2142
+ if (payResult) {
2143
+ console.log('payResult', payResult)
2144
+ const order_price = Number(payResult.amount.order_amount) / 100
2145
+ // await app.service[orderModel].notify({
2146
+ // app,
2147
+ // order: orderModel,
2148
+ // order_id: id,
2149
+ // order_price,
2150
+ // transactionid: payResult.wxpay_transaction_id,
2151
+ // openid:payResult.payer_openid,
2152
+ // mch_id: payResult.mchid,
2153
+ // out_trade_no: payResult.out_trade_no,
2154
+ // })
2155
+ }
2156
+
2157
+ ctx.SUCCESS({ prefix, ...payResult })
2158
+ }
2159
+
2160
+ exports.b2b_checkRefund = async (ctx, _data) => {
2161
+ const { app, appName, controller } = getAppByCtx(ctx)
2162
+
2163
+ const {
2164
+ id,
2165
+ prefix,
2166
+ type = 'MP-WEIXIN',
2167
+ config = 'weixin_mp',
2168
+ pay_config = 'weixin_pay',
2169
+ out_refund_no,
2170
+ mch_id = '',
2171
+ } = _data || ctx.request.body
2172
+
2173
+ const appConfig = getConfig(app)
2174
+ const { app_id, app_secrect } = await appConfig.getObject(config)
2175
+ const { mchId, b2b_mchId, key, app_key } = await appConfig.getObject(
2176
+ pay_config
2177
+ )
2178
+
2179
+ const mchid = mch_id || b2b_mchId || mchId
2180
+
2181
+ const weixinMp = new WeixinMp({
2182
+ appid: app_id,
2183
+ secrect: app_secrect,
2184
+ })
2185
+
2186
+ weixinMp.init()
2187
+
2188
+ if (!id) return ctx.ERROR('?id')
2189
+ const orderModel = prefix ? `${prefix}_order` : 'order'
2190
+ const orderDetail = await app.model[orderModel].findOne({
2191
+ where: {
2192
+ id,
2193
+ },
2194
+ })
2195
+
2196
+ if (!orderDetail) return ctx.SUCCESS('找不到')
2197
+
2198
+ const result = await weixinMp.b2bCheckRefund({
2199
+ mchid,
2200
+ app_key,
2201
+ out_refund_no,
2202
+ })
2203
+
2204
+ ctx.SUCCESS(result)
2205
+ return result
2206
+ }
2207
+
1803
2208
  exports.init_mp_openid = async (ctx) => {
1804
2209
  const { app, appName } = getAppByCtx(ctx)
1805
2210