简体   繁体   English

使用 Python 的 Google Actions 推送通知?

[英]Google Actions Push Notification with Python?

I'm trying to figure out how to initiate a push notification using DialogFlow/Google Actions.我正在尝试弄清楚如何使用 DialogFlow/Google Actions 启动推​​送通知。 I've cobbled together some test code, but when I test it, I get a '403 Forbidden' response.我拼凑了一些测试代码,但是当我测试它时,我得到了“403 Forbidden”响应。 Can somebody provide me a good example of how to do this using Python 3.有人可以为我提供一个如何使用 Python 3.x 做到这一点的好例子吗?

` `

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)

` `

Can anybody provide any suggestions about how to get this to work?任何人都可以提供有关如何使其工作的任何建议吗?

============================================================= ================================================== ============

Update: I revised the auth header as suggested and now I'm getting '401:Unauthorized'.更新:我按照建议修改了 auth 标头,现在我收到了“401:Unauthorized”。 I'm not sure if I'm creating the access token properly.我不确定我是否正确创建了访问令牌。 Here's how I'm doing it:这是我的做法:

I created an RSA256 private key on the Google Console website.我在 Google Console 网站上创建了一个 RSA256 私钥。 I use that key to encode a JWT containing these fields:我使用该密钥对包含这些字段的 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\""
    ]
}

I don't know if this is correct: the documentation for all of this is hard to pull together.我不知道这是否正确:所有这些的文档很难整合在一起。

UPDATE 2:更新 2:

I modified the code suggested by Prisoner, and I'm now able to get what appears to be a valid access_token.我修改了 Prisoner 建议的代码,现在我能够获得看似有效的 access_token。 This is the modified code:这是修改后的代码:

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

When I try to use the access token, I'm still getting a '401 Unauthorized' response.当我尝试使用访问令牌时,我仍然收到“401 未经授权”响应。 Has anybody actually done this?真的有人这样做过吗? If so, can you give me some specifics on the correct URL to use and how to format the urllib.request message?如果是这样,您能否详细说明要使用的正确 URL 以及如何格式化 urllib.request 消息?

You've placed some things into the body of the request that belong in the header.您已将一些属于请求头的内容放入请求正文中。 In particular, the " 403 forbidden " suggests that the Authorization header is either wrong or missing, and in your case, it looks like it is missing since you're trying to put it in the body.特别是,“ 403 forbidden ”表明Authorization标头错误或丢失,在您的情况下,由于您试图将其放入正文,因此它看起来好像丢失了。

The body of what you're sending should just contain the JSON with the customPushMessage attribute.您发送的内容的正文应该只包含带有customPushMessage属性的 JSON。

I'm not very familiar with python, but I think something like this is more what you want:我对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)

If you continue to get the "403 Forbidden" message - make sure your access_token is current and is actually an access token.如果您继续收到“403 Forbidden”消息 - 确保您的access_token是最新的并且实际上是一个访问令牌。 Access tokens are created from the service account key, but are not the key itself.访问令牌是根据服务帐户密钥创建的,但不是密钥本身。 They have a limited lifetime (usually 1 hour), while the key is long-lasting.它们的寿命有限(通常为 1 小时),而关键是持久。

Update about generating an access token from the keys.关于从密钥生成访问令牌的更新

You can't just create and sign a JWT to use as an access token.您不能只是创建和签署 JWT 以用作访问令牌。

The easiest way is to use the Google APIs Client Library for Python , which includes a library to handle OAuth with service accounts .最简单的方法是使用适用于 PythonGoogle API 客户端库,其中包含一个用于处理服务帐户 OAuth的库。

I haven't tested, but you should be able to do something like this, setting SERVICE_ACCOUNT_FILE to the location of where the keys are stored.我还没有测试过,但是您应该可以执行类似的操作,将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()

Ok, I've figured out how to get the the access_token, so that part of the problem is solved.好的,我已经弄清楚如何获取access_token,这样部分问题就解决了。 I've run into another problem getting updates permission working for my test account, but I'm going to post a new question to cover that.我在为我的测试帐户获取更新权限时遇到了另一个问题,但我将发布一个新问题来解决这个问题。 I adapted code from another answer and this seems to work:我改编了另一个答案的代码,这似乎有效:

# 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM