We love designing and developing websites, but what really drives us is solving problems and cultivating strong relationships with our clients
Using Paypal with Django
By : shabda
Paypal has a comprehensive API to use their services programatically. The ExpressCheckout API allows you to get the user's details and then process the payments on your servers. They include a SOAP and NVP API. With NVP you do a GET to the Paypal servers with Url encoded values, get responses in plain text and work with them.
The basic flow for ExpressCheckout is something like this,
- You make a SetExpressCheckout request to Paypal, passing your credentials and and the amount you want to charge etc.
- Paypal returns an response with ACK of SUCCESS and token which you need to pass to subsequent requests.
- You transfer the user to Paypal site, passing the token returned in step 2.
- User logs in, and authorises transfer. Paypal redirects back to the SUCCESS_URL specified in step 1, passing the token and PayerID.
- You make a GetExpressCheckoutDetails request to Paypal, apssing token, payer id and other details.
- Paypal returns the user's and transactions details.
- You ask user to confirm details.
- You make a DoExpressCheckoutPayment request to Paypal. At this point the money is transferred from user's account to your account.
Now you can do the requests to Paypal very simply by sending requests, (it is just Url encoded name-value pair), but here is a Django snippet to make this wonderfully easy.
Before you can make requests to Paypal, servers you need to get API credentials. While developing your app, you of course, do not want to use actual Paypal money. Paypal makes available a sandbox where you can use virtual money before you go live.
- Go to developer.paypal.com and request a new sandbox API credentials.
- (Optionally)Read
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_api_referenceto understand how does the Paypal NVP api works. - We would two pages. [a] View 1: Where we do SetExpressCheckout and show a link to Paypal. [b] View 2: Where we do GetExpressCheckoutDetails, get the user's details, get a confirm from user. On a confirmation from user we post to the same page and do a DoExpressCheckoutPayment.
[Totally untested code ahead. I am copying and simplifying from one of our applications.]
#view 1
def veiw1(request):
...........
pp = paypal.PayPal()
token = pp.SetExpressCheckout(...)
paypal_url = pp.PAYPAL_URL + token
payload = {'paypal_url':paypal_url}
return render_to_response('template1.html', payload, RequestContext(request))
In the template send user to {{ paypal_url }} when they want to pay.
#View 2
#View 2 would be called after Paypal redirects after user authorises the transfer.
def view2(request):
token = request.GET.get('token', '')
pp = paypal.PayPal()
if request.method == 'GET':
paypal_details = pp.GetExpressCheckoutDetails(token, return_all = True)
payload = {}
if 'Success' in paypal_details['ACK']:
payload['ack'] = True
token = paypal_details['TOKEN'][0]
first_name = paypal_details['FIRSTNAME'][0]
.....
return render_to_response('template2.html', payload, RequestContext(request))
if request.method == POST:
payment_details = pp.DoExpressCheckoutPayment(token = token)
if 'Success' in payment_details['ACK']:
pass
#We have been paid. DO things like, enable subsciprion, ship goods etc.
return HttpResponseRedirect(payment_done_url)
Here in template2.html, we show the user/transaction details, and a on user's confirmation do a post to the same url. This should help you get started with integrating Paypal with Django.
Resources.
Need to build a Paypal enabled webapp? We can help
Comments
I'm a little confused about the order in which you're doing things in your example. It seem to me that your view1 is like a checkout page where they see the details of the purchase and then have a link by which they can choose to pay with PayPal (and possibly other links to pay with other methods). The click that link, are taken to the PayPal site where they log in and confirm the transaction, then are taken back to your site at view2 where they confirm the transaction again? I guess I'm just not getting the flow here. Why isn't their having logged into PayPal and confirmed there enough to actually process the payment as soon as they're returned to your site?
Josh: This is so you can do the checkout on your own site. You get the details of user who authorised the transaction, and then do the checkout on _your_ site, not on paypal's.
I don't see the purpose of having the user confirm twice (the second time on your site). Why not just issue the DoExpressCheckoutPayment() after they have hit your "success" view? I mean without a valid token the transaction will not be processed anyways.
Seems like the extra step isn't really needed.
I personally still use IPN for my payment processing app but I have been looking into this method lately. Simply because sometimes IPN has a delay in the confirmation and my customers end up waiting a minute or two before they can download their purchase. PITA.
Thank you so much!
Is there going to be an updated version of this snippet?
So where's an example for a directpayment? Not everyone is using expresscheckout ya know...
Thanks!
I didnt get this part
'Go to developer.paypal.com and request a new sandbox API credentials. '
I went there , made account, created API credentials and under then under test accounts I see some information. What I dont know is how to use that information in the code. What information to be used and where in the code?
Help please.
Thanks,
Dhruv
seo(æœç´¢å¼•æ“Žå„ªåŒ–ï¼‰æ˜¯æˆ‘å€‘ä¸»è¦æ¥å‹™ï¼Œç‚ºå¤§åž‹ä¼æ¥ç¶²çµ¡æä¾›SEOæœå°‹å¼•擎最佳化解決方案;數åƒå®¶ä¸å¤§åž‹ä¼æ¥ç¶²ç«™ç‡ŸéŠ·ç–劃經驗,æä¾›ä¼æ¥SEO培訓,整站優化方案制定,整站優化實施,百度網站收錄æ¢å¾©ï¼Œç¶²ç«™é‡æ§‹å£¹æ¢é¾æœå‹™
thank you this helpful information.
I somehow get the following error message when during "request.method == 'POST'":
"The view ecomstore.checkout.views.process_paypal didn't return an HttpResponse object."
My view code:
BEGIN
def process_paypal(request, template_name='checkout/order_confirm.html'):
""" Paypal API GetExpressCheckoutDetails """
token = request.GET.get('token', '')
transaction_id = request.GET.get('transaction_id', '')
amount_with_ship_price = request.GET.get('amt', '')
pp = paypal.PayPal()
if request.method == 'GET':
paypal_details = pp.GetExpressCheckoutDetails(token, return_all = True)
payload = {}
if 'Success' in paypal_details['ACK']:
payload['ack'] = True
if paypal_details['TOKEN'][0] == token: # Make sure TOKEN matches the value in SetExpressCheckout response
token = paypal_details['TOKEN'][0]
email_adress = paypal_details['EMAIL'][0]
...
else:
error_message = u'TOKEN from GetExpressCheckoutDetails does not match the SetExpressCheckout response TOKEN'
form = CheckoutForm()
page_title = 'Order Confirm'
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
if request.method == 'POST':
payment_details = pp.DoExpressCheckoutPayment(token = token, payer_id = transaction_id, amt = amount_with_ship_price)
if 'Success' in payment_details['ACK']:
request.session['order_number'] = order_number
receipt_url = urlresolvers.reverse('checkout_receipt')
return HttpResponseRedirect(receipt_url)
END
I don't know if there is anything wrong with the indentation.
Thank you for your help.
thank you this helpful information.
I somehow get the following error message when during "request.method == 'POST'":
"The view ecomstore.checkout.views.process_paypal didn't return an HttpResponse object."
My view code:
def process_paypal(request, template_name='checkout/order_confirm.html'):
""" Paypal API GetExpressCheckoutDetails """
token = request.GET.get('token', '')
transaction_id = request.GET.get('transaction_id', '')
amount_with_ship_price = request.GET.get('amt', '')
pp = paypal.PayPal()
if request.method == 'GET':
paypal_details = pp.GetExpressCheckoutDetails(token, return_all = True)
payload = {}
if 'Success' in paypal_details['ACK']:
payload['ack'] = True
if paypal_details['TOKEN'][0] == token: # Make sure TOKEN matches the value in SetExpressCheckout response
token = paypal_details['TOKEN'][0]
email_adress = paypal_details['EMAIL'][0]
...
else:
error_message = u'TOKEN from GetExpressCheckoutDetails does not match the SetExpressCheckout response TOKEN'
form = CheckoutForm()
page_title = 'Order Confirm'
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
if request.method == 'POST':
payment_details = pp.DoExpressCheckoutPayment(token = token, payer_id = transaction_id, amt = amount_with_ship_price)
if 'Success' in payment_details['ACK']:
request.session['order_number'] = order_number
receipt_url = urlresolvers.reverse('checkout_receipt')
return HttpResponseRedirect(receipt_url)
I don't know if there is anything wrong with the indentation.
Thank you for your help.
Yes, you are very much right, you cannot open a PayPal account for Charity, if your charity is registered in India, same thing happened with me also, I applied a Charity account for my client and after completing all the formalities they just denied for the account.
I have a suggestion for you, apply for a normal account with some other website and then use it for your Charity website, I have list of websites who are doing the same thing.
You can also try some other Payment Gateways like CCavenue, but in case you are using Vbulletin script, I don’t think so that it may help you. The first suggestion may work for you.
- How to use pep8.py to write better Django code
- Screencast: Django Tutorial Part 1
- How and why to use pyflakes to write better Python
- Getting started with South for Django DB migrations
- A brief overview of Vagrant
- Writing jQuery plugins using Coffeescript
- Behind the Scenes: Request to Response
- Using SQLite Database with Android
- Haml for Django developers
- Coffeescript for Python programmers
- rails
- django
- linkroundup
- django opinion
- opinion
- business
- API
- appengine
- python
- satire
- startup
- Uncategorized
- marketing
- personal
- rambling
- search
- interviews
- seo-interviews
- 5startupideas
- ideas
- seo
- tips
- forms
- paypal
- utilities
- datetime
- web2.0
- Amazon
- algorithms
- presentations
- products
- pinax
- satchmo
- ecommerce
- microsoft
- yahoo
- book
- tutorial
- models
- aggreagtion
- meta
- India
- apps
- about
- CSS
- Design
- wordpress
- test slug
- vim
- urls
- reviews
- javascript
- xmpp
- emacs
- Typography
- Grid Theory
- Color Theory
- iphone
- android
- titanium
- mobile applications
- CSS3
- Browser Compatibility
- mobile
- jobs
- lamson
- django setup
- files
- upload
- jsTree
- hierarchical view
- web page
- Treeview
- coffeescript
- request
- response
- South
- django south
- django migration
- --fake
- screencasts
- February 2012
- January 2012
- December 2011
- October 2011
- September 2011
- July 2011
- June 2011
- April 2011
- February 2011
- January 2011
- December 2010
- November 2010
- October 2010
- September 2010
- June 2010
- April 2010
- March 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- April 2009
- March 2009
- February 2009
- November 2008
- October 2008
- June 2008
- May 2008
- April 2008
Awesome. something I wanted to play with... cool!!