Django: How to next process Stripe's ACH Verification Error - django

I want to be able to act on an error that happens when I run one of the commands to interface stripe. I can see the error, but can't seem to capture it.
When I run a the verification for stripe's ACH payment format and use bad deposist, I get the following error:
in handle_error_response
raise err
stripe.error.CardError: Request req_UyfXgBVRSOqUuJ: The amounts provided do not match the amounts that were sent to the bank account.
How do I take this and do something meaningful with it. My code looks like this:
ank_account_response = customer.sources.retrieve(request.stripe_id)
bank_account_response.verify(amounts=[request._post['deposit_1'], request._post['deposit_2']])
The error appears on the last line of code. I want either set do something like output = bank_account_response.verify... or try: bank_account_response, but I can't get it to work.
Thoughts?

You should handle error response something like below.
try:
bank_account_response.verify(amounts=[request._post['deposit_1'], request._post['deposit_2']])
except CARD_ERROR as card_error:
return JsonResponse(status_code=400,
message=card_error.message)

Related

Return Granite validation errors as JSON

I have a Granite User model with some validations. When someone makes a POST request to users/new, I'd like to return the validation errors (if any) as JSON. Currently, I have:
if user.errors.size > 0
halt env, status_code: 500, response: user.errors.to_json
end
But when I try to compile, I get:
in /usr/local/Cellar/crystal/0.26.1/src/json/to_json.cr:66: no overload
matches 'Granite::Error#to_json' with type JSON::Builder
Overloads are:
- Object#to_json(io : IO)
- Object#to_json()
each &.to_json(json)
^~~~~~~
So the issue is that User#errors is an Array(Granite::Error), i.e. an Array holding Granite::Errors. Unfortunately, it doesn't look like Granite::Error implements the to_json(JSON::Builder) method (i.e. the method to_json taking a parameter of type JSON::Builder), which Array#to_json relies on (that snippet you see there is from the implementation of Array#to_json which you can view on GitHub.).
I'd recommend building the JSON yourself using JSON.build. This has the added side-effect of keeping the JSON that you respond with (which I imagine is being consumed by some client) is entirely in your control. If the developers of Granite were to change how they encode Granite::Errors in JSON and you were using their to_json method, the change wouldn't raise anything at compile time.
As a side-note, I'd recommend against using a status code of 500 to denote a validation error, as that is typically reserved for unexpected errors internal to your server. A 4xx error (e.g. 400 - Bad Request) would be more appropriate. As a second side-note, it would be more RESTful to have the POST be made to the /users endpoint, as opposed to /users/new.
With these changes, here would be the resulting snippet:
if user.errors.size > 0
errors_as_json = JSON.build do |json|
json.array do
user.errors.each do |error|
json.string error.to_s
end
end
end
halt env, status_code: 400, response: errors_as_json
end

Django testing, issue with localised error messages

I am making the first steps with using Django localisation, and I have just faced the first difficulty. I am trying to test that something in models works as expected. For invalid input, a specific ValidationError should occur. The code in the test looks like this:
try:
p = ...
p.full_clean()
self.fail('Expected exception not raised')
except ValidationError as e:
dict_err = dict(e)
self.assertIn('category', dict_err.keys())
self.assertEqual(len(dict_err.keys()), 1, 'Encountered more than one error')
self.assertIn('blank', dict_err['category'][0])
As long as the site operates in English (LANGUAGE_CODE = 'en-uk'), the caught error looks like this:
ValidationError({'category': ['This field cannot be blank.']})
To check that I've got exactly this ValidationError, I am searching for the work 'blank' in the error message (last line of the code above).
It fails as soon as I switch the site to another language. E.g. for German it looks so:
ValidationError({'category': ['Dieses Feld darf nicht leer sein.']})
Looking for 'blank' obviously fails the test. How could I check the error message? I expect, somewhere deep in Django, there should be a unique identifier of this message (so that Django knows how to translate). But I don't see any traces of it in the error value. I would expect something like
self.assertIn(_(id), dict_err['category'][0])
would do the trick, if I could guess what id should be, and if I understand correctly what _() does.
By further trial and error, I've found that for simple messages the message ID is simply the original English message. That is, one can do:
...
expected_error = _("This field cannot be blank.")
self.assertIn(expected_error, dict_err['category'][0])
or even
self.assertEqual(expected_error, dict_err['category'][0])
It works then independent of the site language.
For errors using named-string interpolation, the code would look like follows. Assuming the English-language error message is Value 'x' is not a valid choice., we do:
expected_error = _("Value %(value)r is not a valid choice.") % {'value': 'x'}
self.assertEqual(expected_error, dict_err['category'][0])
I've found that the easiest way to determine the respective message ID is to search for the part of the English error message in the venv files. For example, I found the error above searching for "is not a valid choice", which is obviously an immutable part of the message.
Special thanks to #MosesKoledoye: his comment to my question hinted in the right direction.

How to debug a Internal Error current transaction is aborted, commands ignored until end of transaction block?

I am coming across this error current transaction is aborted, commands ignored until end of transaction block,
the traceback is too long so, am printing out the line that seems to cause the error,
File "/home/matsinvasion/food4less/restaurant_detail/views.py" in pre_save
176. user=User.objects.create(username=obj.restaurant_detail.email,email=obj.restaurant_detail.email)
and here is part(its pretty long) of where the error is being generated
user=User.objects.create(username=obj.restaurant_detail.email,email=obj.restaurant_detail.email)
user.email_user(
"F4L account activation",
"Your membership to F4L has been approved go to the following link to activate your account \n \n http://f4l.herokuapp.com/restaurant_detail/restaurant/activate/%s/ \n \n After you have activated your account, login using your full email address as username and your password \n \n And customize what will be published on your F4L website profile by click profile link on the left of members \n \n This email is generated by the F4L website do not reply to it. " % obj.token,"website#f4l.herokuapp.com"
)
group=Group.objects.get(name='Restaurants')
user.groups.add(group)
user.first_name=userapp.first_name
user.last_name=userapp.last_name
user.email=userapp.email
user.set_unusable_password()
user.save()
obj.user=user
obj.is_active=False
obj.save()
return obj
Now what confuses me most is that this worked fine with sqlite but when i switched to postgresql, this error come by.
I have looked here (DatabaseError: current transaction is aborted, commands ignored until end of transaction block) and here (Django+Postgres: "current transaction is aborted, commands ignored until end of transaction block") but to no vain.
How do you suggest i squash this bug?
EDIT: After looking around, i realised the error was caused by a library that am using and has never been tested with postgres.
I think the issue comes from:
user.groups.add(group)
To me, this doesn't seems legit before having saved the user. I think the "add" method interacts with the database by creating a new tuple in the m2m relation, and that is not possible while "user" has no id. Furthermore I found in this documentation it raised an error (unfortunatly a ValueError and not a DatabaseError).
So I think you have to save your user before managing its relationship.
Let me know if this solved your issue!

Django Next Parameter Redirect - Adding Additional Parameters

I'm trying to add authentication to my webapp. A user begins the authentication process by going to:
/authorization/v1/new?client_id=X&response_type=Y&redirect_uri=Z
If request.user does not exist, I redirect using the following code:
try:
user_identity = Identity.objects.get(user=request.user)
except:
resource = '%s?next=/authorization/v1/new' % settings.LOGIN_URL
return HttpResponseRedirect(resource)
This takes the user to /login/?next=/authorization/v1/new.
The user logs in successfully, and is redirected back to /authorization/v1/new.
However, now I'm missing the required GET parameters client_id, response_type, and redirect_uri, and this causes the authorization endpoint to throw an error for missing required parameters.
What is the best way to capture the initial GET params, pass them through to login, and attach them to the redirection back to the auth endpoint?
I thought about using sessions or modifying the redirect_uri to attach the other params, but I still need to figure out how to capture a single parameter through this process. I'd like to not have to modify the login code, if possible. Any ideas/suggestions greatly appreciated. Thanks!
If you were using Django's built-in #login_required decorator, I believe this would be taken care of for you as of r2954.
Given that you're not, you just need to replicate the same steps. Just set next to the value of the full path (as Django does in #login_required), like so:
from urllib import quote
...
try:
user_identity = Identity.objects.get(user=request.user)
except Identity.DoesNotExist:
return HttpResponseRedirect('%snext=%s' % (settings.LOGIN_URL, quote(request.get_full_path()))
NB I've also changed your code to avoid your Pokémon exception handling ("Gotta catch 'em all!").

Django - Passing a filtered result to a template

Inside of my Django view I am trying to retrieve results from my database and then pass them on to my template with the following code:
f = request.GET.get('f')
try:
fb_friends_found= UserProfile.objects.filter(facebookid__in=f).values('facebookid')
i = fb_friends_found[0] #To get the dictionary inside of the list
results = i['facebookid'] #To retrieve the value for the 'facebookid' key
variables = RequestContext (request, {'results': results })
return render_to_response('findfriends.html', variables)
I carried out the first three lines within the 'try' block using manage.py shell and this worked fine, printing the correct 'facebookid'.
Unfortunately I can't get it to work in my browser. Any suggestions?
Do you have a specific problem you're running into, such as an exception?
I feel like you should get some kind of exception if you have a try block without an except statement.
try:
# something
except Exception: # but be more specific
print "exception occurred"
Otherwise, the code looks good, and if nothing is rendering in your browser, I'd look into the template. Unless... you're hiding errors in your try block, in which case you should remove the try block and let the error occur to understand what's wrong.