Files
wordpress-theme-aksrt/inc/classes/class-aksrt-sms-signature-helper.php
T

88 lines
2.7 KiB
PHP

<?php
/**
* AKSRT SMS Signature Helper — 阿里云 API 签名助手
*
* 对齐 zibll 的 SignatureHelper 实现:POST 方式 + HMAC-SHA1 签名。
*
* @package AKSRT
* @link https://help.aliyun.com/document_detail/31426.html
*/
defined('ABSPATH') || exit;
class AKSRT_SMS_Signature_Helper {
/**
* 生成签名并发起请求
*
* @param string $accessKeyId AccessKeyId
* @param string $accessKeySecret AccessKeySecret
* @param string $domain API 域名
* @param array $params API 参数
* @param bool $https 是否使用 HTTPS
* @return array|WP_Error
*/
public function request(string $accessKeyId, string $accessKeySecret, string $domain, array $params, bool $https = true) {
$apiParams = array_merge([
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => uniqid((string) mt_rand(0, 0xffff), true),
'SignatureVersion' => '1.0',
'AccessKeyId' => $accessKeyId,
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
'Format' => 'JSON',
], $params);
ksort($apiParams);
$sortedQueryString = '';
foreach ($apiParams as $key => $value) {
$sortedQueryString .= '&' . $this->encode($key) . '=' . $this->encode((string) $value);
}
$stringToSign = 'POST&%2F&' . $this->encode(substr($sortedQueryString, 1));
$sign = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
$signature = $this->encode($sign);
$url = ($https ? 'https' : 'http') . "://{$domain}/";
$body = "Signature={$signature}{$sortedQueryString}";
return $this->fetchContent($url, $body);
}
/**
* URL 编码(对齐阿里云规范)
*/
private function encode(string $str): string {
$res = rawurlencode($str);
$res = str_replace('+', '%20', $res);
$res = str_replace('*', '%2A', $res);
$res = str_replace('%7E', '~', $res);
return $res;
}
/**
* 发送 HTTP POST 请求
*
* @return array|WP_Error
*/
private function fetchContent(string $url, string $body) {
$response = wp_remote_post($url, [
'timeout' => 10,
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
'x-sdk-client' => 'php/2.0.0',
],
'body' => $body,
]);
if (is_wp_error($response)) {
return $response;
}
$content = wp_remote_retrieve_body($response);
$decoded = json_decode($content, true);
return is_array($decoded) ? $decoded : ['raw' => $content];
}
}