75 lines
2.4 KiB
PHP
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);
|
|
}
|
|
}
|