If I correctly understand the essence of the action - take the form, make a payment, sign, send further to the merchant - maybe everything should look something like this:
# <form action="http://your.example.org/handle-payment" method="POST"> # {% csrf_token %} # <input name="amount" type="text" value=""> # <input name="description" type="text" value=""> # <input type="submit"> # </form> # Ключ подписи храним не посреди кода вьюшки, а в settings.py, добавив туда # MERCHANT_SIGNING_KEY = "..." logger = logging.getLogger(__name__) @require_POST @transaction.commit_manually def handle_payment(request): # Разбираем данные формы, проверяем. Фильтруем поля — # вдруг злой хакер или излишне напичканный расширениями # браузер добавит отсебятины. post_data = {} for key in ("amount", "description"): if not key in request.POST: # Ругаемся, завершаем обработку return HttpResponseBadRequest("BUG REF#1234: Missing required data.") post_data[key] = str(request.POST[key]) try: # Создаем платеж, дополняем форму его ID # (при отправке формы мы же не знаем ID, так?) payment = Payment(**post_data) payment.save() post_data["merchant_order_id"] = str(payment.id) # Подписываем данные формы post_data["checksum"] = hmac.new( key=settings.MERCHANT_SIGNING_KEY, msg=";".join("%s=%s" % (k, v) for k, v in post_data.iteritems()), digestmod=hashlib.sha1 ).hexdigest() # Отправляем (с сервера) итоговый подписанный запрос на мерчанта merchant_req = requests.post("http://merchant.example.net/pay", # auth=(settings.MERCHANT_USER, settings.MERCHANT_PASSWORD), data=post_data ) # Проверяем ответ, например, просто посмотрев код if merchant_req.status_code != 200: # Не прошло, откатываем транзакцию, пишем логи transaction.rollback() logger.error("Merchant rejected payment request [...]") # TODO: Лог! return HttpResponseBadRequest("BUG REF#4321: Merchant rejected") except Exception, e: logger.error("Exception during payment processing [...]") raise e # Перебрасываем исключение дальше, пусть middleware разбирается else: transaction.commit() logger.notice("Successfully processed payment #%d: [...]", payment.id) # Заканчиваем редиректом, чтобы POST не повторился return HttpResponseRedirect(reverse("payment_handled", payment.id))
Is this what you need, or did I misunderstand the point?