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

Business Central对接SharePoint令牌无效问题排查求助

Business Central与SharePoint接口对接问题排查

问题描述

已在Postman中成功实现Business Central与SharePoint的GET、POST接口对接,但在Business Central开发时,尽管能生成令牌,却无法正常调用接口,怀疑是连接或URL配置问题。相关代码单元如下:

codeunit 50100 "APISharePoint"
{

    var
        OAuth2: Codeunit OAuth2;
        ClientIdTxt: Label '4d148348-137a-40e7-b20c-a458c2a03c65', Locked = true;
        ClientSecret: Label 'Ai2pOhE7yeZ8WRxrwSrHdpVtNqJg51tg2X+s8CJDLy4=', Locked = true;
        ResourceUrlTxt: Label 'https://crmbc384959.sharepoint.com', Locked = true;
        OAuthAuthorityUrlTxt: Label 'https://login.microsoftonline.com/ec36749a-af47-4f04-892c-98666b6cac1b/oauth2/v2.0/token', Locked = true;


    procedure GetAccessToken(): Text
    var
        PromptInteraction: Enum "Prompt Interaction";
        AccessToken: Text;
        AuthCodeError: Text;
        RedirectURLTxt: Text;
    begin
        // OAuth2.GetDefaultRedirectURL(RedirectURLTxt);
        RedirectURLTxt := 'https://localhost';
        if OAuth2.AcquireTokenWithClientCredentials(ClientIdTxt, ClientSecret, OAuthAuthorityUrlTxt, RedirectURLTxt, ResourceURLTxt, AccessToken) then
            exit(AccessToken)
        else
            exit('');
    end;


    procedure HttpGet(AccessToken: Text; Url: Text /*var JResponse: JsonObject*/): Boolean
    var
        Client: HttpClient;
        Headers: HttpHeaders;
        RequestMessage: HttpRequestMessage;
        ResponseMessage: HttpResponseMessage;
        RequestContent: HttpContent;
        ResponseText: Text;
        IsSucces: Boolean;

    begin
        Headers := Client.DefaultRequestHeaders();
        Headers.Add('Authorization', StrSubstNo('Bearer %1', AccessToken));
        Headers.Add('Accept', 'application/json;odata=verbose');
        RequestMessage.Content.GetHeaders(Headers); //asd
        Headers.Remove('Content-Type');
        Headers.Add('Content-Type', 'application/json;odata=verbose');
        RequestMessage.SetRequestUri(Url);
        RequestMessage.Method := 'GET';

        if Client.Send(RequestMessage, ResponseMessage) then
            if ResponseMessage.IsSuccessStatusCode() then begin
                if ResponseMessage.Content.ReadAs(ResponseText) then
                    IsSucces := true;
                //     end else
                //         ResponseMessage.Content.ReadAs(ResponseText);

                // JResponse.ReadFrom(ResponseText);
                exit(IsSucces);

            end;

    end;
}

核心问题排查点

1. OAuth2端点参数不匹配

你使用的是Azure AD v2.0令牌端点,但传入的是ResourceURLTxt(SharePoint站点地址)。v2.0协议中,客户端凭证流需使用scope参数而非resource,正确的SharePoint scope格式为https://<tenant>.sharepoint.com/.default,这个值包含了应用注册中配置的所有权限。

2. 重定向URL配置错误

手动设置RedirectURLTxt := 'https://localhost',需确保该URL已在Azure AD应用注册的“重定向URI”列表中添加,且类型为“Web”。Postman中可能使用了不同的重定向URL,导致生成的令牌权限范围不一致。建议恢复使用OAuth2.GetDefaultRedirectURL(RedirectURLTxt)获取BC默认重定向URL,并确保该URL已在Azure AD中注册。

3. HTTP请求头冗余操作

HttpGet方法中,GET请求无需设置Content,但代码中调用RequestMessage.Content.GetHeaders(Headers)获取空的Content头,后续修改Content-Type属于无效操作,反而可能引发请求格式错误。应移除所有与RequestContent相关的代码。

4. 令牌有效性验证

生成令牌后,用JWT解码工具查看令牌的aud(受众)和scp(权限)字段,对比Postman中生成的令牌,确认是否匹配SharePoint的要求。若BC生成的令牌缺少必要权限,需检查Azure AD应用注册的权限配置是否完成管理员同意。

修改后的代码示例

codeunit 50100 "APISharePoint"
{
    var
        OAuth2: Codeunit OAuth2;
        ClientIdTxt: Label '4d148348-137a-40e7-b20c-a458c2a03c65', Locked = true;
        ClientSecret: Label 'Ai2pOhE7yeZ8WRxrwSrHdpVtNqJg51tg2X+s8CJDLy4=', Locked = true;
        SharePointScopeTxt: Label 'https://crmbc384959.sharepoint.com/.default', Locked = true;
        OAuthAuthorityUrlTxt: Label 'https://login.microsoftonline.com/ec36749a-af47-4f04-892c-98666b6cac1b/oauth2/v2.0/token', Locked = true;

    procedure GetAccessToken(): Text
    var
        AccessToken: Text;
        RedirectURLTxt: Text;
    begin
        // 使用Business Central默认重定向URL,需提前在Azure AD注册
        OAuth2.GetDefaultRedirectURL(RedirectURLTxt);
        // v2.0端点使用scope参数而非resource
        if OAuth2.AcquireTokenWithClientCredentials(ClientIdTxt, ClientSecret, OAuthAuthorityUrlTxt, RedirectURLTxt, SharePointScopeTxt, AccessToken) then
            exit(AccessToken)
        else
            exit('');
    end;

    procedure HttpGet(AccessToken: Text; Url: Text): Boolean
    var
        Client: HttpClient;
        Headers: HttpHeaders;
        RequestMessage: HttpRequestMessage;
        ResponseMessage: HttpResponseMessage;
        ResponseText: Text;
        IsSuccess: Boolean;
    begin
        Headers := Client.DefaultRequestHeaders();
        Headers.Add('Authorization', StrSubstNo('Bearer %1', AccessToken));
        Headers.Add('Accept', 'application/json;odata=verbose');

        RequestMessage.SetRequestUri(Url);
        RequestMessage.Method := 'GET';

        if Client.Send(RequestMessage, ResponseMessage) then begin
            if ResponseMessage.IsSuccessStatusCode() then begin
                IsSuccess := ResponseMessage.Content.ReadAs(ResponseText);
                // 可在此处添加JSON解析逻辑
            end else begin
                // 捕获错误响应用于排查
                ResponseMessage.Content.ReadAs(ResponseText);
                Message('请求失败: ' + ResponseText);
            end;
        end else begin
            Message('发送请求失败');
        end;
        exit(IsSuccess);
    end;
}

额外排查建议

  • 检查Azure AD应用权限:确保已添加SharePoint的应用权限(如Sites.Read.All),并完成管理员同意操作。
  • 开启BC HTTP日志:在Business Central管理中心启用HTTP请求日志,查看完整的请求和响应详情,定位具体错误信息。
  • 令牌交叉测试:将BC生成的令牌复制到Postman中调用接口,验证令牌本身是否有效,以此区分是令牌问题还是请求构造问题。

内容的提问来源于stack exchange,提问作者Henrique Araújo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 20:01:11