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

Postman中正常的API令牌请求在PHP脚本中提示缺少grant_type参数

问题描述

我通过API获取令牌时,Postman调用能正常拿到结果,但使用Postman生成的PHP cURL代码却返回AADSTS900144错误,提示请求体必须包含grant_type参数。代码中已明确设置该参数,本地和服务器环境都测试过,也参考了相关帖子,问题仍未解决。

错误信息

{"error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: 096b2d08-2a58-46b9-80a1-701867418c00\r\nCorrelation ID: c96623e2-475f-48c5-bced-a1e87a557705\r\nTimestamp: 2023-05-08 16:01:55Z","error_codes":[900144],"timestamp":"2023-05-08 16:01:55Z","trace_id":"096b2d08-2a58-46b9-80a1-701867418c00","correlation_id":"c96623e2-475f-48c5-bced-a1e87a557705","error_uri":"https://login.microsoftonline.com/error?code=900144"}

我的PHP代码

<?php
    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_URL => 'https://api.myendpoint.com/api/oauth2/v2.0/token',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 0,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_POSTFIELDS => array(
            'client_id' => '--hidden-for-obvious-reasons--',
            'client_secret' => '--hidden-for-obvious-reasons--',
            'grant_type' => 'client_credentials',
            'scope' => 'https://api.myendpoint.com/.default'
        ),
        CURLOPT_HTTPHEADER => array(
        'Content-Type: application/x-www-form-urlencoded',
        'Ocp-Apim-Subscription-Key: hidden-for-obvious-reasons'
        ),
    ));

    $response = curl_exec($curl);

    if (curl_errno($curl)) {
        echo 'cURL Error: ' . curl_error($curl);
        exit;
    }

    curl_close($curl);

    echo "<pre>$response</pre>";
?>

请问我可能遗漏了什么?为何请求体中的grant_type参数未被识别?


解决方案

问题出在请求体的格式处理上:当你给CURLOPT_POSTFIELDS传入数组时,PHP的cURL会自动将请求的Content-Type设置为multipart/form-data,但你手动指定了application/x-www-form-urlencoded,这就导致服务端无法正确解析你传入的参数,自然识别不到grant_type。

修复步骤

将CURLOPT_POSTFIELDS的数组转换为URL编码的字符串,使用http_build_query()函数处理即可:

<?php
    $curl = curl_init();
    // 先定义参数数组
    $postData = array(
        'client_id' => '--hidden-for-obvious-reasons--',
        'client_secret' => '--hidden-for-obvious-reasons--',
        'grant_type' => 'client_credentials',
        'scope' => 'https://api.myendpoint.com/.default'
    );

    curl_setopt_array($curl, array(
        CURLOPT_URL => 'https://api.myendpoint.com/api/oauth2/v2.0/token',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 0,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => 'POST',
        // 用http_build_query将数组转为URL编码字符串
        CURLOPT_POSTFIELDS => http_build_query($postData),
        CURLOPT_HTTPHEADER => array(
            'Content-Type: application/x-www-form-urlencoded',
            'Ocp-Apim-Subscription-Key: hidden-for-obvious-reasons'
        ),
    ));

    $response = curl_exec($curl);

    if (curl_errno($curl)) {
        echo 'cURL Error: ' . curl_error($curl);
        exit;
    }

    curl_close($curl);

    echo "<pre>$response</pre>";
?>

额外检查点

  1. 确认你的PHP环境中cURL扩展正常启用
  2. 检查参数值是否包含特殊字符,若有需确保http_build_query()能正确编码(该函数会自动处理)
  3. 可以通过开启cURL的调试选项(CURLOPT_VERBOSE)查看实际发送的请求头和体,确认格式是否正确

内容的提问来源于stack exchange,提问作者John Hubler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 08:57:13