wechatpay-axios-plugin
Version:
微信支付APIv2及v3 NodeJS SDK,支持CLI模式请求OpenAPI,支持v3证书下载,v2付款码支付、企业付款、退款,企业微信-企业支付-企业红包/向员工付款,v2&v3 Native支付、扫码支付、H5支付、JSAPI/小程序支付、合单支付...
123 lines (106 loc) • 3.78 kB
JavaScript
const {
createHash, createHmac, timingSafeEqual, createSecretKey,
KeyObject,
} = require('crypto');
const { queryStringLike, ksort } = require('./formatter');
/**
* @typedef {import('node:crypto').CipherKey} CipherKey
* @typedef {import('node:crypto').BinaryLike} BinaryLike
*/
const md5 = 'md5';
const hex = 'hex';
const sha256 = 'sha256';
const sha1 = 'sha1';
const ALGO_MD5 = 'MD5';
const ALGO_HMAC_SHA256 = 'HMAC-SHA256';
function isSymmetricKeyObject(thing) {
return (thing instanceof KeyObject) && thing.type === 'secret';
}
/**
* Crypto hash functions utils.
*/
class Hash {
static ALGO_MD5 = ALGO_MD5
static ALGO_HMAC_SHA256 = ALGO_HMAC_SHA256
static isKeyObject = isSymmetricKeyObject
/**
* @param {BinaryLike|KeyObject} thing - the thing.
* @returns {KeyObject} - The symmetric KeyObject.
*/
static keyObjectFrom(thing) { return isSymmetricKeyObject(thing) ? thing : createSecretKey(Buffer.from(thing)); }
/**
* Calculate the input with an optional secret `key` in MD5,
* when the `key` is Falsey, this method works as normal `MD5`.
*
* @since v0.9.2 - The first argument is supported a `KeyObject`.
*
* @param {BinaryLike|KeyObject} thing - The input.
* @param {CipherKey} [key] - The secret key.
* @param {boolean|number|string} [agency = false] - `true` or better of the `AgentId` value.
*
* @return {string} - data signature
*/
static md5(thing, key = '', agency = false) {
return createHash(md5)
.update(thing instanceof KeyObject ? thing.export() : thing)
.update(key ? (agency ? '&secret=' : '&key=') : '') /* eslint-disable-line no-nested-ternary */
.update(key instanceof KeyObject ? key.export() : key)
.digest(hex);
}
/**
* Calculate the input string with a secret `key` as of `algorithm` string which is one of the 'sha256', 'sha512' etc.
* @param {BinaryLike} thing - The input string.
* @param {CipherKey} key - The secret key.
* @param {string} [algorithm = sha256] - The algorithm string, default is `sha256`.
* @return {string} - data signature
*/
static hmac(thing, key, algorithm = sha256) {
return createHmac(algorithm, key)
.update(thing)
.update('&key=')
.update(key instanceof KeyObject ? key.export() : key)
.digest(hex);
}
/**
* Calculate the input in SHA1.
* @param {BinaryLike} thing - The input.
* @return {string} - data signature
*/
static sha1(thing) {
return createHash(sha1).update(thing).digest(hex);
}
/**
* Calculate the input in SHA256.
* @param {BinaryLike} thing - The input.
* @return {string} - data signature
*/
static sha256(thing) {
return createHash(sha256).update(thing).digest(hex);
}
/**
* Wrapping the builtins `crypto.timingSafeEqual` function.
* @param {string} known - The string of known length to compare against.
* @param {string?} [user] - The user-supplied string.
* @return {boolean} - Returns true when the two are equal, false otherwise.
*/
static equals(known, user) {
const a = Buffer.from(known);
const b = (user === undefined || user === null) ? undefined : Buffer.from(user);
return Buffer.isBuffer(b) && a.length === b.length && timingSafeEqual(a, b);
}
/**
* Utils of the data signature calculation.
* @param {string} type - The sign type, one of the MD5 or HMAC-SHA256.
* @param {object} data - The input data.
* @param {CipherKey} key - The secret key.
* @return {string} - The data signature.
*/
static sign(type, data, key) {
return {
[ALGO_MD5]: this.md5,
[ALGO_HMAC_SHA256]: this.hmac,
}[type](queryStringLike(ksort(data)), key).toUpperCase();
}
static get default() { return this; }
}
module.exports = Hash;