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,435 @@
|
|
|
1
|
+
const util = require('util')
|
|
2
|
+
const axios = require('axios')
|
|
3
|
+
|
|
4
|
+
const { lodash } = require('multiple-quick-koa')
|
|
5
|
+
const getAccessTokenUrl =
|
|
6
|
+
'https://api.weixin.qq.com/cgi-bin/token?grant_type=%s&appid=%s&secret=%s'
|
|
7
|
+
const createQRCodeUrl =
|
|
8
|
+
'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s'
|
|
9
|
+
const sendMessageUrl =
|
|
10
|
+
'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=%s'
|
|
11
|
+
const handleMessageUrl =
|
|
12
|
+
'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s'
|
|
13
|
+
const uploadFile =
|
|
14
|
+
'https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s'
|
|
15
|
+
const serviceMarketUrl =
|
|
16
|
+
'https://api.weixin.qq.com/wxa/servicemarket?access_token=%s&type=%s'
|
|
17
|
+
const createLiveUrl =
|
|
18
|
+
'https://api.weixin.qq.com/wxaapi/broadcast/room/create?access_token=%s'
|
|
19
|
+
const getLiveUrl =
|
|
20
|
+
'https://api.weixin.qq.com/wxa/business/getliveinfo?access_token=%s'
|
|
21
|
+
const addSubanchorUrl =
|
|
22
|
+
'https://api.weixin.qq.com/wxaapi/broadcast/room/addsubanchor?access_token=%s'
|
|
23
|
+
|
|
24
|
+
const addRoleUrl =
|
|
25
|
+
'https://api.weixin.qq.com/wxaapi/broadcast/addRole?access_token=%s'
|
|
26
|
+
|
|
27
|
+
const getExpressUrl =
|
|
28
|
+
'https://api.weixin.qq.com/cgi-bin/express/business/delivery/getall?access_token=%s'
|
|
29
|
+
const addOrderUrl =
|
|
30
|
+
'https://api.weixin.qq.com/cgi-bin/express/business/order/add?access_token=%s'
|
|
31
|
+
|
|
32
|
+
const path = require('path')
|
|
33
|
+
const fs = require('fs')
|
|
34
|
+
const LRU = require('lru-cache')
|
|
35
|
+
const request = require('request')
|
|
36
|
+
const cache = new LRU({
|
|
37
|
+
max: 100,
|
|
38
|
+
maxAge: 1000 * 60 * 60,
|
|
39
|
+
})
|
|
40
|
+
const uuid = require('node-uuid')
|
|
41
|
+
|
|
42
|
+
const uploadPromise = (options) => {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
request.post(
|
|
45
|
+
{
|
|
46
|
+
...options,
|
|
47
|
+
},
|
|
48
|
+
(err, response, body) => {
|
|
49
|
+
if (err || response.statusCode !== 200) {
|
|
50
|
+
reject(err)
|
|
51
|
+
}
|
|
52
|
+
resolve(JSON.parse(body))
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = class Singleton {
|
|
59
|
+
constructor(config) {
|
|
60
|
+
this.config = {
|
|
61
|
+
...config,
|
|
62
|
+
grant_type: 'client_credential',
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 单例模式
|
|
66
|
+
*/
|
|
67
|
+
if (!Singleton.instance) {
|
|
68
|
+
Singleton.instance = this
|
|
69
|
+
}
|
|
70
|
+
const previous = Singleton.instance.getConfig()
|
|
71
|
+
if (!lodash.isEqual(previous, config)) {
|
|
72
|
+
Singleton.instance = this
|
|
73
|
+
}
|
|
74
|
+
return Singleton.instance
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
init() {
|
|
78
|
+
if (!this.config.appid || !this.config.secrect) {
|
|
79
|
+
throw new Error('没有配置appid或secrect')
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async getAccessToken() {
|
|
84
|
+
const { appid, secrect, grant_type } = this.config
|
|
85
|
+
if (cache.get(appid)) {
|
|
86
|
+
return cache.get(appid)
|
|
87
|
+
}
|
|
88
|
+
const url = util.format(getAccessTokenUrl, grant_type, appid, secrect)
|
|
89
|
+
const { access_token } = await axios.get(url).then((res) => res.data)
|
|
90
|
+
cache.set(appid, access_token)
|
|
91
|
+
return access_token
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async getExpress() {
|
|
95
|
+
const access_token = await this.getAccessToken()
|
|
96
|
+
const url = util.format(getExpressUrl, access_token)
|
|
97
|
+
const result = await axios.post(url).then((res) => res.data)
|
|
98
|
+
if (result.errcode) {
|
|
99
|
+
if (result.errcode === 40001) {
|
|
100
|
+
cache.reset()
|
|
101
|
+
return await this.getExpress()
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
104
|
+
}
|
|
105
|
+
return result
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async addOrder({
|
|
109
|
+
add_source = 0,
|
|
110
|
+
order_id,
|
|
111
|
+
openid = '',
|
|
112
|
+
delivery_id = '',
|
|
113
|
+
biz_id = '',
|
|
114
|
+
sender,
|
|
115
|
+
receiver,
|
|
116
|
+
cargo,
|
|
117
|
+
shop,
|
|
118
|
+
insured,
|
|
119
|
+
service,
|
|
120
|
+
}) {
|
|
121
|
+
const access_token = await this.getAccessToken()
|
|
122
|
+
const url = util.format(addOrderUrl, access_token)
|
|
123
|
+
|
|
124
|
+
const formatOptions = {
|
|
125
|
+
order_id,
|
|
126
|
+
openid,
|
|
127
|
+
delivery_id,
|
|
128
|
+
biz_id,
|
|
129
|
+
sender,
|
|
130
|
+
receiver,
|
|
131
|
+
cargo,
|
|
132
|
+
shop,
|
|
133
|
+
insured,
|
|
134
|
+
service,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const result = await axios.post(url, formatOptions).then((res) => res.data)
|
|
138
|
+
if (result.errcode) {
|
|
139
|
+
if (result.errcode === 40001) {
|
|
140
|
+
cache.reset()
|
|
141
|
+
return await this.addOrder({
|
|
142
|
+
add_source,
|
|
143
|
+
order_id,
|
|
144
|
+
openid,
|
|
145
|
+
delivery_id,
|
|
146
|
+
biz_id,
|
|
147
|
+
sender,
|
|
148
|
+
receiver,
|
|
149
|
+
cargo,
|
|
150
|
+
shop,
|
|
151
|
+
insured,
|
|
152
|
+
service,
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
156
|
+
}
|
|
157
|
+
return result
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async addSubanchor({ roomId, username }) {
|
|
161
|
+
const access_token = await this.getAccessToken()
|
|
162
|
+
const url = util.format(addSubanchorUrl, access_token)
|
|
163
|
+
|
|
164
|
+
const formatOptions = {
|
|
165
|
+
roomId,
|
|
166
|
+
username,
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const result = await axios.post(url, formatOptions).then((res) => res.data)
|
|
170
|
+
if (result.errcode) {
|
|
171
|
+
if (result.errcode === 40001) {
|
|
172
|
+
cache.reset()
|
|
173
|
+
return await this.addSubanchor({
|
|
174
|
+
roomId,
|
|
175
|
+
username,
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
179
|
+
}
|
|
180
|
+
return result
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async addRole({ username, role = 2 }) {
|
|
184
|
+
const access_token = await this.getAccessToken()
|
|
185
|
+
const url = util.format(addRoleUrl, access_token)
|
|
186
|
+
|
|
187
|
+
const formatOptions = {
|
|
188
|
+
username,
|
|
189
|
+
role,
|
|
190
|
+
}
|
|
191
|
+
const result = await axios.post(url, formatOptions).then((res) => res.data)
|
|
192
|
+
if (result.errcode) {
|
|
193
|
+
if (result.errcode === 40001) {
|
|
194
|
+
cache.reset()
|
|
195
|
+
return await this.addRole({
|
|
196
|
+
username,
|
|
197
|
+
role,
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
201
|
+
}
|
|
202
|
+
return result
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async createLive({
|
|
206
|
+
name,
|
|
207
|
+
createrWechat,
|
|
208
|
+
coverImg,
|
|
209
|
+
startTime,
|
|
210
|
+
endTime,
|
|
211
|
+
shareImg,
|
|
212
|
+
feedsImg,
|
|
213
|
+
subAnchorWechat = '',
|
|
214
|
+
anchorWechat = '',
|
|
215
|
+
anchorName = '',
|
|
216
|
+
closeReplay = 1,
|
|
217
|
+
}) {
|
|
218
|
+
const access_token = await this.getAccessToken()
|
|
219
|
+
const url = util.format(createLiveUrl, access_token)
|
|
220
|
+
|
|
221
|
+
const formatOptions = {
|
|
222
|
+
name, // 房间名字
|
|
223
|
+
coverImg, // 通过 uploadfile 上传,填写 mediaID
|
|
224
|
+
startTime, // 开始时间
|
|
225
|
+
endTime, // 结束时间
|
|
226
|
+
anchorName, // 主播昵称
|
|
227
|
+
anchorWechat, // 主播微信号
|
|
228
|
+
subAnchorWechat, // 主播副号微信号
|
|
229
|
+
createrWechat, // 创建者微信号
|
|
230
|
+
shareImg, // 通过 uploadfile 上传,填写 mediaID
|
|
231
|
+
feedsImg, // 通过 uploadfile 上传,填写 mediaID
|
|
232
|
+
isFeedsPublic: 0, // 是否开启官方收录,1 开启,0 关闭
|
|
233
|
+
type: 0, // 直播类型,1 推流 0 手机直播
|
|
234
|
+
closeLike: 0, // 是否关闭点赞 1:关闭
|
|
235
|
+
closeGoods: 1, // 是否关闭商品货架,1:关闭
|
|
236
|
+
closeComment: 1, // 是否开启评论,1:关闭
|
|
237
|
+
closeReplay, // 是否关闭回放 1 关闭
|
|
238
|
+
closeShare: 1, // 是否关闭分享 1 关闭
|
|
239
|
+
closeKf: 1, // 是否关闭客服,1 关闭
|
|
240
|
+
}
|
|
241
|
+
const result = await axios.post(url, formatOptions).then((res) => res.data)
|
|
242
|
+
if (result.errcode) {
|
|
243
|
+
if (result.errcode === 40001) {
|
|
244
|
+
cache.reset()
|
|
245
|
+
return await this.createLive({
|
|
246
|
+
name,
|
|
247
|
+
createrWechat,
|
|
248
|
+
coverImg,
|
|
249
|
+
startTime,
|
|
250
|
+
endTime,
|
|
251
|
+
shareImg,
|
|
252
|
+
feedsImg,
|
|
253
|
+
subAnchorWechat,
|
|
254
|
+
anchorWechat,
|
|
255
|
+
anchorName,
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
259
|
+
}
|
|
260
|
+
return result
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async getLive(start = 0, limit = 10) {
|
|
264
|
+
const access_token = await this.getAccessToken()
|
|
265
|
+
const url = util.format(getLiveUrl, access_token)
|
|
266
|
+
|
|
267
|
+
const formatOptions = {
|
|
268
|
+
start,
|
|
269
|
+
limit,
|
|
270
|
+
}
|
|
271
|
+
const result = await axios.post(url, formatOptions).then((res) => res.data)
|
|
272
|
+
if (result.errcode) {
|
|
273
|
+
if (result.errcode === 40001) {
|
|
274
|
+
cache.reset()
|
|
275
|
+
return await this.getLive({
|
|
276
|
+
start,
|
|
277
|
+
limit,
|
|
278
|
+
})
|
|
279
|
+
}
|
|
280
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
281
|
+
}
|
|
282
|
+
return result.room_info
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async createQR(options) {
|
|
286
|
+
if (!this.config.targetPath) throw new Error('没有配置文件夹')
|
|
287
|
+
const access_token = await this.getAccessToken()
|
|
288
|
+
const url = util.format(createQRCodeUrl, access_token)
|
|
289
|
+
const payLoad = {
|
|
290
|
+
...options,
|
|
291
|
+
scene: options.scene
|
|
292
|
+
? Object.keys(options.scene)
|
|
293
|
+
.map((item) => `${item}=${options.scene[item]}`)
|
|
294
|
+
.join('&')
|
|
295
|
+
: '',
|
|
296
|
+
}
|
|
297
|
+
const creatuuid = uuid.v1()
|
|
298
|
+
|
|
299
|
+
const bufferResult = await axios
|
|
300
|
+
.post(url, payLoad, {
|
|
301
|
+
responseType: 'arraybuffer',
|
|
302
|
+
})
|
|
303
|
+
.then((res) => {
|
|
304
|
+
if (res.headers['content-type'].includes('json')) {
|
|
305
|
+
return JSON.parse(Buffer.from(res.data).toString('utf8'))
|
|
306
|
+
}
|
|
307
|
+
return res.data
|
|
308
|
+
})
|
|
309
|
+
if (bufferResult.errcode) {
|
|
310
|
+
if (bufferResult.errcode === 40001) {
|
|
311
|
+
cache.reset()
|
|
312
|
+
return await this.createQR(options)
|
|
313
|
+
}
|
|
314
|
+
throw new Error(bufferResult.errmsg)
|
|
315
|
+
}
|
|
316
|
+
await fs.writeFileSync(
|
|
317
|
+
`${this.config.targetPath}/${creatuuid}.png`,
|
|
318
|
+
bufferResult
|
|
319
|
+
)
|
|
320
|
+
return `${creatuuid}.png`
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async createQRBuffer(options) {
|
|
324
|
+
const access_token = await this.getAccessToken()
|
|
325
|
+
const url = util.format(createQRCodeUrl, access_token)
|
|
326
|
+
const payLoad = {
|
|
327
|
+
...options,
|
|
328
|
+
scene: options.scene
|
|
329
|
+
? Object.keys(options.scene)
|
|
330
|
+
.map((item) => `${item}=${options.scene[item]}`)
|
|
331
|
+
.join('&')
|
|
332
|
+
: '',
|
|
333
|
+
}
|
|
334
|
+
const creatuuid = uuid.v1()
|
|
335
|
+
|
|
336
|
+
const bufferResult = await axios
|
|
337
|
+
.post(url, payLoad, {
|
|
338
|
+
responseType: 'arraybuffer',
|
|
339
|
+
})
|
|
340
|
+
.then((res) => {
|
|
341
|
+
if (res.headers['content-type'].includes('json')) {
|
|
342
|
+
return JSON.parse(Buffer.from(res.data).toString('utf8'))
|
|
343
|
+
}
|
|
344
|
+
return res.data
|
|
345
|
+
})
|
|
346
|
+
if (bufferResult.errcode) {
|
|
347
|
+
if (bufferResult.errcode === 40001) {
|
|
348
|
+
cache.reset()
|
|
349
|
+
return await this.createQR(options)
|
|
350
|
+
}
|
|
351
|
+
throw new Error(bufferResult.errmsg)
|
|
352
|
+
}
|
|
353
|
+
return bufferResult
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async sendMessage(options) {
|
|
357
|
+
const access_token = await this.getAccessToken()
|
|
358
|
+
const url = util.format(sendMessageUrl, access_token)
|
|
359
|
+
const formatOptions = {
|
|
360
|
+
...options,
|
|
361
|
+
data: lodash.mapValues(options.data, (item) => {
|
|
362
|
+
return {
|
|
363
|
+
value: item,
|
|
364
|
+
}
|
|
365
|
+
}),
|
|
366
|
+
}
|
|
367
|
+
const result = await axios.post(url, formatOptions).then((res) => res.data)
|
|
368
|
+
if (result.errcode) {
|
|
369
|
+
if (result.errcode === 40001) {
|
|
370
|
+
cache.reset()
|
|
371
|
+
return await this.sendMessage(options)
|
|
372
|
+
}
|
|
373
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
374
|
+
}
|
|
375
|
+
return result
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
async handleMessage(options) {
|
|
379
|
+
const access_token = await this.getAccessToken()
|
|
380
|
+
const url = util.format(handleMessageUrl, access_token)
|
|
381
|
+
const result = await axios.post(url, options).then((res) => res.data)
|
|
382
|
+
if (result.errcode) {
|
|
383
|
+
if (result.errcode === 40001) {
|
|
384
|
+
cache.reset()
|
|
385
|
+
return await this.handleMessage(options)
|
|
386
|
+
}
|
|
387
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
388
|
+
}
|
|
389
|
+
return result
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
async uploadFile(imgUrl) {
|
|
393
|
+
if (!imgUrl || !imgUrl.includes('//')) throw new Error('检查imgUrl是否链接')
|
|
394
|
+
|
|
395
|
+
const access_token = await this.getAccessToken()
|
|
396
|
+
const url = util.format(uploadFile, access_token, 'image')
|
|
397
|
+
const formData = {
|
|
398
|
+
media: request(imgUrl.startsWith('//') ? `http:${imgUrl}` : imgUrl),
|
|
399
|
+
}
|
|
400
|
+
const uploadResult = await uploadPromise({
|
|
401
|
+
url,
|
|
402
|
+
formData,
|
|
403
|
+
})
|
|
404
|
+
if (uploadResult.errcode) {
|
|
405
|
+
if (uploadResult.errcode === 40001) {
|
|
406
|
+
cache.reset()
|
|
407
|
+
return await this.uploadFile(imgUrl)
|
|
408
|
+
}
|
|
409
|
+
throw new Error(`${uploadResult.errcode};${uploadResult.errmsg}`)
|
|
410
|
+
}
|
|
411
|
+
return uploadResult.media_id
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
async invokeService(payLoad) {
|
|
415
|
+
const access_token = await this.getAccessToken()
|
|
416
|
+
const url = util.format(serviceMarketUrl, access_token)
|
|
417
|
+
const result = await axios
|
|
418
|
+
.post(url, {
|
|
419
|
+
...payLoad,
|
|
420
|
+
})
|
|
421
|
+
.then((res) => res.data)
|
|
422
|
+
if (result.errcode) {
|
|
423
|
+
if (result.errcode === 40001) {
|
|
424
|
+
cache.reset()
|
|
425
|
+
return await this.invokeService(payLoad)
|
|
426
|
+
}
|
|
427
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
428
|
+
}
|
|
429
|
+
return result.data
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
getConfig() {
|
|
433
|
+
return this.config
|
|
434
|
+
}
|
|
435
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const {
|
|
4
|
+
WapPay,
|
|
5
|
+
PubPay,
|
|
6
|
+
RequestError,
|
|
7
|
+
CommunicationError,
|
|
8
|
+
utils: { getXMLBody },
|
|
9
|
+
} = require('@sigodenjs/wechatpay')
|
|
10
|
+
|
|
11
|
+
module.exports = class WeixinPay {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.pay = new WapPay({
|
|
14
|
+
appId: config.appId,
|
|
15
|
+
key: config.key,
|
|
16
|
+
mchId: config.mchId,
|
|
17
|
+
pfx: null,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async run(options) {
|
|
22
|
+
const config = {
|
|
23
|
+
spbill_create_ip: '8.8.8.8',
|
|
24
|
+
...options,
|
|
25
|
+
}
|
|
26
|
+
return await this.pay.unifiedOrder(config)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async getXMLBody(data) {
|
|
30
|
+
return await getXMLBody(data, {
|
|
31
|
+
limit: '1mb',
|
|
32
|
+
encoding: 'utf8',
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
const { parseString, Builder } = require('xml2js')
|
|
3
|
+
|
|
4
|
+
const xmlToJson = (str) => {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
parseString(str, (err, result) => {
|
|
7
|
+
if (err) {
|
|
8
|
+
reject(err)
|
|
9
|
+
} else {
|
|
10
|
+
resolve(result)
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
exports.xmlToJson = xmlToJson
|
|
16
|
+
|
|
17
|
+
exports.jsonToXml = (obj) => {
|
|
18
|
+
const builder = new Builder()
|
|
19
|
+
return builder.buildObject(obj)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.xmlPromise = ctx => new Promise(function (resolve, reject) {
|
|
23
|
+
let buf = ''
|
|
24
|
+
ctx.req.setEncoding('utf8')
|
|
25
|
+
ctx.req.on('data', (chunk) => {
|
|
26
|
+
buf += chunk
|
|
27
|
+
})
|
|
28
|
+
ctx.req.on('end', () => {
|
|
29
|
+
xmlToJson(buf)
|
|
30
|
+
.then(resolve)
|
|
31
|
+
.catch(reject)
|
|
32
|
+
})
|
|
33
|
+
})
|