Paypal IPN和Golang在GAE上的集成

Ook*_*Ook 5 google-app-engine paypal map go

我正在编写一个用于处理Paypal IPN消息和响应的监听器.

根据Paypal IPN要求,监听器必须以相同的顺序发回从Paypal接收的值,并在值列表的前面插入新参数"cmd = _notify-validate".

您的侦听器HTTP将完整的,未更改的消息发送回PayPal.注意:此消息必须包含与PayPal中原始IPN 相同的相同字段,所有字段前面都有cmd = _notify-validate.此外,此消息必须使用与原始编码相同的编码.

但是,Go的url.Values变量在地图数据结构中实现,每次迭代时,该值的顺序不保证相同.

...当使用范围循环迭代映射时,未指定迭代顺序,并且不保证从一次迭代到下一次迭代是相同的"

当调用url.Values编码方法时,它将按键排序

Encode将值编码为按URL排序的"URL编码"形式("bar = 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)
Run Code Online (Sandbox Code Playgroud)

由于url.Values是一个地图,因此不保证地图中值的顺序是有序的.我怎么可能以Paypal IPN收到的相同顺序将参数值传回Paypal和GAE urlfetch服务?

Cal*_*leb 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)
Run Code Online (Sandbox Code Playgroud)

  • 是的,抱歉,使用“io.Copy”使用主体将使其无法用于“ParseForm”。(反之亦然)您可以用 `TeeReader` 替换 Body:http://golang.org/pkg/io/#TeeReader。因此,不要执行“io.Copy”,而是执行“r.Body = io.TeeReader(r.Body, &buf)”,然后调用:“r.ParseForm()”。 (2认同)
  • 抱歉没注意到这一点。您必须制作自己的支持关闭的“TeeReader”。这实际上并不难,因为“TeeReader”的代码很简单:http://golang.org/src/pkg/io/io.go?s=15125:15166#L465。这是一个未经测试的示例:http://play.golang.org/p/-0qsJrkw_x。然后你可以使用`r.Body = TeeReadCloser(r.Body, &buf)`。 (2认同)