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

如何通过MS Graph API配置Teams用户呼叫转接策略

概要

用于设置Teams用户呼叫转接策略的MS Graph API是什么?

问题背景

当前正在将基于Lync/Skype的.NET应用迁移至Teams平台,Teams侧开发需求为配置指定用户的呼叫转接偏好。这类用户均启用了直连路由(Direct Routing),拨打固定PSTN/分机号码时,呼叫会转接至用户的移动终端;转接目标的移动号码需根据值班排班动态调整,由程序自动匹配当前值班人员完成配置。

已尝试的方案
  • 已完成MS Graph API的身份认证对接
  • 已知TAC扩展可实现该功能
  • 已知存在对应PowerShell扩展模块可实现该功能,对应cmdlet为Set-CsUserCallingSettings
  • 已有其他开发者提出同类问题,但相关讨论帖均未给出最终可行解决方案
  • Call-Redirect接口不符合需求,该接口需要主动监听呼叫实例,不适用于静态配置用户呼叫转接规则的场景
  • 官方Teams相关脚本仓库未提供对应实现源码
  • 暂未对PowerShell扩展模块做反射分析
  • MS Graph Beta版本的user settings接口仅支持排班相关配置,不支持呼叫转接规则设置
备选方案
  • 通过PowerShell SDK调用对应cmdlet实现,但该方案实现方式较为老旧,不作为优先选型
2022-06-20更新进展
  • 开始对PowerShell模块做反射分析,初步定位到对应接口地址格式为https://api.interfaces.records.teams.microsoft.com/Skype.VoiceGroup/userRoutingSettings/{userId}
  • Teams用户ID可通过官方接口获取
  • Teams部分功能仍依赖旧版REST API实现
2022-06-30更新进展

目前已整理出可优化的概念验证(POC)代码如下(后续将常规AcquireTokenOnBehalfOf认证逻辑整合后,会作为答案补充):

Imports System.IO
Imports Microsoft.Identity.Client
Imports System.Globalization
Imports System.Net.Http
Imports System.Text
Imports System.Net.Http.Headers
Imports System.Net
Imports Newtonsoft.Json
Imports System.IdentityModel.Tokens.Jwt

Public Class LyncTest

    Public Shared Sub Test()
        Dim InstanceId As String = "https://login.microsoftonline.com/"
        Dim RedirectURI As String = "https://login.microsoftonline.com/common/oauth2/nativeclient"

        ' 以下ID、密钥信息可在Azure应用注册页面获取
        Dim TenantId As String = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        Dim AppId As String = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        Dim secretVal As String = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        Dim username As String = "xxxxxxx.xxxxxx@xxxxxxxxxxxx.com"
        Dim password As String = "xxxxxxxxxxxx"
        ' Teams接口权限范围
        Dim scope As String = "48ac35b8-9aa8-4d74-927d-1f4a14a0b239/.default"

        Dim httpClient = New HttpClient()

        ' 发起资源所有者密码凭据流认证
        Dim baseParam As String =
            $"client_id={AppId}" &
            $"&username={WebUtility.UrlEncode(username)}" &
            $"&password={WebUtility.UrlEncode(password)}" &
            $"&grant_type=password" &
            $"&client_secret={WebUtility.UrlEncode(secretVal)}" &
            $"&scope={scope}"

        ' 获取user_impersonation权限的访问令牌
        Dim tokenReq As New HttpRequestMessage(HttpMethod.Post, $"https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token") With {
            .Content = New StringContent(baseParam, Encoding.UTF8, "application/x-www-form-urlencoded")
        }
        Dim TokenRes As HttpResponseMessage = httpClient.SendAsync(tokenReq).Result
        Dim TokenObj As GraphToken = JsonConvert.DeserializeObject(Of GraphToken)(TokenRes.Content.ReadAsStringAsync.Result())
        Dim JwtReader As New JwtSecurityTokenHandler
        Dim JwtToken As JwtSecurityToken = JwtReader.ReadToken(TokenObj.AccessToken)
        Dim UserOid As String = JwtToken.Payload("oid")

        ' 配置用户呼叫路由规则
        Dim RoutingURL As String = $"https://api.interfaces.records.teams.microsoft.com/Skype.VoiceGroup/userRoutingSettings/{UserOid}"

        httpClient.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Bearer", TokenObj.AccessToken)

        Dim RoutingJSON As String =
            "{""sipUri"":""sip:andreas.beeker@kraiburg-tpe.com""," &
            """forwardingSettings"":{""isEnabled"":false,""forwardingType"":""Simultaneous"",""targetType"":""Unknown"",""target"":""""}," &
            """unansweredSettings"":{""isEnabled"":true,""targetType"":""SingleTarget"",""target"":""+491701234567"",""delay"":""00:00:20""}," &
            """callGroupDetails"":{""targets"":[],""order"":""Simultaneous""},""callGroupMembershipSettings"":{""callGroupMembershipDetails"":[]}}"

        Dim RoutingReq As New HttpRequestMessage(HttpMethod.Post, RoutingURL) With {
            .Content = New StringContent(RoutingJSON, Encoding.UTF8, "application/json")
        }
        Dim RoutingRes As HttpResponseMessage = httpClient.SendAsync(RoutingReq).Result

        Console.WriteLine(If(RoutingRes.IsSuccessStatusCode, "success", "failed"))
    End Sub

    Public Class GraphToken
        <JsonProperty(PropertyName:="access_token")>
        Public Property AccessToken As String
        <JsonProperty(PropertyName:="expires_in")>
        Public Property ExpiresIn As Integer
        <JsonProperty(PropertyName:="ext_expires_in")>
        Public Property ExpiresInExt As Integer
        <JsonProperty(PropertyName:="scope")>
        Public Property Scope As String
        <JsonProperty(PropertyName:="token_type")>
        Public Property TokenType As String

    End Class
End Class

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:42:36