kentzo
kentzo

Reputation: 65

django-paypal does not receive ipn signal

I am trying to use django-paypal. I was following what was mentioned in Jay on Django

Here is what i did...

##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)

My question are:

  1. According to jay on django, i have to put a @csrf_exempt before paypay.standard.ipn.views.ipn function to avoid django complaining about the @csrf_token problem. I did it but i still facing the same problem. Then i put the @csrf_exempt before my return url view function, in this case the payment_status(request,status), the the csrf_token problem is gone. So I am not sure why it is the case.

  2. what is this statement in the signal handler are for? "if ipn_obj.custom == "Upgrade all users!": .... " Is this coming from paypay? What are the possible value besides the "Upgrade all users?"

  3. I manage to do the purchase and complete the whole payment process at sandbox. But now the problem is that the paypal does not post the IPN back to my notify_url which is a localhost. I read from Paypal Sandbox IPN Problem that i cannot use localhost (http://127.0.0.1:8000) to test IPN. Then what are the steps needed to test? I don't understand the solution provided in that post. Can someone teach me how to test IPN without deploying the real production server?

Upvotes: 3

Views: 3880

Answers (3)

dlb8685
dlb8685

Reputation: 351

For #1 -- The only place I needed to put the @csrf_exempt tag was on the view that is called by the return_url. PayPal actually posts a lot of data about the payment to this url as well, for whatever reason.

For #2 -- You can specify a "custom" field in the paypal_dict, which will then be passed back to the notify_url. If you're only selling from one url or endpoint, it will be obvious what the payment is for, in combination with the invoice you have specified. But you might want to provide an additional field here to work with. "Upgrade all users!" is just a random example that the django-paypal documentation has.

For #3 -- I used ngrok, as mentioned in the django-paypal docs now (http://django-paypal.readthedocs.org/en/stable/standard/ipn.html#testing). I found it pretty easy to set up, not knowing anything about the tool before-hand.

Additionally -- one gotcha on the postbacks that nailed me for awhile was the following: I believed that PayPal was not posting to my notify_url, and I was researching answers like this.

Eventually I realized that PayPal was actually posting to my notify_url, but that my local machine was using an old version of SSL which would not complete a handshake when posting back to the PayPal sandbox (to get the VERIFIED/INVALID result). My version was 0.9.8 and they need something 1.0 or above. To make a long story short, the notify_url is a multi-step process and the problem could be something besides PayPal making the initial post to the notify_url.

Upvotes: 0

PhoebeB
PhoebeB

Reputation: 8570

I was stuck on this problem for a very long time! Turns out I had an error in my signals code but the error was never displayed, just appeared as though the signal was not being called. Eventually tracked it down by modifying the code in paypal-django like this:

in paypal.standard.ipn.views.py - 3 lines from the bottom:

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

Then check the apache error log for any errors.

Upvotes: 2

Tim Fletcher
Tim Fletcher

Reputation: 7396

Regarding your third point, as Daniel says in the answer to the question you linked, you need to allow Paypal to POST to your local machine. That means you need to open the port 80 on your router and forward the request to your development machine on port 8000. Go to http://whatismyip.com, get the IP and try to access it in your browser. Unless you have your router configured correctly you'll get nothing.

Once you've got your router set up you'll need to run the django server with:

python manage.py runserver 0.0.0.0:8000

Then you'll be able to access it externally. You can test this by putting your Internet connection's IP into the browser - you should see your Django site. If you don't then Paypal can't 'see' you either and will never be able to post back.

Upvotes: 4

Related Questions