在 Django 视图中处理 Paypal IPN

Process Paypal IPN in Django view

根据 PayPal IPN 文档,您必须首先向 https://www.sandbox.paypal.com/cgi-bin/webscr 发送一个空的 HTTP 200 响应,然后发送一个 HTTP POST 请求来响应 IPN。我想出发送 HTTP 200 响应的唯一方法是在视图中返回 HttpResponse(''),这是有效的,因为 IPN 模拟器说 "IPN was sent and the handshake was verified." 但是我将如何发送 HTTP POST 在视图已经返回时请求?我的计划是使用 urllib2 生成 POST 请求。

我还想在不使用 HttpResponse('') 的情况下发送 HTTP 200 响应,因为我不知道原始请求来自哪里,而且我想确保我正在将响应发送到https://www.sandbox.paypal.com/cgi-bin/webscr。我查看了 urllib2、requests 和 PyCurl,但一直无法找到一种方法来创建对特定 URL.

的空响应

只是响应paypal 的请求。对于其他请求没有响应(403 http 状态)

from django.http import HttpResponseForbidden

def answer_to_pp_ipn():
    # ...
    if 'paypal' in request.META['HTTP_HOST']:
        return HttpResponse('OK 200')

    return HttpResponseForbidden()

正如您所说,requestsmake a post request 的完美选择。

您想使用 requestsurllib2 发出 POST 请求来验证 IPN ,然后 您 return HttpResponse('');文档暗示您必须以相反的顺序执行此操作,但实际上您不必这样做,而且这种方式在大多数 Web 框架中要简单得多。所以你的视图应该看起来像

def ipn(request):
    verification = requests.POST(PAYPAL_URL, data=request.body)
    if verification.text == 'VERIFIED':
        # process IPN
        return HttpResponse('')
    else:
        return HttpResponseForbidden()

请注意,如果这在某处出错,您将 return 向 PayPal 支付 500,他们会重试。如果你这样做太多,他们会生你的气并最终停用你的帐户,因此请确保你以某种方式收到有关错误的警报。 (您也可以将内容包装在 try/except 块中,但是如果出现错误,您可能会 return 冒着 return 没有实际进行处理的风险,这可能会更糟。) =16=]