My goal is to obtain PayPal's transaction ID after the client-side payment approval. I'm currently integrating PayPal and Django on the client-side. While I can easily retrieve the Payment ID and order ID, PayPal discards these once the payment is approved. The only crucial data that PayPal retains is the Transaction ID, which is essential for tracking the payment with PayPal. Strangely, when I attempt to serialize the return actions that capture the Transaction ID, I encounter a 500 - Internal Server Error. What's interesting is that I am able to access the transaction ID in the console by using console.log(transaction.id). Below is the snippet of my problematic code:
In my payment.html file, there is a substantial amount of HTML content which I won't include here. I will just focus on where the JavaScript starts:
<script>
// Generating csrf_token dynamically
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;
}
let amount = "{{ grand_total }}"
const url = "{% url 'payment' %}"
let csrftoken = getCookie('csrftoken');
let orderID = "{{ order.order_number }}"
const payment_method = 'PayPal'
const redirect_url = "{% url 'order_complete' %}"
// Render the PayPal button into #paypal-button-container
const paypalButtonsComponent = paypal.Buttons({
// optional styling for buttons
// https://developer.paypal.com/docs/checkout/standard/customize/buttons-style-guide/
style: {
color: "gold",
shape: "pill",
layout: "vertical"
},
// set up the transaction
createOrder: (data, actions) => {
// pass in any options from the v2 orders create call:
// https://developer.paypal.com/api/orders/v2/#orders-create-request-body
const createOrderPayload = {
purchase_units: [
{
amount: {
value: amount
}
}
]
};
return actions.order.create(createOrderPayload);
},
// finalize the transaction
onApprove: (data, actions) => {
const captureOrderHandler = (details) => {
const payerName = details.payer.name.given_name;
console.log(details);
console.log('Transaction completed');
sendData();
function sendData() {
fetch(url, {
method: "POST",
headers: {
"Content-type": "application/json",
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({
orderID: orderID,
transID: details.id,
payment_method: payment_method,
status: details.status,
}),
})
.then((response) => response.json())
.then((data) => {
window.location.href = redirect_url + '?order_number=' + data.order_number + '&payment_id=' + data.transID;
});
}
};
return actions.order.capture().then(captureOrderHandler);
},
// handle unrecoverable errors
onError: (err) => {
console.error('An error prevented the buyer from checking out with PayPal');
}
});
paypalButtonsComponent
.render("#paypal-button-container")
.catch((err) => {
console.error('PayPal Buttons failed to render');
});
</script>
In my order's view, I have the following logic:
def payment(request):
body = json.loads(request.body)
order = Order.objects.get(user=request.user, is_ordered=False, order_number=body['orderID'])
# Store transaction details inside Payment model
processed_payment = Payment(
user=request.user,
payment_id=body['transID'],
payment_method=body['payment_method'],
amount_paid=order.order_total,
status=body['status'],
)
processed_payment.save()
order.payment = processed_payment
order.is_ordered = True
order.save()
# Move the cart items to Ordered Product table
cart_items = CartItem.objects.filter(user=request.user)
...
# Send order received email to customer
mail_subject = 'Thank you for your order!'
message = render_to_string('order_received_email.html', {
'user': request.user,
'order': order,
})
...
# Send order number and transaction id back to sendData method via JsonResponse
data = {
'order_number': order.order_number,
'transID': processed_payment.payment_id,
}
return JsonResponse(data)
...