10. Оплата
20 ноября 2017 г. 2:35
Провайдеры Оплаты (Payment Providers) являются простыми классами, которые создают интерфейс между Платёжной Системой (Payment Service Providers, PSP, дословно Сервис-Провайдер Оплаты) (сокращённо ПС) и нашим фреймворком django-shop.
Провайдеры оплаты должны быть унаследованы от Payment Cart Modifier (Платёжный модификатор корзины). Здесь Payment Cart Modifier вычисляет дополнительные сборы в случае, когда выбран платёжный метод. В это время наш класс Payment Provider, взаимодействует с настроенной ПС, всякий раз, когда покупатель посылает запрос о покупке.
В django-SHOP Провайдеры Оплаты обычно располагаются в различных плагинах, поэтому здесь мы будет показывать как создать свой Провайдер Оплаты вместо объяснения конфигурации существующей интеграции Оплаты.
Меры предосторожности при оплате кредитными картами заключаются в том, что наш интернет-магазин не должен знать о вводимых номерах карты или другой важной информации. В противном случае эти продавцы должны быть сертифицированы PCI-DSS, которая является дополнительной, но часто ненужной бюрократической задачей, так как большинство ПС обрабатывают эту задачу сами.
10.1. Формы оформления заказа
Так как продавец не должен "видеть" вводимую информацию кредитных карт, некоторые ПС требуют, чтобы покупатели перенаправлялись на их сайт и вводили там номера карт. У некоторых пользователей может возникнуть беспокойство, потому что они визуально покидают текущий сайт магазина.
Чтобы этого не происходило, другие ПС позволяют создавать HTML-форму, данные которой отправляются на их сайт для решения задачи по оплате. Это работает, благодаря POST запросу, который возвращается назад к клиенту. Другие провайдеры используют Javascript для представления и возврата платёжного токена клиенту, который сам дальше отправляет этот токен на сайт магазина.
В общем, существует множество различных способов оплаты, и поэтому довольно сложно написать универсальный код, который поддерживал бы все эти способы.
В django-SHOP используется Javascript во время операции покупки. Попробуем объяснить, как это происходит.
10.1.1. Операция покупки
Во время оформления заказа клиенты конечным шагом клиентов может быть щёлчок по кнопке "Купить сейчас". Эта кнопка принадлежит контроллеру AngularJS, предоставленного директивой shop-dialog-proceed. Это может выглядеть так:
<button shop-dialog-proceed ng-click=”proceedWith(‘PURCHASE_NOW’)” class=”btn btn-success”>Buy Now</button>
Всякий раз, когда покупатели щёлкают по кнопке, функция proceedWith('PURCHASE_NOW')
вызывается в scope контроллера AngularJS, принадлежащего данной директовой.
Эта функция сначала загружает текущие формы оформления заказа на сервер. Там они валидируются, и если всё ОК, то загружают данные (context) оформления заказа назад клиенту. Подробнее: shop.views.checkout.CheckoutViewSet.upload().
Далее, успешный обработчик предыдущего представления смотрит на данное действие. в proceedWith, мы использовали магическое ключевое слово PURCHASE_NOW, который отправляет второе представление на сервер, запрашивая начать операцию покупки (Подробнее: shop.views.checkout.CheckoutViewSet.purchase()). Этот метод определяет провайдера оплаты, выбранного покупателем. Затем он вызывает метод get_payment_request()
этого провайдера, который возвращает Javascript-выражение.
На клиенте это возвращенное Javascript-выражение обрабатывается функцией eval()
и выполняется. Далее, покупатель обычно начинает подавать платежный запрос, отправляя все данные кредитной карты в данную ПС.
При обработке платежа ПС обычно должны взаимодействовать с инфраструктурой магазина, чтобы сообщить нам об успешности или неудаче платежа. Чтобы связаться с нами, им может понадобиться несколько конечных точек (endpoints). Каждый Провайдер Оплаты может переопределить метод get_urls()
, возвращающий список URL-адресов, который затем используется механизмом разрешения URL-адресов Django.
class MyPSP(PaymentProvider): namespace = 'my-psp-payment' def get_urls(self): urlpatterns = [ url(r'^success$', self.success_view, name='success'), url(r'^failure$', self.failure_view, name='failure'), ] return urlpatterns def get_payment_request(self, cart, request): js_expression = 'scope.charge().then(function(response) { $window.location.href=response.data.thank_you_url; });' return js_expression @classmethod def success_view(cls, request): # одобрение платежа с использованием данных request, возвращённых ПС cart = CartModel.objects.get_from_request(request) order = OrderModel.objects.create_from_cart(cart, request) order.add_paypal_payment(payment.to_dict()) order.save() thank_you_url = OrderModel.objects.get_latest_url() return HttpResponseRedirect(thank_you_url) @classmethod def failure_view(cls, request): """Перенаправление в URL, где покупатель информируется об отменённом платеже""" cancel_url = Page.objects.public().get(reverse_id='cancel-payment').get_absolute_url() return HttpResponseRedirect(cancel_url)
Директива shop-dialog-proceed обрабатывает возвращённое Javascript-выражение внутри привязанного
then(...)-handler
от AngularJS. Это означает, что каждая функция может сама вернуть новое обещание, которое выполнится следующим then(...)-handler
.Как мы видим в этом примере, выполняя произвольный Javascript на клиенте в сочетании с HTTP-обработчиками для любой конечной точки (endpoint), django-SHOP может предложить API, в котором новые ПС не потребуют каких-либо специальных трюков (костылей) для их работоспособности.
Представляю вашему вниманию книгу, написанную моим близким другом Максимом Макуриным: Секреты эффективного управления ассортиментом.
Книга предназначается для широкого круга читателей и, по мнению автора, будет полезна специалистам отдела закупок и логистики, категорийным и финансовым менеджерам, менеджерам по продажам, аналитикам, руководителям и директорам, в компетенции которых принятие решений по управлению ассортиментом.
Комментарии: 3
18.07.2018 2:02 #
Привет. Не подскажешь, как подключить яндекс кассу (api) https://github.com/yandex-money/yandex-checkout-sdk-python к django cms ?
Ответить
19.07.2018 1:50 #
Приветствую! Сам пока не подключал Яндекс.Кассу, но в принципе у всех платёжек похожий api, поэтому сам процесс подключения не должен вызывать трудностей. Другое дело как в django-cms внедрить. В общем случае могу сказать следующее - есть два способа внедрения:
Ответить
19.07.2018 2:05 #
Спасибо за ответ, буду пробовать второй вариант
Ответить