Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 谷歌动作推送通知与Python?_Python 3.x_Google Cloud Platform_Google Oauth_Dialogflow Es_Actions On Google - Fatal编程技术网

Python 3.x 谷歌动作推送通知与Python?

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”。我不确定是否正确创建了访问令

我试图弄清楚如何使用DialogFlow/Google操作启动推送通知。我拼凑了一些测试代码,但当我测试它时,我得到了一个“403禁止”的响应。有人能给我一个很好的例子说明如何使用Python3实现这一点吗

`

`

有人能就如何使这项工作发挥作用提供一些建议吗

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

更新:我按照建议修改了auth标题,现在我得到了“401:Unauthorized”。我不确定是否正确创建了访问令牌。我是这样做的:

我在谷歌控制台网站上创建了一个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\""
    ]
}
我不知道这是否正确:所有这些的文档都很难整理

更新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)