日期: 2021/10/25 天气:晴
- test.js
```javascript
/*
- @Description:
- @Author: 惜神
- @Date: 2021-10-11 09:56:47 */ const axios = require(‘axios’); const uuid = require(‘uuid’); const moment = require(‘moment’); const qs = require(‘qs’); const { rsaSign, formatParams, bizSort, rsaVerify } = require(‘./util’); const host = ‘https://api.com.cn‘; const appid = ‘’;
const mchPrivateKey = /YpX0SyHWzaC0hb5X7Vq+Wn3Oa83qti1k8me/ea2vWkpwGjW8zBaf9t8SMWDoEYzRmBD3VBiXdXdj7dbJhjciMW/8K7gbmi11Z+dwmCN6HVubEOO9xAL/ha0+EX60bI5xc+ORNJWuY4uqOhsyWlu5/ZHfoK5m2wLasaY8Z0axyZ6+ctMAg5WfMVEoJWYeLyD/WqgNj2hfKIlSuKElBKWTwGsVXeemjpThN/RGybRAbfBFXxt/xZExmejjAoO+8oN/+LAgMBAAECggEAN11sjPTAMwjZbl6ihLZNVfdsJ2FNL6r5oMjiQNO07o9GGY77upUQS58EJHYiiCY3RhDadNcbJCkMEkfx03b9DLfeLpVfqURPpbyeWAfxu4TTsX4ebZkB5eDWjWWIcWn38EJLuzw9ev/McsmPVzgWVs/v21lpuA3qNeQwIiC5zTYSVHZ/KMvAb62S9HlmFCjqhDjY1ChV5bbFXml0dxJ6AqJ1pbP9nwTgjOOyto6Po4fwCnjx/lh1lFnTJhPjnj9yMwyYaz4gfs92gT+DQVBFLp8RAOI2JxngcYog0qKokyabTKJwElBbYDraupBTEk8dluee2LikglBrMLMkVFXWIQKBgQD6bBOHcqJlEIYIhr6C/u2WfRYKAzy89dDgdmoDa/pyX9KsZFjLE/EnL/yckdjIqIDSYOX2wJkIP4x4WzHc/yCZiF7PFRqqpjDl58XDTQscUMAfNZmnBKL/+WIRR8NPuN+oSIDDTioBd5IUdiw6x4/dkekLeHzZIAFwBVmIDZjl8QKBgQCW9hoBejkJBgY7EQlM37SU3yY/dUsP0pxDDyTG37OcWFN/0zTPlii6jZH9kUX5KiNHypTdbCSVN/hpKDntyNWHpoSGkLYkp9oF3N8nIInhn85gzGxSFh8JyHxLVoZYQ/NYzj/yDR4yjSiuayNNqdjt4IprTg1Qv4L+SHjO3BYROwKBgQCIfS+Hu6tXelITg52CuH+2bib8/ha0xyY5sVDG3Kt8e03QOEFNLmlZ+oWssLF/bJgKElZEz2SZYkmlr87VrRiPlgxWwiHusPYl2NWpROyxWjHc0NIWfih5a+tPj9WcNh9xEVNdH9U1R36POHmS8AIxub1TSzCBBzjBXakWxpJ3gQKBgAOPpqlmQrYtyDPYgQmpNU9VvEc+8xhadYk3cDyoxknn44BecR58glV0RX9fz/DCx7ZH1x8qD+rdOSTx5/vuAuuCSBoMi99tfj0pKrJ3mAkUhf/OkreVAgJvEk+MqPqoD7OGmgeRu6ahodYLfPe2DAIAjANgAfxnqCVrfD4U/whFAoGBAKHmHsGrtQx90KYkTa3EkNwu8FbtvKOe799i/dStbl66J9Y43XTLhL4LtcJ/yXXNCs6IGpF3FOyOR2fktVe+d3vDkrPTuhiIRVxFUe/LpfTI1pauWUfNrV60c5gplRjR1gVWX0pX7XpW4c3S5c6dDtr8R1rg0f9MM/7XzC4SJ416
const mchPubKey = +16bWZ5BMNgvEeuEQwfQYkRVwI9HFOGkwNTMn5hiJXHnlXYCX+zp5r6R52MY0O7BsTCLT7aHaxsANsvI9ABGx3OaTVlPB59M6GPbJh0uXvio0m1r/lTW3Z60RU6Q3oid/rNhP3CiNgg0W6O3AGqwIDAQAB
class GSSDK { constructor(props) { this.mchPrivateKey = props && props.mchPrivateKey ? props.mchPrivateKey : mchPrivateKey; this.host = props && props.host ? props.host : host; }
async getSign (url, params) {
let formatBiz = bizSort(params.biz_content);
params.biz_content = JSON.stringify(formatBiz);
let sortString = formatParams(params, ‘&’);
console.log(‘====sortString=====’, sortString)
sortString = ${url}?${sortString}
;
const sign = rsaSign(sortString, this.mchPrivateKey, ‘SHA256withRSA’);
return sign;
}
async verify(url, parmas, sign) {
let formatBiz = bizSort(parmas.biz_content);
parmas.biz_content = JSON.stringify(formatBiz);
let sortString = formatParams(parmas, ‘&’);
console.log(‘====sortString=====’, sortString)
sortString = ${url}?${sortString}
;
console.log(‘====urlsortString=====’, sortString);
const a = rsaVerify(sortString,mchPubKey,’SHA256withRSA’,sign)
console.log(‘====aurlsortString=====’, a);
}
async commomParmas(bizContent) { const commonArgs = { app_id: appid, msg_id: uuid.v4(), format: ‘json’, charset: ‘UTF-8’, sign_type: ‘RSA2’, timestamp: moment().format(“YYYY-MM-DD hh:mm:ss”) } const fomartBizContent = { biz_content: bizContent } const args = Object.assign(commonArgs, fomartBizContent); return args; }
async request ({ url, params }) {
const args = await this.commomParmas(params);
const sign = await this.getSign(url, args);
console.log(‘====sign=====’, sign)
const formatParams = Object.assign(args, { sign: sign })
console.log(‘====params====’, formatParams)
return axios.post(${host}${url}
, qs.stringify(formatParams), {
headers: {
‘Content-Type’: ‘application/x-www-form-urlencoded; charset=UTF-8’
}
}).then(res => {
return Promise.resolve(res.data);
}, err => {
return Promise.reject(err);
})
}
}
module.exports = GSSDK;
- util.js
```javascript
/*
* @Description:
* @Author: 惜神
* @Date: 2021-10-11 09:57:37
*/
const { KJUR, hextob64, b64tohex } = require('jsrsasign')
module.exports = {
formatKey: (key) => {
const PEM_BEGIN = '-----BEGIN PRIVATE KEY-----\n'
const PEM_END = '\n-----END PRIVATE KEY-----'
if (!key.startsWith(PEM_BEGIN)) {
key = PEM_BEGIN + key
}
if (!key.endsWith(PEM_END)) {
key = key + PEM_END
}
return key
},
formatPubKey: (key) => {
const PEM_BEGIN = '-----BEGIN PUBLIC KEY-----\n'
const PEM_END = '\n-----END PUBLIC KEY-----'
if (!key.startsWith(PEM_BEGIN)) {
key = PEM_BEGIN + key
}
if (!key.endsWith(PEM_END)) {
key = key + PEM_END
}
return key
},
rsaSign: (content, privateKey, hash) => {
privateKey = module.exports.formatKey(privateKey)
// 创建 Signature 对象
const signature = new KJUR.crypto.Signature({
alg: hash,
//!这里指定 私钥 pem!
prvkeypem: privateKey
})
signature.updateString(content)
const signData = signature.sign()
// 将内容转成base64
return hextob64(signData)
},
rsaVerify: (content, pubKey, hash, sign) => {
console.log('======content=========', content, '======pubKey====', pubKey, '====hash======', hash, '=======sign=======', sign)
pubKey = module.exports.formatPubKey(pubKey)
console.log('-------', pubKey)
let signatureVf = new KJUR.crypto.Signature({ alg: 'SHA1withRSA', prvkeypem: pubKey });
signatureVf.updateString(content);
// !接受的参数是16进制字符串!
let b = signatureVf.verify(b64tohex(sign));
console.log("jsrsasign verify: " + b);
return b
},
bizSort: (args) => {
let keys = Object.keys(args);
keys = keys.sort();
let newArgs = {};
keys.forEach(function (key) {
newArgs[key] = args[key] //参数名区分大小写;
})
return newArgs;
},
formatParams: (args, join) => {
let keys = Object.keys(args)
keys = keys.sort()
let newArgs = {}
keys.forEach(function (key) {
if (args[key] != "" && args[key] != 'undefined') { //如果参数的值为空不参与签名;
newArgs[key] = args[key] //参数名区分大小写;
}
})
let string = ''
for (let k in newArgs) {
string += join + k + '=' + newArgs[k]
}
string = string.substr(1)
return string
}
}