订阅未返回201创建的HTTP状态代码

时间:2020-04-02 16:10:18

标签: microsoft-graph-api

我正在尝试使用Microsoft Graph订阅来订阅用户的邮箱。我尝试仅使用“创建的” changeType订阅特定用户的邮箱,通过使用我公司租户在AD中的客户端凭据创建的令牌(应用程序注册)来访问该邮箱。这是在我的开发环境(Laravel框架,使用Laravel Valet + ngrok)中完成的。

我可以在MS端成功创建订阅,将通知URL设置为ngrok URL,并且我可以通过验证等,但是MS似乎没有返回确认已使用“ 201 Created”响应创建订阅的确认像它说的那样应该放在docs中。

我可以确认自己的订阅有效,因为我可以向该邮箱发送电子邮件,并且ngrok捕获包含正确信息的请求-仅在成功创建webhook时,它不会返回201。

我希望得到此确认,因此我可以将Webhook的ID存储在应用程序中以供进一步使用(更新cron等的到期时间)。

很抱歉,如果我没有提供足够的信息来澄清问题-请询问相关细节。

我应该如何进行呢?

编辑-包括代码示例和路由

我使用的代码是一个自定义类,因此我无法包含所有内容,但这是如何构建的:

Microsoft.php

    public function subscribe($resource)
    {
        $this->verb = "POST";

        $this->endpoint = "/subscriptions";

        $this->body = [
            "notificationUrl" => config('app.env') === 'production'
                ? env('APP_URL') . route('ms', null, false)
                : env('NGROK_URL') . route('ms', null, false),
            "resource" => $resource,
            "expirationDateTime" => Carbon::now('UTC')->addDay(),
            "latestSupportedTlsVersion" => "v1_2"
        ];

        return $this;
    }

    public function changes($array)
    {
        $this->body['changeType'] = implode(",", $array);

        return $this;
    }

    public function send()
    {
        $token = $this->getToken()->token;

        $this->headers['Authorization'] = "Bearer $token";

        try {
            $response = $this->client
                ->request($this->verb, env('GRAPH_BASE_URL') . $this->endpoint, [
                    'headers' => $this->headers,
                    'body' => json_encode($this->body, JSON_UNESCAPED_SLASHES)
                ]);

            return json_decode($response->getBody());
        } catch (RequestException $e) {
            echo Psr7\str($e->getRequest());
            if ($e->hasResponse()) {
                echo Psr7\str($e->getResponse());
            }
        }
    }

运行命令的代码:

    public function handle()
    {
        $client = new MicrosoftClient();

        $webhookUrl = "users/" .
            env('AZURE_USER_ID') .
            "/mailFolders('Inbox')/messages";

        $changes = ['created'];

        $client->subscribe($webhookUrl)->changes($changes)->send();
    }

我的应用逻辑上的POST路由:

Route::post('[my webhook url]', function (Request $request) {
    if ($request->query('validationToken')) {
        // MS requires that successful requests must send back a 200 status code
        // using a plain text response
        return response($request->query('validationToken', 200))
            ->header('Content-Type', 'text/plain');
    } else {
        // just a regular webhook create/update...
        Log::info('Got email' . $request->input('value.resourceData'));
        Log::debug($request);
    }
})->name('ms');

^在else语句中,我在其中放置了日志,以查看Laravel是否捕获了任何额外的响应,但201不在那里。实际的Webhook通知已被捕获。

这是请求发送之前的转储,其格式为JSON,以确保美观:

POST /v1.0/subscriptions HTTP/1.1
User-Agent: GuzzleHttp/6.5.1 curl/7.68.0 PHP/7.4.3
Host: graph.microsoft.com
Content-Type: application/json
Authorization: Bearer [token]

{
  "notificationUrl":"[ngrok url]/[my chosen webhook endpoint]",
  "resource":"users/[user id]/mailFolders('Inbox')/messages",
  "expirationDateTime":"[24 hours after request made]",
  "latestSupportedTlsVersion":"v1_2",
  "changeType":"created"
}

这是我从MS回来以验证订阅的内容:

POST /[my webhook url]?validationToken=Validation%3a+Testing+client+application+reachability+for+subscription+Request-Id%3a+262d7fae-31c3-4541-8de0-c1fc26ddd41b HTTP/1.1

Host: ticket-system.test:60
Content-Length: 0
Content-Type: text/plain; charset=utf-8
X-Forwarded-For: 40.113.95.219
X-Forwarded-Proto: https
X-Original-Host: [ngrok url]

这是我发回MS的验证响应(验证令牌位):

HTTP/1.1 200 OK
Server: nginx/1.15.11
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/7.4.3
Cache-Control: no-cache, private
Date: Fri, 03 Apr 2020 08:42:34 GMT
Set-Cookie: XSRF-TOKEN=[XSRF token]; expires=Fri, 03-Apr-2020 10:42:34 GMT; Max-Age=7200; path=/
Set-Cookie: [sluggified_app_name]_session=[session]; expires=Fri, 03-Apr-2020 10:42:34 GMT; Max-Age=7200; path=/; httponly


75

Validation: Testing client application reachability for subscription Request-Id: 262d7fae-31c3-4541-8de0-c1fc26ddd41b

0

这是所有ngrok都说完之后所发现的全部内容,一个200的响应代码似乎只是在创建Webhook之前的“验证”请求:

Link to Webhook response example很抱歉,由于我是新会员,所以无法在此处发布图片。

如您所见,我似乎没有得到任何东西来确认webhook的详细信息。

1 个答案:

答案 0 :(得分:0)

主要问题是,通过查看代码,未使用(记录,存储等)订阅创建请求的响应。 (句柄方法的最后一行)。
如评论中所述,订阅信息将在响应中,而不是在到达端点的验证请求中。