了解在django-paypal中放置IPN接收器功能的位置

时间:2017-03-22 04:55:32

标签: django paypal django-views django-paypal

关于为paypal-ipn设置接收器功能,我在帖子here上有类似的问题

我们想要做什么(我不知道这个人,但我认为我们在这个主题上站在一起)是要了解如何推断接收PayPal IPN信号的路径,然后我们可以更新django数据库中。

我已按照here

的指示实施了django-paypal API

总的来说,我在views.py中创建了一个视图,如下所示

def payment_page(request):
   """This fucntion returns payment page for the form"""
   if not request.session.get('form-submitted', False):
       return HttpResponseRedirect(reverse('grap_main:error_page'))
   else:
       amount = set_payment()
       paypal_dict = {
           "business": "business@gmail.com",
           "amount": str(amount),
           "item_name": "2017 USGF Championships",
           "notify_url": "https://15b6b6cb.ngrok.io" + reverse('paypal-ipn'),
           "return_url": "https://15b6b6cb.ngrok.io/Confirm",
           "cancel_return": "https://15b6b6cb.ngrok.io/RegistrationForm",

  }
       form = PayPalPaymentsForm(initial=paypal_dict)
       context = confirm_information()
       context["amount"] = amount
       context["form"] = form
       request.session['form-submitted'] = False
       valid_ipn_received.connect(show_me_the_money)
       return render(request, "grap_main/payment.html", context)

然后,我的pay.html,然后只需使用文档中建议的行创建paypal按钮

{{ form.render }}

现在我可以收到我在文档中指定的PayPal网址的POST,但是我不知道在我完成购买后我应该将信号功能放到哪里以获取IPN。

def show_me_the_money(sender, **kwargs):
   """signal function"""
   ipn_obj = sender
   if ipn_obj.payment_status == ST_PP_COMPLETED:
       print 'working'
   else:
       print "not working"

现在我在视图payment_page()中调用此函数但是我知道这是在POST之前的PayPal并且不正确 我不明白我应该在哪里调用show_me_the_money()函数。我习惯于创建一个从html脚本调用的视图,如下所示

def register(request):
   """aquire information from new entry"""
   if request.method != 'POST':
       form = RegisterForm()
   else:
       if 'refill' in request.POST:
           form = RegisterForm()
       else:
           form = RegisterForm(data=request.POST)
           if form.is_valid():
               form.save()
               request.session['form-submitted'] = True
               return HttpResponseRedirect(reverse('grap_main:payment_page'))

html的

<form action="{% url 'grap_main:register' %}" method='post' class="form">
     {% csrf_token %}
     {% bootstrap_form form %}
     <br>
     {% buttons %}
     <center>
       <button name='submit' class="btn btn-primary">Submit</button>
     </center>
     {% endbuttons %}
   </form>

我相信我需要在一个人完成购买后调用该函数,但我不知道如何在我的代码中定位该时间窗口。我想确保我处理的情况是,一旦完成支付,用户就不会总是返回商家网站。

任何有关此主题的帮助不仅有益于我,也有利于早期的海报。我希望在我解决这个问题的时候制作一个教程来帮助那些可能会陷入困境的人。

请注意,我还使用ngrok确保我的项目可以通过paypal IPN服务访问。我正在使用两个urls.py文件,其中主要看起来如此

urlpatterns = [
   url(r'^paypal/', include('paypal.standard.ipn.urls')),
   url(r'^admin/', admin.site.urls),
   url(r'', include('grap_main.urls', namespace='grap_main')),
]

其中'grap_main.urls'是我网站的所有特定视图,例如

urlpatterns = [
   url(r'^$', views.index, name='index'),
   url(r'^Confirm', views.confirm, name='confirm'),
   url(r'^Events', views.events, name='events'),
   .........]

2 个答案:

答案 0 :(得分:1)

[更新] :忘记提及您编写的代码的位置和方式(如果您愿意,可以使用处理程序)。在handlers.py文件内写如下:

# grap_main/signals/handlers.py

from paypal.standard.ipn.signals import valid_ipn_received, invalid_ipn_received

@receiver(valid_ipn_received)
def show_me_the_money(sender, **kwargs):
    """Do things here upon a valid IPN message received"""
    ...

@receiver(invalid_ipn_received)
def do_not_show_me_the_money(sender, **kwargs):
    """Do things here upon an invalid IPN message received"""
    ...

虽然信号(和处理程序)可以在任何地方生活,但一个不错的惯例是将它们存储在应用程序的signals目录中。因此,grap_main应用的结构应如下所示:

project/
    grap_main/
        apps.py
        models.py
        views.py
        ...
        migrations/
        signals/
            __init__.py
            signals.py
            handlers.py            

现在,为了加载handlers,在grap_main/apps.py内写入(或添加)

# apps.py

from django.apps.config import AppConfig


class GrapMainConfig(AppConfig):
    name = 'grapmain'
    verbose_name = 'grap main' # this name will display in the Admin. You may translate this value if you want using ugettex_lazy

    def ready(self):
        import grap_main.signals.handlers

最后,在settings.py文件的INSTALLED_APPS设置下,而不是'grap_main'使用此代码:

# settings.py

INSTALLED_APPS = [
    ... # other apps here
    'grap_main.apps.GrapMainConfig',
    ... # other apps here
]

一些附注

  1. 使用encrypted buttons而不是使用标准表单来呈现贝宝按钮。这样你就可以防止任何可能的形式修改(主要是价格的变化)。

  2. 几个月前我使用了很棒的django-paypal软件包,完全在你的轨道上。但是,我需要将我的项目升级到Python 3.但是因为我使用了encrypted buttons我无法升级。为什么?因为加密按钮依赖于M2Crypto,它不支持(还有)Python 3.我是怎么做到的?我放弃了django-paypal并加入了Braintree,这是一家PayPal公司。现在,我不仅可以接受PayPal付款,还可以接受信用卡付款。所有Python 3!

答案 1 :(得分:0)

这是令人尴尬但问题是我没有使用测试业务帐户...我也实施了答案nik_m suggegested所以我建议做同样的事情。放功能:

def show_me_the_money(sender, **kwargs):
   """signal function"""
   ipn_obj = sender
   if ipn_obj.payment_status == ST_PP_COMPLETED:
       print 'working'
   else:
       print "not working"



valid_ipn_received.connect(show_me_the_money)
handlers.py

中的