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

如何通过Dynamics 365 Web API为外部调研页面拉取工单关联的用户与公司信息

实现方案(外部独立页面拉取Dynamics 365 Online数据)

Dynamics 365 Web API默认不允许跨域匿名调用,你找到的CRM内部Web资源教程是因为共享了上下文鉴权,外部页面必须走Azure AD客户端凭据鉴权流程,用你现有的PHP后端做代理调用规避前端跨域问题,具体实现步骤如下:

1. 前置配置(Azure AD侧和Dynamics 365侧)

  • 登录Azure Portal,注册新的应用注册,不需要配置重定向URI(因为使用客户端凭据流)
  • 注册完成后记录3个值:客户端ID(Application ID)、租户ID(Tenant ID),再进入「证书和密码」页面新建客户端密码,记录密码值(仅显示一次,注意保存)
  • 进入Dynamics 365 Online的「高级设置-安全-用户」,新建一个应用用户,绑定刚才注册的Azure AD应用的客户端ID,给这个用户分配工单实体的读取权限,以及关联的客户、联系人实体的读取权限

2. 后端(PHP侧)代理实现

前端直接调用Dynamics API会触发跨域限制,所有API请求走PHP后端转发:

2.1 获取Dynamics 365鉴权Access Token

// 配置参数替换为你自己的实际值
$tenantId = '你的Azure AD租户ID';
$clientId = '注册应用的客户端ID';
$clientSecret = '注册应用的客户端密码';
$dynamicsUrl = '你的Dynamics 365实例URL,例如https://xxx.crm.dynamics.com';

// 请求获取Access Token
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/token";
$postData = [
    'grant_type' => 'client_credentials',
    'client_id' => $clientId,
    'client_secret' => $clientSecret,
    'resource' => $dynamicsUrl
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $tokenUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$tokenResponse = json_decode(curl_exec($ch), true);
$accessToken = $tokenResponse['access_token'];

2.2 调用Dynamics Web API拉取工单关联数据

以下示例默认使用Dynamics 365原生工单实体逻辑名incident,如果是自定义实体、自定义字段需要替换为你系统内的实际逻辑名:

// 从前端获取URL传递的工单编号
$ticketNumber = $_GET['ticket_number'];

// 构造Web API查询语句,按工单编号过滤,返回关联的联系人姓名、所属企业名称
$apiUrl = "$dynamicsUrl/api/data/v9.2/incidents?"
    ."\$filter=ticketnumber eq '$ticketNumber'"
    ."&\$select=incidentid"
    ."&\$expand=customerid(\$select=fullname,name)";

// 发起API请求
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer $accessToken",
    "OData-MaxVersion: 4.0",
    "OData-Version: 4.0",
    "Accept: application/json"
]);
$apiResponse = json_decode(curl_exec($ch), true);
curl_close($ch);

// 处理返回结果返回给前端
if(!empty($apiResponse['value'])) {
    $ticketData = $apiResponse['value'][0];
    $result = [
        'user_name' => $ticketData['customerid']['fullname'] ?? '',
        'company_name' => $ticketData['customerid']['name'] ?? ''
    ];
    echo json_encode(['code' => 200, 'data' => $result]);
} else {
    echo json_encode(['code' => 404, 'msg' => '未找到对应工单']);
}

3. 前端JS调用

前端直接调用自己的PHP代理接口即可,不需要直接对接Dynamics 365:

// 从URL参数获取工单编号
function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i=0;i<vars.length;i++) {
        var pair = vars[i].split("=");
        if(pair[0] == variable) return pair[1];
    }
    return false;
}
const ticketNumber = getQueryVariable('ticket_id');

// 调用PHP后端接口拉取数据
fetch(`/你的PHP代理文件路径.php?ticket_number=${encodeURIComponent(ticketNumber)}`)
.then(res => res.json())
.then(res => {
    if(res.code === 200) {
        // 把获取到的姓名、企业名称填充到页面对应位置
        document.getElementById('user_name').textContent = res.data.user_name;
        document.getElementById('company_name').textContent = res.data.company_name;
    } else {
        alert(res.msg);
    }
})

注意事项

  • 实体和字段的逻辑名称可以在Dynamics 365的自定义实体设置页查看,有自定义字段的话需要替换代码里的对应字段名
  • 可以对获取到的Access Token做本地缓存,默认有效期1小时,避免每次请求都重新获取Token,提升接口性能
  • 生产环境要对前端传递的工单编号做参数校验,避免注入类风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 12:27:01