@ErikHabr

Как правильно реализовать модуль оплаты на Django?

есть вьюшка checkout, там модель order создается и то что было в корзине появляется в order. Ну и плюс еще payment_type и user_info. Есть модель Payment которая создается сразу после Order в checkout view и связан объект с user, order и филиалом. Я интегрировал пока вместо банковских шлюзов Yoomoney, чтобы понять вообще процесс и написал api клиента.
Так вот, после того как мне yoomoney дает ссылку на оплату, как проверить что оплата прошла успешно и поменять статусы payment и order на complete. Webhook не вариант так как нужно авторизация по токену каждый раз для того чтобы смотреть историю операций.
Yoomoney дает параметр successfulUrl, туда надо вставить может урл на еще одну вьюшку и если это вьюшка вызывается, то и статус транзакции и заказа я ставлю в оплачен? А где тогда и в каких ситуациях указывать статусы canceled или failed или вызывать вьюшку failed payment? Как быть если выбран тип оплаты не онлайн через карту, а наличными или картой при получении? Админ сам типо вручную будет в этих случаях отмечать статус оплаты и заказа? Инфы достойной вообще про workflow этого процесса я не нашел, если кто-то может рассказать как правильно делается или где об этом прочитать, очень прошу.

Вот пока как у меня идет, пример вьюшки checkout:
class CheckoutAPIView(APIView):

    permission_classes = [IsAuthenticated]

    def get(self, request, domain):
        institution = Institution.objects.get(domain=domain)
        session = self.request.session
        user = self.request.user

        # check if request data exists
        if "name" not in request.data:
            return Response({"detail": "Enter your name"},
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            name = request.data['name']

        if "phone" not in request.data:
            return Response({"detail": "Enter your phone"},
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            phone = request.data['phone']

        if "comment" not in request.data:
            comment = ""
        else:
            comment = request.data['comment']

        if "payment_type" not in request.data:
            return Response({"detail": "Choose your payment_type"},
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            payment_type = request.data['payment_type']

        # check if payment_type exists in db with affiliate
        if payment_type in institution.payment_type.values_list("type",
                                                                flat=True):
            payment_type = institution.payment_type.get(type=payment_type).type
        else:
            return Response({"detail": "Wrong payment type"},
                            status=status.HTTP_400_BAD_REQUEST)

        # cart check
        cart = Cart.objects.filter(institution=institution,
                                   customer=user)
        if cart.exists():
            cart = cart.first()

            # order create or update
            order, order_created = Order.objects.update_or_create(
                institution=institution, customer=user, cart=cart,
                defaults={"name": name,
                          "phone": phone,
                          "comment": comment,
                          "payment_type": payment_type})

            # payment create or update
            payment, payment_created = Payment.objects.update_or_create(
                institution=institution, user=user, order=order,
                defaults={"total": order.final_price})

            # check if payment type is online by card
            if payment_type == PaymentType.ONLINE:
                if "gateway" not in request.data:
                    return Response({"detail": "Choose your payment gateway"},
                                    status=status.HTTP_400_BAD_REQUEST)
                else:
                    gateway = request.data['gateway']

                payment.type = PaymentType.ONLINE
                payment.status = PaymentStatus.PENDING
                payment.save()

                # if customer choose pay by yoomoney
                if gateway == "yoomoney":
                    wallet = institution.user.yoomoney.values_list("wallet", flat=True)[0]
                    if wallet:
                        from apps.payment.services.YooMoney.send_payment import YooMoneyPay
                        client = YooMoneyPay(wallet,
                                             "shop",
                                             order.code,
                                             "AC",
                                             order.final_price,
                                             f"APP: заказ {order.id}",
                                             f"APP: заказ {order.id}",
                                             order.code,
                                             "localhost")
                        return Response({"url": client.redirected_url})

        if user.is_authenticated:
            pass
            # cart check
            # cart = Cart.objects.filter(institution=institution,
            #                            customer=user)
            # # if settings.CART_SESSION_ID in session:
            # #     cart = Cart.objects.filter(institution=institution,
            # #                                customer=user,
            # #                                session_id=session[
            # #                                    settings.CART_SESSION_ID])
            # if cart.exists():
            #     cart = cart.first()
            #
            #     order, created = Order.objects.update_or_create(
            #         institution=institution, customer=user, cart=cart,
            #         defaults={"name": name,
            #                   "phone": phone,
            #                   "comment": comment,
            #                   "payment_type": payment_type.type})
            #
            #     serializer = OrderSerializer(order)
            #
            # return Response({"detail": serializer.data})
        else:
            return Response({"detail": "Please login"})
  • Вопрос задан
  • 45 просмотров
Пригласить эксперта
Ответы на вопрос 1
@bacon
1. Serializer придумали чтобы не было этих длинных портянок с not in request.data
2.
Webhook не вариант так как нужно авторизация по токену каждый раз для того чтобы смотреть историю операций
это ты сам придумал, webhook очень даже вариант, с ним приходит вся нужная информация про для идентификации операции, понятно что там не будет твоего ауф токена, но запросы приходят с определенных ip и они в добавок подписаны
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы