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

使用Python向D365 Sales发送PATCH请求更新联系人时遇到HTTP方法不支持的错误

使用Python向D365 Sales发送PATCH请求更新联系人时遇到HTTP方法不支持的错误

我刚帮你排查了这个问题,核心原因是你用错了API端点——Dynamics 365的OData API不允许直接对带过滤条件的集合端点发送PATCH/PUT请求,更新操作必须针对单个实体的具体资源URL(也就是包含联系人ID的URL)。

错误根源分析

你当前构造的contact_url是类似https://x.api.crm.dynamics.com/api/data/v9.2/contacts?$filter=emailaddress1 eq 'xxx'的集合查询端点,这类端点仅支持:

  • GET:查询符合条件的集合数据
  • POST:创建新的联系人记录

而PATCH/PUT这类更新操作,必须指向单个联系人的专属资源URL(格式为{contacts_endpoint}({contact_id})),否则就会返回你遇到的“不支持HTTP方法”错误。

修复后的代码示例

下面是调整后的完整代码,核心逻辑是先通过邮箱查询到目标联系人的ID,再针对单个联系人的URL发送PATCH请求:

import requests
import json
import csv

# Step 1: Parse the CSV data
csv_file_path = 'test.csv'
with open(csv_file_path, 'r') as file:
    reader = csv.reader(file)
    contacts = [row[0] for row in reader if row]

# Step 2: Authenticate and obtain an access token
client_id = 'x'
client_secret = 'x'
tenant_id = 'x'
token_endpoint = 'x'

token_payload = {
    'grant_type': 'client_credentials',
    'client_id': client_id,
    'client_secret': client_secret,
    'resource': 'x'
}

response = requests.post(token_endpoint.format(tenant_id=tenant_id), data=token_payload)
print(response.text)
access_token = json.loads(response.text)['access_token']

# Replace the placeholders with the appropriate API endpoint and request payload
contacts_endpoint = 'https://x.api.crm.dynamics.com/api/data/v9.2/contacts'
headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/json',
    'OData-MaxVersion': '4.0',
    'OData-Version': '4.0'
}

for email in contacts:
    # 1. 先查询目标联系人的ID
    filter_url = f'{contacts_endpoint}?$filter=emailaddress1 eq \'{email}\'&$select=contactid'
    get_response = requests.get(filter_url, headers=headers)
    
    if get_response.status_code != 200:
        print(f"查询联系人{email}失败: {get_response.text}")
        continue
    
    contact_data = json.loads(get_response.text)
    if not contact_data.get('value'):
        print(f"未找到邮箱为{email}的联系人")
        continue
    
    # 取第一个匹配的联系人(假设邮箱唯一)
    contact_id = contact_data['value'][0]['contactid']
    
    # 2. 构造单个联系人的更新URL
    update_url = f'{contacts_endpoint}({contact_id})'
    
    # 3. 发送PATCH请求更新字段
    contact_payload = {
        'description': 'x'  # 要添加标记的字段
    }
    
    patch_response = requests.patch(update_url, headers=headers, json=contact_payload)
    
    if patch_response.status_code == 204:
        print(f"成功为联系人{email}应用标记")
    else:
        print(f"更新联系人{email}失败: {patch_response.text}")

额外优化建议

  • 关于HTTP方法:PATCH只需要传入要更新的字段,而PUT需要传入完整的实体必填字段,所以推荐优先用PATCH。
  • 使用dynamics365crm包简化操作:你提到的这个包确实能大幅减少手动编码的工作量,示例代码如下:
    from dynamics365crm import XrmClient
    
    # 初始化客户端
    client = XrmClient(tenant_id, client_id, client_secret, resource_url='https://x.api.crm.dynamics.com')
    
    for email in contacts:
        # 查询目标联系人
        matched_contacts = client.query("contacts", filter=f"emailaddress1 eq '{email}'", select=["contactid"])
        if not matched_contacts:
            print(f"未找到邮箱为{email}的联系人")
            continue
        
        # 更新联系人字段
        contact_id = matched_contacts[0]["contactid"]
        client.update("contacts", contact_id, {"description": "x"})
        print(f"成功更新联系人{email}")
    
  • 权限检查:确保你的应用注册在D365中被授予了联系人的更新权限(通过安全角色配置),否则可能会遇到权限相关的错误。

备注:内容来源于stack exchange,提问作者Aidan Rosamond

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 07:53:07