2010-10-18 3 views
2

Попытка начать работу с Amazon SNS. API очень простой REST. Кажется, я повесил трубку на подпись. Пример API является:Amazon SNS с Python

http://sns.us-east-1.amazonaws.com/ 
?Subject=My%20first%20message 
&TopicArn=arn%3Aaws%3Asns%3Aus-east-1%3A698519295917%3AMy-Topic 
&Message=Hello%20world%21 
&Action=Publish 
&SignatureVersion=2 
&SignatureMethod=HmacSHA256 
&Timestamp=2010-03-31T12%3A00%3A00.000Z 
&AWSAccessKeyId=AKIAJHS4T6XPF7XIURNA 
&Signature=9GZysQ4Jpnz%2BHklqM7VFTvEcjR2LIUtn6jW47054xxE%3D 

Я был после API docs for signatures, так что я пытаюсь:

from time import strftime,gmtime,time 
import urllib2 
import hmac 
import hashlib 
import base64 
import string 

def publichSNSMsg(Subject,TopicArn,Message,AWSAccessKeyId,privatekey): 
    #http://docs.amazonwebservices.com/AWSSimpleQueueService/2008-01-01/SQSDeveloperGuide/ 
    amzsnshost = 'sns.us-east-1.amazonaws.com' 
    values = {'Subject' : Subject, 
      'TopicArn' : TopicArn, 
      'Message' :Message, 
      'Timestamp' : strftime("%Y-%m-%dT%H:%M:%S.000Z", gmtime(time())), 
      'AWSAccessKeyId' : AWSAccessKeyId, 
      'Action' : 'Publish', 
      'SignatureVersion' : '2', 
      'SignatureMethod' : 'HmacSHA256', 
      } 

    amazquote=lambda v: urllib2.quote(v).replace('%7E','~') 
    cannqs=string.join(["%s=%s"%(amazquote(key),amazquote(values[key])) for key in sorted(values.keys(),key=str.lower)],'&') 
    string_to_sign=string.join(["GET",amzsnshost,"/",cannqs],'\n') 

    sig=base64.encodestring(hmac.new(privatekey,string_to_sign,hashlib.sha1).digest()) 
    querystring = "%s&Signature=%s"%(cannqs,amazquote(sig)) 
    url="http://%s/?%s"%(amzsnshost,querystring) 

    try: 
    return urllib2.urlopen(url).read() 
    except urllib2.HTTPError, exception: 
    return "Error %s (%s):\n%s"%(exception.code,exception.msg,exception.read()) 

И получить обратно:

<ErrorResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/"> 
    <Error> 
    <Type>Sender</Type> 
    <Code>SignatureDoesNotMatch</Code> 
    <Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message> 
    </Error> 
    <RequestId>8d6e5a41-dafb-11df-ac33-f981dc4e6c50</RequestId> 
</ErrorResponse> 

Есть идеи?

ответ

3

Aw, это было просто!

Ключами в строке запроса должны были быть byte-order сортировка, а не регистр-нечувствительность сортировка (это было для подписей 1-й версии).

Немного обновленный (и теперь правильный) код доступен на gist.

+3

Также есть очень полная библиотека AWS python под названием [boto] (http://github.com/boto/boto). –

1

Я нашел этот пример настолько полезным, что переписал его на C#. Поскольку AWS не имеет библиотеки WP7 для SNS, возможно, это кому-то поможет: https://gist.github.com/2705156

1

Я предлагаю вам использовать boto3 для SNS. Документацию можно найти по адресу http://boto3.readthedocs.io/en/latest/reference/services/sns.html. Следующий фрагмент кода можно использовать для получения подписи как JSON.

import boto3 
from django.views.decorators.csrf import csrf_exempt 
topic_arn = <your topic> 
client = boto3.client('sns',region_name="us-west-2") 

#Call this to publish 
def sns_publish(arg1,arg2): 
    response = client.publish(
         TopicArn=topic_arn, 
         Message=arg2, 
         Subject=arg2 
        ) 

#Function to subscribe to topic 
@csrf_exempt 
def sns_parse(request): 
    print request.body.decode('utf-8') 
    if request.method == "POST": 
     response = json.loads(request.body.decode('utf-8')) 
     type = response.get('Type') 
     if type == 'Subscription': 
      print(type) 
      return("Subscription URL: "+<Url obtained>) 
     elif type == 'Notification': 
      return HttpResponse(type.get('Signature')) 
    else: 
     return HttpResponse('Not a POST object') 

Это всего лишь код шаблона, но да, boto3 действительно полезен.

Смежные вопросы