django-paypal 收不到 ipn 信号

Posted

技术标签:

【中文标题】django-paypal 收不到 ipn 信号【英文标题】:django-paypal does not receive ipn signal 【发布时间】:2011-08-15 14:10:30 【问题描述】:

我正在尝试使用 django-paypal。我正在关注中提到的内容 Jay on Django

这就是我所做的......

##in my view.py file    
def ask_payment(request):
   # What you want the button to do.
   paypal_dict = 
    "business": settings.PAYPAL_RECEIVER_EMAIL,
    "amount": "0.10",
    "item_name": "book",
    "invoice": "yong138peng",
    "notify_url": "http://127.0.0.1:8000/accounts/my-ipn-location/",
    "return_url": "http://127.0.0.1:8000/accounts/my-return-location/",
    "cancel_return": "http://127.0.0.1:8000/accounts/my-cancel-location/",
     
   # Create the instance.
   form = PayPalPaymentsForm(initial=paypal_dict)
   context = "PP_form": form
   return render_to_response("paypal/payment.html",'PP_form':form,context_instance=RequestContext(request))

@csrf_exempt
def payment_status(request,status):
   return render_to_response("paypal/payment_status.html",       
             'status':status,context_instance=RequestContext(request))

##then in my urls.py file 
(r'^askforpayment/$','coltrane.views.ask_payment'),
(r'^my-ipn-location/', include('paypal.standard.ipn.urls')),
(r'^my-return-location/$','coltrane.views.payment_status','status':'success'),
(r'^my-cancel-location/$','coltrane.views.payment_status','status':'cancel'),

##in my models.py
def show_me_the_money(sender, **kwargs):
   ipn_obj = sender
   print "payment was successful!"
   # Undertake some action depending upon `ipn_obj`.
   if ipn_obj.custom == "Upgrade all users!":  ## what is this for, this is sent by paypal??
       Users.objects.update(paid=True)        
payment_was_successful.connect(show_me_the_money)

我的问题是:

    根据jay on django,我必须在 paypay.standard.ipn.views.ipn 函数之前放置一个@csrf_exempt 以避免django 抱怨@csrf_token 问题。我做到了,但我仍然面临同样的问题。然后我把@csrf_exempt放在我的return url view函数之前,在这种情况下是payment_status(request,status),csrf_token问题就消失了。所以我不知道为什么会这样。

    信号处理程序中的这条语句是干什么用的? "if ipn_obj.custom == "升级所有用户!": .... " 这是来自paypay吗?除了“升级所有用户”之外,还有什么可能的价值?

    我设法在沙盒中完成了购买并完成了整个支付过程。但现在的问题是,paypal 没有将 IPN 发布回我的 notify_url,它是一个本地主机。我从Paypal Sandbox IPN Problem 读到我不能使用 localhost (http://127.0.0.1:8000) 来测试 IPN。那么测试需要哪些步骤呢?我不明白post 中提供的解决方案。谁能教我如何在不部署真正的生产服务器的情况下测试 IPN?

【问题讨论】:

【参考方案1】:

#1 -- 我需要放置@csrf_exempt 标记的唯一位置是return_url 调用的视图。实际上,无论出于何种原因,PayPal 都会向该 URL 发布大量有关付款的数据。

#2 -- 您可以在 paypal_dict 中指定一个“自定义”字段,然后将其传递回 notify_url。如果您只从一个 url 或端点进行销售,那么结合您指定的发票,付款的用途就很明显了。但是您可能想在此处提供一个额外的字段来使用。 “升级所有用户!”只是 django-paypal 文档中的一个随机示例。

#3 -- 我使用了 ngrok,正如 django-paypal 文档中提到的那样 (http://django-paypal.readthedocs.org/en/stable/standard/ipn.html#testing)。我发现它很容易设置,事先对工具一无所知。

另外——在回发中让我困扰了一段时间的一个问题是:我认为 PayPal 没有发布到我的 notify_url,我正在研究这样的答案。

最终我意识到 PayPal 实际上是在向我的 notify_url 发帖,但是我的本地机器使用的是旧版本的 SSL,当发回 PayPal 沙箱时无法完成握手(以获取 VERIFIED/INVALID 结果)。我的版本是 0.9.8,他们需要 1.0 或更高版本。长话短说,notify_url 是一个多步骤的过程,除了 PayPal 将初始帖子发送到 notify_url 之外,问题可能还存在。

【讨论】:

【参考方案2】:

我被这个问题困扰了很长时间!原来我的信号代码中有错误,但该错误从未显示,只是看起来好像没有调用信号。最终通过像这样修改paypal-django中的代码来追踪它:

在 paypal.standard.ipn.views.py - 从底部算起 3 行:

        try:
            ipn_obj.verify(item_check_callable)
        except:
            import sys, traceback
            traceback.print_exc(file=sys.stdout)

然后检查 apache 错误日志是否有任何错误。

【讨论】:

【参考方案3】:

关于您的第三点,正如丹尼尔在回答您链接的问题时所说,您需要允许 Paypal 发布到您的本地计算机。这意味着您需要打开路由器上的 80 端口并将请求转发到端口 8000 上的开发机器。转到http://whatismyip.com,获取 IP 并尝试在浏览器中访问它。除非您正确配置了路由器,否则您将一无所获。

设置好路由器后,您需要运行 django 服务器:

python manage.py runserver 0.0.0.0:8000

然后您就可以从外部访问它了。您可以通过将 Internet 连接的 IP 放入浏览器来进行测试——您应该会看到您的 Django 站点。如果您不这样做,那么 Paypal 也无法“看到”您,并且永远无法回帖。

【讨论】:

蒂姆,谢谢。我设法做到了。但我没有使用 whatismyip.com,因为返回的 IP 地址不正确(或者不是我的路由器的真实 IP,它返回 220.255.1.50)我使用的是dyndns.com/support/tools/openport.html 提供的工具。但是每次我重新启动路由器时,我都必须执行此步骤并更新 notify_url(到新的 ip)。有点不方便。寻找脚本以获取我的路由器的正确 IP,但大多数都不起作用。

以上是关于django-paypal 收不到 ipn 信号的主要内容,如果未能解决你的问题,请参考以下文章

Django-Paypal IPN 403 错误

django-paypal:IPN 请求总是无效的

为啥Paypal在使用django-paypal时会重试IPN

Django-paypal 不在 DB 中创建 IPN 表 - 如何修复?

收不到 PayPal IPN 回调

Django Paypal 订阅