const request = require("../../request"); const baseUrl = process.env.CONFIG_CA_BASE_URL; const appId = process.env.CONFIG_CA_APPID; const secret = process.env.CONFIG_CA_SECRET; const crypto = require("crypto"); const caRequest = (url, data) => { let params = { appId, signAlgo: "HmacSHA256", version: "1.0", ...data, }; params.signature = calculateSignature(params); console.log(params); console.log(`${baseUrl}${url}`); return request.main(`${baseUrl}${url}`, params, "POST"); }; /** * 添加用户 * @param {Object} param0 - 用户信息 * @param {string} param0.userName - 用户名 * @param {string} param0.idNumber - 身份证号码 * @param {string} param0.idType - 证件类型 * @param {string} param0.mobile - 手机号码 * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.userId - 用户ID */ exports.addUser = async ({ userName, idNumber, idType = "SF", mobile }) => { const { data, status, message } = await caRequest("addUser", { userName, idNumber, idType, mobile, }); if (status == 200) { return { success: true, message: "添加用户成功", data, }; } else { return { success: false, message: message || "添加用户失败", }; } }; /** * 产生激活码 * @param {string} userId - 用户ID * @returns {Promise} 返回包含用户信息的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.authCode - 激活码二维码,用于在手机端扫码发起用户 身份激活操作 整体生成二维码 * @returns {string} returns.data.code -用户激活码,用于在手机端输入激活码发起 用户身份激活操作 */ exports.getAuthCode = async ({ userId }) => { const { data, status, message } = await caRequest("getAuthCode", { userId, }); if (status == 200) { return { success: true, message: "生成激活码成功", data, }; } else { return { success: false, message: message || "生成激活码失败", }; } }; /** * 添加签名任务 * @param {Object} param0 - 任务信息 * @param {string} param0.userId - 用户ID * @param {string} param0.dataType - 任务类型 DATA:原文 * @param {string} param0.algo -签名算法(SM3withSM2) * @param {string} param0.data - 待签数据(必须是 base64 编码,默认最大不超过 1M,也可以通过配置文件重新设置。) * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.signDataId - 任务ID * @returns {string} returns.data.qrCode - 二维码,用于在手机端扫码发起签名操作 */ exports.addSignJob = async ({ userId, dataType, data }) => { const { data: res, status, message, } = await caRequest("addSignJob", { userId, dataType: "DATA", algo: "SM3withSM2", data, }); if (status == 200) { return { success: true, message: "添加签名任务成功", res, }; } else { return { success: false, message: message || "添加签名任务失败", }; } }; /** * 查询用户信息 * @param {string} idNumber - 身份证号码 * @param {string} idType - 证件类型 * @returns {Promise} 返回包含用户信息的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.userId - 用户ID */ exports.getUserInfo = async ({ uniqueId }) => { const { data, status, message } = await caRequest("queryUserInfo", { uniqueId, }); if (status == 200) { return { success: true, message: "查询用户信息成功", data, }; } else { return { success: false, message: message || "查询用户信息失败", }; } }; /** *查询印章图片 * @param {string} userId - 用户ID * @returns {Promise} 返回包含印章图片的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.image - 印章图片 */ exports.queryImage = async ({ userId }) => { const { data, status, message } = await caRequest("queryImage", { userId, }); if (status == 200) { return { success: true, message: "查询印章图片成功", data, }; } else { return { success: false, message: message || "查询印章图片失败", }; } }; /** * 获取签名结果 * @param {string} signDataId - 任务ID * @returns {Promise} 返回包含任务信息的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.signResult - 签名结果 * @returns {string} returns.data.signCert - 签名证书 * @returns {string} returns.data.jobStatus - 任务状态 * @returns {string} returns.data.dataType - 原文类型 */ exports.getSignResult = async (signDataId) => { const { data, status, message } = await caRequest("getSignResult", { signDataId, }); if (status == 200) { return { success: true, message: "获取签名结果成功", data, }; } else { return { success: false, message: message || "获取签名结果失败", }; } }; /** * 开启时效签名 * @param {string} userId - 用户ID * @param {string} timeRegion - 有效时间区间 * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.qrCode - 二维码,用于在手机端扫码发起签名操作 * @returns {string} returns.data.data - 原文 */ exports.startAutoSign = async ({ userId, timeRegion }) => { // 通过 uniqueId 获取 userId const { data, status, message } = await caRequest("startAutoSign", { userId, timeRegion, }); if (status == 200) { return { success: true, message: "开启时效签名成功", data: data.qrCode, }; } else { return { success: false, message: message || "开启时效签名失败", }; } }; /** * 查询时效签时间 * @param {string} userId - 用户ID * @param {string} signToken - 签名令牌 * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.region - 时间 * @returns {string} returns.data.autoSignStatus - 时效签状态 * @returns {string} returns.data.signToken - 签名令牌 * */ exports.queryAutoSignRegion = async ({ userId, signToken }) => { const { data, status, message } = await caRequest("queryAutoSignRegion", { userId, signToken, }); if (status == 200) { return { success: true, message: "查询时效签时间成功", data, }; } else { return { success: false, message: message || "查询时效签时间失败", }; } }; /** * 时效签名 * @param {Object} param0 - 任务信息 * @param {string} param0.userId - 用户ID * @param {string} param0.dataType - 任务类型 DATA:原文 * @param {string} param0.algo -签名算法(SM3withSM2) * @param {string} param0.data - 待签数据(必须是 base64 编码,默认最大不超过 1M,也可以通过配置文件重新设置。) * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.signResult - 签名结果 * @returns {string} returns.data.signCert - 签名证书 */ exports.autoSign = async ({ userId, data }) => { const { data: res, status, message, } = await caRequest("autoSign", { userId, dataType: "DATA", algo: "SM3withSM2", data, }); if (status == 200) { return { success: true, message: "时效签名成功", data: res, }; } else { return { success: false, message: message || "时效签名失败", }; } }; /** * 验证数据签名 * @param {Object} param0 - 任务信息 * @param {string} param0.userId - 用户ID * @param {string} param0.plain - 任务类型 DATA:原文 * @param {string} param0.signAlg -签名算法(SM3withSM2) * @param {string} param0.signValue - 签名值 时效签名时获取的 signResult * @param {string} param0.cert - 证书时 效签名时获取的signCert * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 */ exports.verifySign = async ({ plain, signValue, cert }) => { const { data: res, status, message, } = await caRequest("verifySign", { plain, signAlg: "SM3withSM2", signValue, cert, }); if (status == 200) { return { success: true, message: "验证数据签名成功", res, }; } else { return { success: false, message: message || "验证数据签名失败", }; } }; /** *产生时间戳 * @param {string} userId - 用户ID * @param {string} signDataId - 待签数据 * @param {string} oriData - 数据原文 * @param {string} attachCert - 是否返回证书 * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.tsResp - 时间戳响应 */ exports.createAndGetTssInfo = async ({ oriData, attachCert }) => { const { data, status, message } = await caRequest("createAndGetTssInfo", { oriData, attachCert, }); if (status == 200) { return { success: true, message: "产生时间戳成功", data, }; } else { return { success: false, message: message || "产生时间戳失败", }; } }; /** * 验证时间戳 * @param {string} userId - 用户ID * @param {string} signDataId - 待签数据 * @param {string} oriData - 时间戳ID * @param {string} tsResp - 时间戳响应 * @returns {Promise} 返回包含操作结果的对象 * @returns {boolean} returns.status - 操作是否成功 * @returns {string} returns.message - 操作结果信息 * @returns {Object} returns.data - 操作结果数据 * @returns {string} returns.data.verifyRes - 时间戳响应 1 为时间戳有效 -1 为时间戳验证不通过 -2 为原文验证不通过 -3 为不是所信任的根 -4 证书未生效 -5 查询不到此证书 -6 为签发时间戳时服务器证书过期 */ exports.verifyTS = async ({ oriData, tsResp }) => { const { data, status, message } = await caRequest("verifyTS", { tsResp, oriData, }); if (status == 200) { return { success: true, message: "验证时间戳成功", data, }; } else { return { success: false, message: message || "验证时间戳失败", }; } }; /** * 取消时效签 */ exports.closeAutoSign = async ({ userId }) => { const { data, status, message } = await caRequest("endAutoSign", { userId, }); if (status == 200) { return { success: true, message: "关闭时效签成功", data, }; } else { return { success: false, message: message || "关闭时效签失败", }; } }; function calculateSignature(params) { // 过滤空值参数(根据文档:值为空的参数不参与签名) const filteredParams = {}; for (const key in params) { const value = params[key]; if (value !== null && value !== undefined && value !== "") { filteredParams[key] = value; } } // 按 ASCII 字典序排序参数 const sortedKeys = Object.keys(filteredParams).sort(); // 拼接 URL 键值对字符串 const stringA = sortedKeys .map((key) => `${key}=${filteredParams[key]}`) .join("&"); // 转换算法名称(HmacSHA256 -> sha256) const hmacAlgo = params.signAlgo ? params.signAlgo.replace(/^hmac/i, "").toLowerCase() : "sha256"; // 计算 HMAC const hmac = crypto.createHmac(hmacAlgo, secret); hmac.update(stringA, "utf8"); const signature = hmac.digest("base64"); return signature; }