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
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.Serializer
this 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 Stripe
request, 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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With