I am trying to integrate stripe with my django project, so I try to create a PaymentIntent and if a network communication with stripe failed I will try to do like this:
try:
intent = stripe.PaymentIntent.create(
amount=100,
currency='usd'
)
return JsonResponse({
'clientSecret': intent['client_secret']
})
except stripe.error.CardError as e:
pass
except stripe.error.RateLimitError as e:
pass
except stripe.error.InvalidRequestError as e:
pass
except stripe.error.AuthenticationError as e:
pass
except stripe.error.APIConnectionError as e:
try:
intent_cancel = stripe.PaymentIntent.cancel(
intent['id']
)
except Exception as e:
# (If an exception is raised this means that the PaymentIntent was not created, I am right ?)
# I redirect the user to the payment page and inform him
# that a network problem has occurred and ask him to repeat his request
pass
except stripe.error.StripeError as e:
pass
except Exception as e:
pass
My questions are:
1 Is my way of handling the exception right ?
2 Can I apply this logic to the other exception ?
3 In the documentation they say that we should use an idempotency_key to retry the failed requests, how can I implement this ? and what about if I retry the failed request and it fails again, what should I do ?
You have 2 Stripe API requests in the same try block. This means if one succeeds but the other fails due to a connection error you'll treat both as failed. A better flow would be to only have one API operation per try/catch block.
You also have a request to cancel a hardcoded PaymentIntent after your code returns a JSON object. Since the return isn't conditional this is likely dead code.
The cancel logic in the case of a connection error doesn't make sense here. You should only hit this path if the connection failed and the intent wasn't created, so trying to cancel the non-existent PaymentIntent will likely result in yet another error. Instead you should introduce retry logic here. Luckily stripe-python has this built in specifically for network errors: https://github.com/stripe/stripe-python#configuring-automatic-retries
Once all retries have failed, you should probably log that somewhere and inform your user that a problem occurred and that they should try again later.
As for idempotency keys, the Stripe docs have a primer on that here: https://stripe.com/docs/api/idempotent_requests?lang=python
Related
I am trying to execute some statements within Try block. I am calling an API and performing some operations. There is one specific operation which is resulting in RuntimeError which is puked while running the program, although I am catching it with an exception. How do I go about avoiding the errors being puked from Try block?
try:
call API and perform some tasks.
encounters an error here
Except RunTimeError as ex:
print(ex)
Well as Susmit R. Veena said the point of try and except is to catch the error thrown in the try block.
In case you have some flow you want to ignore from its exceptions in the try block, than you can have a nested try catch block for the specific error you want to ignore and keep doing the logic after it is ignored.
for example:
try:
try:
call API and perform some tasks.
encounters an error here
Except TheErrorYouWantToIngore:
pass
keep on doing some stuff even TheErrorYouWantToIngore has been throwed
Except RunTimeError as ex:
print(ex)
the whole point of try and except is to catch the errors thrown by the code in try block in except block. Post the code for solution to the error
I was going to use send_mail function to send email, and I was hoping that using fail_silently=True would prevent this function from raising exceptions.
It turns out it does work if SMTPException is raised; however I noticed it doesn't intercept socket.error exception - so if STMP server is down, an exception will be raised even with fail_silently=True
I'm now wondering how to get the complete list of exceptions raised by send_mail so I can catch them in try/except loop. Any suggestions?
I'd say that catch an Exception is a very final approach. Since both SMTPException and socket.error are children of IOError you can catch an IOError instead. If you'll ever catch something else - you can add this to your catch list later.
Somehow, using django 1.7 with the default email backend, I get an error: 111 Connection Refused. This is triggered as an exception, even when the fail_silently parameter is True.
The line goes like this:
return send_mail(subject=u"Bienvenido a Mi CNT!",
message=render_to_string('micnt/mail.welcome.txt', context),
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=[email_address],
fail_silently=True,
html_message=render_to_string('micnt/mail.welcome.html', context))
I know how to fix the excepcion (I forgot to configure certain parameters). However, there will be cases where, perhaps, the exception will be due to other reasons (e.g. I correctly specified the mail parameters, but the server got down).
Why is fail_silently not working? What is the "scope" of fail_silently? (i.e. which errors does it cover, and which errors does it let pass to the invoker?).
I would like to correctly cover the exceptions without having to:
try:
return send_mail(...)
except Exception as e:
# I want to understand what exception types will be triggered here.
pass
fail_silently will only catch SMTPException's when send_mail attempts to connect to email server (executes get_connection).
I like to take issues like this as an opportunity to look into the django source code, which contains all the answers:
https://github.com/django/django/blob/master/django/core/mail/backends/smtp.py#L69
All, I'm trying to raise a custom error using Flask-Restful, following the docs. For testing purposes, I've defined and registered the errors dictionary exactly link in the docs: api = flask_restful.Api(app, errors=errors).
However, when I want to raise the custom error using (e.g.) abort(409) within the resource module, firebug reports:
{
"message": "Conflict",
"status": 409
}
This seems like the standard 409 error, nothing custom; from the docs, I would expect the custom error message- "A user with that username already exists."
I think I'm missing something regarding the raising of the error itself. Should I use the dictionary key in any way? Reviewing the Flask-Restful source code didn't help, though I tried.
To define a message for a standard HTTP status code with Flask-RESTful, you must redefine one of the HTTP exceptions provided by Werkzeug, on which Flask is based.
Following your question, here is an example to override the Conflict exception:
errors = {
'Conflict': {
'message': "A user with that username already exists.",
'status': 409,
},
}
app = Flask(__name__)
api = flask_restful.Api(app, errors=errors)
Hence, every time you will call abort(409), this will return a representation in the right mediatype, and with the defined message.
However, by using this method, in any place you will abort with a 409 status code, this will return a message about a user with a username that already exists. This is unlikely what you want when you call abort(409) in a view that deals with other resources than users.
So, I advise you to simply use the abort method of Flask-RESTful as follows, every time you want to provide a custom message:
from flask.ext.restful import abort
abort(409, description="A user with that username already exists.")
Generally speaking, extending Flask-RESTful by defining custom error messages is useful when you raise custom exceptions (with raise(), not abort()) which are not in the HTTP exceptions provided by Werkzeug.
I'm trying to access a Google Drive using gdata-Python-client package. I can get access to an account by providing authentication details (user name, password) and open a client to manipulate spreadsheets.
import gdata.spreadsheet.service
client=gdata.spreadsheet.service.SpreadsheetsService()
client.email=some_username
client.password=some_pwd
Now I want to check whether the login process was successful and I write the following piece of code.
try:
client.ProgrammaticLogin()
return True
except:
return False
This code throws an exception if the login fails.
Are there other ways we can achieve this without catching this exception? (Eg. checking within an if clause using a return value of a method)
As far as I know ProgrammaticLogin() method itself does not return any value (i.e. type(ProgrammaticLogin()) returns 'NoneType')
If try-except is the only way to check this what is the name of the exact Exception thrown at this instant?
Thanks
According to this link multiple types of exceptions are thrown based on the error type
http://gdata-python-client.googlecode.com/hg/pydocs/gdata.service.html