Featured image of post Как отправлять сообщения в Microsoft Teams из C++ (WinHTTP + Graph API)

Как отправлять сообщения в Microsoft Teams из C++ (WinHTTP + Graph API)

Как отправлять сообщения в Microsoft Teams из C++ (WinHTTP + Graph API)

Хотите автоматически отправлять сообщения в чат Microsoft Teams? Для этого отлично подойдет ** Microsoft Graph API **. В этой статье мы пошагово рассмотрим ** примеры кода на C++ с использованием WinHTTP ** и ** необходимые шаги для аутентификации API **.


🔧 Необходимая подготовка (настройка аутентификации Microsoft Graph API)

1. Регистрация приложения на портале Azure

Во-первых, чтобы использовать Microsoft Graph API, необходимо зарегистрировать приложение в Azure.

  1. Перейдите на Azure Portal
  2. ** “Microsoft Entra ID” ** > ** “+Добавить” ** > ** “Регистрация приложения” ** > ** “Новая регистрация” **
  3. Введите любое имя приложения и нажмите «Зарегистрировать»

2. Добавление разрешений API

  1. В левом меню перейдите в «Разрешения API»
  2. Выберите ** “Microsoft Graph” ** > ** “Выбрать разрешения” **, найдите следующие области и нажмите ** “Обновить разрешения” **
  • Chat.ReadWrite
  • User.Read

※ Если вы хотите отправлять сообщения в канал, также потребуется ChannelMessage.Send

3. Запишите идентификатор клиента и идентификатор арендатора

Сохраните следующие два значения, отображаемые на вкладке «Обзор»:

  • Идентификатор приложения (клиента)
  • Идентификатор каталога (арендатора)

4. Создание секрета клиента

  1. Перейдите на вкладку «Сертификаты и секреты»
  2. «Новый секрет клиента» > установите срок действия и нажмите «Добавить»
  3. ** Обязательно сразу запишите отображаемое значение (секрет) **

🔐 Получение маркера доступа (OAuth2)

Мы будем использовать поток client_credentials для получения маркера. Выполните следующую команду с помощью curl, чтобы получить маркер доступа.

1
2
3
4
5
6
7
curl -X POST ^
  https://login.microsoftonline.com/{Идентификатор_арендатора}/oauth2/v2.0/token ^
  -H "Content-Type: application/x-www-form-urlencoded" ^
  -d "client_id={Идентификатор_клиента}" ^
  -d "scope=https%3A%2F%2Fgraph.microsoft.com%2F.default" ^
  -d "client_secret={Секрет_клиента}" ^
  -d "grant_type=client_credentials"

Пример ответа

1
2
3
4
5
6
{
  "token_type":"Bearer",
  "expires_in":3599,
  "ext_expires_in":3599,
  "access_token": "eyJ0eXAiOiJKV1QiLCJub... (пропущено)"
}

Используйте этот access_token для вызова Microsoft Graph API.

💬 Пример на C++ для отправки сообщения в чат Teams

Ниже приведен пример на C++ с использованием WinHTTP для публикации сообщения в чате.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <windows.h>
#include <winhttp.h>
#include <iostream>
#include <string>

#pragma comment(lib, "winhttp.lib")

void PostToTeamsChat(const std::wstring& accessToken, const std::wstring& chatId, const std::wstring& message) {
    HINTERNET hSession = WinHttpOpen(L"TeamsPoster/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                                     WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);

    HINTERNET hConnect = WinHttpConnect(hSession, L"graph.microsoft.com", INTERNET_DEFAULT_HTTPS_PORT, 0);

    std::wstring endpoint = L"/v1.0/chats/" + chatId + L"/messages";
    HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", endpoint.c_str(), NULL,
                                            WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);

    std::wstring jsonBody = L"{\"body\": {\"content\": \"" + message + L"\"}}";
    std::wstring headers = L"Authorization: Bearer " + accessToken + L"\r\nContent-Type: application/json\r\n";

    BOOL bResult = WinHttpSendRequest(hRequest,
                                      headers.c_str(), (DWORD)-1L,
                                      (LPVOID)jsonBody.c_str(), (DWORD)(jsonBody.length() * sizeof(wchar_t)),
                                      (DWORD)(jsonBody.length() * sizeof(wchar_t)), 0);

    if (bResult)
        WinHttpReceiveResponse(hRequest, NULL);

    DWORD dwSize = 0;
    WinHttpQueryDataAvailable(hRequest, &dwSize);

    if (dwSize > 0) {
        std::wstring response(dwSize / sizeof(wchar_t), 0);
        DWORD dwDownloaded = 0;
        WinHttpReadData(hRequest, &response[0], dwSize, &dwDownloaded);
        std::wcout << L"Response: " << response << std::endl;
    }

    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
}

int main() {
    std::wstring access;
    std::wstring chatId = L"19:";
    std::wstring message = L"Hello from C++!";
    std::wcout << L"Enter your access token: ";
    std::getline(std::wcin, access);
    std::wcout << L"Enter chat ID: ";
    std::getline(std::wcin, chatId);
    PostToTeamsChat(access, chatId, message);
    return 0;
}

🔍 Как получить идентификатор чата

Вы можете узнать идентификатор чата, используя GET /v1.0/me/chats.

1
2
3
4
curl -X GET ^
  https://graph.microsoft.com/v1.0/me/chats ^
  -H "Authorization: Bearer {access_token}" ^
  -H "Content-Type: application/json"

Пример ответа

1
2
3
4
5
6
7
8
9
{
  "value": [
    {
      "id": "19:abc123xyz@thread.v2",
      "topic": null,
      "chatType": "oneOnOne"
    }
  ]
}

📌 Примечания

  • Этот пример — минимальная реализация. В реальных условиях:
    • Обработка истечения срока действия маркера
    • Проверка сертификата HTTPS
    • Улучшенная обработка ошибок
  • Для публикации в каналах используйте teams/{team-id}/channels/{channel-id}/messages.
  • Для отправки вложений требуется многокомпонентная обработка или Graph Drive API.

📎 Заключение

ФункцияОписание
Graph APIОфициальный API для взаимодействия с Teams
Регистрация приложенияНеобходимые процедуры аутентификации в Azure
Маркер доступаПолучен через OAuth2, используется для запросов
Реализация C++Вызов Graph API с использованием WinHTTP

🚀 Следующие шаги

В качестве более сложных примеров также возможно:

  • Отправка сообщений в каналы команды (/teams/{team-id}/channels/...)
  • Отправка сообщений с вложениями
  • Переключение между учетными записями ботов и пользователей
  • Полная реализация на C++, включая получение маркера

Если у вас есть пожелания, смело оставляйте комментарии!

comments powered by Disqus
Создано при помощи Hugo
Тема Stack, дизайн Jimmy