Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paypal IPN and Golang integration on GAE

I am writing a listener for handling Paypal IPN messages and responses.

From Paypal IPN requirement, The listener have to post the values received from Paypal back in the same order with a new parameter "cmd=_notify-validate" inserted at the front of the value list.

Your listener HTTP POSTs the complete, unaltered message back to PayPal. Note: This message must contain the same fields, in the same order, as the original IPN from PayPal, all preceded by cmd=_notify-validate. Further, this message must use the same encoding as the original.

However, Go's url.Values variable is implemented in map data structure which order of the value is not guaranteed to be the same when being iterated each time.

...When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next"

And when url.Values encoded method is called, it will be sorted by key

Encode encodes the values into “URL encoded” form ("bar=baz&foo=quux") sorted by key.

The listener is running on GAE thus I use "appengine/urlfetch"'s PostForm function which takes url.Values as the second parameter

c := appengine.NewContext(r)
client := urlfetch.Client(c)
resp, err := client.PostForm("https://www.sandbox.paypal.com/cgi-bin/webscr", r.Form)

As url.Values is a map, the order of values in the map are not guaranteed to be in order. How can I possibly pass the parameter values back in the same order received from Paypal IPN back to Paypal with GAE urlfetch service?

like image 206
Ook Avatar asked Oct 02 '22 01:10

Ook


1 Answers

Use Post instead of PostForm. You can probably use the body from the request:

var buf bytes.Buffer
buf.WriteString("cmd=_notify-validate&")
io.Copy(&buf, r.Body)

client.Post("http://localhost", "application/x-www-form-urlencoded", &buf)
like image 96
Caleb Avatar answered Oct 13 '22 12:10

Caleb