阿里云短信PHP集成api类

news2024/9/21 4:27:57

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1933334.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git镜像链接

镜像链接https://registry.npmmirror.com/binary.html?pathgit-for-windows/ CNPM Binaries Mirror 1.git init 2.克隆 IDEA集成git git分支

WSL-Ubuntu20.04部署环境配置

1.更换Ubuntu软件仓库镜像源 为了在WSL上使用TensorRT进行推理加速&#xff0c;需要安装以下环境&#xff0c;下面将按以下顺序分别介绍安装、验证以及删除环境&#xff1a; #1.C环境配置 gcc、gdb、g #2.gpu环境 cuda、cudnn #3.Cmake环境 CMake #4.OpenCV环境 OpenCV #5.Ten…

13.8和13.11哪个大?网友吵翻!多个大模型翻车

13.8和13.11哪个更大&#xff1f; 没想到 这样一道简单的数学题 竟引发网友激烈讨论 还难倒了不少大模型 13.8%和13.11%哪个大&#xff1f; 《歌手》排名引网友热议 上周 最新一期的《歌手》公布排名 孙楠得票13.8% 外国歌手香缇莫得票13.11% 引发了网友对排名的质疑…

3.动态规划.题目3

3.动态规划.题目3 题目23.买卖股票的最佳时机3-困难24.买卖股票的最佳时机425.买卖股票的最佳时机含冷冻期26.买卖股票的最佳时机含手续费27.最长递增子序列28.最长连续递增序列29.最长重复子数组30.最长公共子序列31.不相交的线 编辑距离总结 题目 23.买卖股票的最佳时机3-困…

探索LangFlow 1.0:多代理RAG应用程序的未来

在当今快速发展的科技时代&#xff0c;自动化和人工智能&#xff08;AI&#xff09;已经成为了许多企业和个人提高效率的关键工具。对于那些对科技有兴趣的用户来说&#xff0c;寻找一种既创新又易于使用的解决方案是非常重要的。今天&#xff0c;我们将介绍一款名为LangFlow的…

排序算法(4)之快速排序(1)

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 排序算法(4)之快速排序(1) 收录于专栏【数据结构初阶】 本专栏旨在分享学习数据结构学习的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目…

【HarmonyOS】HarmonyOS NEXT学习日记:三、初识ArkUI

【HarmonyOS】HarmonyOS NEXT学习日记&#xff1a;三、初识ArkUI 忘掉HTML和CSS&#xff0c;ArkUI里构建页面的最小单位就是 “组件”&#xff0c;所以今天的目标就是认识一些常用的基础组件&#xff0c;以及他们的用法&#xff0c;对ArkUI形成一个基本认识。 基本组成 了解…

Java反射机制基础知识赏析、接口、实现类、方法

前言 最近打算手写一个RPC&#xff0c;但奈何自己Java基础知识中的反射就很欠缺&#xff0c;第一章就看不太懂了&#xff0c;特地编写了几个小Demo验证一下Java中关于反射的基础知识。 目录组织结构 代码编写 // TestService接口 package reflect.testServices;import main.v…

图神经网络实战(17)——深度图生成模型

图神经网络实战&#xff08;17&#xff09;——深度图生成模型 0. 前言1. 变分图自编码器2. 自回归模型3. 生成对抗网络小结系列链接 0. 前言 我们已经学习了经典的图生成算法&#xff0c;虽然它们能够完成图生成任务&#xff0c;但也存在一些问题&#xff0c;促使基于图神经网…

pytorch学习(四)绘制loss和correct曲线

这一次学习的时候静态绘制loss和correct曲线&#xff0c;也就是在模型训练完成后&#xff0c;对统计的数据进行绘制。 以minist数据训练为例子 import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvisi…

GESP CCF C++ 三级认证真题 2024年6月

第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级&#xff0c;那他可以选择的认证语言有&#xff08;&#xff09;种。 A. 1 B. 2 C. 3 D. 4 第 2 题 下面流程图在yr输入2024时&#xff0c;可以判定yr代表闰年&#xff0c;并输出 2月是29天 &#x…

python-字符金字塔(赛氪OJ)

[题目描述] 请打印输出一个字符金字塔&#xff0c;字符金字塔的特征请参考样例。输入格式&#xff1a; 输入一个字母&#xff0c;保证是大写。输出格式&#xff1a; 输出一个字母金字塔&#xff0c;输出样式见样例。样例输入 C样例输出 A ABA …

【前端8】element ui常见页面布局:注意事项

【前端8】element ui常见页面布局&#xff1a;注意事项 写在最前面遇到的问题Element UI 常见页面布局&#xff1a;注意事项1. 了解基本布局组件常用的菜单1多一个下角 常用的菜单2 2. 栅格系统的使用3. 响应式布局4. Flex 布局的应用5. 避免滥用嵌套6. 处理边距和填充 小结 &a…

基于STC89C51单片机的烟雾报警器设计(煤气火灾检测报警)(含文档、源码与proteus仿真,以及系统详细介绍)

本篇文章论述的是基于STC89C51单片机的烟雾报警器设计的详情介绍&#xff0c;如果对您有帮助的话&#xff0c;还请关注一下哦&#xff0c;如果有资源方面的需要可以联系我。 目录 摘要 原理图 实物图 仿真图 元件清单 代码 系统论文 资源下载 摘要 随着现代家庭用火、…

TikTok内嵌跨境商城全开源_搭建教程/前端uniapp+后端源码

多语言跨境电商外贸商城 TikTok内嵌商城&#xff0c;商家入驻一键铺货一键提货 全开源完美运营&#xff0c;接在tiktok里面的商城内嵌&#xff0c;也可单独分开出来当独立站运营 二十一种语言&#xff0c;可以做很多国家的市场&#xff0c;支持商家入驻&#xff0c;多店铺等等…

服务器IP和电脑IP有什么不同

服务器IP和电脑IP有什么不同&#xff1f;在当今的信息化时代&#xff0c;IP地址作为网络世界中不可或缺的元素&#xff0c;扮演着举足轻重的角色。然而&#xff0c;对于非专业人士来说&#xff0c;服务器IP和电脑IP之间的区别往往模糊不清。本文旨在深入探讨这两者之间的不同&a…

若依前端和后端时间相差8小时

原因基类未设置时区 实体类继承 BaseEntity 加上timezone"GMT8" /** 创建时间 */ JsonFormat(pattern "yyyy-MM-dd HH:mm:ss" , timezone"GMT8") private Date createTime; 解决

golang程序性能提升改进篇之文件的读写---第一篇

背景&#xff1a;接手的项目是golang开发的&#xff08;本人初次接触golang&#xff09;经常出现oom。这个程序是计算和io密集型&#xff0c;调用流量属于明显有波峰波谷&#xff0c;但是因为各种原因&#xff0c;当前无法快速通过serverless或者动态在高峰时段调整资源&#x…

MViTv2:Facebook出品,进一步优化的多尺度ViT | CVPR 2022

论文将Multiscale Vision Transformers (MViTv2) 作为图像和视频分类以及对象检测的统一架构进行研究&#xff0c;结合分解的相对位置编码和残差池化连接提出了MViT的改进版本 来源&#xff1a;晓飞的算法工程笔记 公众号 论文: MViTv2: Improved Multiscale Vision Transforme…

Fiddler抓包过滤host及js、css等地址

1、如上图所示 在Filter页面中勾选Hide if URL contains&#xff1b;输入框输入 REGEX:\.(js|css|png|google|favicon\?.*) 隐藏掉包含js、css、png、google等的地址&#xff1a; Hide if URL contains: REGEX:\.(js|css|png|google|favicon\?.*) 2、使Filters设置生效 A…