阅读量:2
无需安装sdk扩展包,直接引入类即可使用
V3版本请求体&签名机制:自研请求体和签名机制 - 阿里云SDK - 阿里云
模版内容:
<?php namespace common\components; use common\constant\UserConst; use common\models\bee\SmsReferer; use common\models\bee\SmsStatistics; use yii\base\Component; use yii\helpers\Json; class AlSms { public $ALGORITHM = 'ACS3-HMAC-SHA256'; public $AccessKeyId; public $AccessKeySecret; const REGISTER_NEW = 'register_new'; const REGISTER_APPROVED = 'register_approved'; const CODE_MAP = [ self::REGISTER_NEW => 'SMS_468995712' //模版code ]; /** * @see https://help.aliyun.com/zh/sdk/product-overview/v3-request-structure-and-signature?spm=a2c4g.11186623.0.0.3bfd52d6SOjFjU#sectiondiv-zua-ikm-33s * @title main */ public function __construct() { date_default_timezone_set('UTC'); // 设置时区为GMT $this->AccessKeyId = getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'); // 从环境变量中获取RAM用户Access Key ID $this->AccessKeySecret = getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'); // 从环境变量中获取RAM用户Access Key Secret $this->ALGORITHM = 'ACS3-HMAC-SHA256'; // 设置加密算法 } public function main() { // RPC接口请求 $request = $this->createRequest('POST', '/', 'ecs.cn-beijing.aliyuncs.com', 'DescribeRegions', '2014-05-26'); $request['queryParam']= ['RegionId' => 'cn-beijing']; // ROA接口POST请求 // $request = $this->createRequest('POST', '/clusters', 'cs.cn-beijing.aliyuncs.com', 'CreateCluster', '2015-12-15'); // $this->addRequestBody($request, [ // 'name' => 'PhoneNumbers', // 'region_id' => 'cn-beijing', // 'cluster_type' => 'ExternalKubernetes', // 'vpcid' => 'vpc-2zeo42r27y4opXXXXXXXX', // 'service_cidr' => '172.16.5.0/20', // 'security_group_id' => 'sg-2zeh5ta2ikljXXXXXXXX', // "vswitch_ids" => [ // "vsw-2zeuntqtklsk0XXXXXXXX" // ], // ]); // ROA接口GET请求 // canonicalUri如果存在path参数,需要对path参数encode,rawurlencode({path参数}) // $cluster_id = 'cb7cd6b9bde934f6193801878XXXXXXXX'; // $canonicalUri = sprintf("/clusters/%s/resources", rawurlencode($cluster_id)); // $request = $this->createRequest('GET', $canonicalUri, 'cs.cn-beijing.aliyuncs.com', 'DescribeClusterResources', '2015-12-15'); // $request['queryParam'] = [ // 'with_addon_resources' => true, // ]; $this->getAuthorization($request); $this->callApi($request); } /** * @title createRequest * * @param $httpMethod 请求类型 * @param $canonicalUri * @param $host 请求地址 * @param $xAcsAction 请求方法 * @param $xAcsVersion 请求版本 * * @return * @date 2024/7/17 */ private function createRequest($httpMethod, $canonicalUri, $host, $xAcsAction, $xAcsVersion) { $headers = [ 'host' => $host, 'x-acs-action' => $xAcsAction, 'x-acs-version' => $xAcsVersion, 'x-acs-date' => gmdate('Y-m-d\TH:i:s\Z'), 'x-acs-signature-nonce' => bin2hex(random_bytes(16)), ]; return [ 'httpMethod' => $httpMethod, 'canonicalUri' => $canonicalUri, 'host' => $host, 'headers' => $headers, 'queryParam' => [], 'body' => null, ]; } private function addRequestBody(&$request, $bodyData) { $request['body'] = json_encode($bodyData, JSON_UNESCAPED_UNICODE); $request['headers']['content-type'] = 'application/json; charset=utf-8'; } private function getAuthorization(&$request) { $canonicalQueryString = $this->buildCanonicalQueryString($request['queryParam']); $hashedRequestPayload = hash('sha256', $request['body'] ?? ''); $request['headers']['x-acs-content-sha256'] = $hashedRequestPayload; $canonicalHeaders = $this->buildCanonicalHeaders($request['headers']); $signedHeaders = $this->buildSignedHeaders($request['headers']); $canonicalRequest = implode("\n", [ $request['httpMethod'], $request['canonicalUri'], $canonicalQueryString, $canonicalHeaders, $signedHeaders, $hashedRequestPayload, ]); $hashedCanonicalRequest = hash('sha256', $canonicalRequest); $stringToSign = $this->ALGORITHM . "\n" . $hashedCanonicalRequest; $signature = strtolower(bin2hex(hash_hmac('sha256', $stringToSign, $this->AccessKeySecret, true))); $authorization = $this->ALGORITHM . " Credential=" . $this->AccessKeyId . ",SignedHeaders=" . $signedHeaders . ",Signature=" . $signature; $request['headers']['Authorization'] = $authorization; } private function callApi($request) { try { // 通过cURL发送请求 $url = "https://" . $request['host'] . $request['canonicalUri']; // 初始化cURL会话 $ch = curl_init(); // 根据请求类型设置cURL选项 switch ($request['httpMethod']) { case "GET": break; case "POST": curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $request['body']); break; case "DELETE": curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); break; case "PUT": curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS, $request['body']); break; default: echo "Unsupported HTTP method: " . $request['body']; throw new \Exception("Unsupported HTTP method"); } // 添加请求参数到URL if (!empty($request['queryParam'])) { $url .= '?' . http_build_query($request['queryParam']); } // 设置cURL选项 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用SSL证书验证,请注意,这会降低安全性,不应在生产环境中使用(不推荐!!!) curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回而不是输出内容 curl_setopt($ch, CURLOPT_HTTPHEADER, $this->convertHeadersToArray($request['headers'])); // 添加请求头 // 发送请求 $result = curl_exec($ch); // 检查是否有错误发生 if (curl_errno($ch)) { echo "Failed to send request: " . curl_error($ch); } // 关闭cURL会话 curl_close($ch); } catch (\Exception $e) { // echo "Error: " . $e->getMessage(); return $e; } return Json::decode($result); } private function convertHeadersToArray($headers) { $headerArray = []; foreach ($headers as $key => $value) { $headerArray[] = $key . ': ' . $value; } return $headerArray; } private function buildCanonicalQueryString($queryParams) { ksort($queryParams); // Build and encode query parameters $params = []; foreach ($queryParams as $k => $v) { if (null === $v) { continue; } $str = rawurlencode($k); if ('' !== $v && null !== $v) { $str .= '=' . rawurlencode($v); } else { $str .= '='; } $params[] = $str; } return implode('&', $params); } private function buildCanonicalHeaders($headers) { // Sort headers by key and concatenate them uksort($headers, 'strcasecmp'); $canonicalHeaders = ''; foreach ($headers as $key => $value) { $canonicalHeaders .= strtolower($key) . ':' . trim($value) . "\n"; } return $canonicalHeaders; } private function buildSignedHeaders($headers) { // Build the signed headers string $signedHeaders = array_keys($headers); sort($signedHeaders, SORT_STRING | SORT_FLAG_CASE); return implode(';', array_map('strtolower', $signedHeaders)); } /** * 发送短信验证码 * @title sendSms */ public function sendSms($act_code,$mobile,$params=[],$code='') { $request = $this->createRequest('POST', '/', 'dysmsapi.aliyuncs.com', 'SendSms', '2017-05-25'); $request['queryParam']= [ 'PhoneNumbers' => $mobile, 'SignName' => '签名', 'TemplateCode' => self::CODE_MAP[$act_code], 'TemplateParam' => json_encode($params), ]; $this->getAuthorization($request); $resultArr = $this->callApi($request); if($resultArr['Code'] != "OK"){ return [ 'code'=>0, 'msg'=>$resultArr['Message'] ]; } return [ 'code'=>200, 'msg'=>'ok' ]; } } $AlSms = new AlSms(); $AlSms->sendSms('register_new',13500002000,['code'=>1234]);