Sunday, April 26, 2015

Host your Django Website In Ubuntu Server With Ngnix and Uwsgi.


Host your Django Website In Ubuntu Server With Ngnix and Uwsgi.




Introduction 

What is Ngnix ?

     Nginx (pronounced engine-x) is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. Igor Sysoev started development of Nginx in 2002, with the first public release in 2004. Nginx now hosts nearly 12.18% (22.2M) of active sites across all domains. Nginx is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption.

What is Uwsgi ?

      The uWSGI project aims at developing a full stack for building hosting services.applicaton servers( for various programing languages and protocols),proxies , process managers and monitors are all implemented using a common api and common configuration style.

Working Diagram for Ngnix, uWSGI with Python frameworks.

Configuration  

First install required applications:

sudo apt-get install nginx uwsgi uwsgi-plugin-python python-virtualenv, Here we are installing all the packages in single command ( ngnix , uwsgi and uwsgi packages and virtual env )
I think you all have ready Django project. Now iam going to explain about the configuration for Hosting our django project with Ubuntu Server.

Versions of packages that will be used:
  • Nginx 
  • Uwsgi
  • Virtualenv
  • Django 1.7.7
Step 1 :  Activate your virtual env and run your django project ,

Example : 

         cd `/myprojects/

         virtualenv  global
         
         source gobal/bin/activate
         
          pip install django 
          
          django-admin.py startprojeect logiconline

Step 2 : Nginx configuration.

        Configuration files are stored in /etc/ngnix/site-available. Go to this Directory and create new file for our project logiconline.

cd /etc/nginx/site-available 
sudo subl logiconline.in
 ( This command will create  a file for project , subl( Sublime text editor )

Example configuration :

server {
    listen  80;
    server_name logiconline.in www.logiconline.in;
    access_log /var/log/nginx/logiconline.in_access.log;
    error_log /var/log/nginx/logiconline.in_error.log;

    location / { 
        uwsgi_pass  unix:///tmp/logiconline.in.sock;
        include     uwsgi_params;
    }   

    location /media/  {
         alias /home/myprojects/logiconline/media/;
    }

    location  /static/ {
        alias /home/myprojects/logiconline/static/;
    }

}

We must create symlink to enable this.

cd /etc/ngnix/sites-enabled 
ln -s ../sites-available/logiconline.in.


Uwsgi Configurat.ion
Like with Nginx.. configuration files are stored in /etc/uwsgi/apps-available. Go to this directory and create a new file.
cd /etc/uwsgi/apps-available 
sudo subl logiconline.in.ini
Example : Uwsgi File 
[uwsgi]
vhost = true
plugins = python
socket = /tmp/logiconline.in.sock
master = true
enable-threads = true
processes = 2
wsgi-file = /home/myprojects/logiconline/logiconline/wsgi.py
virtualenv = /home/global
chdir = /home/myprojects/logiconline
touch-reload = /home/myprojects/logiconline/reload
Enable this.
cd /etc/uwgi/apps-enabled/
ln -s ../apps-available/logiconline.in.ini
Step 3 : That's all. Now, run this services.
sudo service nginx start
sudo service uwsgi start
This is very basic configuration for Hosting your project in Ubuntu server.Change it according to your need , any Querys Please feel free to contact me : renjithsraj@live.com and 9746272610





       
    




Tuesday, April 7, 2015

Django Custom User Authentication Backend


                           Django Custom User Authentication Backend


Introduction


In some Django projects we need to customize user model. We don’t want to go with the Django’s existing user model because we need more fields in user model. Sometimes we want to login user with the unique-id of third party service like Facebook, Twitter and etc.
In this blog I describe how to create custom user model and custom authentication backend to perform such requirements.

Creating Custom User Model

In this example I have created custom user model named as ‘Staff’. I have extended this Staff model with Django’s User model and added more fields in Member which I needed.

from django.contrib.auth.models import User, UserManager
from django.db import models

class Designation(models.Model):
    key = models.CharField(max_length=5)
    name = models.CharField(max_length=32)
    
    def __unicode__(self):
        return str(self.name)

class Staff(User):
    """User with app settings."""
    avatar = models.ImageField(upload_to="static/member_avatar/", blank=True, 
                               null=True)
    designation = models.ForeignKey(Designation)

    # Use StaffManager to get the create_user method, etc.
    objects = StaffManager()

    class Meta(object):
        verbose_name = 'Staff'
        verbose_name_plural = 'Staffs'

Changes Required in Settings File

Then, in settings.py file you have to explicitly mention custom user model and custom authentication backend.


AUTHENTICATION_BACKENDS = ('auth_backends.StaffModelBackend',)

CUSTOM_USER_MODEL = 'app.Staff'


Creating custom authentication backend

Create the custom authentication backend class and in this class we have to change user_class property method to get user instance from our custom model instead of Django’s User model. We have mentioned this class in settings file so that Django will get user instance of our custom model using this class (instead of Django’s User model).

from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ImproperlyConfigured
from django.db.models import get_model

class StaffModelBackend(ModelBackend):
    def authenticate(self, username=None, password=None):
        try:
            user = self.user_class.objects.get(username=username)
            if user.check_password(password):
                return user
        except self.user_class.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return self.user_class.objects.get(pk=user_id)
        except self.user_class.DoesNotExist:
            return None

    @property
    def user_class(self):
        if not hasattr(self, '_user_class'):
            self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.', 2))
            if not self._user_class:
                raise ImproperlyConfigured('Could not get custom user model')
        return self._user_class


Admin interface to add/edit custom User

You can also make a admin interface of your custom user model (i.e Staff). In below example, I have created StaffAdmin class which is used by Django’s admin to create/modify an instance of custom user model. In this class I have changed the fieldsets to create and modify forms.

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import ugettext_lazy as _

from app.models import Staff

class StaffChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = Staff
       
class StaffCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = Staff

class StaffAdmin(UserAdmin):
    form = StaffChangeForm
    add_form = StaffCreationForm
   
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                       'user_permissions')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
        (None, {'fields': ('designation', 'avatar')}),
    )
    add_fieldsets = UserAdmin.add_fieldsets + (
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                       'user_permissions')}),
        (None, {'fields': ('designation')}),
    )

admin.site.register(Staff, StaffAdmin)

                                            <========Thank You ========>




  

Saturday, April 4, 2015

Payu payment gateway integration with Django


                                  Payu Payment  Gateway Integration With Django 



  Introduction  

       
        This Blog is describes the steps for technical integration process between merchant 
website and PayU Payment Gateway for enabling online transactions. This Blog is covered payment gateway integration with Django Framework.



PayU Payment Gateway




PayU offers electronic payment services to merchant website through its partnerships with various banks and payment instrument companies. Through PayU, the customers would be able to make  




Electronic payments through a variety of modes which are mentioned below:


  • Credit cards
  • Debit cards
  • Online net banking accounts
  • EMI payments
  • Cash Cards
  • Email Invoicing
  • IVR
  • Cash on Delivery (COD)


PayU also offers an online interface (known as PayU Dashboard) where the merchant has access to various features like viewing all the transaction details, settlement reports, analytical reports etc.Through this interface, the merchant can also execute actions like capturing, cancelling andrefunding the transactions. This online interface can be accessed through Payu using the username and password provided to you.




Payment Gateway Process Flow 




      







PayU payment Gateway Process Flow





Steps for Integration Process


The steps for integrating with PayU can technically be described as below:




1) To start off the integration process, you would be provided a test setup by PayU where you

would be given a test merchant account and test credit card credentials to have a first-hand
experience of the overall transaction flow. Here, you need to make the transaction request
on our test server (and not the production server). Once your testing is complete, then only
you will be ready to move to the PayU production server.



2) To initiate a transaction, the merchant needs to generate a POST REQUEST - which must

consist of mandatory and optional parameters mentioned in the later section. This POST
REQUEST needs to be hit on the below mentioned PayU URLs:



For PayU Test Server:



For PayU Production (LIVE) Server:




3) In the merchant initiated POST REQUEST, one of the mandatory parameters is named as

hash. The details of this hash parameter have been covered in the later section. But it is
absolutely critical for the merchant to calculate the hash correctly and post to us in the
request.



4) When the transaction POST REQUEST hits the PayU server, a new transaction entry is

created in the PayU Database. To identify each new transaction in the PayU Database, a
unique identifier is created every time at PayU’s end. This identifier is known as the PayU ID
(or MihPayID).



5) With the POST REQUEST, customer would be re-directed to PayU’s payment page. Customer now selects the particular payment option on PayU’s page (Credit Card/Debit Card/NetBanking etc) and clicks on ‘Pay Now’. PayU re-directs the customer to the chosen bank. Thecustomer goes through the necessary authorization/authentication process at bank’s login page, and the bank gives the success/failure response back to PayU.




6) PayU marks the transaction status on the basis of response received from Bank. PayU

provides the final transaction response string to the merchant through a POST RESPONSE.
The parameters in this response are covered in the subsequent sections.



7) In the POST RESPONSE sent by PayU, you would receive the final status of the transaction.

You will receive the hash parameter here also. Similar to step 3, it is absolutely crucial to
verify this hash value at your end and then only accept/reject the invoice order. This is done
to strictly avoid any tampering attempt by the user.


Note : 


Test URL: The Test URL is provided to PayU merchants to test the integration of their  server with that of PayU or Bank. It is understood that since this is merely a Test URL, the Merchant should not treat any transactions done on this Test server as live and should not deliver the products/services with respect to any such test transactions even in the case your server receive a successful transaction confirmation from PayU/Bank.


Merchants are herein forth requested to set up required control checks on their               (merchant) systems/servers to ensure that only those transactions should get routed to the  PayU test server which are initiated with sole intention of test the environment.





PayU payment Gateway Integration with DJANGO





Onces you create the account With Payu they will provide SALT and KEY we need this two

credentials for the integration



Parameters to be posted by Merchant to PayU in Transaction Request:

  •  key (Mandatory)
  • txnid (Mandatory)
  • amount(Mandatory)
  • productinfo(Mandatory)
  • firstname(Mandatory)
  • email (Mandatory)
  • phone (Mandatory)
  • lastname
  • Udf1-Udf5
  • address1
  • city
  • state
  • country
  • zipcode
  • surl(Mandatory)
  • furl(Mandatory)
  • curl(Mandatory)
  • hash(Checksum)Mandatory)     :sha512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||SALT)

Udf : user defind field
Surl : Sucess URL ( Success redirection URLs ) 
Furl : Failure URL ( Failure redirectio URLs )
Curl : Cancelation URL( cancelation URLs)

Integration Steps 

Settings.py in your project

Add this Section.

####### Pay yu payment integration information###################





PAYU_INFO = {
              'merchant_key': "test merchant key",

             'merchant_salt': "test merchant salt",
             # for production environment use 'https://secure.payu.in/_payment'
             'payment_url': 'https://test.payu.in/_payment',
             'surl':'http://example.com/pay-success/',
             'furl':'http://example.com/failure/',
             'curl':'http://example.com/cancel/',
            }

###################End payment info ###############################


models.py 

from django.db import models
from uuid import uuid4

from uuid import UUID
import uuid
from django_extensions.db.fields import UUIDField


class MyOrder(models.Model):

    items = models.ManyToManyField(OrderItem, null=True, blank=True)
    order_date = models.DateField(auto_now=True)
    buyer = models.ForeignKey(Buyer)

    txnid = models.CharField(max_length=36, primary_key=True)
    amount = models.FloatField(null=True, blank=True,default=0.0)
    hash = models.CharField(max_length=500, null=True, blank=True)
    billing_name = models.CharField(max_length=500, null=True, blank=True)
    billing_street_address = models.CharField(max_length=500, null=True, blank=True)
    billing_country = models.CharField(max_length=500, null=True, blank=True)
    billing_state = models.CharField(max_length=500, null=True, blank=True)
    billing_city = models.CharField(max_length=500, null=True, blank=True)
    billing_pincode = models.CharField(max_length=500, null=True, blank=True)
    billing_mobile = models.CharField(max_length=500, null=True, blank=True)
    billing_email = models.CharField(max_length=500, null=True, blank=True)

    shipping_name = models.CharField(max_length=500, null=True, blank=True)
    shipping_street_address = models.CharField(max_length=500, null=True, blank=True)
    shipping_country = models.CharField(max_length=500, null=True, blank=True)
    shipping_state = models.CharField(max_length=500, null=True, blank=True)
    shipping_city = models.CharField(max_length=500, null=True, blank=True)
    shipping_pincode = models.CharField(max_length=500, null=True, blank=True)
    shipping_mobile = models.CharField(max_length=500, null=True, blank=True)
    shipping_rate = models.FloatField(null=False, blank=False, default=0.0)
    status = models.CharField(max_length=500, null=True, blank=True)
    shipping_email = models.CharField(max_length=500, null=True, blank=True)

    payment_method = models.CharField(max_length=1000,verbose_name='Payment-method')
    is_paid = models.BooleanField(default=False)
    is_delivered = models.BooleanField(default=False)
    is_accepted = models.BooleanField(default=False)



Views.py 

When the user click on the checkout button in your online shop,add this code add in to the that views.py


from django.core.exceptions import ObjectDoesNotExist

from django.contrib.auth.decorators import login_required
import hashlib
from django.conf import settings
from .util import generate_hash

@login_required

def buy_order(request):
    """ funtion for save all orders and genarate order id"""
    items = None
    orderitem = None
    extra = False
    if request.user.is_authenticated() and not request.user.is_staff:
        user = Buyer.objects.get(id=request.user.id)
        try:
            cart = Cart.objects.get(buyer=request.user)
        except ObjectDoesNotExist:
            extra = "You dont have any item in your cart"
            variables = RequestContext(request, {'extra': extra})
            return render_to_response('home.html', variables)
            total_amount = OrderItem.objects.filter(buyer=request.user)
            item_list = []
            rg = request.POST.get
            if cart:
                if request.POST:
                    rg('shippingnme')and rg('shippingaddress') and rg('shippingemail') and                                                   rg('shippingpostel') and rg('shippingcity') and rg('shippingcountry') and                                                 rg('shippingcountry') rg('shippingphone'):
                    try:
                        """store all products to myorder model and genarate order id for the order"""
                        myorder = MyOrder(buyer=user)
                        # billing User
                        myorder.buyer = user
                        # myorder of Billing  Address
                        myorder.billing_name = request.POST.get('billingname')
                        myorder.billing_street_address = request.POST.get(
                            'billingaddress')
                        myorder.billing_pincode = request.POST.get('billingpostel')
                        myorder.billing_city = request.POST.get('billingcity')
                        myorder.billing_country = request.POST.get('billingcountry')
                        myorder.billing_state = request.POST.get('billingstate')
                        myorder.billing_mobile = request.POST.get('billingphone')
                        myorder.billing_email = request.POST.get('billingemail')

                        # myorder of shipping Address
                        myorder.shipping_pincode = request.POST.get('shippingpostel')
                        myorder.shipping_name = request.POST.get('shippingnme')
                        myorder.shipping_street_address = request.POST.get(
                            'shippingaddress')
                        myorder.shipping_city = request.POST.get('shippingcity')
                        myorder.shipping_state = request.POST.get('shippingstate')
                        myorder.shipping_mobile = request.POST.get('shippingphone')
                        myorder.shipping_country = request.POST.get('shippingcountry')
                        myorder.shipping_email = request.POST.get('shippingemail')
                        if request.POST.get('paymentmethod'):
                            myorder.payment_method = request.POST.get('paymentmethod')
                        else:
                            myorder.payment_method = 'ON'
                        myorder.comment =  request.POST.get('prodcutmessage')

                        print "my messages "
                        print myorder.comment

                      # payment_method
                      # comment
                        myorder.txnid = str(uuid.uuid1().int >> 64)
                        myorder.save()
                        """genarate an oredr id, the below loop will add all orderd product to the                                               order"""

                        for order in cart.items.all():
                            orderitem = OrderItem()
                            orderitem.buyer = order.buyer
                            orderitem.product_id = order.product.id
                            orderitem.product_title = order.product.name
                            orderitem.weight = order.product.weight
                            orderitem.product_price = order.product.gross_pay()[0]
                            orderitem.total_amount = order.total
                            orderitem.quantity = order.quantity
                            orderitem.save()
                            myorder.items.add(orderitem)
                        total_details = total_price_fu(myorder)

                        """ After adding products to order assigning a
                        transaction amount and shipping charge to the order"""
                        myorder = MyOrder.objects.get(pk=myorder.txnid)

                        myorder.amount = total_details['grand_total']
                        myorder.shipping_rate = total_details['shipping_rate']

                        """Assigning all values for hash funtion for payu"""

                        cleaned_data = {'key': settings.PAYU_INFO['merchant_key'], 'txnid':                                                                   myorder.txnid, 'amount': myorder.amount, 'productinfo':                                                                   orderitem.product_title,'firstname': myorder.billing_name, 'email':                                                            myorder.billing_email, 'udf1': ' '', 'udf2': '', 'udf3': '', 'udf4': '', 'udf5': '', 'udf6': '',                                   'udf7': '',  'udf8': '', 'udf9': '', 'udf10': ''}

                        """ the generate_hash funtion is use for genarating hash
                         value from cleaned_data"""
                        hash_o = generate_hash(cleaned_data)
                        myorder.hash =hash_o
                        myorder.save()

                            return HttpResponse(
                                         """
                                              <html>
                                                  <head><title>Redirecting...</title></head>
                                                  <body>
                                                  <form action='%s' method='post' name="payu">
                                                      <input type="hidden" name="firstname" value="%s" />
                                                      <input type="hidden" name="surl" value="%s" />
                                                      <input type="hidden" name="phone" value="%s" />
                                                      <input type="hidden" name="key" value="%s" />
                                                      <input type="hidden" name="hash" value =
                                                      "%s" />
                                                      <input type="hidden" name="curl" value="%s" />
                                                      <input type="hidden" name="furl" value="%s" />
                                                      <input type="hidden" name="txnid" value="%s" />
                                                      <input type="hidden" name="productinfo" value="%s" />
                                                      <input type="hidden" name="amount" value="%s" />
                                                      <input type="hidden" name="email" value="%s" />
                                                      <input type="hidden" value="submit">
                                                  </form>
                                                  </body>
                                                  <script language='javascript'>
                                                  window.onload = function(){
                                                   document.forms['payu'].submit()
                                                  }
                                                  </script>
                                              </html>

                                          """ % (settings.PAYU_INFO['payment_url'],
                                                 myorder.billing_name, settings.PAYU_INFO[
                                                     'surl'],
                                                 myorder.billing_mobile,
                                                 settings.PAYU_INFO['merchant_key'],
                                                 hash_o,
                                                 settings.PAYU_INFO['curl'],
                                                 settings.PAYU_INFO['furl'],
                                                 myorder.txnid,
                                                 orderitem.product_title,
                                                 myorder.amount,
                                                 myorder.billing_email
                                                 )
                                        )



util.py 


from hashlib import sha512
from django.conf import settings
KEYS = ('key', 'txnid', 'amount', 'productinfo', 'firstname', 'email',
        'udf1', 'udf2', 'udf3', 'udf4', 'udf5',  'udf6',  'udf7', 'udf8',
        'udf9',  'udf10')

def generate_hash(data):
    keys = ('key', 'txnid', 'amount', 'productinfo', 'firstname', 'email',
            'udf1', 'udf2', 'udf3', 'udf4', 'udf5',  'udf6',  'udf7', 'udf8',
            'udf9',  'udf10')
    hash = sha512('')
    for key in KEYS:
        hash.update("%s%s" % (str(data.get(key, '')), '|'))
    hash.update(settings.PAYU_INFO.get('merchant_salt'))
    return hash.hexdigest().lower()

def verify_hash(data, SALT):
    keys.reverse()
    hash = sha512(settings.PAYU_INFO.get('merchant_salt'))
    hash.update("%s%s" % ('|', str(data.get('status', ''))))
    for key in KEYS:
        hash.update("%s%s" % ('|', str(data.get(key, ''))))
    return (hash.hexdigest().lower() == data.get('hash'))

Once the transaction comple we will get a set of query set in the form of Json Dictionary 

eg :

<QueryDict: {u'name_on_card': [u'sda'], u'net_amount_debit': [u'10'], u'payment_source': [u'payu'], u'udf10': [u''], u'issuing_bank': [u'AXIS'], u'field7': [u''], u'udf3': [u''], u'unmappedstatus': [u'captured'], u'card_type': [u'VISA'], u'PG_TYPE': [u'HDFC'], u'addedon': [u'2014-10-20 18:50:38'], u'city': [u''], u'field8': [u''], u'field9': [u'SUCCESS'], u'field2': [u'999999'], u'field3': [u'2819211501842931'], u'field1': [u'429367481506'], u'field6': [u''], u'zipcode': [u''], u'field4': [u'-1'], u'field5': [u''], u'productinfo': [u'adsdsd'], u'address1': [u''], u'discount': [u'0.00'], u'email': [u'arungopi.online@gmail.com'], u'cardhash': [u'This field is no longer supported in postback params.'], u'udf4': [u''], u'status': [u'success'], u'bank_ref_num': [u'2819211501842931'], u'error_Message': [u'No Error'], u'hash': [u'2f274b1f5ca4004db6eac28f317f9e1bff0105b7c14039ac663b9fcf50dc5910f20eaae33a938ef7989d0ecd28c6557d41f396229c21f18f4fb6f01a562ba667'], u'firstname': [u'Arun'], u'state': [u''], u'lastname': [u''], u'address2': [u''], u'error': [u'E000'], u'phone': [u'8113943843'], u'cardnum': [u'512345XXXXXX2346'], u'key': [u'gtKFFx'], u'bankcode': [u'CC'], u'mihpayid': [u'403993715510265476'], u'country': [u''], u'txnid': [u'9470041433304666596'], u'udf1': [u''], u'amount': [u'10.00'], u'udf2': [u''], u'udf5': [u''], u'mode': [u'CC'], u'udf7': [u''], u'udf6': [u''], u'udf9': [u''], u'udf8': [u'']}>

According to status in the callback queryset from the Payu. The url automaticaly redirect to the appropriate views( we mentioned this urls in settings.py and we pass the urls in the buyorder views )  



# order sucess mail views
@csrf_exempt
def success(request):
       ========================
       do what functionality you need 
     =========================



@csrf_exempt

def failure(request):
       ========================

       do what functionality you need 

     =========================



@csrf_exempt

def cancel(request):
       ========================

       do what functionality you need 

     =========================

    

I hope you all understood the payu payment gateway integration. this is working fine for me you can check the working with this link Electrotrendz online shop


                        <===============THANK YOU ============>