122 lines
3.1 KiB
JavaScript
122 lines
3.1 KiB
JavaScript
|
|
const Sm4Util = require('../../utils/sm4-util');
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 需要加密的字段列表
|
|||
|
|
*/
|
|||
|
|
const ENCRYPTED_FIELDS = ['name', 'mobile', 'idCard'];
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 判断数据是否已加密
|
|||
|
|
* @param {string} value - 待判断的值
|
|||
|
|
* @param {string} field - 字段名称
|
|||
|
|
* @returns {boolean} true表示已加密,false表示未加密
|
|||
|
|
*/
|
|||
|
|
function isEncrypted(value, field) {
|
|||
|
|
if (!value || typeof value !== 'string') {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 手机号:如果是11位纯数字,则未加密
|
|||
|
|
if (field === 'mobile') {
|
|||
|
|
return !/^1\d{10}$/.test(value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 身份证:如果是15或18位数字(最后一位可能是X),则未加密
|
|||
|
|
if (field === 'idCard') {
|
|||
|
|
return !/^(\d{15}|\d{17}[\dXx])$/.test(value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 姓名:如果是常见的中文/英文姓名格式(2-20个字符),则未加密
|
|||
|
|
if (field === 'name') {
|
|||
|
|
// 纯中文姓名(2-10个字符)或纯英文字母姓名(含空格,2-50个字符)
|
|||
|
|
if (/^[\u4e00-\u9fa5]{2,10}$/.test(value) || /^[a-zA-Z\s]{2,50}$/.test(value)) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 其他情况:如果符合base64格式且长度较长,则认为已加密
|
|||
|
|
// URL-safe base64 格式:包含字母、数字、-、_
|
|||
|
|
if (/^[A-Za-z0-9_-]+={0,2}$/.test(value) && value.length >= 20) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 默认认为未加密
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 加密订单敏感字段
|
|||
|
|
* @param {Object} data - 订单数据
|
|||
|
|
* @returns {Object} 加密后的数据
|
|||
|
|
*/
|
|||
|
|
function encryptOrderFields(data) {
|
|||
|
|
if (!data || typeof data !== 'object') {
|
|||
|
|
return data;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const encryptedData = { ...data };
|
|||
|
|
|
|||
|
|
ENCRYPTED_FIELDS.forEach(field => {
|
|||
|
|
if (encryptedData[field] && typeof encryptedData[field] === 'string' && encryptedData[field].trim() !== '') {
|
|||
|
|
try {
|
|||
|
|
encryptedData[field] = Sm4Util.encryptDataForSm3(encryptedData[field]);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error(`加密字段 ${field} 失败:`, error.message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return encryptedData;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 解密订单敏感字段
|
|||
|
|
* @param {Object} data - 订单数据
|
|||
|
|
* @returns {Object} 解密后的数据
|
|||
|
|
*/
|
|||
|
|
function decryptOrderFields(data) {
|
|||
|
|
if (!data || typeof data !== 'object') {
|
|||
|
|
return data;
|
|||
|
|
}
|
|||
|
|
const decryptedData = { ...data };
|
|||
|
|
|
|||
|
|
ENCRYPTED_FIELDS.forEach(field => {
|
|||
|
|
if (decryptedData[field] && typeof decryptedData[field] === 'string' && decryptedData[field].trim() !== '') {
|
|||
|
|
// 先判断是否已加密,如果未加密则跳过解密
|
|||
|
|
if (!isEncrypted(decryptedData[field], field)) {
|
|||
|
|
return; // 跳过此字段
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
decryptedData[field] = Sm4Util.decryptDataForSm3(decryptedData[field]);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error(`解密字段 ${field} 失败:`, error.message);
|
|||
|
|
// 解密失败时保留原值
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return decryptedData;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 批量解密订单列表的敏感字段
|
|||
|
|
* @param {Array} list - 订单列表
|
|||
|
|
* @returns {Array} 解密后的订单列表
|
|||
|
|
*/
|
|||
|
|
function decryptOrderList(list) {
|
|||
|
|
if (!Array.isArray(list)) {
|
|||
|
|
return list;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return list.map(item => decryptOrderFields(item));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
encryptOrderFields,
|
|||
|
|
decryptOrderFields,
|
|||
|
|
decryptOrderList,
|
|||
|
|
isEncrypted,
|
|||
|
|
ENCRYPTED_FIELDS
|
|||
|
|
};
|
|||
|
|
|