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?
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With