Reputation: 912
I am setting a PayPal payment for my E-commerce project and everything is working fine except that after the payment is executed and the PayPal windows is closed, the website page remains open and the items remain in the cart.
I have set the stripe payment to redirect to a page called "order completed" with some order reference code, which I am trying to implement to PayPal payment option.
Here is the views.html:
def payment_complete(request):
body = json.loads(request.body)
order = Order.objects.get(
user=request.user, ordered=False, id=body['orderID'])
payment = Payment(
user=request.user,
stripe_charge_id=body['payID'],
amount=order.grand_total()
)
payment.save()
# assign the payment to order
order.payment = payment
order.ordered = True
order.ref_code = create_ref_code()
order.save()
messages.success(request, "Your Order was Successful ! ")
# Email when order is made
template = render_to_string("payment_confirmation_email.html", {'first_name': request.user.first_name,
'last_name': request.user.last_name,
'order': order})
msg = EmailMessage('Thanks for Purchasing', template,
settings.EMAIL_HOST_USER, [request.user.email])
msg.content_subtype = "html" # Main content is now text/html
msg.fail_silently = False
msg.send()
# End of the email send
return render(request, "order_completed.html", {'order': order})
class PaymentView(View):
def get(self, *args, **kwargs):
# order
order = Order.objects.get(user=self.request.user, ordered=False)
if order.billing_address:
context = {
'order': order,
'DISPLAY_COUPON_FORM': False
}
return render(self.request, "payment.html", context)
else:
messages.warning(
self.request, "You have not added a billing address")
return redirect("core:checkout")
# `source` is obtained with Stripe.js; see https://stripe.com/docs/payments/accept-a-payment-charges#web-create
# -token
def post(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
token = self.request.POST.get('stripeToken')
amount = int(order.grand_total() * 100)
try:
charge = stripe.Charge.create(
amount=amount, # cents
currency="usd",
source=token,
)
# create payment
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.user = self.request.user
payment.amount = order.grand_total()
payment.save()
# assign the payment to the order
order_items = order.items.all()
order_items.update(ordered=True)
for item in order_items:
item.save()
order.ordered = True
order.payment = payment
order.ref_code = create_ref_code()
order.save()
messages.success(self.request, "Your Order was Successful ! ")
# Email when order is made
template = render_to_string("payment_confirmation_email.html", {'first_name': self.request.user.first_name,
'last_name': self.request.user.last_name,
'order': order})
msg = EmailMessage('Thanks for Purchasing', template,
settings.EMAIL_HOST_USER, [self.request.user.email])
msg.content_subtype = "html" # Main content is now text/html
msg.fail_silently = False
msg.send()
# End of the email send
return render(self.request, "order_completed.html", {'order': order})
here is the PayPal script:
<!--Paypal Script-->
<script>
// Render the PayPal button into #paypal-button-container
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 = 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;
}
var csrftoken = getCookie("csrftoken");
var orderID = "{{order.id}}";
var amount = "{{order.grand_total|floatformat:2}}";
var url = "{% url 'core:payment_complete' %}";
paypal.Buttons({
style: {
color: "blue",
shape: "pill",
label: "pay",
height: 40,
},
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: amount,
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log(details);
sendData();
function sendData() {
fetch(url, {
method: "POST",
headers: {
"Content-type": "application/json",
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({ orderID: orderID, payID: details.id }),
});
}
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
}
}).render('#paypal-button-container');
</script>
<!--Paypal Script-->
Upvotes: 0
Views: 1201
Reputation: 73
Paypal client-side integration using Django: To handle your situation, create a new view in your view.py Your JS request is processed and then redirected, but not your browser window! You need your js code to listen for a response and then trigger a redirect.
urls.py
urlpatterns = [
path('paypal-payment/', views.paypal_payment, name="paypal_payment"),
path('order-complete/', views.order_complete, name="order_complete"),
]
views.py:
from django.http import JsonResponse
def payment_process(request):
body = json.loads(request.body)
order = Order.objects.get(user=request.user, ordered=False, id=body['orderID'])
# create the payment
payment = Payment()
payment.stripe_charge_id = body['payID']
payment.user = request.user
payment.amount = order.get_total()
payment.save()
# assign the payment to the order
order_items = order.items.all()
order_items.update(ordered=True)
for item in order_items:
item.save()
order.ordered = True
order.payment = payment
order.save()
# your other logic goes here
return JsonResponse('Payment submitted..', safe=False)
def order_complete(request):
messages.success(request, "Your order was successful!")
return render(request, 'order_complete.html') # you can pass any context as needed
And in you PayPal script
<!--Paypal Script-->
<
script >
// Render the PayPal button into #paypal-button-container
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 = 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;
}
var csrftoken = getCookie("csrftoken");
var orderID = "{{order.id}}";
var amount = "{{order.grand_total|floatformat:2}}";
var url = "{% url 'core:paypal_payment' %}";
paypal.Buttons({
style: {
color: "blue",
shape: "pill",
label: "pay",
height: 40,
},
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: amount,
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log(details);
sendData();
function sendData() {
fetch(url, {
method: "POST",
headers: {
"Content-type": "application/json",
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({
orderID: orderID,
payID: details.id
}),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data); // Just for testing, you can delete
alert('Transaction completed'); // Just for testing, you can delete
window.location.href = "{% url 'products:order_complete' %}"
});
}
}
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!'); // Just for testing, you can delete
});
}
}).render('#paypal-button-container'); <
/script>
<!--Paypal Script-->
Upvotes: 2
Reputation: 3527
In this example we use ajax to send a post request to the django backend when a user clicks the 'submit' button.
urls.py:
urlpatterns = [
...
path('process_payment', views.process_payment, name='process_payment'),
...
]
views.py:
from django.http import HttpResponse
import json
def process_payment(request):
# unpack request:
field1 = request.POST['field1']
# other logic, send email, etc.:
...
# pack context:
context = json.dumps({
'payment_success' : True # true or false
})
return HttpResponse(context)
In paypal.js (your js script):
// this buttons executes when the user presses the 'submit' button:
function process_payment() {
$.ajax({
url : 'process_payment',
data : {
csrfmiddlewaretoken: 'the_csrf_token',
field1 : 'field1_data', // pass other fields as needed
...
},
success: payment_success_function,
});
} $('#submit-button-id').click(payment_success);
// this function executes when a response is received from the backend:
payment_method_success(response) {
// unpack response (context) from views.py:
var payment_success = response.payment_success;
if (payment_success) window.location('the_new_url');
else alert('Something went wrong with your payment!');
}
Upvotes: 0