Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework and Stripe, best practice?

I'm struggling with philosophical questions in my DRF structure using the payement handler Stripe. I'm selling a product that has a django model Product through my DRF REST API. I'm wondering if I should create the Product and then handle the payment in my create view as follow:

class ProductViewSet(viewsets.ModelViewSet):

...

def create(self, request):
    serializer = ProductSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    product = serializer.save()

    try:
        response = stripe.Charge.create(
            amount=product.cost,
            currency="usd",
            source=request.data["token"], # Done with Stripe.js
            description="Product"
        )
        product.charge_id = response.charge_id

        ...

or instead, if I should handle the payement in the serializer of Product:

class ProductSerializer(serializers.Serializer):

    ...

    def create(self, validated_data):
        product = Product.objects.create(**validated_data)

        # Will raise an Excetpion and stop the creation:
        response = stripe.Charge.create(
            amount=product.cost,
            currency="usd",
            source=validated_data["token"], # Done with Stripe.js
            description="Product"
        )


        return product 

Which one is the better practice? Or, do I completely miss the point and should do it differently?

Secondly, is there a way to embed Stripe.js and the required form in the Browsable API template for the create route so I can test my REST without the need of any frontend?

Thank you for your help

like image 736
user2024621 Avatar asked Feb 26 '15 07:02

user2024621


1 Answers

In my opinion the right approach is a mix of the two provided approaches because you should send the Stripe request in the ModelViewSet class but save the Product entity only after the service's successful response.

Otherwise if the service's response is not successful I would rollback each database operation(with Django 1.6+ you can do it using transaction.atomic() documented here).

I don't like your second approach because according to the DRF documentation about the create method of serializers.Serializerthis method should only return a new Entity instance given the validated data, so I would not add other business logic.

Regarding the second question I would structure the create method to use an injected mock object for the Striperequest, in this way you can test your code regarding any frontend interaction (obviously in this way you don't do an integration test but a unit test).

like image 107
Riccardo Avatar answered Oct 04 '22 09:10

Riccardo