Files
zyt/server/app/common/service/qywx/QywxPromotionCredentialCipher.php
T
2026-08-05 11:08:02 +08:00

75 lines
2.4 KiB
PHP

<?php
declare(strict_types=1);
namespace app\common\service\qywx;
use RuntimeException;
/** 企业微信推广凭证加密器:密钥仅来自服务器配置,密文可安全落库。 */
class QywxPromotionCredentialCipher
{
private const CIPHER = 'aes-256-gcm';
public static function encrypt(string $plain): string
{
if ($plain === '') {
return '';
}
$iv = random_bytes(12);
$tag = '';
$cipher = openssl_encrypt($plain, self::CIPHER, self::key(), OPENSSL_RAW_DATA, $iv, $tag);
if ($cipher === false) {
throw new RuntimeException('企业微信授权凭证加密失败');
}
return base64_encode(json_encode([
'v' => 1,
'iv' => base64_encode($iv),
'tag' => base64_encode($tag),
'data' => base64_encode($cipher),
], JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR));
}
public static function decrypt(string $payload): string
{
if ($payload === '') {
return '';
}
$json = base64_decode($payload, true);
$data = is_string($json) ? json_decode($json, true) : null;
if (!is_array($data)) {
throw new RuntimeException('企业微信授权凭证格式无效');
}
$iv = base64_decode((string) ($data['iv'] ?? ''), true);
$tag = base64_decode((string) ($data['tag'] ?? ''), true);
$cipher = base64_decode((string) ($data['data'] ?? ''), true);
if (!is_string($iv) || !is_string($tag) || !is_string($cipher)) {
throw new RuntimeException('企业微信授权凭证格式无效');
}
$plain = openssl_decrypt($cipher, self::CIPHER, self::key(), OPENSSL_RAW_DATA, $iv, $tag);
if ($plain === false) {
throw new RuntimeException('企业微信授权凭证解密失败,请检查 CREDENTIAL_KEY 是否发生变更');
}
return $plain;
}
private static function key(): string
{
$material = trim((string) config('qywx_promotion.credential_key', ''));
if ($material === '') {
$material = trim((string) config('qywx_promotion.suite_secret', ''));
}
if ($material === '') {
throw new RuntimeException('未配置企业微信推广凭证加密密钥');
}
return hash('sha256', $material, true);
}
}