【问题标题】:Understanding where to put the IPN reciever function in django-paypal了解在 django-paypal 中放置 PIN 接收器功能的位置
【发布时间】:2017-08-14 01:25:17
【问题描述】:

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

我们正在尝试做的(我不认识其他人,但我假设我们在这个主题上站在一起)是了解如何推断接收贝宝 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)

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

{{ form.render }}

现在我可以接收到我在文档中指定的 paypal url 的 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'),
   .........]

【问题讨论】:

    标签: django paypal django-views django-paypal


    【解决方案1】:

    [UPDATE]:忘记提及您编写的代码的放置位置和方式(如果您愿意,可以使用处理程序)。在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!

    【讨论】:

    • 感谢您的回复。我仍然对正在发生的事情的整体过程感到困惑。当我创建 handlers.pysingals.py 时,里面到底发生了什么?我猜我在信号中输入了show_me_the_money 函数,但不确定handlers.py 中的内容。我也很困惑我的程序如何从贝宝获取 IPN 消息。再次感谢您的回复
    • @MichaelG。是的,您应该将此函数放在handlers.py 文件下。忘了说:/。我会更新我的答案!
    • 嗨@nik_m,请也看看这个问题!请参阅this 问题!
    【解决方案2】:

    这很尴尬,但问题是我没有使用测试业务帐户...我也实施了 nik_m 建议的答案,所以我建议也这样做。放函数:

    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

    【讨论】:

    猜你喜欢
    • 2013-06-02
    • 1970-01-01
    • 2022-01-27
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 2019-06-29
    相关资源
    最近更新 更多