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.
- package/core/file/plugins/log/service.js +1 -1
- package/core/file/plugins/model/service.js +26 -25
- package/core/file/plugins/weixin/controller.js +427 -22
- package/core/file/plugins/weixin/service.js +408 -14
- package/core/file/services/allinpay.js +389 -0
- package/core/file/services/weixinMP.js +75 -6
- package/package.json +4 -2
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
const axios = require('axios')
|
|
2
|
+
const crypto = require('crypto')
|
|
3
|
+
|
|
4
|
+
const is_dev = process.env.NODE_ENV !== 'production'
|
|
5
|
+
|
|
6
|
+
const config = {
|
|
7
|
+
allinpay: {
|
|
8
|
+
orgid: '',
|
|
9
|
+
cusid: '56458105193URP4',
|
|
10
|
+
appid: '00412889',
|
|
11
|
+
subAppid: '',
|
|
12
|
+
frontUrl: 'https://your-domain.com/pay/result',
|
|
13
|
+
isTest: true,
|
|
14
|
+
signType: 'RSA',
|
|
15
|
+
md5Key: '123456',
|
|
16
|
+
privateKey:
|
|
17
|
+
'MIIEowIBAAKCAQEAnNkSdA2SelrReNOdNgto5OnkLKvntzzX47pvO1byIj7ewfNlEZtKpzn9b8khyKrAPdQe5O0jTzx3W7wuUnExeCgfB5FjpZP5oSrvaEP0jJq/rYtF84k6zpc/aL+9dXaqN+k5atv1OliJRMovOCsWjWpG2+TuNXeB649mp297hLJfdBp8Fm0SZE6O8SOxLAhOkB4fk+kNWQW0puquxydSqS9gJQ/cFlHYaTa4HJ53TgISj+OEycbyOXBwMR9iz7MvLiueDI1fNEA1LcyXP4hvsBxciJe4wMLrlUlY0OvHbRoF/EmJmb0yTPwUREjcPVFrQwBX0J2Xflm6A/tFAhZQvwIDAQABAoIBAA3xdiR++GCMJkb5eOZPCVogOLqH5adybza9YhoCVrAYqrDPNFLmXTKUgyUm2iv+kextKPns4tCubWXoSq3lhiJKXsfLcvJLP0vGh1XbhKfjMdr5oJRPxLyM0YQ8V1lT3TnvL72CJEC1ki5dUulJW03i/r2ZkluKbjBEpTmJPY/EL/jSQ6eG6JJfYIf8Ew4SfW1Tr+1JVunvhH6hymR4mdcepKKpd9HkC/I/7HkyTftlJsZl3iyLBNMO9w5xoKGEhwIQShJfDZNe6cev0FyOtVwsoXjki13sGNM6xBCDf8rSZo0IksIIHj8k/uNkI/I0MfPpaUY+5pxTR5Mv4UmVOAECgYEAzWPQhhiioHUWAFcN+avxHvW1S6/QR9U7HlZ+B4QjuNYGJneKfj/LsBd/MRUbbNiPm9GJvxeHTvIaPtrGvHzDl8KkJzKxcYh9cko6AsCcvYaf0tVDi5Dyir+syk5qR7qbw1jQyaiuo55+PARDj7vvFTV4aqcyafufx6HT3DducgECgYEAw38vfM+3SE9dsP3kXo6y70gaYccKQyFBvHLGEndZGKaVay+U5oXENZOL0YEEs+iFylbMK1uLa3hiULyy23E0SsLTpuS0/8GItWqqN9oYV/TYeleUUaMje1EEBlMRnJilvzEtATYX8s++hj1AS/aGReC9N/bg/WKnfvlVs8dLQr8CgYBrsfbZGXnMoRhUPVF6pQndrgDOGvYfdFN3aOrUjhkdBjxbVzsrT9BCGU/8MJEc1cEXdxu/M1sjrhbM9nJWyyTUIp9oXlBks6jzkLAyWUTWrAyJxIGSYQKMdkzoF43q5pJeL+fqlaRc7vJKDgJPD8AhYtQtOFZa9DGnv9cTFY24AQKBgQCZFysfySWU+Zm79UZ1ibezy7nlIdH2eb+ZjCNx6IYb2K+frTYkQ1JARleyax88p3TF26yss1Z9hVswMGS7lW3GscS+p9DZizu8HVhIvoBbuIAhZh3exCsP8YR+U2SyRZNeImtEzJB6c5aWVrbYBahmZjSm86yCoFPcCfLEAuf7zwKBgFktK+pUMv+UTLNXvM7j6EcdYKwno5Emg1aU7s9YYh4Hi6exmYVoqnZMhXDvvX2zjUDl2MiLTbs2B4wKSycVOOQ18bN+aqlxcM9UPyUxx93gAKCOeddabjgarxlu7koyDS1MjvjNq8YQakOv3201z85kkf+eIVVgC3C/8aNBgrhx',
|
|
18
|
+
apiUrl: {
|
|
19
|
+
test: 'https://syb-test.allinpay.com/apiweb/unitorder',
|
|
20
|
+
production: 'https://vsp.allinpay.com/apiweb/unitorder',
|
|
21
|
+
},
|
|
22
|
+
publicKey: {
|
|
23
|
+
test: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYXfu4b7xgDSmEGQpQ8Sn3RzFgl5CE4gL4TbYrND4FtCYOrvbgLijkdFgIrVVWi2hUW4K0PwBsmlYhXcbR+JSmqv9zviVXZiym0lK3glJGVCN86r9EPvNTusZZPm40TOEKMVENSYaUjCxZ7JzeZDfQ4WCeQQr2xirqn6LdJjpZ5wIDAQAB',
|
|
24
|
+
production:
|
|
25
|
+
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm9OV6zH5DYH/ZnAVYHscEELdCNfNTHGuBv1nYYEY9FrOzE0/4kLl9f7Y9dkWHlc2ocDwbrFSm0Vqz0q2rJPxXUYBCQl5yW3jzuKSXif7q1yOwkFVtJXvuhf5WRy+1X5FOFoMvS7538No0RpnLzmNi3ktmiqmhpcY/1pmt20FHQQIDAQAB',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class AllinPay {
|
|
31
|
+
constructor(options = {}) {
|
|
32
|
+
this.orgid = options.orgid || config.allinpay.orgid
|
|
33
|
+
this.cusid = options.cusid || config.allinpay.cusid
|
|
34
|
+
this.appid = options.appid || config.allinpay.appid
|
|
35
|
+
this.subAppid = options.subAppid || config.allinpay.subAppid
|
|
36
|
+
this.notifyUrl = options.notifyUrl || config.allinpay.notifyUrl
|
|
37
|
+
this.frontUrl = options.frontUrl || config.allinpay.frontUrl
|
|
38
|
+
this.isTest =
|
|
39
|
+
options.isTest !== undefined ? options.isTest : config.allinpay.isTest
|
|
40
|
+
this.signType = options.signType || config.allinpay.signType
|
|
41
|
+
this.privateKey = options.privateKey || config.allinpay.privateKey
|
|
42
|
+
this.publicKey = this.isTest
|
|
43
|
+
? config.allinpay.publicKey.test
|
|
44
|
+
: config.allinpay.publicKey.production
|
|
45
|
+
this.baseUrl = this.isTest
|
|
46
|
+
? config.allinpay.apiUrl.test
|
|
47
|
+
: config.allinpay.apiUrl.production
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
buildSignStr(params) {
|
|
51
|
+
const sortedKeys = Object.keys(params).sort()
|
|
52
|
+
let signStr = ''
|
|
53
|
+
for (const key of sortedKeys) {
|
|
54
|
+
if (
|
|
55
|
+
params[key] !== undefined &&
|
|
56
|
+
params[key] !== null &&
|
|
57
|
+
params[key] !== ''
|
|
58
|
+
) {
|
|
59
|
+
if (signStr) signStr += '&'
|
|
60
|
+
signStr += `${key}=${params[key]}`
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return signStr
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
sign(params) {
|
|
67
|
+
const signStr = this.buildSignStr(params)
|
|
68
|
+
|
|
69
|
+
if (this.signType === 'RSA') {
|
|
70
|
+
const privateKey = `-----BEGIN RSA PRIVATE KEY-----\n${this.privateKey}\n-----END RSA PRIVATE KEY-----`
|
|
71
|
+
const sign = crypto.createSign('RSA-SHA1')
|
|
72
|
+
sign.update(signStr, 'utf8')
|
|
73
|
+
const signature = sign.sign(privateKey, 'base64')
|
|
74
|
+
|
|
75
|
+
// crypto.createHash('md5').update(originStr).digest('hex')
|
|
76
|
+
return signature
|
|
77
|
+
} else if (this.signType === 'SM2') {
|
|
78
|
+
throw new Error('SM2 signing not implemented')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
throw new Error(`Unsupported signType: ${this.signType}`)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
verifySign(params) {
|
|
85
|
+
const sign = params.sign
|
|
86
|
+
if (!sign) {
|
|
87
|
+
console.log('No sign found in response')
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const paramsCopy = { ...params }
|
|
92
|
+
delete paramsCopy.sign
|
|
93
|
+
|
|
94
|
+
const signStr = this.buildSignStr(paramsCopy)
|
|
95
|
+
|
|
96
|
+
const publicKey = `-----BEGIN PUBLIC KEY-----\n${this.publicKey}\n-----END PUBLIC KEY-----`
|
|
97
|
+
const verify = crypto.createVerify('RSA-SHA1')
|
|
98
|
+
verify.update(signStr, 'utf8')
|
|
99
|
+
const result = verify.verify(publicKey, sign, 'base64')
|
|
100
|
+
|
|
101
|
+
return result
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async request(url, params) {
|
|
105
|
+
const _params = new URLSearchParams()
|
|
106
|
+
Object.keys(params).forEach((key, value) => {
|
|
107
|
+
_params.append(key, params[key])
|
|
108
|
+
})
|
|
109
|
+
try {
|
|
110
|
+
if (is_dev) {
|
|
111
|
+
console.log('Request URL:', url)
|
|
112
|
+
console.log('Request params:', _params)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const response = await axios.post(url, _params, {
|
|
116
|
+
headers: {
|
|
117
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
118
|
+
'User-Agent': 'AllinPay Node.js SDK',
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
if (response.data.errmsg) {
|
|
122
|
+
throw new Error(response.data.errmsg)
|
|
123
|
+
}
|
|
124
|
+
if (is_dev) {
|
|
125
|
+
console.log('Response data:', JSON.stringify(response.data))
|
|
126
|
+
}
|
|
127
|
+
return response.data
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (is_dev) {
|
|
130
|
+
console.error('Request error:', error.message)
|
|
131
|
+
}
|
|
132
|
+
if (is_dev && error.response) {
|
|
133
|
+
console.error('Response status:', error.response.status)
|
|
134
|
+
console.error('Response data:', JSON.stringify(error.response.data))
|
|
135
|
+
}
|
|
136
|
+
throw new Error(`AllinPay request error: ${error.message}`)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async createOrder(orderData) {
|
|
141
|
+
const {
|
|
142
|
+
reqsn,
|
|
143
|
+
trxamt,
|
|
144
|
+
body,
|
|
145
|
+
acct,
|
|
146
|
+
remark = '',
|
|
147
|
+
validtime = '',
|
|
148
|
+
limitPay = '',
|
|
149
|
+
goodsTag = '',
|
|
150
|
+
benefitdetail = '',
|
|
151
|
+
chnlstoreid = '',
|
|
152
|
+
subbranch = '',
|
|
153
|
+
extendparams = '',
|
|
154
|
+
cusip = '',
|
|
155
|
+
idno = '',
|
|
156
|
+
truename = '',
|
|
157
|
+
asinfo = '',
|
|
158
|
+
fqnum = '',
|
|
159
|
+
} = orderData
|
|
160
|
+
|
|
161
|
+
const params = {}
|
|
162
|
+
|
|
163
|
+
if (this.orgid) params.orgid = this.orgid
|
|
164
|
+
params.cusid = this.cusid
|
|
165
|
+
params.appid = this.appid
|
|
166
|
+
params.version = '11'
|
|
167
|
+
params.trxamt = trxamt
|
|
168
|
+
params.reqsn = reqsn
|
|
169
|
+
params.paytype = 'W06'
|
|
170
|
+
params.randomstr = this.generateRandomStr()
|
|
171
|
+
|
|
172
|
+
if (body) params.body = body.substring(0, 100)
|
|
173
|
+
if (remark) params.remark = remark
|
|
174
|
+
if (validtime) params.validtime = validtime
|
|
175
|
+
if (acct) params.acct = acct
|
|
176
|
+
if (this.notifyUrl) params.notify_url = this.notifyUrl
|
|
177
|
+
if (limitPay) params.limit_pay = limitPay
|
|
178
|
+
if (this.subAppid) params.sub_appid = this.subAppid
|
|
179
|
+
if (goodsTag) params.goods_tag = goodsTag
|
|
180
|
+
if (benefitdetail) params.benefitdetail = benefitdetail
|
|
181
|
+
if (chnlstoreid) params.chnlstoreid = chnlstoreid
|
|
182
|
+
if (subbranch) params.subbranch = subbranch
|
|
183
|
+
if (extendparams) params.extendparams = extendparams
|
|
184
|
+
if (cusip) params.cusip = cusip
|
|
185
|
+
if (idno) params.idno = idno
|
|
186
|
+
if (truename) params.truename = truename
|
|
187
|
+
if (asinfo) params.asinfo = asinfo
|
|
188
|
+
if (fqnum) params.fqnum = fqnum
|
|
189
|
+
|
|
190
|
+
params.signtype = this.signType
|
|
191
|
+
params.sign = this.sign(params)
|
|
192
|
+
|
|
193
|
+
const url = `${this.baseUrl}/pay`
|
|
194
|
+
const result = await this.request(url, params)
|
|
195
|
+
|
|
196
|
+
if (result && result.retcode === 'SUCCESS') {
|
|
197
|
+
if (result.sign && this.verifySign(result)) {
|
|
198
|
+
return result
|
|
199
|
+
} else {
|
|
200
|
+
console.warn(
|
|
201
|
+
'Sign verification failed, but retcode is SUCCESS. Returning result anyway.'
|
|
202
|
+
)
|
|
203
|
+
return result
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
throw new Error(`AllinPay error: ${result.retmsg || 'Unknown error'}`)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async queryOrder(reqsn) {
|
|
210
|
+
const params = {
|
|
211
|
+
cusid: this.cusid,
|
|
212
|
+
appid: this.appid,
|
|
213
|
+
version: '11',
|
|
214
|
+
reqsn,
|
|
215
|
+
signtype: this.signType,
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
params.sign = this.sign(params)
|
|
219
|
+
|
|
220
|
+
const url = `${this.baseUrl}/query`
|
|
221
|
+
const result = await this.request(url, params)
|
|
222
|
+
|
|
223
|
+
if (result && result.retcode === 'SUCCESS') {
|
|
224
|
+
if (result.sign && this.verifySign(result)) {
|
|
225
|
+
return result
|
|
226
|
+
} else {
|
|
227
|
+
console.warn(
|
|
228
|
+
'Sign verification failed, but retcode is SUCCESS. Returning result anyway.'
|
|
229
|
+
)
|
|
230
|
+
return result
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
throw new Error(`AllinPay error: ${result.retmsg || 'Unknown error'}`)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async checkOrder(reqsn) {
|
|
237
|
+
const params = {
|
|
238
|
+
cusid: this.cusid,
|
|
239
|
+
appid: this.appid,
|
|
240
|
+
version: '11',
|
|
241
|
+
reqsn,
|
|
242
|
+
signtype: this.signType,
|
|
243
|
+
}
|
|
244
|
+
if (this.notifyUrl) params.notify_url = this.notifyUrl
|
|
245
|
+
|
|
246
|
+
params.sign = this.sign(params)
|
|
247
|
+
|
|
248
|
+
const url = this.isTest
|
|
249
|
+
? 'https://syb-test.allinpay.com/apiweb/tranx/query'
|
|
250
|
+
: 'https://vsp.allinpay.com/apiweb/tranx/query'
|
|
251
|
+
const result = await this.request(url, params)
|
|
252
|
+
|
|
253
|
+
if (result && result.retcode === 'SUCCESS') {
|
|
254
|
+
if (result.sign && this.verifySign(result)) {
|
|
255
|
+
return result
|
|
256
|
+
} else {
|
|
257
|
+
console.warn(
|
|
258
|
+
'Sign verification failed, but retcode is SUCCESS. Returning result anyway.'
|
|
259
|
+
)
|
|
260
|
+
return result
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
throw new Error(`AllinPay error: ${result.retmsg || 'Unknown error'}`)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async refundOrder(orderData) {
|
|
267
|
+
const { reqsn, trxamt, oldreqsn, remark = '', acct = '' } = orderData
|
|
268
|
+
|
|
269
|
+
const params = {
|
|
270
|
+
cusid: this.cusid,
|
|
271
|
+
appid: this.appid,
|
|
272
|
+
version: '11',
|
|
273
|
+
trxamt,
|
|
274
|
+
reqsn,
|
|
275
|
+
oldreqsn,
|
|
276
|
+
signtype: this.signType,
|
|
277
|
+
}
|
|
278
|
+
if (remark) params.remark = remark
|
|
279
|
+
if (acct) params.acct = acct
|
|
280
|
+
params.signtype = this.signType
|
|
281
|
+
if (this.notifyUrl) params.notify_url = this.notifyUrl
|
|
282
|
+
|
|
283
|
+
params.sign = this.sign(params)
|
|
284
|
+
|
|
285
|
+
const url = this.isTest
|
|
286
|
+
? 'https://syb-test.allinpay.com/apiweb/tranx/refund'
|
|
287
|
+
: 'https://vsp.allinpay.com/apiweb/tranx/refund'
|
|
288
|
+
const result = await this.request(url, params)
|
|
289
|
+
|
|
290
|
+
if (result && result.retcode === 'SUCCESS') {
|
|
291
|
+
if (result.sign && this.verifySign(result)) {
|
|
292
|
+
return result
|
|
293
|
+
} else {
|
|
294
|
+
console.warn(
|
|
295
|
+
'Sign verification failed, but retcode is SUCCESS. Returning result anyway.'
|
|
296
|
+
)
|
|
297
|
+
return result
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
throw new Error(`AllinPay error: ${result.retmsg || 'Unknown error'}`)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async cancelOrder(reqsn) {
|
|
304
|
+
const params = {
|
|
305
|
+
cusid: this.cusid,
|
|
306
|
+
appid: this.appid,
|
|
307
|
+
version: '11',
|
|
308
|
+
reqsn,
|
|
309
|
+
signtype: this.signType,
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
params.sign = this.sign(params)
|
|
313
|
+
|
|
314
|
+
const url = `${this.baseUrl}/cancel`
|
|
315
|
+
const result = await this.request(url, params)
|
|
316
|
+
|
|
317
|
+
if (result && result.retcode === 'SUCCESS') {
|
|
318
|
+
if (result.sign && this.verifySign(result)) {
|
|
319
|
+
return result
|
|
320
|
+
} else {
|
|
321
|
+
console.warn(
|
|
322
|
+
'Sign verification failed, but retcode is SUCCESS. Returning result anyway.'
|
|
323
|
+
)
|
|
324
|
+
return result
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
throw new Error(`AllinPay error: ${result.retmsg || 'Unknown error'}`)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async downloadBill({ date }) {
|
|
331
|
+
const params = {
|
|
332
|
+
cusid: this.cusid,
|
|
333
|
+
appid: this.appid,
|
|
334
|
+
date,
|
|
335
|
+
randomstr: this.generateRandomStr(),
|
|
336
|
+
filetype: '1',
|
|
337
|
+
signtype: this.signType,
|
|
338
|
+
}
|
|
339
|
+
params.signtype = this.signType
|
|
340
|
+
|
|
341
|
+
params.sign = this.sign(params)
|
|
342
|
+
|
|
343
|
+
const url = this.isTest
|
|
344
|
+
? 'https://syb-test.allinpay.com/vsppcusapi/trxfile/get'
|
|
345
|
+
: 'https://cus.allinpay.com/cusapi/trxfile/get'
|
|
346
|
+
const result = await this.request(url, params)
|
|
347
|
+
|
|
348
|
+
if (result && result.retcode === 'SUCCESS') {
|
|
349
|
+
if (result.sign && this.verifySign(result)) {
|
|
350
|
+
return result
|
|
351
|
+
} else {
|
|
352
|
+
console.warn(
|
|
353
|
+
'Sign verification failed, but retcode is SUCCESS. Returning result anyway.'
|
|
354
|
+
)
|
|
355
|
+
return result
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
throw new Error(`AllinPay error: ${result.retmsg || 'Unknown error'}`)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
generateRandomStr(length = 32) {
|
|
362
|
+
const chars =
|
|
363
|
+
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
364
|
+
let result = ''
|
|
365
|
+
for (let i = 0; i < length; i++) {
|
|
366
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length))
|
|
367
|
+
}
|
|
368
|
+
return result
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
generateOrderNum() {
|
|
372
|
+
const timestamp = Date.now().toString()
|
|
373
|
+
const random = Math.random().toString(36).substr(2, 6).toUpperCase()
|
|
374
|
+
return `ORD${timestamp}${random}`
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
formatDateTime() {
|
|
378
|
+
const now = new Date()
|
|
379
|
+
const year = now.getFullYear()
|
|
380
|
+
const month = String(now.getMonth() + 1).padStart(2, '0')
|
|
381
|
+
const day = String(now.getDate()).padStart(2, '0')
|
|
382
|
+
const hour = String(now.getHours()).padStart(2, '0')
|
|
383
|
+
const minute = String(now.getMinutes()).padStart(2, '0')
|
|
384
|
+
const second = String(now.getSeconds()).padStart(2, '0')
|
|
385
|
+
return `${year}${month}${day}${hour}${minute}${second}`
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
module.exports = AllinPay
|
|
@@ -96,6 +96,13 @@ const b2bCheckRefundUrl =
|
|
|
96
96
|
|
|
97
97
|
const b2bCheckOrderUrl =
|
|
98
98
|
'https://api.weixin.qq.com/retail/B2b/getorder?access_token=%s&pay_sig=%s'
|
|
99
|
+
|
|
100
|
+
const b2bPreStoreUrl =
|
|
101
|
+
'https://api.weixin.qq.com/wxa/business/batchcreateretail?access_token=%s'
|
|
102
|
+
|
|
103
|
+
const b2bFinishUrl =
|
|
104
|
+
'https://api.weixin.qq.com/retail/B2b/finishprofitsharingorder?access_token=%s&pay_sig=%s'
|
|
105
|
+
|
|
99
106
|
const fsPromise = require('fs/promises')
|
|
100
107
|
const LRU = require('lru-cache')
|
|
101
108
|
const request = require('request')
|
|
@@ -1123,7 +1130,7 @@ module.exports = class Singleton {
|
|
|
1123
1130
|
return result
|
|
1124
1131
|
}
|
|
1125
1132
|
|
|
1126
|
-
async b2bCheckRefund({ mchid, app_key,
|
|
1133
|
+
async b2bCheckRefund({ mchid, app_key, out_refund_no }) {
|
|
1127
1134
|
const requestUrl = b2bCheckRefundUrl
|
|
1128
1135
|
|
|
1129
1136
|
const access_token = await this.getAccessToken()
|
|
@@ -1132,7 +1139,7 @@ module.exports = class Singleton {
|
|
|
1132
1139
|
|
|
1133
1140
|
const signData = {
|
|
1134
1141
|
mchid,
|
|
1135
|
-
|
|
1142
|
+
out_refund_no,
|
|
1136
1143
|
}
|
|
1137
1144
|
|
|
1138
1145
|
const pay_sig = hmacSha256(`${uri}&${JSON.stringify(signData)}`, app_key)
|
|
@@ -1142,14 +1149,14 @@ module.exports = class Singleton {
|
|
|
1142
1149
|
if (result.errcode) {
|
|
1143
1150
|
if (result.errcode === 40001) {
|
|
1144
1151
|
cache.reset()
|
|
1145
|
-
return await this.b2bCheckRefund({ mchid, app_key,
|
|
1152
|
+
return await this.b2bCheckRefund({ mchid, app_key, out_refund_no })
|
|
1146
1153
|
}
|
|
1147
1154
|
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
1148
1155
|
}
|
|
1149
1156
|
return result
|
|
1150
1157
|
}
|
|
1151
1158
|
|
|
1152
|
-
async b2bCheckOrder({ mchid, app_key,
|
|
1159
|
+
async b2bCheckOrder({ mchid, app_key, out_trade_no }) {
|
|
1153
1160
|
const requestUrl = b2bCheckOrderUrl
|
|
1154
1161
|
|
|
1155
1162
|
const access_token = await this.getAccessToken()
|
|
@@ -1158,7 +1165,69 @@ module.exports = class Singleton {
|
|
|
1158
1165
|
|
|
1159
1166
|
const signData = {
|
|
1160
1167
|
mchid,
|
|
1161
|
-
|
|
1168
|
+
out_trade_no,
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
const pay_sig = hmacSha256(`${uri}&${JSON.stringify(signData)}`, app_key)
|
|
1172
|
+
|
|
1173
|
+
const url = util.format(requestUrl, access_token, pay_sig)
|
|
1174
|
+
const result = await axios.post(url, signData).then((res) => res.data)
|
|
1175
|
+
if (result.errcode) {
|
|
1176
|
+
if (result.errcode === 40001) {
|
|
1177
|
+
cache.reset()
|
|
1178
|
+
return await this.b2bCheckOrder({ mchid, app_key, out_trade_no })
|
|
1179
|
+
}
|
|
1180
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
1181
|
+
}
|
|
1182
|
+
return result
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
async b2bPreStore(list) {
|
|
1186
|
+
const access_token = await this.getAccessToken()
|
|
1187
|
+
const url = util.format(b2bPreStoreUrl, access_token)
|
|
1188
|
+
|
|
1189
|
+
const result = await axios
|
|
1190
|
+
.post(url, {
|
|
1191
|
+
retail_info_list: list,
|
|
1192
|
+
})
|
|
1193
|
+
.then((res) => res.data)
|
|
1194
|
+
if (result.errcode) {
|
|
1195
|
+
if (result.errcode === 40001) {
|
|
1196
|
+
cache.reset()
|
|
1197
|
+
return await this.b2bPreStore({
|
|
1198
|
+
retail_info_list: list,
|
|
1199
|
+
})
|
|
1200
|
+
}
|
|
1201
|
+
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
1202
|
+
}
|
|
1203
|
+
return result
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// async b2bFinish(payLoad) {
|
|
1207
|
+
// const access_token = await this.getAccessToken()
|
|
1208
|
+
// const url = util.format(b2bFinishUrl, access_token)
|
|
1209
|
+
|
|
1210
|
+
// const result = await axios.post(url, payLoad).then((res) => res.data)
|
|
1211
|
+
// if (result.errcode) {
|
|
1212
|
+
// if (result.errcode === 40001) {
|
|
1213
|
+
// cache.reset()
|
|
1214
|
+
// return await this.b2bFinish(payLoad)
|
|
1215
|
+
// }
|
|
1216
|
+
// throw new Error(`${result.errcode};${result.errmsg}`)
|
|
1217
|
+
// }
|
|
1218
|
+
// return result
|
|
1219
|
+
// }
|
|
1220
|
+
|
|
1221
|
+
async b2bFinish({ mchid, app_key, out_trade_no }) {
|
|
1222
|
+
const requestUrl = b2bFinishUrl
|
|
1223
|
+
|
|
1224
|
+
const access_token = await this.getAccessToken()
|
|
1225
|
+
|
|
1226
|
+
const uri = requestUrl.split('api.weixin.qq.com')[1].split('?')[0]
|
|
1227
|
+
|
|
1228
|
+
const signData = {
|
|
1229
|
+
mchid,
|
|
1230
|
+
out_trade_no,
|
|
1162
1231
|
}
|
|
1163
1232
|
|
|
1164
1233
|
const pay_sig = hmacSha256(`${uri}&${JSON.stringify(signData)}`, app_key)
|
|
@@ -1168,7 +1237,7 @@ module.exports = class Singleton {
|
|
|
1168
1237
|
if (result.errcode) {
|
|
1169
1238
|
if (result.errcode === 40001) {
|
|
1170
1239
|
cache.reset()
|
|
1171
|
-
return await this.
|
|
1240
|
+
return await this.b2bFinish({ mchid, app_key, out_trade_no })
|
|
1172
1241
|
}
|
|
1173
1242
|
throw new Error(`${result.errcode};${result.errmsg}`)
|
|
1174
1243
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "q-koa",
|
|
3
|
-
"version": "13.6.
|
|
3
|
+
"version": "13.6.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -61,7 +61,9 @@
|
|
|
61
61
|
"yly-nodejs-sdk": "^1.0.2",
|
|
62
62
|
"vm2": "^3.9.19",
|
|
63
63
|
"xlsx": "^0.18.5",
|
|
64
|
-
"pm2": "^7.0.1"
|
|
64
|
+
"pm2": "^7.0.1",
|
|
65
|
+
"dayjs": "^1.11.13",
|
|
66
|
+
"request": "^2.88.2"
|
|
65
67
|
},
|
|
66
68
|
"devDependencies": {
|
|
67
69
|
"eslint": "^4.19.1",
|