implementing PayPal IPN in Django Application - django

I'm writing an application in Django 2.0
It is a multi membership application. I have to implement PayPal payment method and activate the membership based on payment received.
For this, I have created a button in PayPal with generates code as
upgrade.html
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="<button-id>">
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
and views.py is
class Pricing(TemplateView):
template_name = 'membership/pricing.html'
class Upgrade(TemplateView):
template_name = 'membership/upgrade.html'
class PaymentSuccess(TemplateView):
template_name = 'membership/payment-success.html'
class PaymentFailed(TemplateView):
template_name = 'membership/payment-failed.html'
def paypal_ipn(request):
# IPN response goes here
and urls.py
urlpatterns = [
path('pricing/', Pricing.as_view(), name='pricing'),
path('upgrade/', Upgrade.as_view(), name='upgrade'),
path('payment-success/', PaymentSuccess.as_view(), name='payment-success'),
path('payment-failed/', PaymentFailed.as_view(), name='payment-failed'),
path('paypal-ipn/', paypal_ipn, name='paypal-ipn'),
]
All is working fine as Payment is being made and user is redirected to the payment-success page.
But How do I receive the payment confirmation so that I could process the membership and record the transaction data in the database?
I have enabled instant payment notification from the settings in paypal sandbox accoun on url https://example.com/paypal-ipn/
I do not want to use django-paypal plugin due to some limitations.

You can create your own IPN handling page to receive PayPal IPN message. IPN Sample code below.
https://github.com/paypal/ipn-code-samples

Related

Django & AJAX to show DB objects upon user's input submission

I'm pretty new in the Web development world, have been using Django so far.
I've been trying to figure out how to render data back to page after clicking on a submit button, so I see I'll need to use AJAX for that purpose.
I've created a very simple app just to understand the basics of AJAX.
However, googling, I couldn't really find a basic straight-forward implementation so I kinda got lost...
What I'm trying to achieve:
I have a model called Country:
class Country(models.Model):
name = models.CharField(primary_key=True, max_length=35)
continent = models.CharField(max_length=10)
capital = models.CharField(max_length=35)
currency = models.CharField(max_length=10)
And a super simple main page that asks the user to insert some country name.
The idea is to bring to the page all the info from the DB.
So it would look like this:
Main page HTML body:
<body>
<h2><em>Please type a country name:</em></h2><br><br>
<div class="container">
<form id="get_info" method="post">
{{ form }}
{% csrf_token %}
<input id="submit_button" type="submit" name="submit" value="Get info">
</form>
</div>
</body>
views.py:
from django.shortcuts import render
from country_trivia import forms
def main_page(request):
get_info_form = forms.GetInfo()
return render(request, 'country_trivia/index.html', {'form': get_info_form})
forms.py:
from django import forms
class GetInfo(forms.Form):
country_name = forms.CharField(label="")
I've seen some examples using forms, but I'm not even sure if it's needed, as I've seen some other examples that count on 'onclick' even listeners, then "grab" the text in the search field and pass it via AJAX...
How should I build my AJAX object for that simple purpose, and how should I integrate it?
Do I need to use forms at all?
I don't post anything to DB, just query it and print out data...
Thanks!!

Intergrating Django with React Frontend: Is a REST API Needed

so I am trying to connect my back-end Django to my front-end React. Now the front-end react is essentially completed and running on a node server to check it out. I want to integrate it into my Django to use as a back-end. My first thing i want to do is set up the login and register page. I have most of the django back-end done but now i need to get the information like the email and password from the React to Django.
The HTML for EMail and Password
<form action="/authentication/" method ="POST">
{% csrf_token %}
Email :
<input type="email" name="email"><br><br>
Password :
<input type="password" name="pass"><br><br>
<input type="submit" value="Login">
<button type="button" onclick="location.href='{% url 'register' %}'">Register</button>
</form>
the react text field for just the email looks like this:
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
type="email"
name="email"
autoComplete="email"
autoFocus
/>
Django
def user_login(request):
return render(request, 'user_login.html') # page which user will login at
def authentication(request):
email = request.POST.get('email')
passwrd = request.POST.get('pass')
try:
user = authen.sign_in_with_email_and_password(email, passwrd)
except Exception as E:
# Where login fails goes
message = "Credentials Wrong"
return render(request, 'user_login.html', {'message':message}) # sends message login failed
My first question is do i need to create a separate REST API fro the back-end? At the moment the back end is taking a simple test HTML file where i can enter the email and password which is as below, but if i wanted to implement it with react would i have to change out the .html for the .js file?
For React to communicate with Django, it requires an api(Restful or Graphql) to work. Django has a nice way by providing django_resful api or django_graphene which works well with the Django model and reactjs for frontend. For me I use graphql for Django and reactjs, it way so easy and later I will send you a GitHub link of my project or you can check on Youtube (justdjango).

A create view in another view django

I am new to django. I've created a basic posts app where users post messages. The project has posts app for posting messages. The app has two models- Post and Comment where one post can have many comments. My posts are shown in list view with comments for a particular post.
Now, i want to have an 'add comment' button for each post so i can directly add comment (stack exchange design!) . This can otherwise be implemented by a seperate createview for comments model. I want an textarea on listview itself to input comments for a post.
How can i do this?
In the most basic form, you can define different routes for your desired views (CreateComment, PostDetails) and send a POST request to the CreateComment view from the PostDetails route.
urls.py
urlpatterns = [
path('post/<pk>/', post_details, name='post-details'),
path('comment/new/', add_comment, name='create-comment'),
]
and in your post/<pk>/ route, set up a form like below:
<form method="POST" action="/comment/new/">
<input value="" name="description" type="text" />
<input value="/current/path/" name="redirect" type="hidden" />
{% csrf_token %}
</form>
You can then redirect the user to the page he was making the request from in the first place, using the redirect value which is passed by the form from the origin route.

Django Rest Framework returns 200 OK even though login request has incorrect credentials

This is my URLS.py:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^CMS/', include('CMSApp.urls')),
url(r'^admin/', include(admin.site.urls)),
]
and this is CMSApp/urls.py:
from django.conf.urls import url
from django.conf.urls import include
from CMSApp import views
urlpatterns = [
url(r'^$', views.HomePageView.as_view()),
url(r'^users$', views.user_list.as_view()),
url(r'^users/(?P<pk>[0-9]+)$', views.user_detail.as_view()),
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
]
My HomePageView serves this home.html page:
<h3>Register</h3>
<form ng-submit="ctrl.add()" name="myForm">
<label>Username</label>
<input type="text" name="uname" ng-model="ctrl.user.username" required>
<label>Password</label>
<input type="password" name="pwd" ng-model="ctrl.user.password" required>
<label>Email</label>
<input type="email" name="mail" ng-model="ctrl.user.email" required>
<input type="submit" value="Register">
</form>
<h3>Login</h3>
<form ng-submit="ctrl.loginUser()" name="myLoginForm">
<label>Username</label>
<input type="text" name="uname" ng-model="ctrl.user.username" required>
<label>Password</label>
<input type="password" name="pwd" ng-model="ctrl.user.password" required>
<input type="submit" value="Login">
</form>
<script>
angular.module("notesApp", [])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}])
.controller("MainCtrl", ["$http", function($http) {
var self = this;
self.users = {};
var fetchUsers = function() {
return $http.get("/CMS/users").then(function(response) { // get list of existing users
self.users = response.data;
}, function(errResponse) {
console.error("Error while fetching users.");
});
};
self.loginUser = function() {
$http.post("/CMS/api-auth/login/", self.user)
.error(function(data, status, headers, config) {
console.log(data);
})
.then(fetchUsers);
console.log("Success Login with ", self.user);
};
}]);
</script>
When I register a user which already exists, then Django returns a 400 Bad Request error, which is good because I use AngularJS on the frontend to handle the 400 status code.
The issue is, when I try to log in with an incorrect username and password (a username which does not exist or a username and password which do not match), Django returns a 200 OK status code so I can't track the issue using AngularJS on the frontend. Any idea why Django returns a 200 OK when I try to log in with an incorrect username and password? How do I get Django to return a 400 when an incorrect username / password is submitted?
Edit: This was my original post: Django Rest Framework + AngularJS not logging user in or throwing errors and charlietfl commented on it saying "as for the ajax error handling. If login fails .... using true REST methodology would send back a 401 status which would then fire your ajax error handler", which is why I do not want a 200 OK when login fails.
The first thing to understand is that Django does not by default enforce authentication.. you can use the auth module to enroll users and to authenticate them, but you have to protect your views explicitly. The authentication app only provides API's for you to use, it doesn't actually protect anything unless you use those API's.
Any view that isn't explicitly checked for authentication will be open to anyone.
Sure, admin requires you to log in, but that's because the authors of the admin app included checks in their code...
The Django REST Framework has it's own checks for this, so very little coding needed, you just have to configure each view (see docs):
http://www.django-rest-framework.org/api-guide/authentication/
For any other view you might want to protect, you need to add some checks. The #login_required decorator on your view is one way to do that, for regular function type views. Since you are dealing with Class-Based-Views, look at the Django docs here:
https://docs.djangoproject.com/en/1.8/topics/class-based-views/intro/#mixins-that-wrap-as-view
Another option for checking login status is to use a middleware class. That's what I'm doing in my current system since almost everything on our site requires that the user be logged in. So, in the middleware class, we check to see if request.user.is_anonymous. If they are, then there's just a small subset of pages they can access, and if they aren't accessing those pages, we redirect them to login. The middleware runs before any view so that covers the whole site.
Ok, so now that I understand you want to actually log the user in via an ajax request, and not just check their access.. and you want control over what response comes back, then what I suggest is implementing your own view for the login service. Something like:
class LoginView(View):
def get(self, request, *args, **kwargs):
user = auth.authenticate(
username=request.GET.get('username'),
password=request.GET.get('password'))
# return whatever you want on failure
if not user or not user.is_active:
return HttpResponse(status=500)
auth.login(request, user)
return HttpResponse('OK')
I did not test this code but it should be pretty close.

Django how redirect to other site by post query string

How can I redirect from first site to second site.
Second site have form:
<form action="http://example.com/authAs" method="POST">
<input id="login" type="text" name="login"></td>
<input id="password" type="password" name="password"></td>
<button type="submit">login</button>
</form>
I want to authenticate the user at the first site and redirect it to a second site already authorized by POST request
How can I do it?
I have tried do it:
import urllib2,urllib
post_data = [('login', login), ('password', password)]
result = urllib2.urlopen('http://example.com/authAs', urllib.urlencode(post_data))
content = result.read()
But how redirect user to authorized page on second site?
It is not possible to redirect through POST, if you want the client to post to another site the only option is to use javascript to make a browser based redirection.
Instead of redirecting to example site, you can redirect to a local page with the form html and add this JS:
document.forms['form_id'].submit();
Note that the client will see the page for a few seconds before redirection and it won't work if JS is not enabled.