import { AxiosInstance, AxiosRequestConfig } from 'axios' import sortKeys from 'sort-keys' import MD5 from 'crypto-js/md5' import { serialize } from '../../utils/serialize' import { IData } from '../../intf/IData' import { IPlugin } from '../../intf/IPlugin' import { ISignatureOptions } from '../../intf/ISignatureOptions' /** 过滤空值 */ const filterNullValue = (data: IData): IData => { if (!data || typeof data !== 'object') return data for (const key in data) { const val = data[key] if (val === null || val === undefined || `${val}`.trim() === '') { delete data[key] } if (typeof data[key] === 'object') { data[key] = JSON.stringify(val) } } return data } /** 参数签名 */ export const signature = (options: ISignatureOptions = { key: 'sign' }): IPlugin => { const { key, salt, sort, sign, disableFilterNullValue } = options const appendParamsSignature = async (params: any) => { if (!params || Object.keys(params).length === 0) return params // ? 过滤空值 if (!disableFilterNullValue) { params = filterNullValue(params) } // ? 参数排序 if (sort) { params = sortKeys(params, { compare: typeof sort === 'function' ? sort : (a, b) => a.localeCompare(b) }) } let str: string // 加盐 & 参数序列化 if (salt) { if (typeof salt === 'function') { // # 更新对象引用, 避免污染原始数据 str = serialize(salt({ ...params })) } else if (typeof salt === 'string') { str = serialize(params) + salt } else { str = serialize({ ...params, ...salt }) } } else { str = serialize(params) } // > 计算签名 let signStr: string let crypto switch (sign) { case 'md5': signStr = MD5(str).toString() break case 'sha1': crypto = await import(`crypto-js/sha1`) signStr = crypto.default(str).toString() break case 'sha256': crypto = await import(`crypto-js/sha256`) signStr = crypto.default(str).toString() break default: if (sign) { signStr = sign(str, params) } else { signStr = MD5(str).toString() } break } // @ 写入签名 params[key ?? 'sign'] = signStr return params } return { pluginName: 'signature', handler: (axios: AxiosInstance) => { /** 通过 intercptor 注入签名参数 */ axios.interceptors.request.use(async (res: AxiosRequestConfig) => { res.data = await appendParamsSignature(res.data) return res }) } } }