10. Оплата

19 ноября 2017 г. 21: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, в котором новые ПС не потребуют каких-либо специальных трюков (костылей) для их работоспособности.

Оцените статью

0 из 5 (всего 0 оценок)

Поля, отмеченные звёздочкой ( * ) , являются обязательными.

Спасибо за ваш отзыв!

После нажатия кнопки "Отправить" ваше сообщение будет доставлено мне на почту.

Автор перевода

Права на использование материала, расположенного на этой странице http://vivazzi.pro/django-shop/payment-providers/:

Разрешается копировать материал с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:

Автор перевода: Мальцев Артём
Ссылка на перевод статьи: <a href="http://vivazzi.pro/django-shop/payment-providers/">http://vivazzi.pro/django-shop/payment-providers/</a>

Подробнее: Правила использования сайта

Комментариев: 3

Дмитрий
Дмитрий

17.07.2018 22:02 #

Привет. Не подскажешь, как подключить яндекс кассу (api) https://github.com/yandex-money/yandex-checkout-sdk-python к django cms ?

Ответить

Артём Мальцев
Артём Мальцев автор

18.07.2018 21:50 #

Приветствую! Сам пока не подключал Яндекс.Кассу, но в принципе у всех платёжек похожий api, поэтому сам процесс подключения не должен вызывать трудностей. Другое дело как в django-cms внедрить. В общем случае могу сказать следующее - есть два способа внедрения:

  1. Прикрутить платёжку на странице оформления заказа, как это сделано в демо-магазине проекта через stripe. Но тут нужно умудриться как-то связать вместе с angular.
  2. Прикрутить платёжку на странице Просмотра заказа. Когда уже заказ был оформлен, тебя перебрасывает на страницу Спасибо за покупку - там и можно разместить кнопку Оплатить заказ. В этом случае будет без angular, что может быть попроще.

Ответить

Гость
Гость

18.07.2018 22:05 #

Спасибо за ответ, буду пробовать второй вариант

Ответить

Вы можете оставить комментарий как незарегистрированный пользователь. Но, зарегистрировавшись, вы сможете получать оповещения об ответах, а также иметь доступ к своему личному аккаунту для просмотра своих комментариев.

Чтобы оставить комментарий от своего имени войдите или зарегистрируйтесь обычным способом или через социальные сети:

Отправить

На данный момент нет специального поиска, поэтому я предлагаю воспользоваться обычной поисковой системой, например, Google, добавив "vivazzi" после своего запроса.

Попробуйте