我正在尝试弄清楚如何使用DialogFlow / Google Actions启动推送通知。我整理了一些测试代码,但是当我对其进行测试时,我得到了“ 403 Forbidden”响应。有人可以为我提供一个很好的示例,说明如何使用Python 3进行此操作。
`
import urllib.request
import json
notification = {
'userNotification': {
'title': 'Test Notification',
},
'target': {
'userId': 'user-id here',
'intent': 'Notification Intent',
'locale': 'en-US',
}
}
my_url = 'https://actions.googleapis.com/v2/conversations:send'
access_token = 'access token here'
request = urllib.request.Request(my_url)
request.add_header('Content-Type', 'application/json; charset=utf-8')
payload = { 'auth': { 'bearer': access_token },
'json': 'true',
'body': { 'customPushMessage': notification, 'isInSandbox':
'true' } };
jsondata = json.dumps(payload)
jsondataasbytes = jsondata.encode('utf-8')
response = urllib.request.urlopen(request, jsondataasbytes)
`
有人可以提供有关如何使其正常工作的建议吗?
================================================ =============
更新:我按照建议修改了auth标头,现在我得到的是“ 401:Unauthorized”。我不确定是否正确创建了访问令牌。这是我的操作方式:
我在Google Console网站上创建了RSA256私钥。我使用该密钥对包含以下字段的JWT进行编码:
{
"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\""
]
}
我不知道这是否正确:所有这些的文档很难整理。
我修改了Prisoner建议的代码,现在我可以获取似乎有效的access_token了。这是修改后的代码:
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消息的详细信息吗?
答案 0 :(得分:1)
您已将一些属于标头的内容放入请求的正文中。特别是,“ 403 forbidden”表明Authorization
标头是错误的还是丢失的,在您的情况下,由于您试图将其放入正文中,因此看起来好像丢失了。 / p>
您要发送的内容正文应仅包含带有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 Forbidden”消息,请确保您的access_token
是最新的,并且实际上是访问令牌。访问令牌是通过服务帐户密钥创建的,但不是密钥本身。它们的寿命有限(通常为1小时),而钥匙则是持久的。
更新,有关通过密钥生成访问令牌。
您不能只创建并签名JWT用作访问令牌。
最简单的方法是使用Google APIs Client Library for Python,其中包括一个用于处理OAuth with service accounts的库。
我还没有测试过,但是您应该能够执行类似的操作,将SERVICE_ACCOUNT_FILE
设置为密钥的存储位置。
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()
答案 1 :(得分:0)
好的,我已经弄清楚了如何获取access_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)