爹爹们,谁能给个nodejs 上传图片(营销专用)接口能正常使用的代码? 调试到自闭了
const { KJUR, hextob64 } = require('jsrsasign')
const axios = require('axios')
const fs = require('fs')
// 上传图片
async function upload(req, res, next) {
try {
const method = 'POST'
const pathname = '/v3/marketing/favor/media/image-upload'
const timestamp = Math.round(new Date().getTime() / 1000); // 十位的时间戳
const onece_str = await randomString() // 随机字符串
const bodyParamsStr = {
filename: 'wechatpay_logo.png',
sha256: 'd2973a45b1d528c21ebb77792ef3fcea40fa9a4e04a17e35369102ba9c84c8b1'
}
const mchid = '***' // 商户号
const serial_no = '***' // 商户API证书序列号
const private_key = `***`// appiclient_key.pem里的内容全部复制过来
const signature = await rsaSign(`${method}\n${pathname}\n${timestamp}\n${onece_str}\n${JSON.stringify(bodyParamsStr)}\n`, private_key, 'SHA256withRSA')
//获取到signature后就可以获取到Authorization了
let Authorization = `WECHATPAY2-SHA256-RSA2048 mchid="${mchid}",nonce_str="${onece_str}",timestamp="${timestamp}",signature="${signature}",serial_no="${serial_no}"`
const formData = new FormData();
formData.append('file', fs.createReadStream('./test.png'));
formData.append('meta', bodyParamsStr);
const data = await axios.post('https://api.mch.weixin.qq.com/v3/marketing/favor/media/image-upload', formData, {
headers: {
Authorization,
'Content-Type': 'multipart/form-data;boundary=boundary',
'Accept': 'application/json'
}
})
console.log(data);
res.json(data.data)
} catch (error) {
console.log(error.response.data);
// return next(error)
}
}
// 加密
async function rsaSign(content, privateKey, hash = 'SHA256withRSA') {
console.log(content, 11111);
// 创建 Signature 对象
const signature = new KJUR.crypto.Signature({
alg: hash,
//!这里指定 私钥 pem!
prvkeypem: privateKey
})
signature.updateString(content)
const signData = signature.sign()
// 将内容转成base64
return hextob64(signData)
}
// 生成随机数
async function randomString(e = 32) {
const t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
const a = t.length
let n = ''
for (let index = 0; index < e; index++) {
n += t.charAt(Math.floor(Math.random() * a))
}
return n.toUpperCase()
}
upload()
报错:
{
code: 'SIGN_ERROR',
detail: {
detail: { issue: 'sign not match' },
field: 'signature',
location: 'authorization',
sign_information: {
method: 'POST',
sign_message_length: 104,
truncated_sign_message: 'POST\n' +
'/v3/marketing/favor/media/image-upload\n' +
'1751199760\n' +
'KETTK3NNYARDZFHEXWNQRFBYQNP4BXYS\n' +
'[object \n',
url: '/v3/marketing/favor/media/image-upload'
}
},
message: '错误的签名,验签失败'
}
可以看https://wechatpay.js.org/openapi/v3/marketing/favor/media/image-upload
BusinessError: Verify the response's data with: timestamp=1751361233, nonce=869caa915ac59e77a937d239a70bffd6, signature=u8+zrao/UVSXEzXjpbZUlhTK98c24Nz2mhOlddeGLC5CwTjvHJojF0JdO/tp3RLgdmc8SzTKMwK+YdfwUirORtjkQCZURfQYkt4womNRQRCrskBSnYPjhT7ukYuY+WVYnnOhrEx+m23H3XIlDMRo+IK3WUzDEiDr6XsUFjNSU8dDC2Us1cf8lBllqgv+KY8OcPXHwz6+SeMwhoOFr51nnoo+20uZYYBNKp5LXolaq969U054e2tg+jh9bozgUGIBq/fs8SzxywaM7I94NUa4sK5rmxzcN/ehwnT2y6Dy5TSu3IUkUW8UUMm12bduueddMpnQ3u93wKUI5XAlMEXpVw==, cert={PUB_KEY_ID_0117176096572116000204: ...} failed.
at Object.buildBusinessError (/Users/hking/workspace/ocr-server/v3/node_modules/wechatpay-axios-plugin/lib/utils.js:150:19)
at Object.verifier (/Users/hking/workspace/ocr-server/v3/node_modules/wechatpay-axios-plugin/lib/decorator.js:209:22)
at transform (/Users/hking/workspace/ocr-server/v3/node_modules/axios/dist/node/axios.cjs:2008:15)
at Object.forEach (/Users/hking/workspace/ocr-server/v3/node_modules/axios/dist/node/axios.cjs:288:10)
at Object.transformData (/Users/hking/workspace/ocr-server/v3/node_modules/axios/dist/node/axios.cjs:2007:11)
at onAdapterResolution (/Users/hking/workspace/ocr-server/v3/node_modules/axios/dist/node/axios.cjs:4124:35)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Axios.request (/Users/hking/workspace/ocr-server/v3/node_modules/axios/dist/node/axios.cjs:4275:14) {
code: 'EV3_RES_HEADER_SIGNATURE_DIGEST',
response: {
data: '{"media_url":"https://wxpaylogo.qpic.cn/wxpaylogo/PiajxSqBRaEKcYsiccVkic1Ria3toe4ISibwg1OYBhUSJzEXIlEzdeAQPGw/0"}',
headers: Object [AxiosHeaders] {
server: 'nginx',
date: 'Tue, 01 Jul 2025 09:13:53 GMT',
'content-type': 'application/json; charset=utf-8',
'content-length': '107',
connection: 'close',
'cache-control': 'no-cache, must-revalidate',
'x-content-type-options': 'nosniff',
'request-id': '08D0CD8EC30610B3071888DFBCA80120DB2128B3E103-0',
'content-language': 'zh-CN',
'wechatpay-nonce': '869caa915ac59e77a937d239a70bffd6',
'wechatpay-signature': 'u8+zrao/UVSXEzXjpbZUlhTK98c24Nz2mhOlddeGLC5CwTjvHJojF0JdO/tp3RLgdmc8SzTKMwK+YdfwUirORtjkQCZURfQYkt4womNRQRCrskBSnYPjhT7ukYuY+WVYnnOhrEx+m23H3XIlDMRo+IK3WUzDEiDr6XsUFjNSU8dDC2Us1cf8lBllqgv+KY8OcPXHwz6+SeMwhoOFr51nnoo+20uZYYBNKp5LXolaq969U054e2tg+jh9bozgUGIBq/fs8SzxywaM7I94NUa4sK5rmxzcN/ehwnT2y6Dy5TSu3IUkUW8UUMm12bduueddMpnQ3u93wKUI5XAlMEXpVw==',
'wechatpay-timestamp': '1751361233',
'wechatpay-serial': 'PUB_KEY_ID_01171760965720216000204',
'wechatpay-signature-type': 'WECHATPAY2-SHA256-RSA2048'
},
status: 200
}
}