如何使用Python连接到Microsoft Dataverse API端点

发布于 2025-02-06 07:18:59 字数 10294 浏览 3 评论 0原文

我面临着通过Python连接到Microsoft Dataverse API端点的问题。

该代码分为三个部分:

a)代币生成

b)端点API调用选项1

c)端点API调用选项2 Appi call选项2

################ Token generation code begins ################
import adal

# Tenant ID for your Azure Subscription
TENANT_ID = 'abc'
# Your Service Principal App ID
CLIENT = '52'
# Your Service Principal Password
KEY = '43'


# subscription_id = 'xxxxxxx'

authority_url = 'https://login.microsoftonline.com/'+TENANT_ID
context = adal.AuthenticationContext(authority_url)
token = context.acquire_token_with_client_credentials(
    resource='https://orgabc.api.crm8.dynamics.com/',
    client_id=CLIENT,
    client_secret=KEY
)

print('Fresh token is: ', token["accessToken"])
print('Full response is: ', token)

################ Token generation code ends ################

################ Method/Option 1: Token generation code begins ################
import requests
import json
import msal
config = {
    "authority": "https://login.microsoftonline.com/abc",
    "client_id": "52",
    "client_secret": "43",
    "scope": ["https://orgabc.crm8.dynamics.com/.default"],
}
app = msal.ConfidentialClientApplication(
    config["client_id"],
    authority=config["authority"],
    client_credential=config["client_secret"])
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
    result = app.acquire_token_for_client(scopes=config["scope"])
# bearerToken = result['access_token']
bearerToken = token["accessToken"]
url = "https://orgabc.api.crm8.dynamics.com/api/data/v9.2"
headers = {
    "Accept": "application/json",
    "Content-type": "application/json",
    "Authorization": "Bearer "+bearerToken,
}

response = requests.request("GET", url, headers = headers)
print(response)
################ Method/Option 1: Token generation code ends ################


# ################ Method/Option 2: Token generation code begins ################
# import requests
# import json
#
# # set these values to retrieve the oauth token
# crmorg = 'https://orgabc.crm8.dynamics.com'  # base url for crm org
# clientid = '52'  # application client id
# username = '[email protected]'  # username
# userpassword = 'HgN@6013'  # password
# tokenendpoint = 'https://login.microsoftonline.com/abc/oauth2/v2.0/token'  # oauth token endpoint
#
# # set these values to query your crm data
# crmwebapi = 'https://orgabc.crm8.dynamics.com/api/data/v9.2'  # full path to web api endpoint
# # crmwebapiquery = '/contacts?$select=fullname,contactid'  # web api query (include leading /)
# crmwebapiquery = '/accounts'  # web api query (include leading /)
#
#
# # build the authorization token request
# tokenpost = {
#     'client_id': clientid,
#     'resource': crmorg,
#     'username': username,
#     'password': userpassword,
#     'grant_type': 'password'
# }
#
# # make the token request
# tokenres = requests.post(tokenendpoint, data=tokenpost)
#
# # set accesstoken variable to empty string
# accesstoken = ''
#
# # extract the access token
# try:
#     accesstoken = token["accessToken"]
# except(KeyError):
#     # handle any missing key errors
#     print('Could not get access token')
#
# # if we have an accesstoken
# if (accesstoken != ''):
#     # prepare the crm request headers
#     crmrequestheaders = {
#         'Authorization': 'Bearer ' + token["accessToken"],
#         'OData-MaxVersion': '4.0',
#         'OData-Version': '4.0',
#         'Accept': 'application/json',
#         'Content-Type': 'application/json; charset=utf-8',
#         'Prefer': 'odata.maxpagesize=500',
#         'Prefer': 'odata.include-annotations=OData.Community.Display.V1.FormattedValue'
#     }
#
#     # make the crm request
#     crmres = requests.get(crmwebapi + crmwebapiquery, headers=crmrequestheaders)
#
#     try:
#         # get the response json
#         crmresults = crmres.json()
#
#         # loop through it
#         for x in crmresults['value']:
#             print(x['fullname'] + ' - ' + x['contactid'])
#     except KeyError:
#         # handle any missing key errors
#         print('Could not parse CRM results')
# ################ Method/Option 2: Token generation code ends ################

该代码的块1正常工作,我们正在生成令牌,但是当我们尝试块时2或3,在这两种情况下,代码都失败了以下错误(完整的追溯):

Traceback (most recent call last):
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 597, in urlopen
    httplib_response = self._make_request(conn, method, url,
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 343, in _make_request
    self._validate_conn(conn)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 849, in _validate_conn
    conn.connect()
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connection.py", line 349, in connect
    self.sock = ssl_wrap_socket(
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\util\ssl_.py", line 359, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "C:\Users\aakashbasu1\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "C:\Users\aakashbasu1\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 1040, in _create
    self.do_handshake()
  File "C:\Users\aakashbasu1\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1129)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\adapters.py", line 440, in send
    resp = conn.urlopen(
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 637, in urlopen
    retries = retries.increment(method, url, error=e, _pool=self,
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\util\retry.py", line 398, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='orgabc.api.crm8.dynamics.com', port=443): Max retries exceeded with url: /api/data/v9.2 (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1129)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\internal_experiments\azure_ad_token_generator.py", line 60, in <module>
    response = requests.request("GET", url, headers = headers)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\sessions.py", line 529, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\sessions.py", line 645, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\adapters.py", line 517, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='orgabc.api.crm8.dynamics.com', port=443): Max retries exceeded with url: /api/data/v9.2 (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1129)')))

在开放论坛上,对于Dataverse而言,没有太多帮助。有一个可用的C#代码,但是我们需要使用Python进行相同的操作。 C#代码是:

using Microsoft.AspNetCore.Http;
using Microsoft.Graph;
using Microsoft.WindowsAzure.ActiveDirectory.Authentication;
using MySql.Data.MySqlClient.Memcached;
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;

namespace AccessToken
{
    class Program
    {
        static void Main(string[] args)
        {
            string serviceUrl = "https://orgabc.crm8.dynamics.com";
            string clientId = "52";//"<your app id>";
            string secret = "41";//"<your app secret>";

            AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/53");//tenant ID 
            ClientCredential credential = new ClientCredential(clientId, secret);

            AuthenticationResult result = authContext.AcquireToken(serviceUrl,credential);

            string accessToken = result.AccessToken;
            Console.WriteLine("Hello World!");
            Console.WriteLine("Acces Token for given :"+accessToken);

            //Retrieving data here
            using (var client = new HttpClient())
            {
               
                var tokenType = "Bearer"; //Other APIs use Bearer or other auth types.
                
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);//token type=Bearer, accesstoken refers to token which we generated.
                //https://orgabc.crm8.dynamics.com refers to org URL

                var content = client.GetStringAsync("https://orgabc.crm8.dynamics.com/api/data/v9.2/accounts");//accounts refers to the User Table Logical Name.
                Console.WriteLine("Acces Token for given :" + content.Result);

            }
            //end of retrieve data.
        }
    }
}

我们尝试了什么?

  • 根据Microsoft文档,将API版本从实际的9.2更改为9.2,
  • 根据多个so so so s so s so q/ake this
  • 与Postman工具一起在相同的连接详细信息上工作的效果非常好,

因此,缩小了它的范围,似乎问题是代码键入端点。有帮助吗?

I'm facing an issue in connecting to Microsoft Dataverse API endpoint through Python.

The code is broken down into three parts:

A) Token Generation

B) Endpoint API call Option 1

C) Endpoint API call Option 2

################ Token generation code begins ################
import adal

# Tenant ID for your Azure Subscription
TENANT_ID = 'abc'
# Your Service Principal App ID
CLIENT = '52'
# Your Service Principal Password
KEY = '43'


# subscription_id = 'xxxxxxx'

authority_url = 'https://login.microsoftonline.com/'+TENANT_ID
context = adal.AuthenticationContext(authority_url)
token = context.acquire_token_with_client_credentials(
    resource='https://orgabc.api.crm8.dynamics.com/',
    client_id=CLIENT,
    client_secret=KEY
)

print('Fresh token is: ', token["accessToken"])
print('Full response is: ', token)

################ Token generation code ends ################

################ Method/Option 1: Token generation code begins ################
import requests
import json
import msal
config = {
    "authority": "https://login.microsoftonline.com/abc",
    "client_id": "52",
    "client_secret": "43",
    "scope": ["https://orgabc.crm8.dynamics.com/.default"],
}
app = msal.ConfidentialClientApplication(
    config["client_id"],
    authority=config["authority"],
    client_credential=config["client_secret"])
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
    result = app.acquire_token_for_client(scopes=config["scope"])
# bearerToken = result['access_token']
bearerToken = token["accessToken"]
url = "https://orgabc.api.crm8.dynamics.com/api/data/v9.2"
headers = {
    "Accept": "application/json",
    "Content-type": "application/json",
    "Authorization": "Bearer "+bearerToken,
}

response = requests.request("GET", url, headers = headers)
print(response)
################ Method/Option 1: Token generation code ends ################


# ################ Method/Option 2: Token generation code begins ################
# import requests
# import json
#
# # set these values to retrieve the oauth token
# crmorg = 'https://orgabc.crm8.dynamics.com'  # base url for crm org
# clientid = '52'  # application client id
# username = '[email protected]'  # username
# userpassword = 'HgN@6013'  # password
# tokenendpoint = 'https://login.microsoftonline.com/abc/oauth2/v2.0/token'  # oauth token endpoint
#
# # set these values to query your crm data
# crmwebapi = 'https://orgabc.crm8.dynamics.com/api/data/v9.2'  # full path to web api endpoint
# # crmwebapiquery = '/contacts?$select=fullname,contactid'  # web api query (include leading /)
# crmwebapiquery = '/accounts'  # web api query (include leading /)
#
#
# # build the authorization token request
# tokenpost = {
#     'client_id': clientid,
#     'resource': crmorg,
#     'username': username,
#     'password': userpassword,
#     'grant_type': 'password'
# }
#
# # make the token request
# tokenres = requests.post(tokenendpoint, data=tokenpost)
#
# # set accesstoken variable to empty string
# accesstoken = ''
#
# # extract the access token
# try:
#     accesstoken = token["accessToken"]
# except(KeyError):
#     # handle any missing key errors
#     print('Could not get access token')
#
# # if we have an accesstoken
# if (accesstoken != ''):
#     # prepare the crm request headers
#     crmrequestheaders = {
#         'Authorization': 'Bearer ' + token["accessToken"],
#         'OData-MaxVersion': '4.0',
#         'OData-Version': '4.0',
#         'Accept': 'application/json',
#         'Content-Type': 'application/json; charset=utf-8',
#         'Prefer': 'odata.maxpagesize=500',
#         'Prefer': 'odata.include-annotations=OData.Community.Display.V1.FormattedValue'
#     }
#
#     # make the crm request
#     crmres = requests.get(crmwebapi + crmwebapiquery, headers=crmrequestheaders)
#
#     try:
#         # get the response json
#         crmresults = crmres.json()
#
#         # loop through it
#         for x in crmresults['value']:
#             print(x['fullname'] + ' - ' + x['contactid'])
#     except KeyError:
#         # handle any missing key errors
#         print('Could not parse CRM results')
# ################ Method/Option 2: Token generation code ends ################

The block 1 of the code is working fine, where we're generating the token, but while we try block 2 or 3, in both the cases the code fails with the below error (full traceback):

Traceback (most recent call last):
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 597, in urlopen
    httplib_response = self._make_request(conn, method, url,
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 343, in _make_request
    self._validate_conn(conn)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 849, in _validate_conn
    conn.connect()
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connection.py", line 349, in connect
    self.sock = ssl_wrap_socket(
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\util\ssl_.py", line 359, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "C:\Users\aakashbasu1\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "C:\Users\aakashbasu1\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 1040, in _create
    self.do_handshake()
  File "C:\Users\aakashbasu1\AppData\Local\Programs\Python\Python39\lib\ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1129)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\adapters.py", line 440, in send
    resp = conn.urlopen(
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\connectionpool.py", line 637, in urlopen
    retries = retries.increment(method, url, error=e, _pool=self,
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\urllib3\util\retry.py", line 398, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='orgabc.api.crm8.dynamics.com', port=443): Max retries exceeded with url: /api/data/v9.2 (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1129)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\internal_experiments\azure_ad_token_generator.py", line 60, in <module>
    response = requests.request("GET", url, headers = headers)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\sessions.py", line 529, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\sessions.py", line 645, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\aakashbasu1\PycharmProjects\Personal_RnD\venv\lib\site-packages\requests\adapters.py", line 517, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='orgabc.api.crm8.dynamics.com', port=443): Max retries exceeded with url: /api/data/v9.2 (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1129)')))

There's not much help available on the open forum for this problem for Dataverse. There is a C# code available which works fine, but we need to use Python for the same. C# code for the same is:

using Microsoft.AspNetCore.Http;
using Microsoft.Graph;
using Microsoft.WindowsAzure.ActiveDirectory.Authentication;
using MySql.Data.MySqlClient.Memcached;
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;

namespace AccessToken
{
    class Program
    {
        static void Main(string[] args)
        {
            string serviceUrl = "https://orgabc.crm8.dynamics.com";
            string clientId = "52";//"<your app id>";
            string secret = "41";//"<your app secret>";

            AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/53");//tenant ID 
            ClientCredential credential = new ClientCredential(clientId, secret);

            AuthenticationResult result = authContext.AcquireToken(serviceUrl,credential);

            string accessToken = result.AccessToken;
            Console.WriteLine("Hello World!");
            Console.WriteLine("Acces Token for given :"+accessToken);

            //Retrieving data here
            using (var client = new HttpClient())
            {
               
                var tokenType = "Bearer"; //Other APIs use Bearer or other auth types.
                
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);//token type=Bearer, accesstoken refers to token which we generated.
                //https://orgabc.crm8.dynamics.com refers to org URL

                var content = client.GetStringAsync("https://orgabc.crm8.dynamics.com/api/data/v9.2/accounts");//accounts refers to the User Table Logical Name.
                Console.WriteLine("Acces Token for given :" + content.Result);

            }
            //end of retrieve data.
        }
    }
}

What we tried?

  • Changing the API version to 9.1 and 9.0 from the actual 9.2 as per microsoft documentation
  • Lowering urllib version as per suggestions from multiple SO Q/A like this
  • Working on the same connection details with Postman Tool works perfectly fine

So, narrowing down on it seems the issue is with the code hitting the endpoint. Any help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

木落 2025-02-13 07:19:00

该代码没有错误,它是正确编写的。问题在于当地机器的防火墙/代理/VPN设置问题,该问题阻止了实际的API调用。在打开系统上运行时,它可以正常工作。

The code has no bug, it is correctly written. The issue was with the local machine's firewall/proxy/VPN setting issues which was blocking the actual API call. It works fine when run on an open system.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文