【问题标题】:C2DM with App Engine Python returns 401 error使用 App Engine Python 的 C2DM 返回 401 错误
【发布时间】:2012-05-09 11:07:19
【问题描述】:

我很想向我的手机发送消息。通过浏览器,我调用了执行此操作的方法,我已经记录了registrationId、authToken等。这是正确的,因为我在本地服务器中进行了测试,并且消息已使用这些键发送到我的手机。

但是,在 App Engine 上,urlfetch.fetch 的结果为 'https://android.clients.google.com/c2dm/send' 时出现 401 错误。

或者,如果这是身份验证问题。我怀疑是上面的问题,因为调用了该方法,并且错误发生在我的 App Engine 服务器中方法的末尾。

这是我向 C2DM 服务器发出请求的方式:

params = {
          'registration_id':registrationId,
          'collapse_key':0,
          'data.payload':encoded_msg
         }

        paramsByte = urllib.urlencode(params)
        logging.info(registrationId)

        url = 'https://android.clients.google.com/c2dm/send'
        logging.info(token)
        result = urlfetch.fetch(url=url,
                                payload=paramsByte,
                                method=urlfetch.POST,
                                headers={'Content-Type':'application/x-www-form-urlencoded',
                                         'Authorization':'GoogleLogin auth='+token}
                                )

任何帮助将不胜感激。谢谢。


更新

现在客户端按照建议在托管服务器中运行,并且 联系时发生401错误 'https://android.clients.google.com/c2dm/send'。

但是,当在终端上使用具有相同令牌和 regId 的以下命令时,它可以工作。

curl --header "授权:GoogleLogin auth=your_authenticationid" “https://android.apis.google.com/c2dm/send”-d registration_id=your_registration -d "data.payload=payload" -d collapse_key=0

客户端代码调用服务器中的方法:

$.getJSON('http://myapp.appspot.com/method?userId='+userId+'&message='+theMessage+'&callback=?', 
    function(data)
    {
        console.log(data);
    });

服务器的完整方法代码:

class PushHandler(webapp.RequestHandler):

    '''This method sends the message to C2DM server to send the message to the phone'''
    def get(self):
        logging.info('aqui dentro')
        userId = self.request.get('userId')
        message = self.request.get('message')
        callback = self.request.get('callback')
        token = getToken(self) #this is a method I've implemented to get the token from C2DM servers by passing the SenderId and Password
        registrationId = ''
        contactNumber = ''

        # Get the registrationId to send to the C2DM server to know which 
        # device it may send the message
        regQuery = C2DMUser.all()
        regQuery.filter('userId =', int(userId))
        for k in regQuery:
            registrationId = k.registrationId

        # Builds the json to be sent to the phone
        record_to_json = {
                          'userId':userId,
                          'message':message
                          }
        data = []
        data.append(record_to_json)
        jsondata = simplejson.dumps(data) # Creates the json

        # Encode the JSON String
        u = unicode(jsondata, "utf-8")
        encoded_msg = u.encode("utf-8")

        params = {
                  'registration_id':registrationId,
                  'collapse_key':0,
                  'data.payload':encoded_msg
                  }

        paramsByte = urllib.urlencode(params)

        url = 'https://android.clients.google.com/c2dm/send'
        logging.info(token)
        result = urlfetch.fetch(url=url,
                                payload=paramsByte,
                                method=urlfetch.POST,
                                headers={'Content-Type':'application/x-www-form-urlencoded',
                                         'Authorization':'GoogleLogin auth='+token}
                                )

        data = []
        params_key = { 'status_code':result.status_code }
        data.append(params_key)
        self.response.headers['Content-Type'] = 'application/json'
        jsondata = simplejson.dumps(data)

        if result.status_code == 200:
            logging.info(result.status_code)
            self.response.out.write('' + callback + '(' + jsondata + ')') # handle the JSONP
        else:
            logging.info(result.status_code)
            self.response.out.write(result.status_code)

【问题讨论】:

  • 你为什么要在 apppot 上从 localhost 加载一些东西?

标签: android python google-app-engine android-c2dm


【解决方案1】:

您的代码包名称必须与您在注册​​ c2dm 帐户时提供的名称一致。对于 Java,如果您在注册时提供了 com.myapp,则您的 c2dm 调用必须发生在该包中。不过,不确定这如何转化为 Python。

【讨论】:

  • 确保您没有过期的注册 ID。如果您的代码将凭据存储在数据存储中,您可能需要删除并刷新它们。我以前在使用多个帐户进行测试时遇到过这种情况。
  • 但是我的python服务器中没有使用包名。我只是在注册表单中使用应用程序包名称,这是我的android应用程序的包名称,而不是我的服务器的包名称。对吗?
  • 正确,是安卓包名。
【解决方案2】:

就 C2DM 部分而言,一切似乎都还好。如果您说使用相同的凭据可以与您的本地服务器一起使用,我猜它应该可以在 App Engine 上使用。

就 XMLHttpRequest 错误而言,您不能通过 XMLHttpRequest 向其他域或子域发出请求。因此,您不能从 localhost 向yourSite 发出请求。一个解决方案是使用JSONP

【讨论】:

  • 好吧,我正在使用 JSONP。我的 AppEngine 服务器返回一个包含在回调中的 JSON。你认为我应该尝试不从本地主机调用我的服务器,而是从我的在线网站调用我的服务器吗?
  • 是的。我假设这可能是问题所在。如果您在 stackOverflow 上搜索 XMLHttpRequest cannot load 错误,您将找到与我提供给您的相同答案。我假设这可能是唯一可能的解释,因为您已经说过它可以在您的本地服务器上运行。
  • 我已将我的 Web 客户端上传到托管服务器,并拨打了电话,但 401 错误仍然存​​在。请使用服务器中方法的完整代码检查我的问题的更新,以及通过客户端上的 jQuery 进行的调用。在我在客户端上传并使用getJSON并进入服务器后,同源策略不再显示,但服务器上仍然出现401错误。 =(
猜你喜欢
  • 2021-12-06
  • 2012-02-23
  • 2015-01-19
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-25
相关资源
最近更新 更多