技术
> CentOS 7.5
> Python 3.6.0
> Django 1.10.5
> Postresql 9.2
> Microsoft CRM Dynamics 365 online,具有最新的客户端数据,因此必须使用Web API:https://msdn.microsoft.com/en-us/library/gg334767.aspx
问题
> CRM拥有最新的客户端数据,并希望将其引入Postgresql以用于众多事情
>想要使用www_fdw,因为它是我见过的Postgresql唯一可以使用Web API的外部数据包装器:https://github.com/cyga/www_fdw/wiki
> Dynamics Web API使用OAuth2,www_fdw本身不支持任何类型的身份验证
>与www_fdw的开发人员交谈,他们建议使用代理服务器来处理与Microsoft的OAuth2身份验证
>带有www_fdw的Postgresql将与代理进行通信,代理又会向Microsoft发送身份验证,最终将Web API视为外表,以便将其视为任何其他表
这三个部分以及到目前为止所尝试的内容
三部分= www_fdw代理服务器OAuth2
> www_fdw:我已根据此设置使用以下参数:https://github.com/cyga/www_fdw/wiki/Examples
DROP EXTENSION IF EXISTS www_fdw CASCADE; CREATE EXTENSION www_fdw; CREATE SERVER crm FOREIGN DATA WRAPPER www_fdw OPTIONS (uri 'http://localhost:12345'); -- proxy server CREATE USER MAPPING FOR current_user SERVER crm; -- for testing trying to get 'name' out of the CRM 'accounts' table and naming the foreign table the same as the table in CRM CREATE FOREIGN TABLE accounts ( name varchar(255) ) SERVER crm;
> crmproxytest.py代理服务器,我一直试图使用此链接制作一个简单的骨头:http://effbot.org/librarybook/simplehttpserver.htm
import socketserver import http.server import urllib PORT = 12345 class Proxy(http.server.SimpleHTTPRequestHandler): def do_GET(self): self.copyfile(urllib.urlopen(self.path),self.wfile) httpd = socketserver.ForkingTCPServer(('',PORT),Proxy) print ("serving at port",PORT) httpd.serve_forever()
这似乎工作,因为它说在服务器上的端口12345上运行,显示运行nmap -sT -O localhost,运行nmap时运行服务器的控制台上有一些活动.否则无法从中获得任何活动.
从Postgresql运行SELECT * FROM帐户导致无法从服务器获取响应:无法连接到:: 1:权限被拒绝.
> OAuth2.我把crm.py放在一起,并在与微软交谈后对其进行了工作,整理了他们的文档,并找到了这个链接:http://alexanderdevelopment.net/post/2016/11/27/dynamics-365-and-python-integration-using-the-web-api/
简而言之,您必须向Azure Active Directory注册您的应用程序,以便除了能够获取OAuth 2.0令牌URI和OAuth 2.0授权URI之外,还可以获得client_id,client_secret.然后,您可以向authorizationendpoint发送请求,如果凭据匹配,则返回令牌,然后将令牌发送到tokenendpoint,最终授予对Web API的访问权限.
这是我最终使用的代码,从Dynamics Web API检索数据,并在控制台中填充它:
import requests import json #set these values to retrieve the oauth token crmorg = 'https://ORG.crm.dynamics.com' #base url for crm org clientid = '00000000-0000-0000-0000-000000000000' #application client id client_secret = 'SUPERSECRET' username = 'asd@asd.com' #username userpassword = 'qwerty' #password authorizationendpoint = 'https://login.windows.net/ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ/oauth2/authorize' tokenendpoint = 'https://login.windows.net/ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ/oauth2/token' #oauth token endpoint #set these values to query your crm data crmwebapi = 'https://ORG.api.crm.dynamics.com/api/data/v8.2' #full path to web api endpoint crmwebapiquery = '/accounts?$select=name&$orderby=name' #web api query (include leading /) #build the authorization token request tokenpost = { 'client_id':clientid,'client_secret': client_secret,'resource':crmorg,'oauthUrl': authorizationendpoint,'username':username,'password':userpassword,'grant_type':'password' } #make the token request tokenres = requests.post(tokenendpoint,data=tokenpost) #check the value of tokenres print(tokenres) #set accesstoken variable to empty string accesstoken = '' #extract the access token try: accesstoken = tokenres.json()['access_token'] except(KeyError): #handle any missing key errors print('Could not get access token') # check point for debugging # print(accesstoken) #if we have an accesstoken if(accesstoken!=''): #prepare the crm request headers crmrequestheaders = { 'Authorization': 'Bearer ' + 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']) print (x['name']) except KeyError: #handle any missing key errors print('Could not parse CRM results')
这就像一个魅力,但实际上是测试OAuth2.结合变量crmwebapi和crmwebapiquery的查询实际上不需要在那里,因为Postgresql,如果FDW工作正常,应该允许对Web API运行SQL查询.
无论如何,我希望我能够很好地解释这一切.似乎我有三个独立的拼图工作或工作,但把它们放在一起是我被卡住的地方. crm.py和crmtest.py可能需要合并,但不确定如何.
在此先感谢您的帮助!
编辑:显然有www_ftw到处而不是www_fdw.
解决方法
您在步骤2中的Python脚本需要顶部的shebang.否则它被视为bash,因此前3行运行import(1)
并将屏幕截图保存到名为http.server,socketserver和urllib的新文件中.这使得脚本在PORT线路上死之前会保持一段时间.在此期间(或者甚至在它死后),运行curl http:// localhost:12345会产生与Postgres相同的错误:
curl: (7) Failed to connect to localhost port 12345: Connection refused
添加#!/usr/bin/env python3后,您的脚本将回答请求.例如,我可以说curl http:// localhost:12345 / etc / passwd并得到一个结果.
我不确定你打算如何连接第3步(OAuth),但希望这个答案会让你超越现在阻挡你的东西.