2

I am new to aws-services and amazon-pay-services. I am trying to add Instant payment notification(IPN) for amazon-pay service. I was going through IPN-doc, It's mentioned that We need to verify the signature of IPN-body similar to aws-sns-sign-verify

So I am little confused here.

As per the documentation of aws-sns the post request will be like this

POST / HTTP/1.1
x-amz-sns-message-type: Notification
x-amz-sns-message-id: da41e39f-ea4d-435a-b922-c6aae3915ebe
x-amz-sns-topic-arn: arn:aws:sns:us-west-2:123456789012:MyTopic
x-amz-sns-subscription-arn: arn:aws:sns:us-west-2:123456789012:MyTopic:2bcfbf39-05c3-41de-beaa-fcfcc21c8f55
Content-Length: 761
Content-Type: text/plain; charset=UTF-8
Host: ec2-50-17-44-49.compute-1.amazonaws.com
Connection: Keep-Alive
User-Agent: Amazon Simple Notification Service Agent

{
  "Type" : "Notification",
  "MessageId" : "da41e39f-ea4d-435a-b922-c6aae3915ebe",
  "TopicArn" : "arn:aws:sns:us-west-2:123456789012:MyTopic",
  "Subject" : "test",
  "Message" : "test message",
  "Timestamp" : "2012-04-25T21:49:25.719Z",
  "SignatureVersion" : "1",
  "Signature" : "EXAMPLElDMXvB8r9R83tGoNn0ecwd5UjllzsvSvbItzfaMpN2nk5HVSw7XnOn/49IkxDKz8YrlH2qJXj2iZB0Zo2O71c4qQk1fMUDi3LGpij7RCW7AW9vYYsSqIKRnFS94ilu7NFhUzLiieYr4BKHpdTmdD6c0esKEYBpabxDSc=",
  "SigningCertURL" : "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem",
  "UnsubscribeURL" : "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:123456789012:MyTopic:2bcfbf39-05c3-41de-beaa-fcfcc21c8f55"
} 

And the post request for amazon-pay-IPN look like this

POST /SPN_project2/iopn HTTP/1.1
x-amz-sns-message-type: Notification
x-amz-sns-message-id: 4227aa54-ccf8-5a2a-8038-fb740d9f65d6
x-amz-sns-topic-arn: arn:aws:sns:eu-west-1:598607868003:A18VPDB9UTK24DA3GEDG4FJC14BQ
x-amz-sns-subscription-arn: arn:aws:sns:eu-west-1:598607868003:A18VPDB9UTK24DA3GEDG4FJC14BQ:993a0851-1b8d-4e0c-a48a-c4b2cbd17036
Content-Length: 2301
Content-Type: text/plain; charset=UTF-8
Host: ded73b97.ngrok.io
User-Agent: Amazon Simple Notification Service Agent
Accept-Encoding: gzip,deflate
X-Forwarded-Proto: https
X-Forwarded-For: 54.240.197.7

{

  "Type" : "Notification",
  "MessageId" : "4227aa54-ccf8-5a2a-8038-fb740d9f65d6",
  "TopicArn" : "arn:aws:sns:eu-west-1:598607868003:A18VPDB9UTK24DA3GEDG4FJC14BQ",
  "Message" : "{\"ReleaeEnvironment\":\"Live\",\"MarketplaceID\":\"220451\",\"Version\":\"2013-01-01\",\"NotificationType\":\"OrderReferenceNotification\",\"SellerId\":\"A3GEDG4FJC14BQ\",\"NotificationReferenceId\":\"f80ab4f0-82ca-42c8-a0d1-9b07f5b3fa30\",\"Timestamp\":\"2017-02-17T09:15:18.679Z\",\"NotificationData\":\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?><ChargeTransactionNotification xmlns=\\\"https://mws.amazonservices.com/ipn/OffAmazonPayments/2013-01-01\\\">\\n    <ChargeTransactionDetails>\\n        <OrderID>P04-5366666-6431174<\\/OrderID>\\n        <SellerReferenceId>test<\\/SellerReferenceId>\\n        <Amount>\\n            <Amount>10.0<\\/Amount>\\n            <CurrencyCode>INR<\\/CurrencyCode>\\n        <\\/Amount>\\n        <TotalFee>\\n            <Amount>0.0<\\/Amount>\\n            <CurrencyCode>INR<\\/CurrencyCode>\\n        <\\/TotalFee>\\n        <PaymentModes/>\\n        <FeeBreakup/>\\n        <CreationTimestamp>2017-02-17T09:00:13.592Z<\\/CreationTimestamp>\\n        <Status>\\n            <State>Declined<\\/State>\\n            <LastUpdateTimestamp>2017-02-17T09:15:13.879Z<\\/LastUpdateTimestamp>\\n            <ReasonCode>SessionExpired<\\/ReasonCode>\\n            <ReasonDescription>Session Expired<\\/ReasonDescription>\\n        <\\/Status>\\n    <\\/ChargeTransactionDetails>\\n<\\/ChargeTransactionNotification>\"}",
  "Timestamp" : "2017-02-17T09:15:19.922Z",
  "SignatureVersion" : "1",
  "Signature" : "FIRgFXytZTrpt4axHOHqVto+hbXadKhCnP2gfGaII3+6Jnawz939iT/KW4Z8wVYed3s+EGtC+xM3JCBVNJ5m7Ctf4bZZ9rFy+7Y7hAS/c18J1bNeEbEz2l0WQvpI4MDzH5/mmSVEWawfwX6zPE0R9U9kT81hac7a/NRedbUnJpOQCytCbTHxCn/k1s4WQQpXwIPnOVyp0x3Dj7ofkhJNB7bZk2bQET22DaOpSg01I4/KTU5t1iFzYVeoVRa3BcnB+X9d5GEdbmKjGg0SHhVSkzq0Qx3cpcipiyXzqv1IR62wxlpVC1yYkGXiw5uNU9k8QIweAoO4TuzR1IwYakTO3g==",
  "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-b95095beb82e8f6a046b3aafc7f4149a.pem",
  "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:598607868003:A18VPDB9UTK24DA3GEDG4FJC14BQ:993a0851-1b8d-4e0c-a48a-c4b2cbd17036"
}

As we can see that In case of sns-service, the Message field of the body have the plain string-type value(i.e test message in above example)

But in case of Amazon-pay-IPN-service, the Message field of the body have string-type value but contain json-data, lots of escaping characters as well as xml-string.

So at the time sign-verify in IPN-service, Do I need to take care of this extra data in Message field while creating canonical message? Will this extra data (json, xml-str, escape-char) in IPN-body make any changes in sign-verification process?

Any help would be appreciated. Thanks.

Amit
  • 861
  • 1
  • 9
  • 18

2 Answers2

0

Is there a reason why you want to manually verify the IPN messages? There are SDKs available for major languages such as PHP, Java, Python, .NET/C# and Ruby, that already implement an IPN verification.

If you cannot use any of those SKDs, you can still have look at the implementations such as the IpnHandler class of the PHP SDK or the NotificationVerification class of the Java SDK, to get an idea on how this is working.

Daniel Lemke
  • 1,966
  • 18
  • 24
0

Use a JSON library to deserialize the entire body.

The Message will be a string, and anything that has been escaped by SNS will be correctly unescaped for signature verification purposes. The meaning of the string at this point is not important -- it will be in the correct form for verification.

Then, once the signature is validated, deserialize that Message string a second time with your JSON library, and you'll have the final message, as a valid object, which you can then process.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • So I don't need to manually remove escape characters from `Message` field value while sign verification. I should treat it as a string. Right? – Amit Mar 06 '18 at 06:06
  • And yes I am using Json library to deserialize and creating the canonical form to verify the sign. – Amit Mar 06 '18 at 06:22
  • Take the strings you get when you pass the entire request body through the JSON decoder, once, and use the results, to verify the signature... then pass the value of `Message` through the JSON decoder to extract the object. The reason it works this way is that SNS receives the `Message` as a string, already encoded as JSON -- it happens to be JSON, but it could just as easily be Base64 or plain text. SNS doesn't interpret it or modify it, initially. It generates the signature, and then JSON encodes the entire object, so when you first receive the request, `Message` is JSON-inside-JSON. – Michael - sqlbot Mar 06 '18 at 23:27