允许用户注册的 Django 应用程序,一旦用户单击帐户激活链接,Zoho CRM 就会接收数据并在 CRM 部分创建联系人。
我目前正在开发一个绝对的杰作 - ZOHO API。 我正在努力设置使用 POST/GET 请求的本机 Python 代码。 关于zcrmsdk 3.0.0,我已经完全放弃了这个解决方案,除非有人可以提供一个功能齐全的示例。支持人员只是责怪我的代码。
我查阅的文档: https://www.zoho.com/crm/developer/docs/api/v2/access-refresh.html, https://www.zoho.com/crm/developer/docs/api/v2/insert-records.html
既然 postman API 中的 post 请求工作正常,我不明白为什么它在 python 代码中不起作用
我使用的权限范围是:ZohoCRM.modules.contacts.ALL、ZohoCRM.users.ALL、ZohoCRM.modules.deals.ALL、ZohoCRM.modules.attachments.ALL、ZohoCRM.settings.ALL、AAAserver.profile.ALL
def authenticate_crm():
"""
access to response object id:
response_object.get('data')[0].get('details').get('id')
"""
url = 'https://accounts.zoho.com/oauth/v2/token'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
# one time self-client token here -
request_body = {
"code": "1000.aa8abec144835ab79b8f9141fa1fb170.8ab194e4e668b8452847c7080c2dd479",
"redirect_uri": "http://example.com/yourcallback",
"client_id": "1000.H95VDM1H9KCXIADGF05E0E1XSVZKFQ",
"client_secret": "290e505ec52685fa62a640d874e6560f2fc8632e97",
" grant_type": "authorization_code"
}
response = requests.post(url=url, headers=headers, data=json.dumps(request_body).encode('utf-8'))
if response is not None:
print("HTTP Status Code : " + str(response.status_code))
print(response.json())
我本质上正在努力将 Postman API 请求转换为 Python 请求,以获取令牌作为工作流程的一部分。我在这里做错了什么?
文档指出: 注意:出于安全原因,请将以下参数作为表单数据传递到请求正文中。 (访问刷新链接)但将其作为表单数据传递到邮递员中完全破坏了调用。
根据他们自己的文档(令人费解、矛盾且充满过时的屏幕截图),身份验证密钥仅需要一次。 上面的请求运行后,我将获取第三张图片中的响应并使用刷新键添加联系人。 如果有人可以提供帮助,我也愿意接受 SDK 3.0.0 的解决方案。
我解决了!
我改变了这一行:
response = requests.post(url=url, headers=headers, data=json.dumps(request_body).encode('utf-8'))
为此添加了一些返回语句:
payload = '1000.6d9411488dcac999f02304d1f7843ab2.e14190ee4bae175debf00d2f87143b19&' \
'redirect_uri=http%3A%2F%2Fexample.com%2Fyourcallback&' \
'client_id=1000.H95VDM1H9KCXIADGF05E0E1XSVZKFQ&' \
'client_secret=290e505ec52685fa62a640d874e6560f2fc8632e97&'\
'grant_type=authorization_code'
response = requests.request(method="POST", url=url, headers=headers, data=payload)
if response is not None:
print("HTTP Status Code : " + str(response.status_code))
# print(response.text)
print(response.json())
# catch access and refresh token
at = response.json().get('access_token')
rt = response.json().get('refresh_token')
return at, rt
我不明白为什么会有所不同,但修复了它,我可以从 ZOHO 检索密钥。
使用这个答案给出了“无效代码”错误。我通过在有效负载的开头添加
code=
来修复它。所以,而不是:
payload = '1000.6d9411488dcac999f02304d1f7843ab2.e14190ee4bae175debf00d2f87143b19&' \
# ...
我用过
payload = 'code=1000.6d9411488dcac999f02304d1f7843ab2.e14190ee4bae175debf00d2f87143b19&' \
# ...
由于与 Zoho 集成非常痛苦,因此我将包含脚本的其余部分,其中还展示了如何获取初始授予令牌并刷新访问令牌。
我尝试清理现有答案中的方法,使其更易于维护,避免手动编码查询字符串,并为每个步骤提供更好的文档。希望从发布本文到您阅读本文时 API 不会发生太大变化...
"""
Zoho API access token generator
References:
- https://desk.zoho.com/support/APIDocument.do#OauthTokens
- https://stackoverflow.com/questions/67643027
"""
import requests
import urllib
# TODO set up your config
client_id = "1000.rn8abwxxxxxxxxxxxxxxxxxxxxxxxx"
client_secret = "c2b74fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
redirect_uri = "https://exact-url-from-config.com"
scope = "desk.articles.read"
state = "unused"
def get_auth_url() -> str:
"""Requests a grant token, the first step in the process.
The response has a location header with a URL that can
be used to login to Zoho by a user in a browser.
This should look like:
curl --dump-header - "https://accounts.zoho.com/oauth/v2/auth?response_type=code&client_id=1000.rn8wxxxxxxxxxxxxxxx&scope=desk.articles.read&redirect_uri=https://exact-url-from-config.com&state=-5466400890088961855&access_type=offline"
"""
grant_url = "https://accounts.zoho.com/oauth/v2/auth"
params = {
"response_type": "code",
"client_id": client_id,
"scope": scope,
"redirect_uri": redirect_uri,
"access_type": "offline", # required for refresh token
"state": state,
}
response = requests.get(grant_url, params=params, allow_redirects=False)
response.raise_for_status()
if "location" not in response.headers:
raise ValueError("No location in response headers")
return response.headers["location"]
def parse_grant_code(redirected_url: str) -> str:
"""Extracts the code= parameter from a URL"""
query = urllib.parse.urlsplit(redirected_url).query
grant_code = dict(urllib.parse.parse_qsl(query)).get("code")
return grant_code
def get_tokens(grant_code: str) -> dict:
"""Given a grant_code (which expires in 1 minute),
make a request to get the auth tokens.
Be careful to not make more than 5 refresh tokens in a minute.
"""
url = "https://accounts.zoho.com/oauth/v2/token"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {
"code": grant_code,
"client_id": client_id,
"client_secret": client_secret,
"grant_type": "authorization_code",
"redirect_uri": redirect_uri,
}
response = requests.post(url=url, headers=headers, data=data)
response.raise_for_status()
return response.json()
def refresh_access(refresh_token: str) -> dict:
"""Uses the refresh token to acquire a new access token"""
url = "https://accounts.zoho.com/oauth/v2/token"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {
"refresh_token": refresh_token,
"client_id": client_id,
"client_secret": client_secret,
"scope": scope,
"redirect_uri": redirect_uri,
"grant_type": "refresh_token",
}
response = requests.post(url=url, headers=headers, data=data)
response.raise_for_status()
return response.json()
def interactively_get_tokens():
auth_url = get_auth_url()
print("Go to the following link in a browser and sign in\n")
print(auth_url)
# After logging in, the user will be redirected to a URL
# that has a code= query parameter known as a grant token.
# We need this for the next request. It expires in 1 minute.
# the redirected URL should look like:
# https://your-redirect-url.com/?state=-5466400890088961855&code=1000.dd3d00f32a7190c8cc309370d96fa065.827a08c22d78a7df54c58e24800dc7de&location=us&accounts-server=https%3A%2F%2Faccounts.zoho.com&
redirected_url = input(
"\nthen paste the browser's redirected URL here and press Enter: "
)
grant_code = parse_grant_code(redirected_url)
# Now that we have the grant_code, make another request
# for the tokens. The access_token expires in 1 hour.
# The refresh_token never expires.
data = get_tokens(grant_code)
print("Tokens response JSON:", data)
print("Access token: ", data.get("access_token"))
refresh_token = data.get("refresh_token")
print("Refresh token:", refresh_token)
# After an hour, the access token will expire, so
# create a new one using the refresh token.
# access_token = refresh_access(refresh_token)
# print(access_token)
if __name__ == "__main__":
interactively_get_tokens()