本文目录导读:

我来为你提供一个完整的PHP工资条加密文件生成和推送方案。
整体架构方案
<?php
// 工资条加密处理类
class SalarySlipEncryptor {
private $encryptionKey;
private $cipher = 'aes-256-gcm';
public function __construct($key) {
$this->encryptionKey = hash('sha256', $key, true);
}
/**
* 加密工资条数据
*/
public function encrypt($data) {
$iv = openssl_random_pseudo_bytes(12);
$tag = '';
$encrypted = openssl_encrypt(
json_encode($data),
$this->cipher,
$this->encryptionKey,
OPENSSL_RAW_DATA,
$iv,
$tag,
'',
16
);
// 返回 base64 编码的加密数据
return base64_encode($iv . $tag . $encrypted);
}
/**
* 解密工资条数据
*/
public function decrypt($encryptedData) {
$data = base64_decode($encryptedData);
$iv = substr($data, 0, 12);
$tag = substr($data, 12, 16);
$encrypted = substr($data, 28);
$decrypted = openssl_decrypt(
$encrypted,
$this->cipher,
$this->encryptionKey,
OPENSSL_RAW_DATA,
$iv,
$tag
);
return json_decode($decrypted, true);
}
}
// 工资条生成器
class SalarySlipGenerator {
private $db;
private $encryptor;
public function __construct($db, $encryptionKey) {
$this->db = $db;
$this->encryptor = new SalarySlipEncryptor($encryptionKey);
}
/**
* 生成单个员工的工资条
*/
public function generateSlip($employeeId, $year, $month) {
// 获取员工工资数据
$salaryData = $this->getSalaryData($employeeId, $year, $month);
// 添加元数据
$slipData = [
'employee_id' => $employeeId,
'employee_name' => $salaryData['name'],
'department' => $salaryData['department'],
'year' => $year,
'month' => $month,
'generated_at' => date('Y-m-d H:i:s'),
'salary_details' => [
'basic_salary' => $salaryData['basic_salary'],
'performance_bonus' => $salaryData['performance_bonus'],
'overtime_pay' => $salaryData['overtime_pay'],
'allowance' => $salaryData['allowance'],
'social_insurance' => $salaryData['social_insurance'],
'housing_fund' => $salaryData['housing_fund'],
'tax' => $salaryData['tax'],
'deductions' => $salaryData['deductions'],
'net_salary' => $salaryData['net_salary']
],
'checksum' => $this->calculateChecksum($salaryData)
];
// 加密工资条
$encryptedSlip = $this->encryptor->encrypt($slipData);
// 保存加密后的工资条
$this->saveEncryptedSlip($employeeId, $year, $month, $encryptedSlip);
return [
'encrypted_data' => $encryptedSlip,
'file_name' => "salary_{$employeeId}_{$year}{$month}.enc"
];
}
/**
* 批量生成工资条
*/
public function generateAllSlips($year, $month) {
$employees = $this->getAllEmployees();
$results = [];
foreach ($employees as $employee) {
try {
$result = $this->generateSlip($employee['id'], $year, $month);
$results[] = [
'employee_id' => $employee['id'],
'employee_name' => $employee['name'],
'status' => 'success',
'file_name' => $result['file_name']
];
} catch (Exception $e) {
$results[] = [
'employee_id' => $employee['id'],
'employee_name' => $employee['name'],
'status' => 'failed',
'error' => $e->getMessage()
];
}
}
return $results;
}
/**
* 生成加密文件
*/
public function createEncryptedFile($employeeId, $year, $month, $outputDir) {
$slipData = $this->generateSlip($employeeId, $year, $month);
// 创建目录
if (!is_dir($outputDir)) {
mkdir($outputDir, 0755, true);
}
// 保存加密文件
$filePath = $outputDir . '/' . $slipData['file_name'];
file_put_contents($filePath, $slipData['encrypted_data']);
// 保存元数据文件
$metaData = [
'employee_id' => $employeeId,
'file_name' => $slipData['file_name'],
'encrypted_at' => date('Y-m-d H:i:s'),
'expires_at' => date('Y-m-d H:i:s', strtotime('+30 days'))
];
$metaFilePath = $outputDir . '/' . pathinfo($filePath, PATHINFO_FILENAME) . '.meta';
file_put_contents($metaFilePath, json_encode($metaData));
return $filePath;
}
private function calculateChecksum($data) {
return hash('sha256', json_encode($data));
}
private function getSalaryData($employeeId, $year, $month) {
// 从数据库获取工资数据
$stmt = $this->db->prepare("
SELECT e.name, e.department,
s.*
FROM salaries s
JOIN employees e ON s.employee_id = e.id
WHERE s.employee_id = ? AND s.year = ? AND s.month = ?
");
$stmt->execute([$employeeId, $year, $month]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
private function getAllEmployees() {
// 获取所有在职员工
$stmt = $this->db->query("SELECT id, name FROM employees WHERE status = 'active'");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
private function saveEncryptedSlip($employeeId, $year, $month, $encryptedData) {
// 保存到数据库
$stmt = $this->db->prepare("
INSERT INTO encrypted_salary_slips
(employee_id, year, month, encrypted_data, created_at)
VALUES (?, ?, ?, ?, NOW())
ON DUPLICATE KEY UPDATE encrypted_data = ?, updated_at = NOW()
");
$stmt->execute([$employeeId, $year, $month, $encryptedData, $encryptedData]);
}
}
// 邮件推送类
class SalarySlipMailer {
private $mailer;
private $smtpConfig;
public function __construct($smtpConfig) {
$this->smtpConfig = $smtpConfig;
$this->initMailer();
}
private function initMailer() {
// 使用PHPMailer或SwiftMailer
$this->mailer = new PHPMailer\PHPMailer\PHPMailer();
$this->mailer->isSMTP();
$this->mailer->Host = $this->smtpConfig['host'];
$this->mailer->SMTPAuth = true;
$this->mailer->Username = $this->smtpConfig['username'];
$this->mailer->Password = $this->smtpConfig['password'];
$this->mailer->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
$this->mailer->Port = $this->smtpConfig['port'];
$this->mailer->setFrom($this->smtpConfig['from_email'], '薪资系统');
$this->mailer->CharSet = 'UTF-8';
}
/**
* 推送工资条到员工邮箱
*/
public function sendSalarySlip($employee, $encryptedFilePath, $decryptKey) {
try {
$this->mailer->clearAddresses();
$this->mailer->addAddress($employee['email'], $employee['name']);
$this->mailer->Subject = "{$employee['name']},您的{$employee['month']}月工资条已生成";
// 构建邮件内容
$emailBody = $this->buildEmailContent($employee, $decryptKey);
$this->mailer->isHTML(true);
$this->mailer->Body = $emailBody;
$this->mailer->AltBody = strip_tags($emailBody);
// 添加加密附件
$this->mailer->addAttachment(
$encryptedFilePath,
'salary_slip.enc'
);
// 添加解密说明附件
$decryptGuidePath = $this->createDecryptGuide($decryptKey);
$this->mailer->addAttachment(
$decryptGuidePath,
'解密说明.txt'
);
return $this->mailer->send();
} catch (Exception $e) {
throw new Exception("发送失败: " . $e->getMessage());
}
}
/**
* 批量推送工资条
*/
public function batchSendSalarySlips($slipList) {
$results = [];
foreach ($slipList as $slip) {
try {
$sent = $this->sendSalarySlip(
$slip['employee'],
$slip['file_path'],
$slip['decrypt_key']
);
$results[] = [
'employee_id' => $slip['employee']['id'],
'status' => $sent ? 'success' : 'failed',
'sent_at' => date('Y-m-d H:i:s')
];
} catch (Exception $e) {
$results[] = [
'employee_id' => $slip['employee']['id'],
'status' => 'failed',
'error' => $e->getMessage()
];
}
}
return $results;
}
private function buildEmailContent($employee, $decryptKey) {
return "
<html>
<body style='font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;'>
<h2 style='color: #333;'>尊敬的 {$employee['name']} 您好:</h2>
<p style='color: #666; line-height: 1.6;'>
{$employee['year']}年{$employee['month']}月的工资条已生成,请查收附件。
</p>
<div style='background-color: #f5f5f5; padding: 20px; border-radius: 5px; margin: 20px 0;'>
<h3 style='color: #333; margin-top: 0;'>📁 文件说明</h3>
<ul style='color: #666; line-height: 1.6;'>
<li>附件文件:salary_slip.enc(加密工资条文件)</li>
<li>文件格式:使用 AES-256-GCM 加密</li>
<li>有效期:30天</li>
</ul>
<h3 style='color: #333; margin-top: 20px;'>🔑 解密密钥</h3>
<div style='background-color: #fff; padding: 15px; border: 2px dashed #999; text-align: center;'>
<p style='margin: 0; font-size: 18px; font-weight: bold; color: #d32f2f; letter-spacing: 2px;'>
{$decryptKey}
</p>
<p style='color: #999; font-size: 12px; margin: 5px 0 0;'>请妥善保管此密钥,不要告知他人</p>
</div>
</div>
<div style='background-color: #fff3cd; padding: 15px; border-radius: 5px; margin: 20px 0;'>
<h3 style='color: #856404; margin-top: 0;'>⚠️ 安全提示</h3>
<ul style='color: #856404;'>
<li>请勿将解密密钥告诉他人</li>
<li>公司不会通过任何方式索取您的解密密钥</li>
<li>如发现异常,请立即联系HR部门</li>
</ul>
</div>
<p style='color: #999; font-size: 12px;'>
此邮件由系统自动发送,请勿回复。<br>
如有问题请联系 HR 部门。
</p>
</body>
</html>
";
}
private function createDecryptGuide($decryptKey) {
$guideContent = "工资条文件解密指南\n";
$guideContent .= "====================\n\n";
$guideContent .= "1. 打开解密工具网页: https://your-company.com/decrypt\n";
$guideContent .= "2. 上传附件中的 salary_slip.enc 文件\n";
$guideContent .= "3. 输入您的个人解密密钥: {$decryptKey}\n";
$guideContent .= "4. 点击"解密"按钮查看工资条\n\n";
$guideContent .= "注意事项:\n";
$guideContent .= "- 请妥善保管您的解密密钥\n";
$guideContent .= "- 文件有效期为30天\n";
$guideContent .= "- 如遇问题请联系IT部门\n";
$tmpPath = tempnam(sys_get_temp_dir(), 'decrypt_guide_');
file_put_contents($tmpPath, $guideContent);
return $tmpPath;
}
}
使用示例
<?php
// 配置文件
$config = [
'db' => [
'host' => 'localhost',
'dbname' => 'salary_db',
'username' => 'root',
'password' => 'password'
],
'encryption' => [
'master_key' => 'your-master-encryption-key-here'
],
'smtp' => [
'host' => 'smtp.company.com',
'port' => 587,
'username' => 'noreply@company.com',
'password' => 'smtp-password',
'from_email' => 'noreply@company.com'
]
];
// 初始化
$db = new PDO(
"mysql:host={$config['db']['host']};dbname={$config['db']['dbname']}",
$config['db']['username'],
$config['db']['password']
);
$generator = new SalarySlipGenerator($db, $config['encryption']['master_key']);
$mailer = new SalarySlipMailer($config['smtp']);
// 1. 生成工资条
$year = date('Y');
$month = date('m') - 1; // 上个月
echo "开始生成工资条...\n";
$results = $generator->generateAllSlips($year, $month);
// 2. 创建加密文件并推送
foreach ($results as $result) {
if ($result['status'] === 'success') {
// 创建加密文件
$filePath = $generator->createEncryptedFile(
$result['employee_id'],
$year,
$month,
'/tmp/salary_slips/' . $year . $month
);
// 获取员工信息和解密密钥
$employee = [
'id' => $result['employee_id'],
'name' => $result['employee_name'],
'email' => getEmployeeEmail($result['employee_id']),
'year' => $year,
'month' => $month
];
// 生成个人解密密钥
$personalKey = generatePersonalKey($result['employee_id'], $year, $month);
// 发送邮件
$mailer->sendSalarySlip($employee, $filePath, $personalKey);
echo "已发送: {$result['employee_name']}\n";
}
}
// 辅助函数
function getEmployeeEmail($employeeId) {
global $db;
$stmt = $db->prepare("SELECT email FROM employees WHERE id = ?");
$stmt->execute([$employeeId]);
return $stmt->fetchColumn();
}
function generatePersonalKey($employeeId, $year, $month) {
// 生成个人解密密钥
$base = "{$employeeId}-{$year}-{$month}-personal-salt";
return substr(hash('sha256', $base), 0, 16);
}
安全性建议
-
密钥管理
- 主密钥定期更换
- 个人密钥不存储,通过算法生成
- 使用硬件安全模块(HSM)存储密钥
-
数据传输
- 使用HTTPS传输
- 邮件附件加密
- 文件下载有限时链接
-
访问控制
- 实施二次验证
- IP白名单限制
- 操作日志审计
-
合规性
- 符合GDPR/KYCC要求
- 数据保留期限限制
- 定期安全审计
这个方案提供了完整的加密、生成、推送流程,确保工资条数据的安全性和隐私保护。