阿里云短信PHP集成api类

无需安装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]);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值