Python 3.x 谷歌动作推送通知与Python?
我试图弄清楚如何使用DialogFlow/Google操作启动推送通知。我拼凑了一些测试代码,但当我测试它时,我得到了一个“403禁止”的响应。有人能给我一个很好的例子说明如何使用Python3实现这一点吗 ` ` 有人能就如何使这项工作发挥作用提供一些建议吗 ============================================================= 更新:我按照建议修改了auth标题,现在我得到了“401:Unauthorized”。我不确定是否正确创建了访问令牌。我是这样做的: 我在谷歌控制台网站上创建了一个RSA256私钥。我使用该键对包含以下字段的JWT进行编码:Python 3.x 谷歌动作推送通知与Python?,python-3.x,google-cloud-platform,google-oauth,dialogflow-es,actions-on-google,Python 3.x,Google Cloud Platform,Google Oauth,Dialogflow Es,Actions On Google,我试图弄清楚如何使用DialogFlow/Google操作启动推送通知。我拼凑了一些测试代码,但当我测试它时,我得到了一个“403禁止”的响应。有人能给我一个很好的例子说明如何使用Python3实现这一点吗 ` ` 有人能就如何使这项工作发挥作用提供一些建议吗 ============================================================= 更新:我按照建议修改了auth标题,现在我得到了“401:Unauthorized”。我不确定是否正确创建了访问令
{
"iss": [
"My Service Name",
"\"my_service-account@service_name.iam.gserviceaccount.com\""
],
"iat": 1544018697,
"exp": 1544019898,
"aud":
"https://www.googleapis.com/auth/actions.fulfillment.conversation\"",
"sub": [
"Push Notification",
"\"my-service-account@service_name.iam.gserviceaccount.com\""
]
}
我不知道这是否正确:所有这些的文档都很难整理
更新2:
我修改了囚犯建议的代码,现在我可以得到一个有效的访问令牌。这是修改后的代码:
from oauth2client.client import GoogleCredentials
service_account_file = 'path-to-service_account_file'
credentials = GoogleCredentials.from_stream(SERVICE_ACCOUNT_FILE)
access_token = credentials.get_access_token().access_token
当我尝试使用访问令牌时,仍然会收到“401未经授权”响应。有人真的这样做过吗?如果是这样的话,您能给我一些关于要使用的正确URL以及如何格式化urllib.request消息的详细信息吗?您已经在请求主体中放置了一些属于标题的内容。特别是,“”表示
授权
标题错误或丢失,在您的情况下,它看起来好像丢失了,因为您正试图将其放入正文中
您发送的内容的正文应该只包含带有customPushMessage
属性的JSON
我对python不是很熟悉,但我认为这样的东西更符合您的需要:
request = urllib.request.Request(my_url)
request.add_header('Authorization', 'bearer '+access_token)
request.add_header('Content-Type', 'application/json; charset=utf-8')
payload = { 'customPushMessage': notification }
jsondata = json.dumps(payload)
jsondataasbytes = jsondata.encode('utf-8')
response = urllib.request.urlopen(request, jsondataasbytes)
如果您继续收到“403禁止”消息,请确保您的access\u令牌是最新的,并且实际上是一个访问令牌。访问令牌是从服务帐户密钥创建的,但不是密钥本身。它们的寿命有限(通常为1小时),而钥匙是持久的
更新关于从密钥生成访问令牌的信息
您不能仅仅创建并签署一个JWT来用作访问令牌
最简单的方法是使用,其中包括要处理的库
我还没有测试过,但您应该能够执行类似的操作,将服务帐户文件
设置为密钥存储的位置
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/actions.fulfillment.conversation']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
access_token = credentials.get_access_token()
好的,我已经知道了如何获取access_令牌,这样部分问题就解决了。我遇到了另一个问题,获取测试帐户的更新权限,但我将发布一个新问题来解决这个问题。我根据另一个答案改编了代码,这似乎有效:
# Adapted from https://stackoverflow.com/questions/51821919/how-to-send-push-notification-from-google-assistant-through-dialogflow-fulfilmen/51961677#51961677
import io
import json
import requests
from google.oauth2 import service_account
import google.auth.transport.requests
def send_notification(path_to_service_account="default", intent="default"):
if path_to_service_account == "default":
PATH_TO_SERVICE_ACCOUNT = 'path to downloaded service account json file from Google Cloud Console'
else:
PATH_TO_SERVICE_ACCOUNT = path_to_service_account
if intent == "default":
INTENT = 'Notification Intent'
else:
INTENT = intent
REQUIRED_SCOPE = 'https://www.googleapis.com/auth/actions.fulfillment.conversation'
USER_ID = 'user id here'
INTENT = 'Your intent name'
# Get access token
with io.open(PATH_TO_SERVICE_ACCOUNT, 'r', encoding='utf-8') as json_fi:
credentials_info = json.load(json_fi)
credentials = service_account.Credentials.from_service_account_info(
credentials_info, scopes=[REQUIRED_SCOPE])
request = google.auth.transport.requests.Request()
credentials.refresh(request)
headers = {
'Authorization': 'Bearer ' + credentials.token
}
payload = {
'customPushMessage': {
'userNotification': {
'title': 'App Title',
'text': 'Simple Text'
},
'target': {
'userId': USER_ID,
'intent': INTENT,
# Expects a IETF BCP-47 language code (i.e. en-US)
'locale': 'en-US'
}
}
}
r = requests.request("POST", 'https://actions.googleapis.com/v2/conversations:send', data=json.dumps(payload), headers=headers)
print(str(r.status_code) + ': ' + r.text)
授权进入HTTP头,而不是正文。它应该是这样的授权:承载访问\u令牌
。谢谢!这很有帮助。我现在得到了“401:Unauthorized”,所以我想我的访问令牌有问题。请看一下我的OP中的更新,看看我在做什么。我只是在试验google.oauth2.service_帐户,所以你的答案非常有用。我会尝试一下,看看我能不能让它发挥作用。所以,我尝试了你的建议,但没有效果。credentials.get_Access_token()不是有效的函数,credentials.token的值为空。我认为这种方法缺少一个步骤。get\u access\u token()
应该获取过期或当前不存在的令牌。这是缺失的一步。嗯。。。不知道该怎么说函数丢失了。文件(链接到上面)说它应该存在。用任何可能有用的东西更新你的问题?您使用的源代码是什么?当您尝试使用get\u access\u token()
时出现了什么错误?
# Adapted from https://stackoverflow.com/questions/51821919/how-to-send-push-notification-from-google-assistant-through-dialogflow-fulfilmen/51961677#51961677
import io
import json
import requests
from google.oauth2 import service_account
import google.auth.transport.requests
def send_notification(path_to_service_account="default", intent="default"):
if path_to_service_account == "default":
PATH_TO_SERVICE_ACCOUNT = 'path to downloaded service account json file from Google Cloud Console'
else:
PATH_TO_SERVICE_ACCOUNT = path_to_service_account
if intent == "default":
INTENT = 'Notification Intent'
else:
INTENT = intent
REQUIRED_SCOPE = 'https://www.googleapis.com/auth/actions.fulfillment.conversation'
USER_ID = 'user id here'
INTENT = 'Your intent name'
# Get access token
with io.open(PATH_TO_SERVICE_ACCOUNT, 'r', encoding='utf-8') as json_fi:
credentials_info = json.load(json_fi)
credentials = service_account.Credentials.from_service_account_info(
credentials_info, scopes=[REQUIRED_SCOPE])
request = google.auth.transport.requests.Request()
credentials.refresh(request)
headers = {
'Authorization': 'Bearer ' + credentials.token
}
payload = {
'customPushMessage': {
'userNotification': {
'title': 'App Title',
'text': 'Simple Text'
},
'target': {
'userId': USER_ID,
'intent': INTENT,
# Expects a IETF BCP-47 language code (i.e. en-US)
'locale': 'en-US'
}
}
}
r = requests.request("POST", 'https://actions.googleapis.com/v2/conversations:send', data=json.dumps(payload), headers=headers)
print(str(r.status_code) + ': ' + r.text)