2013-12-26 9 views
5

Я пишу слушатель для обработки сообщений и ответов IPN Paypal.Paypal IPN и интеграция Golang на GAE

Из требования IPN от Paypal слушатель должен опубликовать значения, полученные от Paypal, в том же порядке с новым параметром «cmd = _notify-validate», вставленным в начало списка значений.

Ваш HTTP-прослушиватель HTTP отправляет полное, неизмененное сообщение обратно в PayPal. Примечание: Это сообщение должно содержать те же поля, в том же порядке, что и исходный IPN из PayPal, которому предшествует cmd = _notify-validate. Кроме того, это сообщение должно использовать ту же кодировку, что и оригинал.

Однако переменная Go url.Values ​​реализована в структуре данных карты, порядок выполнения которой не гарантируется при повторении каждого раза.

... Когда итерация над картой с петлей диапазона, порядок итерации не указан и не гарантируется быть одинаковым от одной итерации к следующей»

И когда url.Values ​​закодирован метод вызывается, он будет отсортирован по ключевому

Encode кодирует значения в «URL» закодированы форме ("бар = baz & foo = quux ") отсортировано по ключевым словам.

Слушатель работает на GAE, таким образом, я использую "AppEngine/UrlFetch" 'ы функцию PostForm, которая принимает url.Values ​​в качестве второго параметра

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

В url.Values ​​является карта, порядок значений на карте не гарантируется. Как я могу передать значения параметров обратно в том же порядке, который получен от Paypal IPN, обратно в Paypal с помощью службы urlfetch GAE?

ответ

4

Использовать Post вместо PostForm. Вы, вероятно, можете использовать тело из запроса:

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

client.Post("http://localhost", "application/x-www-form-urlencoded", &buf) 
+0

Это работает, но после io.Copy (& ЬиЙ, r.Body) линия, я попытался запустить r.ParseForm(). У меня не было ошибки, так как у меня есть обработчик ошибок. Тем не менее, я не получил никакой ценности в r.Form. Кажется, что io.Copy что-то сделал для r.Body? И я не могу запустить parseForm() до io.Copy (& buf, r.Body), потому что он каким-то образом изменил тело. Есть ли у вас какие-либо идеи? – Ook

+0

Или мне нужно скопировать r.Body по значению для запуска io.Copy (& buf, r.Body) отдельно? – Ook

+2

Да, извините, что использование тела 'io.Copy' сделает его недоступным для' ParseForm'. (и наоборот). Вы можете заменить тело «TeeReader»: http://golang.org/pkg/io/#TeeReader. Поэтому вместо 'io.Copy', сделайте' r.Body = io.TeeReader (r.Body, & buf) ', а затем вызовите:' r.ParseForm() '. – Caleb

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