q-koa 7.7.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.
- package/core/app.js +1813 -0
- package/core/config.js +124 -0
- package/core/file/plugins/administrator/config.js +17 -0
- package/core/file/plugins/administrator/controller.js +264 -0
- package/core/file/plugins/administrator/model.js +53 -0
- package/core/file/plugins/administrator/validate.js +41 -0
- package/core/file/plugins/alipay/controller.js +68 -0
- package/core/file/plugins/alipay/validate.js +9 -0
- package/core/file/plugins/cache/service.js +16 -0
- package/core/file/plugins/cloudfunction/config.js +4 -0
- package/core/file/plugins/cloudfunction/model.js +15 -0
- package/core/file/plugins/common/controller.js +398 -0
- package/core/file/plugins/common/validate.js +47 -0
- package/core/file/plugins/douyin/config.js +3 -0
- package/core/file/plugins/douyin/controller.js +521 -0
- package/core/file/plugins/douyin/validate.js +40 -0
- package/core/file/plugins/douyin_user/config.js +15 -0
- package/core/file/plugins/douyin_user/model.js +72 -0
- package/core/file/plugins/good_sku/controller.js +80 -0
- package/core/file/plugins/h5_user/config.js +19 -0
- package/core/file/plugins/h5_user/model.js +71 -0
- package/core/file/plugins/lang/config.js +4 -0
- package/core/file/plugins/lang/model.js +15 -0
- package/core/file/plugins/language/config.js +5 -0
- package/core/file/plugins/language/model.js +54 -0
- package/core/file/plugins/log/config.js +25 -0
- package/core/file/plugins/log/controller.js +31 -0
- package/core/file/plugins/log/model.js +51 -0
- package/core/file/plugins/model/config.js +12 -0
- package/core/file/plugins/model/controller.js +69 -0
- package/core/file/plugins/model/model.js +169 -0
- package/core/file/plugins/model/service.js +218 -0
- package/core/file/plugins/model/validate.js +42 -0
- package/core/file/plugins/model_attributes/config.js +12 -0
- package/core/file/plugins/model_attributes/model.js +114 -0
- package/core/file/plugins/mp_user/config.js +19 -0
- package/core/file/plugins/mp_user/model.js +59 -0
- package/core/file/plugins/permission/config.js +15 -0
- package/core/file/plugins/permission/model.js +91 -0
- package/core/file/plugins/role/config.js +27 -0
- package/core/file/plugins/role/controller.js +26 -0
- package/core/file/plugins/role/model.js +58 -0
- package/core/file/plugins/role_permission/config.js +12 -0
- package/core/file/plugins/role_permission/controller.js +27 -0
- package/core/file/plugins/role_permission/model.js +24 -0
- package/core/file/plugins/routes/config.js +17 -0
- package/core/file/plugins/routes/controller.js +153 -0
- package/core/file/plugins/routes/model.js +70 -0
- package/core/file/plugins/routes/service.js +22 -0
- package/core/file/plugins/setting/afterExecute.js +14 -0
- package/core/file/plugins/setting/config.js +14 -0
- package/core/file/plugins/setting/controller.js +50 -0
- package/core/file/plugins/setting/model.js +118 -0
- package/core/file/plugins/setting/validate.js +42 -0
- package/core/file/plugins/system/controller.js +501 -0
- package/core/file/plugins/system/service.js +148 -0
- package/core/file/plugins/system/validate.js +40 -0
- package/core/file/plugins/todolist/config.js +31 -0
- package/core/file/plugins/todolist/model.js +69 -0
- package/core/file/plugins/toutiao/controller.js +201 -0
- package/core/file/plugins/toutiao_user/config.js +15 -0
- package/core/file/plugins/toutiao_user/model.js +66 -0
- package/core/file/plugins/user/afterExecute.js +38 -0
- package/core/file/plugins/user/config.js +9 -0
- package/core/file/plugins/user/controller.js +329 -0
- package/core/file/plugins/user/model.js +96 -0
- package/core/file/plugins/user/test.js +71 -0
- package/core/file/plugins/user/validate.js +44 -0
- package/core/file/plugins/video/config.js +3 -0
- package/core/file/plugins/video/controller.js +15 -0
- package/core/file/plugins/video/validate.js +12 -0
- package/core/file/plugins/weixin/config.js +3 -0
- package/core/file/plugins/weixin/controller.js +994 -0
- package/core/file/plugins/weixin/service.js +105 -0
- package/core/file/plugins/weixin/validate.js +111 -0
- package/core/file/services/aliSms.js +45 -0
- package/core/file/services/alipay.js +123 -0
- package/core/file/services/amap.js +95 -0
- package/core/file/services/card.js +24 -0
- package/core/file/services/config.js +38 -0
- package/core/file/services/douyin.js +151 -0
- package/core/file/services/email.js +45 -0
- package/core/file/services/express.js +37 -0
- package/core/file/services/geo.js +71 -0
- package/core/file/services/qqVideo.js +64 -0
- package/core/file/services/toutiao.js +102 -0
- package/core/file/services/weixin.js +79 -0
- package/core/file/services/weixinArticle.js +53 -0
- package/core/file/services/weixinCrypt.js +34 -0
- package/core/file/services/weixinMP.js +435 -0
- package/core/file/services/weixinPay.js +35 -0
- package/core/file/services/xml.js +33 -0
- package/core/file/task/shop/index.js +589 -0
- package/core/file/task/shop/static/562e45760a44632de6fa7219bab78cce.png +0 -0
- package/core/file/task/shop/static/d7aeaeb6bfd68f71a00a83c0f5548363.png +0 -0
- package/core/file/utils/index.js +61 -0
- package/core/middlewares.js +120 -0
- package/core/restc/.npminstall.done +1 -0
- package/core/restc/LICENSE +21 -0
- package/core/restc/README.md +48 -0
- package/core/restc/faas/index.html +1112 -0
- package/core/restc/faas/index.txt +31 -0
- package/core/restc/faas/install_production.sh +6 -0
- package/core/restc/index.d.ts +7 -0
- package/core/restc/index.js +9 -0
- package/core/restc/lib/express.js +7 -0
- package/core/restc/lib/hapi.js +17 -0
- package/core/restc/lib/hapiLegacy.js +15 -0
- package/core/restc/lib/index.js +46 -0
- package/core/restc/lib/koa.js +9 -0
- package/core/restc/lib/koa2.js +9 -0
- package/core/restc/lib/utils/gateway.js +51 -0
- package/core/restc/package.json +41 -0
- package/core/validator.js +15 -0
- package/index.js +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,994 @@
|
|
|
1
|
+
const { lodash, getAppByCtx, getConfig } = require('multiple-quick-koa')
|
|
2
|
+
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const axios = require('axios')
|
|
5
|
+
const OAuth = require('wechat-oauth')
|
|
6
|
+
const WXPay = require('weixin-pay')
|
|
7
|
+
const WeixinPay = require('../../services/weixinPay')
|
|
8
|
+
const WeixinMp = require('../../services/weixinMP')
|
|
9
|
+
const Weixin = require('../../services/weixin')
|
|
10
|
+
const { jsonToXml } = require('../../services/xml')
|
|
11
|
+
const WXBizDataCrypt = require('../../services/weixinCrypt')
|
|
12
|
+
const weixinArticle = require('../../services/weixinArticle')
|
|
13
|
+
const fxp = require('fast-xml-parser')
|
|
14
|
+
const crypto = require('crypto')
|
|
15
|
+
const OSS = require('ali-oss')
|
|
16
|
+
|
|
17
|
+
exports.getConfig = async (ctx) => {
|
|
18
|
+
const { app } = getAppByCtx(ctx)
|
|
19
|
+
|
|
20
|
+
const { url } = ctx.request.body
|
|
21
|
+
|
|
22
|
+
const appConfig = getConfig(app)
|
|
23
|
+
const { app_id, app_secrect } = await appConfig.getObject('weixin_h5')
|
|
24
|
+
const weixin = new Weixin({
|
|
25
|
+
appid: app_id,
|
|
26
|
+
secrect: app_secrect,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
weixin.init()
|
|
30
|
+
const result = await weixin.sign(url)
|
|
31
|
+
ctx.SUCCESS({
|
|
32
|
+
...result,
|
|
33
|
+
debugFlag: false,
|
|
34
|
+
appId: app_id,
|
|
35
|
+
jsApiList: [
|
|
36
|
+
'updateAppMessageShareData',
|
|
37
|
+
'updateTimelineShareData',
|
|
38
|
+
'getLocation',
|
|
39
|
+
'scanQRCode',
|
|
40
|
+
], // 必填,需要使用的JS接口列表
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.mp_getPhone = async (ctx) => {
|
|
45
|
+
const { app } = getAppByCtx(ctx)
|
|
46
|
+
|
|
47
|
+
const { code, iv, encryptedData, config = 'weixin_mp' } = ctx.request.body
|
|
48
|
+
|
|
49
|
+
const appConfig = getConfig(app)
|
|
50
|
+
const { app_id, app_secrect } = await appConfig.getObject(config)
|
|
51
|
+
|
|
52
|
+
const weixinLoginUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${app_id}&secret=${app_secrect}&js_code=${code}&grant_type=authorization_code`
|
|
53
|
+
|
|
54
|
+
const weixinResult = await axios.get(weixinLoginUrl).then((res) => res.data)
|
|
55
|
+
|
|
56
|
+
const { session_key, openid } = weixinResult
|
|
57
|
+
|
|
58
|
+
if (!openid) {
|
|
59
|
+
throw new Error('微信获取手机失败,请重试')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const pc = new WXBizDataCrypt(app_id, session_key)
|
|
63
|
+
|
|
64
|
+
const { phoneNumber } = pc.decryptData(encryptedData, iv)
|
|
65
|
+
|
|
66
|
+
const exist = await app.model.user.findOne({
|
|
67
|
+
where: {
|
|
68
|
+
mobile: phoneNumber,
|
|
69
|
+
},
|
|
70
|
+
include: [
|
|
71
|
+
{
|
|
72
|
+
model: app.model.mp_user,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const mobileExist =
|
|
78
|
+
exist &&
|
|
79
|
+
exist.mp_user &&
|
|
80
|
+
(!exist.mp_user.appid || exist.mp_user.appid === app_id)
|
|
81
|
+
|
|
82
|
+
if (mobileExist) {
|
|
83
|
+
throw new Error('系统已存在该手机号')
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const userResult = await app.model.mp_user.findOne({
|
|
87
|
+
where: {
|
|
88
|
+
openid,
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
if (!userResult || !userResult.user_id)
|
|
93
|
+
throw new Error('微信获取手机失败,请重试')
|
|
94
|
+
|
|
95
|
+
await app.model.user.upsert({
|
|
96
|
+
id: userResult.user_id,
|
|
97
|
+
mobile: phoneNumber,
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const result = await app.model.user.findOne({
|
|
101
|
+
where: {
|
|
102
|
+
id: userResult.user_id,
|
|
103
|
+
},
|
|
104
|
+
include: [
|
|
105
|
+
{
|
|
106
|
+
model: app.model.h5_user,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
model: app.model.mp_user,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
model: app.model.toutiao_user,
|
|
113
|
+
},
|
|
114
|
+
...app.include.user,
|
|
115
|
+
].filter((item) => item.model),
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
const tokenResult = {
|
|
119
|
+
id: result.id,
|
|
120
|
+
name: result.name,
|
|
121
|
+
mobile: result.mobile,
|
|
122
|
+
h5_user: result.h5_user
|
|
123
|
+
? {
|
|
124
|
+
openid: result.h5_user && result.h5_user.openid,
|
|
125
|
+
}
|
|
126
|
+
: null,
|
|
127
|
+
mp_user: result.mp_user
|
|
128
|
+
? {
|
|
129
|
+
openid: result.mp_user && result.mp_user.openid,
|
|
130
|
+
}
|
|
131
|
+
: null,
|
|
132
|
+
toutiao_user: result.toutiao_user
|
|
133
|
+
? {
|
|
134
|
+
openid: result.toutiao_user && result.toutiao_user.openid,
|
|
135
|
+
}
|
|
136
|
+
: null,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const token = await app.sign({
|
|
140
|
+
user: tokenResult,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
return ctx.SUCCESS({
|
|
144
|
+
token,
|
|
145
|
+
user: result,
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
exports.getPhone = async (ctx) => {
|
|
150
|
+
const { app } = getAppByCtx(ctx)
|
|
151
|
+
|
|
152
|
+
const { code, iv, encryptedData } = ctx.request.body
|
|
153
|
+
|
|
154
|
+
const appConfig = getConfig(app)
|
|
155
|
+
const { app_id, app_secrect } = await appConfig.getObject('weixin_mp')
|
|
156
|
+
|
|
157
|
+
const weixinLoginUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${app_id}&secret=${app_secrect}&js_code=${code}&grant_type=authorization_code`
|
|
158
|
+
|
|
159
|
+
const weixinResult = await axios.get(weixinLoginUrl).then((res) => res.data)
|
|
160
|
+
|
|
161
|
+
const { session_key, openid } = weixinResult
|
|
162
|
+
|
|
163
|
+
if (!openid) {
|
|
164
|
+
throw new Error('微信获取手机失败,请重试')
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const pc = new WXBizDataCrypt(app_id, session_key)
|
|
168
|
+
|
|
169
|
+
const { phoneNumber } = pc.decryptData(encryptedData, iv)
|
|
170
|
+
|
|
171
|
+
return ctx.SUCCESS({ phoneNumber })
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 微信小程序登录
|
|
176
|
+
*/
|
|
177
|
+
exports.mp_login = async (ctx) => {
|
|
178
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
179
|
+
const { code, config = 'weixin_mp', ...rest } = ctx.request.body
|
|
180
|
+
|
|
181
|
+
const appConfig = getConfig(app)
|
|
182
|
+
const { app_id, app_secrect } = await appConfig.getObject(config)
|
|
183
|
+
|
|
184
|
+
const weixinLoginUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${app_id}&secret=${app_secrect}&js_code=${code}&grant_type=authorization_code`
|
|
185
|
+
|
|
186
|
+
const res = await axios
|
|
187
|
+
.get(weixinLoginUrl)
|
|
188
|
+
.then((weixinRes) => weixinRes.data)
|
|
189
|
+
|
|
190
|
+
if (!res) throw new Error('微信登录失败')
|
|
191
|
+
const { openid, unionid } = res
|
|
192
|
+
if (!openid) {
|
|
193
|
+
const msg = `找不到openid, errcode:${res.errcode} app_id:${app_id} app_secrect:${app_secrect}`
|
|
194
|
+
|
|
195
|
+
throw new Error('微信登录失败')
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const post = lodash.pickBy(
|
|
199
|
+
{
|
|
200
|
+
nick_name: lodash.get(rest, 'nickName', null),
|
|
201
|
+
avatar: lodash.get(rest, 'avatarUrl', null),
|
|
202
|
+
openid,
|
|
203
|
+
unionid: lodash.get(res, 'unionid', null),
|
|
204
|
+
appid: app_id,
|
|
205
|
+
user_id: lodash.get(ctx.request, `${appName}-user.id`, null),
|
|
206
|
+
},
|
|
207
|
+
(item) => item !== null
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 查询是否已经有openid
|
|
212
|
+
*
|
|
213
|
+
* 如果已经有openid
|
|
214
|
+
* 更新这条记录
|
|
215
|
+
* 更新token并返回这条记录
|
|
216
|
+
*
|
|
217
|
+
* 如果没有openid
|
|
218
|
+
* 1.如果token里有uid
|
|
219
|
+
* 将uid作为user_id 添加一条微信记录
|
|
220
|
+
*
|
|
221
|
+
* 2.如果token里没有uid
|
|
222
|
+
* user新增一条匿名记录
|
|
223
|
+
* 获得新匿名记录的uid
|
|
224
|
+
* 将uid作为user_id 添加一条微信记录
|
|
225
|
+
*
|
|
226
|
+
* 更新token并返回这条匿名记录
|
|
227
|
+
*/
|
|
228
|
+
|
|
229
|
+
const openIdUser = await app.model.mp_user.findOne({
|
|
230
|
+
where: {
|
|
231
|
+
openid: post.openid,
|
|
232
|
+
},
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
let uid
|
|
236
|
+
if (openIdUser) {
|
|
237
|
+
await app.model.mp_user.update(post, {
|
|
238
|
+
where: {
|
|
239
|
+
openid: post.openid,
|
|
240
|
+
},
|
|
241
|
+
})
|
|
242
|
+
uid = openIdUser.user_id
|
|
243
|
+
} else {
|
|
244
|
+
if (post.user_id) {
|
|
245
|
+
uid = post.user_id
|
|
246
|
+
await app.model.mp_user.create({
|
|
247
|
+
...post,
|
|
248
|
+
user_id: uid,
|
|
249
|
+
})
|
|
250
|
+
} else {
|
|
251
|
+
try {
|
|
252
|
+
await app.sequelize.transaction(async (transaction) => {
|
|
253
|
+
const user = await app.model.user.create(
|
|
254
|
+
{},
|
|
255
|
+
{
|
|
256
|
+
transaction,
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
uid = user.id
|
|
260
|
+
await app.model.mp_user.create(
|
|
261
|
+
{
|
|
262
|
+
...post,
|
|
263
|
+
appid: app_id,
|
|
264
|
+
user_id: uid,
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
transaction,
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
})
|
|
271
|
+
} catch (e) {
|
|
272
|
+
console.log('mp_user.create出错了', { ...post })
|
|
273
|
+
throw new Error(e)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const result = await app.model.user.findOne({
|
|
279
|
+
where: {
|
|
280
|
+
id: uid,
|
|
281
|
+
},
|
|
282
|
+
include: [
|
|
283
|
+
{
|
|
284
|
+
model: app.model.h5_user,
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
model: app.model.mp_user,
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
model: app.model.toutiao_user,
|
|
291
|
+
},
|
|
292
|
+
...app.include.user,
|
|
293
|
+
].filter((item) => item.model),
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
if (!result.id) throw new Error('登录失败')
|
|
297
|
+
|
|
298
|
+
const tokenResult = {
|
|
299
|
+
id: result.id,
|
|
300
|
+
name: result.name,
|
|
301
|
+
mobile: result.mobile,
|
|
302
|
+
h5_user: result.h5_user
|
|
303
|
+
? {
|
|
304
|
+
openid: result.h5_user && result.h5_user.openid,
|
|
305
|
+
}
|
|
306
|
+
: null,
|
|
307
|
+
mp_user: result.mp_user
|
|
308
|
+
? {
|
|
309
|
+
openid: result.mp_user && result.mp_user.openid,
|
|
310
|
+
}
|
|
311
|
+
: null,
|
|
312
|
+
toutiao_user: result.toutiao_user
|
|
313
|
+
? {
|
|
314
|
+
openid: result.toutiao_user && result.toutiao_user.openid,
|
|
315
|
+
}
|
|
316
|
+
: null,
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const token = await app.sign({
|
|
320
|
+
user: tokenResult,
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
return ctx.SUCCESS({
|
|
324
|
+
token,
|
|
325
|
+
user: result,
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* 微信公众号H5登录
|
|
331
|
+
*/
|
|
332
|
+
exports.h5_login = async (ctx) => {
|
|
333
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
334
|
+
const { return_uri } = ctx.query
|
|
335
|
+
const scope = 'snsapi_userinfo'
|
|
336
|
+
// const scope = 'snsapi_base'
|
|
337
|
+
const h5_login_callback_url =
|
|
338
|
+
scope === 'snsapi_base' ? 'h5_login_callback' : 'h5_login_info_callback'
|
|
339
|
+
/**
|
|
340
|
+
* upyun要开启query
|
|
341
|
+
*/
|
|
342
|
+
const appConfig = getConfig(app)
|
|
343
|
+
const { app_id, host_link } = await appConfig.getObject('weixin_h5')
|
|
344
|
+
|
|
345
|
+
console.log(
|
|
346
|
+
'user_id========================',
|
|
347
|
+
lodash.get(ctx.request, `${appName}-user.id`, 0)
|
|
348
|
+
)
|
|
349
|
+
const redirect_uri = lodash.get(ctx.request, `${appName}-user.id`, 0)
|
|
350
|
+
? encodeURIComponent(
|
|
351
|
+
`${host_link}/${appName}/weixin/${h5_login_callback_url}?url=${encodeURIComponent(
|
|
352
|
+
return_uri
|
|
353
|
+
)}&user_id=${ctx.request[`${appName}-user`].id}`
|
|
354
|
+
)
|
|
355
|
+
: encodeURIComponent(
|
|
356
|
+
`${host_link}/${appName}/weixin/${h5_login_callback_url}?url=${encodeURIComponent(
|
|
357
|
+
return_uri
|
|
358
|
+
)}`
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${app_id}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}#wechat_redirect`
|
|
362
|
+
|
|
363
|
+
return ctx.redirect(url)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
exports.h5_login_callback = async (ctx) => {
|
|
367
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
368
|
+
const { code, url, user_id } = ctx.query
|
|
369
|
+
|
|
370
|
+
const appConfig = getConfig(app)
|
|
371
|
+
const { app_id, app_secrect } = await appConfig.getObject('weixin_h5')
|
|
372
|
+
|
|
373
|
+
const client = new OAuth(app_id, app_secrect)
|
|
374
|
+
|
|
375
|
+
const getAccessToken = (c) =>
|
|
376
|
+
new Promise((resolve, reject) => {
|
|
377
|
+
client.getAccessToken(c, (err, result) => {
|
|
378
|
+
if (err) {
|
|
379
|
+
console.log('err===', err)
|
|
380
|
+
return reject(err.data)
|
|
381
|
+
}
|
|
382
|
+
return resolve(result.data)
|
|
383
|
+
})
|
|
384
|
+
})
|
|
385
|
+
const data = await getAccessToken(`${code}`)
|
|
386
|
+
|
|
387
|
+
const post = lodash.pickBy(
|
|
388
|
+
{
|
|
389
|
+
nick_name: lodash.get(data, 'nickname', null),
|
|
390
|
+
avatar: lodash.get(data, 'headimgurl', null),
|
|
391
|
+
openid: data.openid,
|
|
392
|
+
appid: app_id,
|
|
393
|
+
user_id: user_id ? Number(user_id) : null,
|
|
394
|
+
},
|
|
395
|
+
(item) => item !== null
|
|
396
|
+
)
|
|
397
|
+
console.log('post', post)
|
|
398
|
+
/**
|
|
399
|
+
* 查询是否已经有openid
|
|
400
|
+
*
|
|
401
|
+
* 如果已经有openid
|
|
402
|
+
* 更新这条记录
|
|
403
|
+
* 更新token并返回这条记录
|
|
404
|
+
*
|
|
405
|
+
* 如果没有openid
|
|
406
|
+
* 1.如果token里有uid
|
|
407
|
+
* 将uid作为user_id 添加一条微信记录
|
|
408
|
+
*
|
|
409
|
+
* 2.如果token里没有uid
|
|
410
|
+
* user新增一条匿名记录
|
|
411
|
+
* 获得新匿名记录的uid
|
|
412
|
+
* 将uid作为user_id 添加一条微信记录
|
|
413
|
+
* 更新token并返回这条匿名记录
|
|
414
|
+
*/
|
|
415
|
+
|
|
416
|
+
const openIdUser = await app.model.h5_user.findOne({
|
|
417
|
+
where: {
|
|
418
|
+
openid: post.openid,
|
|
419
|
+
},
|
|
420
|
+
})
|
|
421
|
+
let uid
|
|
422
|
+
if (openIdUser) {
|
|
423
|
+
await app.model.h5_user.update(post, {
|
|
424
|
+
where: {
|
|
425
|
+
openid: post.openid,
|
|
426
|
+
},
|
|
427
|
+
})
|
|
428
|
+
uid = openIdUser.user_id
|
|
429
|
+
} else {
|
|
430
|
+
if (post.user_id) {
|
|
431
|
+
uid = post.user_id
|
|
432
|
+
} else {
|
|
433
|
+
// 新增空记录
|
|
434
|
+
const user = await app.model.user.create()
|
|
435
|
+
uid = user.id
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
await app.model.h5_user.create({
|
|
439
|
+
...post,
|
|
440
|
+
user_id: uid,
|
|
441
|
+
})
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const result = await app.model.user.findOne({
|
|
445
|
+
where: {
|
|
446
|
+
id: uid,
|
|
447
|
+
},
|
|
448
|
+
include: [
|
|
449
|
+
{
|
|
450
|
+
model: app.model.h5_user,
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
model: app.model.mp_user,
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
model: app.model.toutiao_user,
|
|
457
|
+
},
|
|
458
|
+
...app.include.user,
|
|
459
|
+
].filter((item) => item.model),
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
const tokenResult = {
|
|
463
|
+
id: result.id,
|
|
464
|
+
name: result.name,
|
|
465
|
+
mobile: result.mobile,
|
|
466
|
+
h5_user: result.h5_user
|
|
467
|
+
? {
|
|
468
|
+
openid: result.h5_user && result.h5_user.openid,
|
|
469
|
+
}
|
|
470
|
+
: null,
|
|
471
|
+
mp_user: result.mp_user
|
|
472
|
+
? {
|
|
473
|
+
openid: result.mp_user && result.mp_user.openid,
|
|
474
|
+
}
|
|
475
|
+
: null,
|
|
476
|
+
toutiao_user: result.toutiao_user
|
|
477
|
+
? {
|
|
478
|
+
openid: result.toutiao_user && result.toutiao_user.openid,
|
|
479
|
+
}
|
|
480
|
+
: null,
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const token = await app.sign({
|
|
484
|
+
user: tokenResult,
|
|
485
|
+
})
|
|
486
|
+
|
|
487
|
+
ctx.cookies.set(`${appName}-token`, token, {
|
|
488
|
+
httpOnly: false,
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
return ctx.redirect(url)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
exports.h5_login_info_callback = async (ctx) => {
|
|
495
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
496
|
+
const { code, url, user_id } = ctx.query
|
|
497
|
+
|
|
498
|
+
const appConfig = getConfig(app)
|
|
499
|
+
const { app_id, app_secrect } = await appConfig.getObject('weixin_h5')
|
|
500
|
+
|
|
501
|
+
const client = new OAuth(app_id, app_secrect)
|
|
502
|
+
|
|
503
|
+
const getUserByCode = (c) =>
|
|
504
|
+
new Promise((resolve, reject) => {
|
|
505
|
+
client.getUserByCode(c, (err, result) => {
|
|
506
|
+
if (err) {
|
|
507
|
+
console.log('err===', err)
|
|
508
|
+
return reject(err.data)
|
|
509
|
+
}
|
|
510
|
+
return resolve(result)
|
|
511
|
+
})
|
|
512
|
+
})
|
|
513
|
+
const data = await getUserByCode(`${code}`)
|
|
514
|
+
console.log('========', data)
|
|
515
|
+
|
|
516
|
+
const post = lodash.pickBy(
|
|
517
|
+
{
|
|
518
|
+
nick_name: lodash.get(data, 'nickname', null),
|
|
519
|
+
avatar: lodash.get(data, 'headimgurl', null),
|
|
520
|
+
openid: data.openid,
|
|
521
|
+
appid: app_id,
|
|
522
|
+
user_id: user_id ? Number(user_id) : null,
|
|
523
|
+
},
|
|
524
|
+
(item) => item !== null
|
|
525
|
+
)
|
|
526
|
+
console.log('post', post)
|
|
527
|
+
/**
|
|
528
|
+
* 查询是否已经有openid
|
|
529
|
+
*
|
|
530
|
+
* 如果已经有openid
|
|
531
|
+
* 更新这条记录
|
|
532
|
+
* 更新token并返回这条记录
|
|
533
|
+
*
|
|
534
|
+
* 如果没有openid
|
|
535
|
+
* 1.如果token里有uid
|
|
536
|
+
* 将uid作为user_id 添加一条微信记录
|
|
537
|
+
*
|
|
538
|
+
* 2.如果token里没有uid
|
|
539
|
+
* user新增一条匿名记录
|
|
540
|
+
* 获得新匿名记录的uid
|
|
541
|
+
* 将uid作为user_id 添加一条微信记录
|
|
542
|
+
* 更新token并返回这条匿名记录
|
|
543
|
+
*/
|
|
544
|
+
|
|
545
|
+
const openIdUser = await app.model.h5_user.findOne({
|
|
546
|
+
where: {
|
|
547
|
+
openid: post.openid,
|
|
548
|
+
},
|
|
549
|
+
})
|
|
550
|
+
let uid
|
|
551
|
+
if (openIdUser) {
|
|
552
|
+
await app.model.h5_user.update(post, {
|
|
553
|
+
where: {
|
|
554
|
+
openid: post.openid,
|
|
555
|
+
},
|
|
556
|
+
})
|
|
557
|
+
uid = openIdUser.user_id
|
|
558
|
+
} else {
|
|
559
|
+
if (post.user_id) {
|
|
560
|
+
uid = post.user_id
|
|
561
|
+
} else {
|
|
562
|
+
// 新增空记录
|
|
563
|
+
const user = await app.model.user.create({
|
|
564
|
+
nick_name: post.nick_name,
|
|
565
|
+
avatar: post.avatar,
|
|
566
|
+
})
|
|
567
|
+
uid = user.id
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
await app.model.h5_user.create({
|
|
571
|
+
...post,
|
|
572
|
+
user_id: uid,
|
|
573
|
+
})
|
|
574
|
+
}
|
|
575
|
+
const result = await app.model.user.findOne({
|
|
576
|
+
where: {
|
|
577
|
+
id: uid,
|
|
578
|
+
},
|
|
579
|
+
include: [
|
|
580
|
+
{
|
|
581
|
+
model: app.model.h5_user,
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
model: app.model.mp_user,
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
model: app.model.toutiao_user,
|
|
588
|
+
},
|
|
589
|
+
...app.include.user,
|
|
590
|
+
].filter((item) => item.model),
|
|
591
|
+
})
|
|
592
|
+
|
|
593
|
+
const tokenResult = {
|
|
594
|
+
id: result.id,
|
|
595
|
+
name: result.name,
|
|
596
|
+
mobile: result.mobile,
|
|
597
|
+
h5_user: result.h5_user
|
|
598
|
+
? {
|
|
599
|
+
openid: result.h5_user && result.h5_user.openid,
|
|
600
|
+
}
|
|
601
|
+
: null,
|
|
602
|
+
mp_user: result.mp_user
|
|
603
|
+
? {
|
|
604
|
+
openid: result.mp_user && result.mp_user.openid,
|
|
605
|
+
}
|
|
606
|
+
: null,
|
|
607
|
+
toutiao_user: result.toutiao_user
|
|
608
|
+
? {
|
|
609
|
+
openid: result.toutiao_user && result.toutiao_user.openid,
|
|
610
|
+
}
|
|
611
|
+
: null,
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
const token = await app.sign({
|
|
615
|
+
user: tokenResult,
|
|
616
|
+
})
|
|
617
|
+
|
|
618
|
+
ctx.cookies.set(`${appName}-token`, token, {
|
|
619
|
+
httpOnly: false,
|
|
620
|
+
})
|
|
621
|
+
|
|
622
|
+
return ctx.redirect(url)
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
exports.h5_pay = async (ctx) => {
|
|
626
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
627
|
+
const {
|
|
628
|
+
name,
|
|
629
|
+
order_id,
|
|
630
|
+
price,
|
|
631
|
+
return_url,
|
|
632
|
+
type,
|
|
633
|
+
is_admin = false,
|
|
634
|
+
} = ctx.request.body
|
|
635
|
+
|
|
636
|
+
const appConfig = getConfig(app)
|
|
637
|
+
const { appId, key, mchId } = await appConfig.getObject('weixin_pay')
|
|
638
|
+
const { is_dev, site_host } = await appConfig.getObject('base')
|
|
639
|
+
|
|
640
|
+
const payObj = new WeixinPay({
|
|
641
|
+
appId,
|
|
642
|
+
key,
|
|
643
|
+
mchId,
|
|
644
|
+
})
|
|
645
|
+
const result = await payObj.run({
|
|
646
|
+
body: name,
|
|
647
|
+
out_trade_no: `${appName}_${order_id}_${type}`,
|
|
648
|
+
total_fee: is_admin || is_dev ? 1 : Math.round(price * 100),
|
|
649
|
+
notify_url: `https://${
|
|
650
|
+
site_host || 'api.kuashou.com'
|
|
651
|
+
}/${appName}/weixin/notify`,
|
|
652
|
+
scene_info: `{"h5_info": {"type":"Wap","wap_url": ${
|
|
653
|
+
site_host || 'https://api.kuashou.com'
|
|
654
|
+
},"wap_name": "腾讯充值"}}`,
|
|
655
|
+
})
|
|
656
|
+
if (result.result_code === 'FAIL') throw new Error(result.err_code_des)
|
|
657
|
+
|
|
658
|
+
ctx.SUCCESS(
|
|
659
|
+
return_url
|
|
660
|
+
? `${result.mweb_url}&redirect_url=${encodeURIComponent(return_url)}`
|
|
661
|
+
: result.mweb_url
|
|
662
|
+
)
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
exports.mp_pay = async (ctx) => {
|
|
666
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
667
|
+
const {
|
|
668
|
+
name,
|
|
669
|
+
order_id,
|
|
670
|
+
price,
|
|
671
|
+
return_url,
|
|
672
|
+
prefix = '',
|
|
673
|
+
type,
|
|
674
|
+
out_trade_no,
|
|
675
|
+
is_admin = false,
|
|
676
|
+
config = 'weixin_mp',
|
|
677
|
+
} = ctx.request.body
|
|
678
|
+
|
|
679
|
+
if (price === 0) throw new Error('价格不能为0')
|
|
680
|
+
|
|
681
|
+
if (type === 'H5-WEIXIN') {
|
|
682
|
+
if (
|
|
683
|
+
!ctx.request[`${appName}-user`] ||
|
|
684
|
+
!ctx.request[`${appName}-user`].h5_user
|
|
685
|
+
) {
|
|
686
|
+
throw new Error('请先微信登录')
|
|
687
|
+
}
|
|
688
|
+
} else if (
|
|
689
|
+
!ctx.request[`${appName}-user`] ||
|
|
690
|
+
!ctx.request[`${appName}-user`].mp_user
|
|
691
|
+
) {
|
|
692
|
+
throw new Error('请先小程序登录')
|
|
693
|
+
}
|
|
694
|
+
const appConfig = getConfig(app)
|
|
695
|
+
|
|
696
|
+
const { mchId, key } = await appConfig.getObject('weixin_pay')
|
|
697
|
+
const { is_dev, site_host } = await appConfig.getObject('base')
|
|
698
|
+
// 公众号支付用 服务号 appid,其他用小程序 appid
|
|
699
|
+
const app_id =
|
|
700
|
+
type === 'H5-WEIXIN'
|
|
701
|
+
? (await appConfig.getObject('weixin_h5')).app_id
|
|
702
|
+
: (await appConfig.getObject(config)).app_id
|
|
703
|
+
|
|
704
|
+
const wxpay = WXPay({
|
|
705
|
+
appid: app_id,
|
|
706
|
+
mch_id: mchId,
|
|
707
|
+
partner_key: key, // 微信商户平台API密钥
|
|
708
|
+
})
|
|
709
|
+
|
|
710
|
+
const pay = (options) =>
|
|
711
|
+
new Promise((resolve, reject) => {
|
|
712
|
+
wxpay.getBrandWCPayRequestParams(options, (err, result) => {
|
|
713
|
+
if (err) return reject(err)
|
|
714
|
+
return resolve(result)
|
|
715
|
+
})
|
|
716
|
+
})
|
|
717
|
+
|
|
718
|
+
const userDetail =
|
|
719
|
+
type === 'H5-WEIXIN'
|
|
720
|
+
? ctx.request[`${appName}-user`].h5_user
|
|
721
|
+
: ctx.request[`${appName}-user`].mp_user
|
|
722
|
+
const {
|
|
723
|
+
appId: appid,
|
|
724
|
+
nonceStr: nonce_str,
|
|
725
|
+
package: prepay_id,
|
|
726
|
+
paySign: sign,
|
|
727
|
+
signType,
|
|
728
|
+
timeStamp,
|
|
729
|
+
} = await pay({
|
|
730
|
+
openid: userDetail.openid,
|
|
731
|
+
body: name,
|
|
732
|
+
detail: '公众号支付测试',
|
|
733
|
+
out_trade_no: out_trade_no
|
|
734
|
+
? out_trade_no
|
|
735
|
+
: prefix
|
|
736
|
+
? `${appName}_${prefix}-${order_id}_${type}`
|
|
737
|
+
: `${appName}_${order_id}_${type}`,
|
|
738
|
+
total_fee: is_admin || is_dev ? 1 : Math.round(price * 100),
|
|
739
|
+
spbill_create_ip: '192.168.2.210',
|
|
740
|
+
notify_url: `http://${
|
|
741
|
+
site_host || 'api.kuashou.com'
|
|
742
|
+
}/${appName}/weixin/notify`,
|
|
743
|
+
})
|
|
744
|
+
|
|
745
|
+
if (prepay_id.includes('undefined')) {
|
|
746
|
+
const model = type === 'H5-WEIXIN' ? 'h5_user' : 'mp_user'
|
|
747
|
+
const userTarget = await app.model[model].findOne({
|
|
748
|
+
where: {
|
|
749
|
+
openid: userDetail.openid,
|
|
750
|
+
},
|
|
751
|
+
})
|
|
752
|
+
if (app_id !== userTarget.appid)
|
|
753
|
+
throw new Error(
|
|
754
|
+
`appid不符,用户appid${userTarget.appid},付款appid${app_id}`
|
|
755
|
+
)
|
|
756
|
+
throw new Error(`支付失败,请重试`)
|
|
757
|
+
}
|
|
758
|
+
return ctx.SUCCESS({
|
|
759
|
+
debug: false,
|
|
760
|
+
appid,
|
|
761
|
+
timeStamp,
|
|
762
|
+
nonce_str,
|
|
763
|
+
prepay_id,
|
|
764
|
+
sign,
|
|
765
|
+
signType,
|
|
766
|
+
jsApiList: ['chooseWXPay'],
|
|
767
|
+
return_url,
|
|
768
|
+
})
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
exports.notify = async (ctx) => {
|
|
772
|
+
const { app } = getAppByCtx(ctx)
|
|
773
|
+
const result = ctx.request.xmlBody
|
|
774
|
+
let prefix = ''
|
|
775
|
+
let order_id = result.xml.out_trade_no.split('_')[1]
|
|
776
|
+
const order_price = Number(result.xml.total_fee) / 100
|
|
777
|
+
if (order_id.includes('-')) {
|
|
778
|
+
const arr = order_id.split('-')
|
|
779
|
+
order_id = Number(arr[1])
|
|
780
|
+
;[prefix] = arr
|
|
781
|
+
} else {
|
|
782
|
+
order_id = Number(order_id)
|
|
783
|
+
}
|
|
784
|
+
const model = prefix ? `${prefix}_order` : 'order'
|
|
785
|
+
let transactionid = ''
|
|
786
|
+
try {
|
|
787
|
+
transactionid = result.xml.transaction_id
|
|
788
|
+
} catch (e) {}
|
|
789
|
+
|
|
790
|
+
console.log(order_id, '微信支付回调-----', model, order_price, transactionid)
|
|
791
|
+
if (app.service[model] && app.service[model].notify) {
|
|
792
|
+
await app.service[model].notify({
|
|
793
|
+
app,
|
|
794
|
+
order_id,
|
|
795
|
+
order: model,
|
|
796
|
+
order_price,
|
|
797
|
+
transactionid,
|
|
798
|
+
})
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
ctx.status = 200
|
|
802
|
+
ctx.res.setHeader('Content-Type', 'application/xml')
|
|
803
|
+
const returnResult = jsonToXml({
|
|
804
|
+
xml: {
|
|
805
|
+
return_code: 'SUCCESS',
|
|
806
|
+
},
|
|
807
|
+
})
|
|
808
|
+
ctx.res.end(returnResult)
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
exports.qr_code = async (ctx) => {
|
|
812
|
+
const { app } = getAppByCtx(ctx)
|
|
813
|
+
|
|
814
|
+
const { page, is_hyaline, scene, is_oss = false } = ctx.request.body
|
|
815
|
+
|
|
816
|
+
// if (!lodash.get(ctx.request, `${appName}-user.id`, null)) throw new Error('没有登录')
|
|
817
|
+
|
|
818
|
+
const appConfig = getConfig(app)
|
|
819
|
+
const { app_id, app_secrect } = await appConfig.getObject('weixin_mp')
|
|
820
|
+
|
|
821
|
+
const { site_host } = await appConfig.getObject('base')
|
|
822
|
+
const weixinMp = new WeixinMp({
|
|
823
|
+
appid: app_id,
|
|
824
|
+
secrect: app_secrect,
|
|
825
|
+
targetPath: `${path.resolve(__dirname, `${process.cwd()}/public/upload`)}`,
|
|
826
|
+
})
|
|
827
|
+
weixinMp.init()
|
|
828
|
+
if (!is_oss) {
|
|
829
|
+
const result = await weixinMp.createQR({
|
|
830
|
+
page,
|
|
831
|
+
is_hyaline,
|
|
832
|
+
scene,
|
|
833
|
+
})
|
|
834
|
+
const qr_image = `https://${
|
|
835
|
+
site_host || 'api.kuashou.com'
|
|
836
|
+
}/upload/${result}`
|
|
837
|
+
|
|
838
|
+
ctx.SUCCESS(qr_image)
|
|
839
|
+
} else {
|
|
840
|
+
const {
|
|
841
|
+
accessKeyId,
|
|
842
|
+
accessKeySecret,
|
|
843
|
+
bucket,
|
|
844
|
+
region,
|
|
845
|
+
} = await appConfig.getObject('oss')
|
|
846
|
+
if (!(accessKeyId && accessKeySecret && bucket && region)) {
|
|
847
|
+
throw new Error('没有配置oss设置')
|
|
848
|
+
}
|
|
849
|
+
const buffer = await weixinMp.createQRBuffer({
|
|
850
|
+
page,
|
|
851
|
+
is_hyaline,
|
|
852
|
+
scene,
|
|
853
|
+
})
|
|
854
|
+
const client = new OSS({
|
|
855
|
+
accessKeyId,
|
|
856
|
+
accessKeySecret,
|
|
857
|
+
bucket,
|
|
858
|
+
region,
|
|
859
|
+
secure: true,
|
|
860
|
+
})
|
|
861
|
+
const fileName = `${
|
|
862
|
+
String(new Date().getTime()).split('').reverse().join('') + Math.random()
|
|
863
|
+
}.png`
|
|
864
|
+
const result = await client.put(fileName, buffer)
|
|
865
|
+
if (result.res && result.res.status === 200) {
|
|
866
|
+
const url = result.url
|
|
867
|
+
return ctx.SUCCESS(url)
|
|
868
|
+
} else {
|
|
869
|
+
throw new Error(result.res.statusMessage)
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
exports.sendMessage = async (ctx) => {
|
|
875
|
+
const { app } = getAppByCtx(ctx)
|
|
876
|
+
|
|
877
|
+
const { openid, template_id, data, page } = ctx.request.body
|
|
878
|
+
|
|
879
|
+
const appConfig = getConfig(app)
|
|
880
|
+
const { app_id, app_secrect } = await appConfig.getObject('weixin_mp')
|
|
881
|
+
|
|
882
|
+
const weixinMp = new WeixinMp({
|
|
883
|
+
appid: app_id,
|
|
884
|
+
secrect: app_secrect,
|
|
885
|
+
})
|
|
886
|
+
weixinMp.init()
|
|
887
|
+
await weixinMp.sendMessage({
|
|
888
|
+
touser: openid,
|
|
889
|
+
template_id,
|
|
890
|
+
miniprogram_state: 'developer',
|
|
891
|
+
data,
|
|
892
|
+
page,
|
|
893
|
+
})
|
|
894
|
+
|
|
895
|
+
ctx.SUCCESS('发送成功')
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
exports.refund = async (ctx) => {
|
|
899
|
+
const { app, appName } = getAppByCtx(ctx)
|
|
900
|
+
const appConfig = getConfig(app)
|
|
901
|
+
const { id, prefix = '', price } = ctx.request.body
|
|
902
|
+
|
|
903
|
+
await app.service.weixin.refund({
|
|
904
|
+
ctx,
|
|
905
|
+
id,
|
|
906
|
+
prefix: '',
|
|
907
|
+
price,
|
|
908
|
+
})
|
|
909
|
+
ctx.SUCCESS('ok')
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
const decryption = function (data, key, iv) {
|
|
913
|
+
if (!data) {
|
|
914
|
+
return ''
|
|
915
|
+
}
|
|
916
|
+
iv = iv || ''
|
|
917
|
+
var clearEncoding = 'utf8'
|
|
918
|
+
var cipherEncoding = 'base64'
|
|
919
|
+
var cipherChunks = []
|
|
920
|
+
var decipher = crypto.createDecipheriv('aes-256-ecb', key, iv)
|
|
921
|
+
decipher.setAutoPadding(true)
|
|
922
|
+
cipherChunks.push(decipher.update(data, cipherEncoding, clearEncoding))
|
|
923
|
+
cipherChunks.push(decipher.final(clearEncoding))
|
|
924
|
+
return cipherChunks.join('')
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
const getRefundResultJson = async ({ req_info, app_key }) => {
|
|
928
|
+
const result = Buffer.from(req_info, 'base64')
|
|
929
|
+
|
|
930
|
+
const key = await crypto.createHash('md5').update(app_key).digest('hex')
|
|
931
|
+
const iv = Buffer.alloc(0) // 设置偏移量
|
|
932
|
+
let decxml = decryption(result, key, iv)
|
|
933
|
+
const reg = new RegExp('root>', 'g')
|
|
934
|
+
decxml = decxml.replace(reg, 'xml>') // 转化为xml格式
|
|
935
|
+
const xml2json = fxp.parse(decxml) // xml转对象
|
|
936
|
+
return xml2json.xml
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
exports.refund_notify = async (ctx) => {
|
|
940
|
+
const { app } = getAppByCtx(ctx)
|
|
941
|
+
const result = ctx.request.xmlBody
|
|
942
|
+
|
|
943
|
+
const appConfig = getConfig(app)
|
|
944
|
+
const { key } = await appConfig.getObject('weixin_pay')
|
|
945
|
+
|
|
946
|
+
const { req_info } = result.xml
|
|
947
|
+
const refundResult = await getRefundResultJson({
|
|
948
|
+
req_info,
|
|
949
|
+
app_key: key,
|
|
950
|
+
})
|
|
951
|
+
|
|
952
|
+
const { out_refund_no, out_trade_no, total_fee, refund_fee } = refundResult
|
|
953
|
+
|
|
954
|
+
const refund_price = Number(refund_fee) / 100
|
|
955
|
+
|
|
956
|
+
const prefix =
|
|
957
|
+
out_trade_no.split('_').length === 4 ? out_trade_no.split('_')[1] : ''
|
|
958
|
+
|
|
959
|
+
const order_id = Number(out_refund_no)
|
|
960
|
+
const model = prefix ? `${prefix}_order` : 'order'
|
|
961
|
+
console.log(out_refund_no, '微信支付回调-----', model)
|
|
962
|
+
if (app.service[model] && app.service[model].refund_notify) {
|
|
963
|
+
await app.service[model].refund_notify({
|
|
964
|
+
app,
|
|
965
|
+
order_id,
|
|
966
|
+
order: model,
|
|
967
|
+
refund_price,
|
|
968
|
+
})
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
ctx.status = 200
|
|
972
|
+
ctx.res.setHeader('Content-Type', 'application/xml')
|
|
973
|
+
const returnResult = jsonToXml({
|
|
974
|
+
xml: {
|
|
975
|
+
return_code: 'SUCCESS',
|
|
976
|
+
},
|
|
977
|
+
})
|
|
978
|
+
ctx.res.end(returnResult)
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
exports.article = async (ctx) => {
|
|
982
|
+
const { app } = getAppByCtx(ctx)
|
|
983
|
+
|
|
984
|
+
const { url } = ctx.request.body
|
|
985
|
+
|
|
986
|
+
if (!url) throw new Error('没有url')
|
|
987
|
+
if (!url.includes('//mp.weixin.qq.com/s')) throw new Error('非法url')
|
|
988
|
+
|
|
989
|
+
const content = await axios.get(url).then((res) => res.data)
|
|
990
|
+
|
|
991
|
+
const result = await weixinArticle.handleHtml(content)
|
|
992
|
+
|
|
993
|
+
return ctx.SUCCESS(result)
|
|
994
|
+
}
|