使用PHP调用Azure Marketplace SaaS履约API解析订阅遇403错误
Azure SaaS履约API PHP调用403授权错误排查
我正在尝试用Azure履约API解析Azure Marketplace订阅,按照Microsoft SaaS履约API文档操作后,PHP端始终无法完成解析。目前能正常获取access_token,且在Postman中结合订阅者跳转到SaaS着陆页时从Azure门户拿到的购买标识token可以成功返回JSON响应,但PHP代码调用时出现403错误,提示“Authorization is missing, incorrect or invalid”。已经排除权限问题(Postman可正常运行),怀疑是授权参数格式有误,相关PHP代码如下:
<?php use Microsoft\Graph\Graph; use Microsoft\Graph\Http; use Microsoft\Graph\Model; use GuzzleHttp\Client; class GraphHelper { private static Client $tokenClient; private static Client $tokenWebClient; private static string $clientId = ''; private static string $tenantId = ''; private static string $clientSec = ''; private static string $graphUserScopes = ''; private static Graph $userClient; private static string $userToken; private static string $resolveToken; private static string $subToken= ''; public static function initializeGraphForUserAuth(): void { GraphHelper::$tokenClient = new Client(); GraphHelper::$clientId = $_ENV['CLIENT_ID']; GraphHelper::$clientSec = $_ENV['CLIENT_SECRET']; GraphHelper::$tenantId = $_ENV['TENANT_ID']; GraphHelper::$graphUserScopes = $_ENV['GRAPH_USER_SCOPES']; GraphHelper::$userClient = new Graph(); } public static function getUserToken(): void { //getting the access token $accessCodeRequestUrl = 'https://login.microsoftonline.com/'.GraphHelper::$tenantId.'/oauth2/token'; $tokenRequestUrl = 'https://marketplaceapi.microsoft.com/api/saas/subscriptions/resolve?api-version=2018-08-31'; $subToken = $_SESSION['subToken']; $tokenResponse = GraphHelper::$tokenClient->post($accessCodeRequestUrl, [ 'form_params' => [ 'client_id' => GraphHelper::$clientId, 'grant_type' => 'client_credentials', 'client_secret' => GraphHelper::$clientSec, 'resource' => '20e940b3-4c77-4b0b-9a53-9e16a1b010a7' ], // These options are needed to enable getting // the response body from a 4xx response 'http_errors' => false, 'curl' => [ CURLOPT_FAILONERROR => false ] ]); if ($tokenResponse->getStatusCode() == 200) { // Return the access_token $responseBody = json_decode($tokenResponse->getBody()->getContents()); GraphHelper::$resolveToken = $responseBody->access_token; $resolveAccessToken= $responseBody->access_token; } else if ($tokenResponse->getStatusCode() == 400) { // Check the error in the response body $responseBody = json_decode($tokenResponse->getBody()->getContents()); if (isset($responseBody->error)) { $error = $responseBody->error; // authorization_pending means we should keep polling if (strcmp($error, 'authorization_pending') != 0) { throw new Exception('Token endpoint returned '.$error, 100); } } } //resolving the subscription $resolveResponse = GraphHelper::$tokenClient->post($tokenRequestUrl, [ 'form_params' => [ 'content-type' => 'application/json', 'authorization' => 'Bearer '.$resolveAccessToken, 'x-ms-marketplace-token'=>$subToken ], // These options are needed to enable getting // the response body from a 4xx response 'http_errors' => false, 'curl' => [ CURLOPT_FAILONERROR => false ] ]); //test whether there is a reponse return $resolveResponse->getStatusCode(); // this returns a 403 - Authorization is missing, incorrect or invalid. } } ?>
问题原因与修复方案
核心问题是请求头参数放置位置错误:你把Authorization、Content-Type、x-ms-marketplace-token这些请求头参数放到了form_params数组中,而Guzzle的form_params是用来传递表单格式的请求体数据,并非设置请求头。
修改后的resolve接口调用代码:
$resolveResponse = GraphHelper::$tokenClient->post($tokenRequestUrl, [ 'headers' => [ 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $resolveAccessToken, 'x-ms-marketplace-token' => $subToken ], // POST请求需传递符合要求的JSON体,此处传空对象即可 'body' => json_encode([]), 'http_errors' => false, 'curl' => [ CURLOPT_FAILONERROR => false ] ]);
额外验证点:
- 确认
$subToken是完整有效的购买标识token,未被转义或截断 - 检查获取access_token时的
resource参数20e940b3-4c77-4b0b-9a53-9e16a1b010a7是否正确(这是Marketplace API的官方资源ID) - 确保Guzzle版本无兼容性问题,避免请求头处理异常
内容的提问来源于stack exchange,提问作者Tovs
相关产品推荐
相关产品推荐

