-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Изменения в README.rst #1
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,34 +63,138 @@ ROBOKASSA (http://robokassa.ru/Doc/Ru/Interface.aspx). Приложение ре | |
Форма для приема платежей | ||
------------------------- | ||
|
||
Для того, чтобы упростить конструирование html-форм для отправки пользователей в | ||
Для того, чтобы упростить отправку и валидацию данных в | ||
Robokassa, в django-robokassa есть форма RobokassaForm. Она нужна | ||
для упрощения вывода информации в шаблонах, вычисления контрольной суммы и | ||
формирования параметров GET-запросов. | ||
для вычисления контрольной суммы (в том числе, для проверки того, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Контрольную сумму только для этой проверки и вычисляют, а "в том числе" подразумевает, что еще для чего-то. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Показалось, что кроме этого, она может использоваться просто для проверки того, не потерялось ли что по дороге при передаче "пакета" полей. |
||
что взаимодействие происходит именно с robokassa.ru, а не его подделкой) | ||
и формирования параметров GET-запросов. Для вывода информации в шаблон и | ||
обработки запроса пользователя необходимо реализовать свою собственную форму | ||
для ввода информации о платеже пользователем и view для обработки этой формы. | ||
При POST запросе из этой формы необходимо во view извлекать ее параметры, | ||
создавать form=RobokassaForm() с нужными значениями в initial и делать redirect | ||
на form.get_redirect_url(). | ||
|
||
Пример:: | ||
Пример view:: | ||
|
||
# views.py | ||
|
||
from django.shortcuts import get_object_or_404, render | ||
from django.contrib.auth.decorators import login_required | ||
|
||
from robokassa.forms import RobokassaForm | ||
|
||
@login_required | ||
def pay_with_robokassa(request, order_id) | ||
order = get_object_or_404(Order, pk = order_id) | ||
|
||
form = RobokassaForm(initial={ | ||
'OutSum': order.total, | ||
'InvId': order.id, | ||
'Desc': order.name, | ||
'Email': request.user.email, | ||
# 'IncCurrLabel': '', | ||
# 'Culture': 'ru' | ||
}) | ||
|
||
return render(request, 'pay_with_robokassa.html', {'form': form}) | ||
def balance_top_up(request): | ||
""" | ||
Отправка запроса на пополнение баланса на robokassa.ru | ||
""" | ||
|
||
if request.method == 'POST': | ||
|
||
# Создание экземпляра своей формы после POST запроса | ||
top_up_balance_form = TopUpBalanceForm(request.POST) | ||
|
||
# Проверка на валидность полей в своей форме | ||
if top_up_balance_form.is_valid(): | ||
|
||
# Здесь необходимо сгенерировать уникальный номер операции op_id | ||
|
||
op_id = ... | ||
|
||
# Генерация контрольной суммы с использованием | ||
# ROBOKASSA_PASSWORD1 и остальными параметрами. | ||
# _get_check_sum() см. ниже | ||
|
||
check_sum = _get_check_sum( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А это зачем? Форма же сама должна подпись считать. Если не считает, то нужно django-robokassa исправлять. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это велосипед мой. У меня обработка делалась в своей вьюхе, поэтому так получилось - поздно заглянул в исходники django-robokassa. Думаю, что, если это делать правильно, то надо передавать свою форму в Вашу внутреннюю вьюху, чтобы она ее выводила для взаимодействия с пользователем. Еще не уверен, что в этом случае необходима вторая форма для конструирования и редиректа, но тут, видимо, Вам виднее - т.е. не знаю, корректно ли будет использовать для этого именно форму, а не что-то другое - две формы как то очень необычно, хотя т.к. не так давно начал работать с формами и вообще с джангой, поэтому, могу чего-то не знать. |
||
# Логин пользователя | ||
login=settings.ROBOKASSA_LOGIN, | ||
# Сумма, на которую происходит повышение баланса | ||
rebalancing_sum=\ | ||
top_up_balance_form.cleaned_data['OutSum'], | ||
# Уникальный счетчик операции | ||
operation_id=op_id, | ||
# Пароль №1 | ||
password=settings.ROBOKASSA_PASSWORD1 | ||
) | ||
|
||
# Отправка запроса на robokassa.ru для инициации процедуры | ||
# начисления средств на счет | ||
|
||
form = RobokassaForm(initial={ | ||
'MrchLogin': settings.ROBOKASSA_LOGIN, | ||
'OutSum': | ||
top_up_balance_form.cleaned_data['OutSum'], | ||
'InvId': op_id, | ||
'Desc': 'description', | ||
'SignatureValue': check_sum, | ||
'Email': request.user.email, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Мне кажется, это важное замечание, и его нужно оставить. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Имхо, надо чуть поменять его контекст, подразумевая, что это вспомогательная форма. |
||
'Culture': 'ru' | ||
}) | ||
|
||
# Перенаправление | ||
return redirect(form.get_redirect_url()) | ||
else: | ||
# Обработка ошибкок валидации.(Чтобы исключить их наличие | ||
# после отправки формы, для каждого из ее полей стоит | ||
# использовать HTML5 атрибут "pattern", содержащий регулярное | ||
# выражение. Подробнее см. ниже) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Атрибут pattern ошибки валидации не исключит; чтоб обрабатывать ошибки валидации, лучше же форму с ошибками показать пользователю. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да, но приведенные html5 атрибуты просто не дадут отправить форму - поэтому я их использую для быстрой валидации, Т.е. пишу регэксп для каждого поля формы и она не отправится и поле будет подсвечиваться красным, пока юзер нормально не заполнит это поле. Тут это действительно не к месту. Все же, приложение, никак с htm5 не связано. |
||
else: | ||
# Создание экземпляра своей формы для взаимодействия с пользователем. | ||
# В данном случае форма содержит одно поле - OutSum - сумма перевода. | ||
|
||
form = TopUpBalanceForm() | ||
|
||
# Шаблон см. ниже | ||
return render( | ||
request, | ||
'example.html', | ||
{ 'form': form } | ||
) | ||
|
||
Пример функции подсчета контрольной суммы:: | ||
|
||
def _get_check_sum(login, rebalancing_sum, operation_id, password): | ||
""" | ||
md5 checksum | ||
""" | ||
|
||
data = u':'.join([ | ||
u"%s" % str(login), | ||
u"%s" % str(rebalancing_sum), | ||
u"%s" % str(operation_id), | ||
u"%s" % password | ||
]) | ||
|
||
return hashlib.md5(data).hexdigest() | ||
|
||
Пример формы:: | ||
|
||
# forms.py | ||
|
||
# Неотрицательное целое число | ||
_regexp_template = r'^\d+$' | ||
_regexp = u'\d+' | ||
|
||
class TopUpBalanceForm(forms.Form): | ||
""" | ||
Пополнение баланса | ||
""" | ||
|
||
OutSum = forms.CharField( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. а почему не DecimalField? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Полностью согласен, DecimalField лучше. |
||
max_length=15, | ||
label=_(u"Введите сумму в рублях для изменения баланса"), | ||
widget=forms.TextInput( | ||
attrs={ | ||
'pattern': _regexp, | ||
'maxlength': '7', | ||
'placeholder': u'Сумма перевода', | ||
'required': 'required', | ||
'value': 100500 | ||
} | ||
) | ||
) | ||
|
||
def clean(self): | ||
cleaned_data = super(TopUpBalanceForm, self).clean() | ||
OutSum = cleaned_data['OutSum'] | ||
if not re.match(_regexp_template, OutSum, re.UNICODE): | ||
raise forms.ValidationError(_(u'Неверная сумма перевода')) | ||
return cleaned_data | ||
|
||
В initial все параметры необязательны. Детальную справку по параметрам | ||
лучше посмотреть в `документации <http://robokassa.ru/ru/Doc/Ru/Interface.aspx#222>`_ | ||
|
@@ -101,29 +205,18 @@ Robokassa, в django-robokassa есть форма RobokassaForm. Она нуж | |
|
||
{% extends 'base.html' %} | ||
|
||
{% load i18n %} | ||
|
||
{% block title %}{% trans "Пополнение баланса" %}{% endblock %} | ||
|
||
{% block content %} | ||
<form action="{{ form.target }}" method="POST"> | ||
<p>{{ form.as_p }}</p> | ||
<p><input type="submit" value="Купить"></p> | ||
<form action="{% url app_name.views.balance_top_up %}" method="post"> | ||
{% csrf_token %} | ||
{{ form.as_p }} | ||
<button type="submit">{% trans "Пополнение баланса" %}</button> | ||
</form> | ||
{% endblock %} | ||
|
||
Форма выведется в виде набора скрытых input-тегов. | ||
|
||
У формы есть атрибут target, содержащий URL, по которому форму следует | ||
отправлять. В тестовом режиме это будет тестовый URL, в боевом - боевой. | ||
|
||
Обратите внимание, {% csrf_token %} в форме не нужен (и более того, добавлять | ||
его к форме небезопасно), т.к. форма ведет на внешний сайт - сайт робокассы. | ||
|
||
Вместо отправки формы можно сформировать GET-запрос. У формы есть | ||
метод get_redirect_url, который возвращает нужный адрес со всеми параметрами. | ||
Редирект на этот адрес равносилен отправке формы методом GET. | ||
|
||
django-robokassa не включает в себя модели "Покупка" (``Order`` в примере), | ||
т.к. эта модель будет отличаться от сайта к сайту. Обработку смены статусов | ||
покупок следует осуществлять в обработчиках сигналов. | ||
|
||
|
||
Получение результатов платежей | ||
------------------------------ | ||
|
@@ -138,10 +231,42 @@ django-robokassa не включает в себя модели "Покупка" | |
3. Можно запрашивать статус платежа через XML-сервис. | ||
|
||
В django-robokassa на данный момент поддерживаются методы 1 и 2 и их совмещение | ||
(дополнительная проверка, что при переходе на Success URL уже было уведомление | ||
на Result URL при использовании опции ROBOKASSA_STRICT_CHECK = True). | ||
(дополнительное подтверждение сначала через ResultURL, а затем переход на | ||
SuccessURL при использовании опции ROBOKASSA_STRICT_CHECK = True, | ||
рекомендуется для безопасного обмена данными). | ||
|
||
Механизм строгой проверки (подтверждения через ResultURL): | ||
|
||
1. robokassa.ru, вызывает ResultURL. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. запятая лишняя |
||
|
||
2. Внутри view, связанного с ResultURL, происходит проверка содержащейся в | ||
запросе md5 подписи через ROBOKASSA_PASSWORD2 - второй пароль, который не | ||
передается по сети и известен только отправителю и получателю. Он нужен | ||
для подтверждения того, что запрос был послан именно с robokassa.ru. | ||
|
||
3. Через callback, который принимает сигнал из этого view, | ||
производятся манипуляции внутри сайта (например, начисление средств согласно | ||
пришедшему запросу). Этот пункт необходим, если не реализуется свой view, | ||
а используется view, содержащийся в django-robokassa. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А когда может понадобиться не использовать вьюху из django-robokassa? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Свои views испольовал только потому, что:
|
||
|
||
4. Затем этот view отправляет на robokassa.ru ответ вида | ||
HttpResponse("".join(["OK", str(operation_id)]), | ||
где operation_id - уникальный id текущей операции. Этот ответ необходим в | ||
том числе для того, чтобы robokassa.ru получила подтверждение того, что все | ||
необходимые действия произведены. | ||
|
||
5. Если robokassa.ru получает этот ответ, она посылает второй запрос уже на | ||
SuccessURL, для вывода информативного сообщения пользователю об успешном | ||
прохождении всей операции. То есть, здесь должен быть только вывод оповещения. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. robokassa.ru не посылает запрос на SuccessURL, запрос посылает браузер клиента. robokassa.ru перенаправляет клиента на SuccessURL. Разница принципиальна тем, что ResultURL - секретная штука для внутреннего общения сайта и робокассы, а по SuccessURL висит публичная вьюха. |
||
|
||
6. Либо, в случае, если HttpResponse не соответвтует ожидаемому, | ||
посылается запрос на FailURL, тогда пользователь видит сообщение о | ||
произошедшей ошибке. | ||
|
||
Обработчики подключаются через urls.py, рендерят соответствующие | ||
шаблоны и шлют сигналы в зависимости от успешности платежа. | ||
Также можно сделать свои views, и подключить их самостоятельно через urls.py, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Про обработчики SuccessURL и FailURL - согласен, а обработчик ResultURL зачем переопределять? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно не переопределять - почему сделано так, написал тремя комментами выше. |
||
а формы робокассы использовать для валидации данных. | ||
|
||
|
||
Сигналы | ||
|
@@ -182,7 +307,6 @@ ROBOKASSA_EXTRA_PARAMS). | |
result_received.connect(payment_received) | ||
|
||
|
||
|
||
urls.py | ||
------- | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RobokassaForm не выполняет валидацию данных.