I have an online store where users pay at domain.com/pay and receive their product after paying at domain.com/done
However, when I was testing it I found out that users can go to the URL and type domain.com/pay manually and all a sudden, they get their product without paying! I want someway to check whether the user accessed it manually or from a redirection,
if manually then raise http403 if from redirect then the function will happen normally
Here is my process_pay view
def payment_process(request, trade_id):
trade = get_object_or_404(Trade, id=trade_id)
host = request.get_host()
paypal_dict = {
'business': trade.seller.email,
'amount': Decimal(trade.price),
'item_name': trade.filename,
'invoice': str(trade.id),
'currency_code': 'USD',
'notify_url': 'http://{}{}'.format(host,
reverse('paypal-ipn')),
'return_url': 'http://{}{}/{}'.format(host,
*reverse('payment_done', kwargs={'trade_id': trade.id})),
'cancel_return': 'http://{}{}'.format(host,
reverse('home')),
}
form = PayPalPaymentsForm(initial=paypal_dict)
return render(request, 'payment/payment_process.html', {'trade': trade, 'form': form})
my done_process view
@csrf_exempt
def payment_done(request, trade_id):
# if user entered from a redirection:
# Give product to user
# elif user entered manually:
raise http403
# else:
messages.error(request, 'something went wrong')
return redirect('home')
return redirect('trade:inbox')
You are probably solving this problem the wrong way especially when it's related to payments. In your
done
view, have a pre-condition to check if the payment is already completed or not.On the other hand, to answer the question, to check if the user landed from redirect or by manually entering the URL, (a hacky solution) generate a token (a unique identifier) in the user local context and add it as a query param in the redirection URL, further validate the token in the redirected view (present in the local context), if the token if different from the local context or not present - user manually entered!