I am developing an e-commerce site for selling cakes online. I have done 90% of the groundwork, including setting up a paypal payment system. I seem to be stuck on a single error I am not being able to resolve. The payment falls apart towards the end of the process. Let me upload some parts of the code for inspection. Please could you help? checkout template (JavaScript)
<script>
// Getting cart total from the server (Django)
var total = ‘{{order.get_cart_total}}’
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Set up the transaction (create order)
//Tells PayPal: “Create an order for £X.XX”
// PayPal stores this order internally
// Returns a PayPal order ID
// No money taken, no backend call, only an intent to pay
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: parseFloat(total).toFixed(2)
}
}]
});
},
// Finalise the transaction
//This fires when a user logs into PayPal, user clicks approve/pay
//actions.order.capture(): actually captures the money finalises the transaction on payPal’s side
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
// Show a success message to the buyer
alert(‘Transaction completed by ’ + details.payer.name.given_name + ‘!’);
//send PayPal order ID to backend - bridge between PayPal and Django
submitFormData(data.orderID)
});
}
}).render(’#paypal-button-container’);
ipt>
// Backend verification and s<script>
// Backend verification and sanity checks (the value is not trusted, backend re-checks it)
var total = parseFloat('{{ order.get_cart_total }}').toFixed(2); // Ensure proper float format
var deliverorder = '{{ order.deliver }}'
//For logged in users, data is already stored in the database- so no need to collect userinfo
if (user != 'AnonymousUser'){
document.getElementById('userinfo').innerHTML = '';
}
//Depending on anonymous user choice - deliver or not not, option are displayed
document.getElementById('deliver').addEventListener('change', function(){
var deliveryinfo = document.getElementById('delivery-info');
if (this.checked){
deliveryinfo.style.display = 'block';
deliverorder = 'True';
}
else {
deliveryinfo.style.display = 'none';
deliverorder = 'False';
}
});
// stops browser from reloading, submitting traditionally - instead you show the PayPal button
var form = document.getElementById('form')
//form.addEventListener('submit', function(e) {
//e.preventDefault()
//console.log('Form submitted..');
//document.getElementById('form-button').classList.add("hidden");
//document.getElementById('payment-info').classList.remove("hidden");
//})
document.getElementById('form-button').addEventListener('click', function () {
console.log('Continue clicked');
this.classList.add("hidden");
document.getElementById('payment-info').classList.remove("hidden");
});
function submitFormData(paypalOrderId) {
console.log('Payment Button clicked');
var userFormData = {
'name': null,
'email': null,
'total': total,
'deliverorder': deliverorder,
'paypal_order_id':paypalOrderId
}
var deliveryInfo = {
'address': null,
'city': null,
'postcode': null,
};
if (deliverorder != 'False'){
deliveryInfo.address = form.address.value
deliveryInfo.city = form.city.value
deliveryInfo.postcode = form.postcode.value
}
if (user == 'AnonymousUser'){
userFormData.name = form.name.value
userFormData.email = form.email.value
}
var url = "/process_order/";
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({'form': userFormData, 'deliveryInfo': deliveryInfo}),
})
.then(response => {
if (!response.ok) {
return response.json().then(err => {
throw new Error(err.details || 'Something went wrong');
});
}
return response.json();
})
.then(data => {
console.log('Success:', data);
alert('Transaction completed');
document.cookie = 'cart=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
cart = {};
window.location.href = "{% url 'home' %}";
})
.catch(error => {
alert('Checkout failed: ' + error.message);
});
}
process_order (views)
def process_order(request):a = json.loads(request.body)
# -------------------------------
# Get customer + order
# -------------------------------
if request.user.is_authenticated:
customer = request.user.customer
order, _ = Order.objects.get_or_create(
customer=customer,
complete=False
)
else:
customer, order = guestOrder(request, data)
print(“Order ID:”, order.id) # -------------------------------
# Verify PayPal payment
# -------------------------------
form_data = data.get(‘form’, {})
paypal_order_id = form_data.get(‘paypal_order_id’)
if not paypal_order_id:
return JsonResponse({‘error’: ‘Missing PayPal order ID’}, status=400)
paypal_data = verify_paypal_order(paypal_order_id)
#if paypal_data[‘status’] != ‘COMPLETED’:
#return JsonResponse({‘error’: ‘Payment not completed’}, status=400)
if paypal_data[‘status’] not in [‘COMPLETED’, ‘APPROVED’]:
return JsonResponse({‘error’: ‘Payment not completed’}, status=400)
#paid_amount = Decimal(
#paypal_data[‘purchase_units’][0][‘amount’][‘value’]
#)
#cart_total = Decimal(order.get_cart_total)
paid_amount = Decimal(
paypal_data[‘purchase_units’][0][‘amount’][‘value’]
).quantize(Decimal(‘0.00’))
#cart_total = Decimal(order.get_cart_total).quantize(Decimal(‘0.00’))
cart_total = Decimal(str(order.get_cart_total)).quantize(Decimal(‘0.00’))
if paid_amount != cart_total:
print(“ Paid:”, paid_amount)
print(“ Cart:”, cart_total)
return JsonResponse({‘error’: ‘Payment amount mismatch’}, status=400)
# -------------------------------
# Update order
# -------------------------------
deliver = form_data.get(‘deliverorder’) == ‘True’
order.deliver = deliver
order.transaction_id = paypal_order_id
order.complete = True
order.status = ‘DEBUG_Saved’
order.save()
print(“Order sabved”)
# -------------------------------
# Delivery address
# -------------------------------
if deliver:
DeliveryAddress.objects.create(
customer=customer,
order=order,
address=data[‘deliveryInfo’][‘address’],
city=data[‘deliveryInfo’][‘city’],
postcode=data[‘deliveryInfo’][‘postcode’],
)
# -------------------------------
# Clear guest cart
# -------------------------------
response = JsonResponse(‘Payment submitted..’, safe=False)
if not request.user.is_authenticated:
response.delete_cookie(‘cart’, path=‘/’)
request.session.pop(‘cart’, None)
return response
except Exception as e:
print(traceback.format_exc())
return JsonResponse({‘error’: str(e)}, status=500)
def get_paypal_access_token():
response = requests.post(
“https://api-m.sandbox.paypal.com/v1/oauth2/token”,
auth=(settings.PAYPAL_CLIENT_ID, settings.PAYPAL_SECRET),
data={“grant_type”: “client_credentials”},
)
response.raise_for_status()
return response.json()[“access_token”]
def verify_paypal_order(paypal_order_id):
access_token = get_paypal_access_token()
headers = {
“Content-Type”: “application/json”,
“Authorization”: f"Bearer {access_token}",
}
#Live change later Replace api-m.sandbox.paypal.com → api-m.paypal.com
response = requests.get(
f"https://api-m.sandbox.paypal.com/v2/checkout/orders/{paypal_order_id}",
headers=headers,
)
response.raise_for_status()
return response.json()
Thanks.
P