泛化调用

更新时间:

阿里云V1.0 SDK支持一种通用的方式调用OpenAPI,此方式被称为泛化调用。本文将为您详细介绍如何使用泛化调用访问OpenAPI。

特点

  1. 轻量级:仅需安装Core包即可调用所有OpenAPI,无需依赖各产品的独立SDK。

  2. 快速迭代兼容性:当云产品尚未提供相应的SDK,或当新API发布但SDK未能及时更新时,可以使用泛化调用。这样,无需等待SDK的更新,即可及时调用最新发布的API接口。

更多介绍,请参见泛化调用与特化调用

使用说明

在使用泛化调用之前,必须手动获取并配置OpenAPI的版本号、请求路径、参数类型等元数据信息。可以通过查看OpenAPI元数据来获取有关OpenAPIAPI风格、请求参数、资源路径等相关信息。

安装核心SDK

Terminal中执行以下命令安装核心SDK。

composer require alibabacloud/client

调用OpenAPI

初始化请求客户端

通过在AlibabaCloud包中创建client以初始化请求客户端,并通过该Client发起OpenAPI调用。此处仅列举使用AccessKey(简称:AK)初始化客户端的方式,更多初始化方式请参见管理访问凭据

说明

为了避免凭据泄露,常见的方案是将其写入到环境变量中,具体操作请参见Linux、macOSWindows系统配置环境变量

use AlibabaCloud\Client\AlibabaCloud;   

   // getenv代表从环境变量获取AK,初始化客户端
    AlibabaCloud::accessKeyClient(
         getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
         getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
    )
    ->regionId('cn-hangzhou') // 指定区域
    ->asDefaultClient(); // 设为默认客户端  
  

配置OpenAPI信息及请求参数

通过AlibabaCloud包中的client来配置OpenAPI所需的公共请求参数及接口请求参数。关于更多公共请求参数的介绍及使用请参见进阶配置

说明

request的核心作用是通过标准化的请求配置流程,将原始API元数据(如版本号、路径、参数类型)和请求参数转化为有效的HTTP请求,最终返回原始响应数据。参数传递方式根据API风格和接口设计选择。

接口请求参数说明

请求参数应该如何传参需要查看接口对应的OpenAPI元数据,例如DescribeInstanceStatus的请求参数RegionId元数据中信息为{"name":"RegionId","in":"query",...}},其中"in":"query"表示RegionId通过options([ 'query' => [ 'key1' => 'value1'] ])传递。

描述

传参方式

请求参数显示"in":"query"时。

options([ 'query' => [ 'key1' => 'value1'] ])

说明

如果请求参数的类型是集合,那么参数应该按照'query' => [ 'key.1' => 'value1','key.2' => 'value2']...格式传参。

请求参数显示"in":"body""in": "formData"时。

options([ 'form_params' => [ 'key1' => 'value1'] ])

说明

如果请求参数的类型不是字符串类型,需要将参数值转为JSON字符串,并赋值给变量value。

        // query 查询参数,参数类型为集合时
        $instanceIDs = ["i-bp1axhql4dqXXXXXXXX", "i-bp124uve8zqXXXXXXXX"];
        // 普通参数
        $queryParams = [
            'RegionId' => 'cn-hangzhou',
            'PageNumber' => 1,
            'PageSize' => 30,
        ]; 
        // 处理集合参数(转换为InstanceId.1, InstanceId.2格式)
        foreach ($instanceIDs as $index => $id) {
            $queryKey = 'InstanceId.' . ($index + 1);
            $queryParams[$queryKey] = $id;
        }
 // 配置OpenAPI基本信息和请求参数
 $result = AlibabaCloud::rpc() // 接口风格:支持RPC、ROA。
                // 1.配置OpenAPI基本信息
                ->host('ecs.cn-hangzhou.aliyuncs.com') 
                ->product('Ecs') // 产品名称
                ->version('2014-05-26') // 注意版本号需要与API文档一致
                ->action('DescribeInstanceStatus') // API名称,当调用RPC风格API时,必须配置action()指定接口名称
                ->method('POST') // 请求方法:GET、POST
                ->setProtocolType('HTTPS') // 请求协议:HTTPS或HTTP,建议使用HTTPS。
                // ->pathPattern()  // 资源路径,ROA接口必传。RPC接口禁止设置该参数。
                // 2.配置请求参数
                ->options([
                    // 场景一:query参数通query设置
                    'query' => $queryParams
                    
                    // 场景二:body参数通过form_params设置
                    // 'form_params' => [ 
                    //     'key1' => 'value1',
                    //     'key2' => 'value2',
                    //     'key3' => 'value3',
                    // ],
                ])
  

发起请求

通过client调用request()发起请求。

 // 调用RPC风格API
 $result = AlibabaCloud::rpc()
           ->request()
 // 调用ROA风格API 
 // $result = AlibabaCloud::roa() 
 //         ->request()        
 // 返回值是 bytes 类型,包含RequestId以及OpenAPI的返回参数          
 print_r($result->toArray());       

代码示例

示例:调用RPC风格的API

以调用ECSDescribeRegions接口为例,展示如何使用泛化调用方式。

<?php

namespace AlibabaCloud\SDK\Sample;
require_once 'vendor/autoload.php';
use AlibabaCloud\Tea\Utils\Utils;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;

class Sample
{   
    public static function main()
    {

    // getenv代表从环境变量获取AK,初始化客户端
    AlibabaCloud::accessKeyClient(
         getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
         getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
    )
    ->regionId('cn-hangzhou') // 指定区域
    ->asDefaultClient(); // 设为默认客户端

        // query 查询参数,参数类型为集合时
        $instanceIDs = ["i-bp1axhql4dqXXXXXXXX", "i-bp124uve8zqXXXXXXXX"];
        // 普通参数
        $queryParams = [
            'RegionId' => 'cn-hangzhou',
            'PageNumber' => 1,
            'PageSize' => 30,
        ]; 
        // 处理集合参数(转换为InstanceId.1, InstanceId.2)
        foreach ($instanceIDs as $index => $id) {
            $queryKey = 'InstanceId.' . ($index + 1);
            $queryParams[$queryKey] = $id;
        }
        try {
            $result = AlibabaCloud::rpc()
                ->method('POST') // 请求方法
                ->verify(false) // 关闭证书校验
                ->debug(true)  // 开启日志
                ->setProtocolType('HTTPS') // 设置协议类型
                ->host('ecs.cn-hangzhou.aliyuncs.com') // 服务地址
                ->version('2014-05-26') // 注意版本号需要与API文档一致
                ->action('DescribeInstanceStatus') // 接口名称
                // 配置请求参数
                ->options([
                    'query' => $queryParams
                ])
                // 发起请求
                ->request();
            print_r($result->toArray());
        } catch (ClientException | ServerException $e) {
            echo $e->getErrorMessage();
        } catch (ServerException $exception) {
            print_r($exception->getErrorMessage());
        }
}
}

Sample::main();

示例:调用 RESTful(ROA)风格的 API

以下代码展示了如何使用泛化调用的方式调用容器服务的 DescribeClustersV1 接口:

<?php
namespace AlibabaCloud\SDK\Sample;
require_once 'vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;

class Sample
{
  public static function main()
    {
    try {
        $result = AlibabaCloud::roa()
                          ->regionId('cn-hangzhou') // 指定请求的地域,不指定则使用客户端地域、默认地域。
                          ->product('CS') // 指定产品。
                          ->version('2015-12-15') // 指定产品版本。
                          ->serviceCode('cs') // 设置 ServiceCode 以备寻址,非必须。
                          ->endpointType('openAPI') // 设置类型,非必须。
                          ->method('GET') // 指定请求方式。
                          ->host('cs.aliyuncs.com') // 指定域名则不会寻址,如认证方式为 Bearer Token 的服务则需要指定。
                          ->pathPattern('/api/v1/clusters') // API资源路径,当调用ROA风格API时,必须配置pathPattern()指定完整资源路径。从OpenAPI元数据中data.path获取资源路径。
                          ->request(); // 发起请求并返回结果对象,请求需要放在设置的最后面。
    print_r($result->toArray());
    } catch (ClientException $exception) {
    print_r($exception->getErrorMessage());
    } catch (ServerException $exception) {
    print_r($exception->getErrorMessage());
}
    }
}
Sample::main();

常见问题

  1. 报错提示“Fatal error: Uncaught AlibabaCloud\Client\Exception\ClientException: AccessKey ID cannot be empty in XXX”。

    问题原因:AK未正确配置。

    解决方案:

    1. 执行以下命令,检查您的环境变量中是否配置有ALIBABA_CLOUD_ACCESS_KEY_IDALIBABA_CLOUD_ACCESS_KEY_SECRET:

      Linux/macOS

      echo $ALIBABA_CLOUD_ACCESS_KEY_ID
      echo $ALIBABA_CLOUD_ACCESS_KEY_SECRET

      Windows

      echo %ALIBABA_CLOUD_ACCESS_KEY_ID%
      echo %ALIBABA_CLOUD_ACCESS_KEY_SECRET%

      若返回正确的AccessKey,则说明配置成功。如果返回为空或错误,请尝试重新设置,具体操作请参见Linux、macOSWindows系统配置环境变量

    2. 检查代码中AK相关内容是否存在错误。

      错误示例:

      AlibabaCloud::accessKeyClient(
               getenv('yourAccessKeyID'),
               getenv('yourAccessKeySecret')
          )
      说明

      此错误示例将getenv()的入参视为需要填入的AK,然而实际上该函数的功能是读取环境变量。当您在机器上设置环境变量名称为ALIBABA_CLOUD_ACCESS_KEY_IDALIBABA_CLOUD_ACCESS_KEY_SECRET时,getenv将能够获取其对应的值。

      正确示例

      AlibabaCloud::accessKeyClient(
               getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
               getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
          )