refactor: flatten src/AKSRT → src (drop theme-identifier dir)

Move all domain folders from src/AKSRT/{Domain} to src/{Domain}; remap
Composer PSR-4 "AKSRT\\": "src/"; update audit script + README + ADR
paths; remove dead tools/build-psr4-map.php (scanned deleted inc/classes).
This commit is contained in:
2026-08-02 22:06:06 +08:00
parent 56f1a8175f
commit 8c5b1555c9
285 changed files with 26 additions and 3600 deletions
+137
View File
@@ -0,0 +1,137 @@
<?php
/**
* @package AKSRT
*/
namespace AKSRT\Sms;
defined('ABSPATH') || exit;
class SMSProviderTencent implements ProviderInterface {
public function get_key(): string {
return 'tencent';
}
public function get_label(): string {
return __('腾讯云短信', 'aksrt');
}
public function validate_config(array $config): array {
$missing = [];
if (empty($config['sms_access_key'])) $missing[] = 'sms_access_key';
if (empty($config['sms_access_secret'])) $missing[] = 'sms_access_secret';
if (empty($config['sms_tencent_app_id'])) $missing[] = 'sms_tencent_app_id';
if (empty($config['sms_sign_name'])) $missing[] = 'sms_sign_name';
if (empty($config['sms_template_code'])) $missing[] = 'sms_template_code';
return $missing;
}
public function send_code(string $phone, string $code, array $config): array {
$secret_id = (string) ($config['sms_access_key'] ?? '');
$secret_key = (string) ($config['sms_access_secret'] ?? '');
$app_id = (string) ($config['sms_tencent_app_id'] ?? '');
$sign_name = (string) ($config['sms_sign_name'] ?? '');
$template_id = (string) ($config['sms_template_code'] ?? '');
$region = (string) ($config['sms_tencent_region'] ?? 'ap-guangzhou');
$result = $this->request($secret_id, $secret_key, $app_id, $sign_name, $template_id, $region, $phone, $code);
if (is_wp_error($result)) {
$this->log('error', $phone, $result->get_error_message());
return ['success' => false, 'message' => $result->get_error_message(), 'transport' => 'tc3_http'];
}
$body = json_decode(wp_remote_retrieve_body($result), true);
$response = $body['Response'] ?? [];
if (isset($response['SendStatusSet'][0]['Code']) && $response['SendStatusSet'][0]['Code'] === 'Ok') {
$this->log('sent', $phone, 'Ok');
return ['success' => true, 'message' => __('验证码已发送', 'aksrt'), 'transport' => 'tc3_http'];
}
$err_code = $response['Error']['Code'] ?? ($response['SendStatusSet'][0]['Code'] ?? 'Unknown');
$err_msg = $response['Error']['Message'] ?? ($response['SendStatusSet'][0]['Message'] ?? __('未知错误', 'aksrt'));
$this->log('error', $phone, "{$err_code}: {$err_msg}");
return ['success' => false, 'message' => sprintf('腾讯云: %s', $err_msg), 'transport' => 'tc3_http'];
}
public function get_status(array $config): array {
$missing = $this->validate_config($config);
return [
'provider' => $this->get_key(),
'configured' => empty($missing),
'available' => !empty($config['sms_enabled']) && empty($missing),
'verified' => !empty($config['sms_tencent_verified']),
'transport' => 'tc3_http',
'missing_fields' => $missing,
];
}
/**
* TC3-HMAC-SHA256 签名请求
*/
private function request(string $secret_id, string $secret_key, string $app_id, string $sign_name, string $template_id, string $region, string $phone, string $code) {
$service = 'sms';
$host = "{$service}.tencentcloudapi.com";
$action = 'SendSms';
$version = '2021-01-11';
$endpoint = "https://{$host}";
$payload = wp_json_encode([
'PhoneNumberSet' => [$phone],
'SmsSdkAppId' => $app_id,
'SignName' => $sign_name,
'TemplateId' => $template_id,
'TemplateParamSet' => [$code],
]);
$timestamp = time();
$date = gmdate('Y-m-d', $timestamp);
// Step 1: CanonicalRequest
$http_request_method = 'POST';
$canonical_uri = '/';
$canonical_querystring = '';
$content_type = 'application/json; charset=utf-8';
$canonical_headers = "content-type:{$content_type}\nhost:{$host}\nx-tc-action:" . strtolower($action) . "\n";
$signed_headers = 'content-type;host;x-tc-action';
$hashed_payload = hash('sha256', $payload);
$canonical_request = "{$http_request_method}\n{$canonical_uri}\n{$canonical_querystring}\n{$canonical_headers}\n{$signed_headers}\n{$hashed_payload}";
// Step 2: StringToSign
$algorithm = 'TC3-HMAC-SHA256';
$credential_scope = "{$date}/{$service}/tc3_request";
$hashed_request = hash('sha256', $canonical_request);
$string_to_sign = "{$algorithm}\n{$timestamp}\n{$credential_scope}\n{$hashed_request}";
// Step 3: Signature
$secret_date = hash_hmac('sha256', $date, "TC3{$secret_key}", true);
$secret_service = hash_hmac('sha256', $service, $secret_date, true);
$secret_signing = hash_hmac('sha256', 'tc3_request', $secret_service, true);
$signature = hash_hmac('sha256', $string_to_sign, $secret_signing);
// Step 4: Authorization header
$authorization = "{$algorithm} Credential={$secret_id}/{$credential_scope}, SignedHeaders={$signed_headers}, Signature={$signature}";
return wp_remote_post($endpoint, [
'timeout' => 10,
'headers' => [
'Authorization' => $authorization,
'Content-Type' => $content_type,
'Host' => $host,
'X-TC-Action' => $action,
'X-TC-Version' => $version,
'X-TC-Timestamp' => (string) $timestamp,
'X-TC-Region' => $region,
],
'body' => $payload,
]);
}
private function log(string $level, string $phone, string $message): void {
if (!defined('WP_DEBUG') || !WP_DEBUG) return;
$masked = substr($phone, 0, 3) . '****' . substr($phone, -4);
error_log(sprintf('[AKSRT SMS] [tencent] [%s] Phone: %s — %s', $level, $masked, $message));
}
}