I'm making a website where you buy stuff and pay through PayPal.
I am done with the PayPal part now I am trying to get a situation where after the payment is complete in checkout the item purchased goes to orders in the admin.
This is the order model.py:
class Order (models.Model):
product = models.ForeignKey(Coinpack, max_length=200, null=True, blank=True, on_delete = models.SET_NULL)
created = models.DateTimeField(auto_now_add=True)
this is the PayPal code part in checkout.html:
<script src="https://www.paypal.com/sdk/js?client-id=idexample¤cy=USD"></script>
<script>
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
var total = '{{checkout.price}}'
var productId = '{{checkout.id}}'
function completeOrder(){
var url = "{% url 'complete' %}"
fecth(url, {
method: 'POST',
headers:{
'content-type':'aplication/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({'productId':productId})
})
}
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: total
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(orderData) {
// Successful capture! For demo purposes:
completeOrder()
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
var transaction = orderData.purchase_units[0].payments.captures[0];
alert('Transaction '+ transaction.status + ': ' + transaction.id + '\n\nSee console for all available details');
});
}
}).render('#paypal-button-container');
</script>
</body>
</html>
and here is the views.py
def paymentComplete(request):
body = json.loads(request.body)
print('BODY:', body)
product = checkout.objects.get(id=body['productId'])
Order.objects.create(
product=product
)
return JsonResponse('Payment completed!', safe=False)
So i was following a tutorial but the tutorial and mine where different so i kinda got confused and i don't know what to do, pls help.
I also have the payment complete in the urls.py:
path('complete/', views.paymentComplete, name="complete"),
Thank you.
Do not use actions.order.create() / actions.order.capture() to create and capture an order on the client side if you are then going to be doing server-side operations with the completed payment. Those JS functions are for simple use cases, not what you are trying to do.
Instead, use PayPal's v2/checkout/orders API and make two routes (url paths) on your server, one for 'Create Order' and one for 'Capture Order'. You could use the (recently deprecated) Checkout-PHP-SDK for the routes' API calls to PayPal, or your own HTTPS implementation of first getting an access token and then doing the call. Both of these routes should return/output only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should verify the amount was correct and store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as reserving product or sending an email) immediately before forwarding return JSON to the frontend caller. In the event of an error forward the JSON details of it as well, since the frontend must handle such cases.
Pair those 2 routes with this frontend approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server . (If you need to send any additional data from the client to the server, such as an items array or selected options, add a body parameter to the fetch with a value that is a JSON string or object)
Related
i'm a beginner, i am working on the e-commerce app. i want to do something that if the user payment is successful, an order would be created and stored in the database.
i finally have found a way of integrating the payment gateway and when the transaction is successful, it redirect to a success page.
the problem i have here is how to create the order when the payment is successful
here is my code
<script>
const API_publicKey = "<ADD YOUR PUBLIC KEY HERE>";
function payWithRave() {
var x = getpaidSetup({
PBFPubKey: API_publicKey,
customer_email: '{{address.email}}',
amount: '{{cart.get_total_price}}',
customer_phone: "234099940409",
currency: "NGN",
txref: "rave-123456",
meta: [{
metaname: "flightID",
metavalue: "AP1234"
}],
onclose: function() {},
callback: function(response) {
var txref = response.data.txRef; // collect txRef returned and pass to a server page to complete status check.
console.log("This is the response returned after a charge", response);
if (
response.data.chargeResponseCode == "00" ||
response.data.chargeResponseCode == "0"
) {
"{% url 'checkout:payment_complete' %}" // redirect to a success page
} else {
// redirect to a failure page.
}
x.close(); // use this to close the modal immediately after payment.
}
});
}
</script>
how do i go about it? what value to pass to the view?
the way i do is, after the successful payment on payment gateway, I pass the pay reference id with amount and other relevant props to view and store them.
in your case, pass the payment order id or(any other things) in your checkout:payment_complete URL.
and in your payment_complete view, retrieve your payment order by its reference id and store its properties (anything u need) into your model.
Hope this helps you to built it.
I have previous experience in Django. If add line {csrf_token} in Django templates then Django handles the functionalities of csrf_token. But when I am trying to develop an API using Django REST Framework then I get stuck. How can I add and handle functionalities like csrf_token in API (back end, developed using Django REST Framework) and React Native/React JS (front end) like Django templates?
The first step is to get CSRF token which can be retrieved from the Django csrftoken cookie.
Now from the Django docs you can find out how to get the csrf token from the cookie by using this simple JavaScript function:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
Now, you can retrieve the CSRF token by calling the getCookie('csrftoken') function
var csrftoken = getCookie('csrftoken');
Next you can use this csrf token when sending a request with fetch() by assigning the retrieved token to the X-CSRFToken header.
fetch(url, {
credentials: 'include',
method: 'POST',
mode: 'same-origin',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: {}
})
}
Rendering the CSRF Token in React Forms:
If you are using React to render forms instead of Django templates you also need to render the csrf token because the Django tag { % csrf_token % } is not available at the client side so you need to create a higher order component that retrieves the token using the getCookie() function and render it in any form.
Lets add some line in csrftoken.js file.
import React from 'react';
var csrftoken = getCookie('csrftoken');
const CSRFToken = () => {
return (
<input type="hidden" name="csrfmiddlewaretoken" value={csrftoken} />
);
};
export default CSRFToken;
Then you can simply import it and call it inside your form
import React, { Component , PropTypes} from 'react';
import CSRFToken from './csrftoken';
class aForm extends Component {
render() {
return (
<form action="/endpoint" method="post">
<CSRFToken />
<button type="submit">Send</button>
</form>
);
}
}
export default aForm;
The Django CSRF Cookie
React renders components dynamically that's why Django might not be able to set a CSRF token cookie if you are rendering your form with React. This how Django docs says about that:
If your view is not rendering a template containing the csrftoken
template tag, Django might not set the CSRF token cookie. This is
common in cases where forms are dynamically added to the page. To
address this case, Django provides a view decorator which forces
setting of the cookie: ensurecsrf_cookie().
To solve this issue Django provides the ensurecsrfcookie decorator that you need to add to your view function. For example:
from django.views.decorators.csrf import ensure_csrf_cookie
#ensure_csrf_cookie
def myview(request):
I used jquery for ajax in react, so in this case here is a solution :
let csrfcookie = function() { // for django csrf protection
let cookieValue = null,
name = "csrftoken";
if (document.cookie && document.cookie !== "") {
let cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) == (name + "=")) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
$.ajax({
type: "POST",
beforeSend: function(request, settings) {
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
request.setRequestHeader("X-CSRFToken", csrfcookie());
}
},
.... /// other codes
I can't do a POST ajax request in Django. If I do a GET request, it works fine. I think it may be a csrf token problem, but I can get it to work
My view:
#login_required
def add_share_points(request):
user = request.user
profile = request.user.profile
if request.method == 'POST':
value = 5.0
# Premia o usuário ao compartilhar conteúdo
VirtualCurrencyTransaction.objects.create(
user=request.user,
reason=2,
description='Você completou seu perfil',
value=value
)
return "ok"
My AJAX request:
$('.my-button').on('click', function(e) {
e.preventDefault();
var pointsCount = $(this).hasClass('homepage-facebook-share') ? 3 : 2;
$.ajax({
type:"POST",
url: "/add_share_points",
data: {
points: pointsCount,
}
}).done(function() {
alert('Posting completed.');
}).fail(function(){
alert('Error while posting.');
});
});
In my script, I also have this setting:
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/).test(method);
}
$.ajaxSetup({
crossDomain: false,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader('X-CSRFToken', CSRF_TOKEN);
}
}
});
What is wrong with my code? It gave my a 500 error code, but no further explanation in the logs.
I will point out several things to correct, some are just ways to do it in a django manner and not problems.
In your view
return HttpResponse(
json.dumps({'result': 'ok',}),
content_type="application/json"
)
In your ajax
url: "/add_share_points",
should be:
url : {% url '<name in url.py>' %},
and you need to add (to the data object):
csrfmiddlewaretoken: '{{ csrf_token }}'
Inside the ajax request, insert this after data:
// handle a successful response
success : function(json) {
if (json.result=== 'ok'){
console.log('It works!');
}else{
console.log('Something wrong with response');
}
// handle a non-successful response
error : function(xhr,errmsg,err) {
console.log(err);
}
In your script
instead of CSRF_TOKEN use '{{ csrf_token }}'
Please use my suggestions and give me feedback and I will update the answer. The two with csfrtoken are probably the problems your having. If you put Django in Debug mode it will be easyer to find out.
My Suggestion
Create a form with what you need to post to gain some features in the validation process.
I am using this library for datatables in django-rest. Everything is working fine expect request.user session in views. It seems to me django-datatable is not authenticating the user token and therefore request.user returns anonymous user. And the same is accessible even without sending user token in headers.
Here is my code :
class MyDataTableView(BaseDatatableView):
"""
"""
model = MyModel
columns = [***columns** ]
order_columns = [***columns**]
def get_initial_queryset(self):
"""
initial queryset for
"""
self.request.user -----> returns antonymous user
queryset = self.model.objects
return queryset
Have You tried to subclass BaseDatatableView and overwrite its .get like:
def get(self, *args, **kwargs):
super().get(*args, **kwargs)
print(self.request)
My guess is that get_initial_queryset can be invoked before actual request dispatch, so the user is anonymous there. When You look into the code of django_datatables/mixins.py, there is a mixin called JsonResponseMixin. It's GET method is directly responsible for request processing, so You should look for Your answers there. The easiest way - subclass it and overwrite the method.
Have you added the token JS to the Datatables initiation JS file? django-datatables just creates the correct JSON string. Initiating the cookie is different.
I fought with this a while and my missing piece was that I had to get and set the cookie:
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
this is above where I set the Datatables params for example :
let table = $('#datatables').DataTable({
"processing": true,
"serverSide": true,
stateSave: true,
"ajax": {
........
I am creating a website having option to login using facebook,google etc(like stackoverflow.com it has an option to login as a google user etc).
My question is
how to manage the user accounts.(i mean users activities)
my user database is
reguser/models.py
class Employer(models.Model):
user=models.OneToOneField(User)
companyname= models.CharField(max_length=100,blank=True)
leader=models.BooleanField(default=True)
#avatar = models.ImageField("Profile Pic", upload_to="images/", blank=True, null=True)
def __unicode__(self):
return self.user.username
class Jobseeker(models.Model):
user=models.OneToOneField(User)
#avatar = models.ImageField("Profile Pic", upload_to="images/", blank=True, null=True)
def __unicode__(self):
return self.user.username
fblogin.html
<html>
<head>
<title>My Facebook Login Page with listener</title>
</head>
<body>
<div id="fb-root"></div>
<div class="box">
<div class="info">
This is an example of subscribing to the auth login event
</div>
<div class="fb-login-button">Login with Facebook</div>
</div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId: '*************',
status: true,
cookie: true,
xfbml: true,
oauth: true
});
FB.Event.subscribe('auth.login', function(response) {
// {
// status: "", /* Current status of the session */
// authResponse: { /* Information about the current session */
// userID: "" /* String representing the current user's ID */
// signedRequest: "", /* String with the current signedRequest */
// expiresIn: "", /* UNIX time when the session expires */
// accessToken: "", /* Access token of the user */
// }
// }
// alert('event status: ' + response.status);
});
FB.getLoginStatus(function(response) {
// {
// status: 'connected',
// authResponse: {
// accessToken: '...',
// expiresIn:'...',
// signedRequest:'...',
// userID:'...'
// }
// }
//alert('getLoginStatus: ' + response.status);
if (response.status=='connected') {
FB.api('/me',function(response){
var field_name=$(this).attr("id");
var field_val=$(this).val();
var params ={ param1:response.name, response.id };
$.ajax({ url: "/createfbuser/",
dataType: "json",
data: params,
success: setResult
});
});
}
});
};
(function(d) {
var js, id = 'facebook-jssdk';
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
</script>
</body>
</html>
do i need to add some thing like in
reguser/models.py
......other models(listed above)
class userFacebook(models.Model):
user=models.OneToOneField(User)
and create the user after first time facebook login like
urls.py
.....other urls
url(r'^createfbuser/$', 'create_facebook_user_ajax'),
reguser/views.py
def create_facebook_user_ajax(request):
f_name=request.GET['param1']
f_id=request.GET['param2']
User.objects.create_user(##########what are the things i want to provide here.)
#if i provide the facebook username then there may be already a user with same username
or is there any other method..
Sorry i am new to facebook login.
django-social-auth is a great very easy to install solution for your requirements. They are other django application, you can learn about it on hackerluddite's blog.
Quoting github readme django-social-auth repository
Django Social Auth
Django Social Auth is an easy way to setup social
authentication/authorization mechanism for Django projects.
Crafted using base code from django-twitter-oauth and
django-openid-auth, it implements a common interface to define new
authentication providers from third parties.
Don't forget to start github repo.