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:
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.
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?"
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?
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.
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.
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.
Related
I have a doubt when using django.contrib.messages or showing a 404 page. In which case do I should use one or the another?
serial = get_object_or_404(SerialNumber, serial_number=sn)
or
try:
serial = SerialNumber.objects.get(serial_number=sn)
except SerialNumber.DoesNotExist
messages.add_message(request, messages.WARNING, 'no found!')
Thanks in advance!
Let's say you have some url like this:
/article/<pk>/
If a end-user calls /article/5/ and there is no article with ID 5, then you should not only return a message, that the searched term is not found, but also the proper HTTP status code, which is 404. Here you should use get_object_or_404.
If you want to display some additional information on the page for /article/4/ and there is article with ID 4, but this particular additional information is not there, then you should display the page for article with ID 4, return HTTP status code 200, which means OK, and display the message, that the additional information is not available.
The main difference is in my opinion the proper handling of the HTTP status codes, but I let others teach me, if I'm wrong.
In my opinion, the main difference between 404 error and Django messages framework is that the 404 is related to the server, and messages are related to your application.
In other words, if a user requires an url which does not exist (ie. /url/which/doesnt/exist/) then the server should send a 404. But if a user requires a feature of your application which can fail or which gives info or debug messages (/articles/feature_acting_on_article_db/), then you should use messages framework.
As you can see in documentation https://docs.djangoproject.com/en/1.7/ref/contrib/messages/, messages are used at application level. The definition of 404 error is given by: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5:
(...)This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
To conclude, I would say that the proper way to handle a url like /article/5/ where there is no 5th article is to send a message, because /article/pk/ is a feature which selects and displays info of the pk'th article (and no article doesn't mean that the command failed), even if the user entered a url (but that's my point of view about this question).
A 404 page page should be displayed when the user is trying to access any resource that is not available on the server.
On the other hand django messaging is used when you want to let the user see your application related custom messages. for example when he deletes or updates an entry you can show him a delete/update successful message.
I have a mirror API based app in which i have assigned a custom menu item, clicking on which should insert a new card. I have a bit of problem in doing that. I need to know of ways i can debug this.
Check if the subscription to the glass timeline was successful.
Print out something on console on click of the menu.
Any other way i can detect whether on click of the menu, the callback URL was called or not.
It sounds like you have a problem, but aren't sure how to approach debugging it? A few things to look at and try:
Question 1 re: checking subscriptions
The object returned from the subscriptions.insert should indicate that the subscription is a success. Depending on your language, an exception or error would indicate a problem.
You can also call subscriptions.list to make sure the subscriptions are there and are set to the values you expect. If a user removes authorization for your Glassware, this list will be cleared out.
Some things to remember about the URL used for subscriptions:
It must be an HTTPS URL and cannot use a self-signed certificate
The address must be resolvable from the public internet. "localhost" and local name aliases won't work.
The machine must be accessible from the public internet. Machines with addresses like "192.168.1.10" probably won't be good enough.
Question 2 re: printing when clicked
You need to make sure the subscription is setup correctly and that you have a webapp listening at the address you specified that will handle POST operations at that URL. The method called when that URL is hit is up to you, of course, so you can add logging to it. Language specifics may help here.
Try testing it yourself by going to the URL you specify using your own browser. You should see the log message printed out, at a minimum.
If you want it printed for only the specific menu item, you will need to make sure you can decode the JSON body that is sent as part of the POST and respond based on the operation and id of the menu item.
You should also make sure you return HTTP code 200 as quickly as possible - if you don't, Google's servers may retry for a while or eventually give up if they never get a response.
Update: From the sample code you posted, I noticed that you're either logging at INFO or sending to stdout, which should log to INFO (see https://developers.google.com/appengine/docs/java/#Java_Logging). Are you getting the logging from the doGet() method? This StackOverflow question suggests that appengine doesn't display items logged at INFO unless you change the logging.properties file.
Question 3 re: was it clicked or not?
Depending on the configuration of your web server and app server, there should be logs about what URLs have been hit (as noted by #scarygami in the comments to your question).
You can test it yourself to make sure you can hit the URL and it is logging. Keep in mind, however, the warnings I mentioned above about what makes a valid URL for a Mirror API callback.
Update: From your comment below, it sounds like you are seeing the URL belonging to the TimelineUpdateServlet is being hit, but are not seeing any evidence that the log message in TimelineUpdateServlet.doPost() is being called. What return code is logged? Have you tried calling this URL manually via POST to make sure the URL is going to the servlet you expect?
Some facts:
I am working on localhost with devserver. I have a Django project where the email sending works perfectly. I set up a new Django project, both 1.4.5, I copy / paste the email settings form the working project (EMAIL_HOST, EMAIL_PORT...) in settings.py to the new one, I open a shell with manage.py and load send_mail from django.core.mail on the first project it can send emails (I receive them in my email client), on the second the email never gets sent. I tried with various servers, gmail and gandi. I tried directly with the smtplib in pure Python code and it works with the same settings. While sending the mail with the first project and with smtplib I can see the function takes a few seconds to return the prompt in the command line but with the second project it returns the prompt immediately which makes me think nothing is happening.
So my question is what could be wrong in my new project's config? Where to look? And if possible how to debug that? (the send_mail function only returns 1, which is the number of mails I have sent, is there a way to get a trace back or some useful error message?)
to answer one of your questions:
>>> how to debug that?
Use pdb.set_trace() just before the call to whatever you want to debug.
I knew it was easy, it had to be a setting and indeed it was. I don't where that one comes from, may be it appears by default in new django projects, I have no idea but I had
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
in my settings file, far from my email settings and I had never entered it myself. Changing it to SMTP or commenting it makes Django actually send the email.
I am trying to implement django-paypal (dcramers version from git) using PDT with subscriptions.
It works fine (meaning that the return_url is requested and answered), however signals are not triggered (put in models.py). I am using the following signals, connected to two different functions.
from paypal.standard.pdt.signals import pdt_successful, pdt_failed
What I noticed while browsing through my access logs is that I do get a POST request from paypal which is turned down.
"POST /an-obscure-string/pdt/ HTTP/1.0" 401 401 "-" "-"
I tried to modify /paypal/standard/pdt/views.py to accept POST requests but I still get the 401 error. I think this is the reason signals are not triggered.
I am having a bad time with this. Any help would be greatly appreciated.
PS: I am using the sandbox account
EDIT These are my PAYPAL POSTBACK values from conf.py
POSTBACK_ENDPOINT = "https://www.paypal.com/cgi-bin/webscr"
SANDBOX_POSTBACK_ENDPOINT = "https://www.sandbox.paypal.com/cgi-bin/webscr"
You are right, that is the reason why the signal does not get called since signals are sent at the very end of the view if the model's verify succeed.
Your solution is indeed wrong, Paypal will definitely send a GET request with the transaction ID to your app url if you choosed to use PDN.
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_html_paymentdatatransfer
I really suggest you to check your settings (on paypal account) since you are probably using IPN which uses POST requests.
Another possible cause of this is that after you received the GET request from paypal your app sends the POST data to your app instead of to paypal postback endpoint. (https://github.com/johnboxall/django-paypal/blob/master/standard/pdt/models.py#L47)
I would look at the access logs to see if the POST request comes after a GET request (for the same url), if yes I would check the value of the SANDBOX_POSTBACK_ENDPOINT and POSTBACK_ENDPOINT settings.
I am using Django-PayPal plugin (http://github.com/johnboxall/django-paypal/tree/master), which works almost fine with one problem.
I followed integration process and think that everything is the same as in the guide.
But there is the problem, that I always get the INVALID response flag. I will not be able to determine the sucessfull IPN.
Do you know, how to not get the INVALID response in the IPN?
I know it's an old question, but some might still benefit from this.
You have to have "Payment Review" disabled for the PayPal test account you use to make the payment with. Then it should work as expected.
I'm developing a site using this at the moment, and when using the sandbox I get the correct responses for the payment status, however the buyers email is always marked as invalid.
I believe it's due to the sandbox environment.
I kept getting an INVALID response from IPN for such a long time....only to figure out that I was using the live server (www.paypal.com) instead of the sandbox (sandbox.paypal.com).