You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zoom API 间歇性挂起问题求助及代码参考

Zoom API间歇性挂起导致脚本超时问题求助

我们开发了一款脚本,通过Zoom API从外部数据源同步联系人信息至Zoom通讯录,并将部分Contact Center数据存储至数据库供客服使用。整体运行正常,但遇到Zoom API间歇性挂起的问题:有时脚本运行顺畅,有时请求无法通过(已通过Zoom App日志确认)。按逻辑,脚本通过next_page_token分页查询,本该正常终止,但实际会持续等待直到服务器超时,似乎一直在等待Zoom API返回数据。

求问是否有人遇到过类似问题,或有潜在解决方法?


当前API调用函数

function getZoomApiData($method, $curl_url, $curl_password, array $post_data = array())
{
    $res_arr = $head_arr = $header_arr = array();
    $response = $data = "";

    $curl = curl_init();

    switch($method)
    {
        case "POST":
            curl_setopt($curl, CURLOPT_POST, 1);

            if(!empty($post_data))
            {
                //$data = flattenHttpArrayHelperZoom($post_data);/// does not work for some reason
                //$curl_url = sprintf("%s?%s", $curl_url, http_build_query($post_data));
                curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($post_data));
            }
            break;
        case "PATCH":
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');

            if(!empty($post_data))
            {
                //$data = flattenHttpArrayHelperZoom($post_data);/// does not work for some reason
                //$curl_url = sprintf("%s?%s", $curl_url, http_build_query($post_data));
                curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($post_data));
            }
            break;
        case "PUT":
            curl_setopt($curl, CURLOPT_PUT, 1);
            if(!empty($post_data))
            {
                $curl_url = sprintf("%s?%s", $curl_url, http_build_query($post_data));
            }
            break;
        case "DELETE":
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
            if(!empty($post_data))
            {
                $curl_url = sprintf("%s?%s", $curl_url, http_build_query($post_data));
            }
            break;
        default:
            if(!empty($post_data))
            {
                $curl_url = sprintf("%s?%s", $curl_url, http_build_query($post_data));
            }
    }

    curl_setopt($curl, CURLOPT_URL, $curl_url);

    $authorization = "Authorization: Bearer " . $curl_password;
    if($method == "POST" || $method == "PATCH")
    {
        curl_setopt($curl, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
    }else
    {
        curl_setopt($curl, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/x-www-form-urlencoded'));
    }


    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($curl, CURLOPT_VERBOSE, 1);
    curl_setopt($curl, CURLOPT_HEADER, 1);

    //// TESTING - OUTPUT REQUEST DATA ////
    // $request = curl_getinfo($curl);
    // echo "<pre>";
    // print_r($request);
    // echo "</pre>";
    ///////////////////////////////////////

    $response = curl_exec($curl);

    $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);

    $headers = substr($response, 0, $header_size);
    $head_arr = explode(PHP_EOL, $headers);
    foreach($head_arr as $key => $value)
    {
        if($key === 0)
        {
            $header_arr['http_code'] = $head_arr[$key];
        }else
        {
            $temp_arr = explode(': ', $head_arr[$key]);
            if(isset($temp_arr[0], $temp_arr[1]))
            {
                $header_arr[$temp_arr[0]] = $temp_arr[1];
            }
        }
    }

    $response_body = substr($response, $header_size);
    $res_arr = json_decode($response_body, true);

    curl_close($curl);
    usleep(500 * 1000);
    return array("header_arr"=>$header_arr, "body_arr"=>$res_arr);
}

API调用示例

function listAllQueueEngagements($access_token, $date_from, $date_to, $queue_id)
{
    $output_arr = array();
    $curl_url = "https://api.zoom.us/v2/contact_center/engagements";
    $curl_method = "GET";
    $next_page_token = "";

    do
    {
        $post_data = array(
            "queue_id"=>$queue_id,
            "from"=>$date_from,
            "to"=>$date_to,
            "page_size"=>75,
            "next_page_token"=> $next_page_token
        );

        $res_arr = getZoomApiData($curl_method, $curl_url, $access_token, $post_data);
        if(isset($res_arr['body_arr']['next_page_token']))
        {
            $next_page_token = $res_arr['body_arr']['next_page_token'];
        }else
        {
            $next_page_token = "";
        }
        if(isset($res_arr['body_arr']['engagements']))
        {
            $output_arr = array_merge($output_arr, $res_arr['body_arr']['engagements']);
        }
    }while ($next_page_token !== '');

    return $output_arr;
}

潜在解决方法

1. 给CURL设置超时时间

当前代码未设置CURL超时参数,一旦API无响应,脚本会无限等待直到服务器超时。添加以下参数到getZoomApiData函数中:

// 设置连接超时(10秒)
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
// 设置总请求超时(30秒)
curl_setopt($curl, CURLOPT_TIMEOUT, 30);

2. 增加CURL错误处理

检查curl_exec返回值,请求失败时记录错误并终止循环,避免死等:
修改getZoomApiData中$response = curl_exec($curl);后的逻辑:

if($response === false) {
    $error = curl_error($curl);
    curl_close($curl);
    error_log("Zoom API请求失败: " . $error);
    return array("header_arr"=>[], "body_arr"=>[], "error"=>$error);
}

同时在listAllQueueEngagements中处理错误:

$res_arr = getZoomApiData($curl_method, $curl_url, $access_token, $post_data);
if(isset($res_arr['error'])) {
    error_log("获取队列数据失败: " . $res_arr['error']);
    $next_page_token = "";
    continue;
}

3. 优化分页逻辑,增加重试机制

针对间歇性失败,添加重试逻辑(调用方示例):

$max_retries = 3;
$retry_count = 0;
do {
    $res_arr = getZoomApiData($curl_method, $curl_url, $access_token, $post_data);
    if(isset($res_arr['error'])) {
        $retry_count++;
        if($retry_count >= $max_retries) {
            error_log("重试次数耗尽,终止请求");
            $next_page_token = "";
            break;
        }
        usleep(1000 * 1000); // 重试前延长等待时间
        continue;
    }
    // 原有处理逻辑
    if(isset($res_arr['body_arr']['next_page_token']))
    {
        $next_page_token = $res_arr['body_arr']['next_page_token'];
    }else
    {
        $next_page_token = "";
    }
    if(isset($res_arr['body_arr']['engagements']))
    {
        $output_arr = array_merge($output_arr, $res_arr['body_arr']['engagements']);
    }
} while ($next_page_token !== '');

4. 完善响应校验

当API响应无法解析为JSON时,终止循环:
在getZoomApiData中添加JSON解析校验:

$res_arr = json_decode($response_body, true);
if(json_last_error() !== JSON_ERROR_NONE) {
    error_log("Zoom API响应解析失败: " . json_last_error_msg());
    return array("header_arr"=>$header_arr, "body_arr"=>[], "error"=>"JSON解析失败");
}

5. 适配Zoom API速率限制

检查API返回的速率限制头信息,剩余请求不足时延长等待:

// 在getZoomApiData中添加
if(isset($header_arr['X-RateLimit-Remaining']) && $header_arr['X-RateLimit-Remaining'] < 5) {
    usleep(2000 * 1000); // 延长等待至2秒
}

内容的提问来源于stack exchange,提问作者Lukas Reeves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:55:14