mirror of https://github.com/zulip/zulip.git
billing: Update stripe error handling code.
This commit is contained in:
parent
aab977dbf8
commit
e804c563a8
|
@ -1,8 +1,22 @@
|
|||
from typing import Any, Dict
|
||||
|
||||
# List of StripeError's from https://stripe.com/docs/api/python#error_handling
|
||||
|
||||
class StripeError(Exception):
|
||||
http_status: str
|
||||
json_body: Dict[str, Any]
|
||||
|
||||
class CardError(Exception):
|
||||
http_status: str
|
||||
|
||||
class InvalidRequestError(Exception):
|
||||
class CardError(StripeError):
|
||||
...
|
||||
|
||||
class RateLimitError(StripeError):
|
||||
...
|
||||
|
||||
class InvalidRequestError(StripeError):
|
||||
...
|
||||
|
||||
class AuthenticationError(StripeError):
|
||||
...
|
||||
|
||||
class APIConnectionError(StripeError):
|
||||
...
|
||||
|
|
|
@ -73,6 +73,12 @@ class BillingError(Exception):
|
|||
self.description = description
|
||||
self.message = message
|
||||
|
||||
class StripeCardError(BillingError):
|
||||
pass
|
||||
|
||||
class StripeConnectionError(BillingError):
|
||||
pass
|
||||
|
||||
def catch_stripe_errors(func: CallableT) -> CallableT:
|
||||
@wraps(func)
|
||||
def wrapped(*args: Any, **kwargs: Any) -> Any:
|
||||
|
@ -85,12 +91,22 @@ def catch_stripe_errors(func: CallableT) -> CallableT:
|
|||
"Plan objects not created. Please run ./manage.py setup_stripe")
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
# See https://stripe.com/docs/api/python#error_handling, though
|
||||
# https://stripe.com/docs/api/ruby#error_handling suggests there are additional fields, and
|
||||
# https://stripe.com/docs/error-codes gives a more detailed set of error codes
|
||||
except stripe.error.StripeError as e:
|
||||
billing_logger.error("Stripe error: %d %s", e.http_status, e.__class__.__name__)
|
||||
err = e.json_body.get('error', {})
|
||||
billing_logger.error("Stripe error: %s %s %s %s" % (
|
||||
e.http_status, err.get('type'), err.get('code'), err.get('param')))
|
||||
if isinstance(e, stripe.error.CardError):
|
||||
raise BillingError('card error', e.json_body.get('error', {}).get('message'))
|
||||
else:
|
||||
raise BillingError('other stripe error', BillingError.CONTACT_SUPPORT)
|
||||
# TODO: Look into i18n for this
|
||||
raise StripeCardError('card error', err.get('message'))
|
||||
if isinstance(e, stripe.error.RateLimitError) or \
|
||||
isinstance(e, stripe.error.APIConnectionError): # nocoverage TODO
|
||||
raise StripeConnectionError(
|
||||
'stripe connection error',
|
||||
_("Something went wrong. Please wait a few seconds and try again."))
|
||||
raise BillingError('other stripe error', BillingError.CONTACT_SUPPORT)
|
||||
return wrapped # type: ignore # https://github.com/python/mypy/issues/1927
|
||||
|
||||
@catch_stripe_errors
|
||||
|
|
|
@ -69,10 +69,11 @@ class StripeTest(ZulipTestCase):
|
|||
return match.group(1) if match else None
|
||||
|
||||
@mock.patch("zilencer.lib.stripe.billing_logger.error")
|
||||
def test_errors(self, mock_billing_logger_error: mock.Mock) -> None:
|
||||
def test_catch_stripe_errors(self, mock_billing_logger_error: mock.Mock) -> None:
|
||||
@catch_stripe_errors
|
||||
def raise_invalid_request_error() -> None:
|
||||
raise stripe.error.InvalidRequestError("Request req_oJU621i6H6X4Ez: No such token: x", None)
|
||||
raise stripe.error.InvalidRequestError(
|
||||
"Request req_oJU621i6H6X4Ez: No such token: x", None, json_body={})
|
||||
with self.assertRaises(BillingError) as context:
|
||||
raise_invalid_request_error()
|
||||
self.assertEqual('other stripe error', context.exception.description)
|
||||
|
@ -84,7 +85,7 @@ class StripeTest(ZulipTestCase):
|
|||
json_body = {"error": {"message": error_message}}
|
||||
raise stripe.error.CardError(error_message, "number", "invalid_number",
|
||||
json_body=json_body)
|
||||
with self.assertRaises(BillingError) as context:
|
||||
with self.assertRaises(StripeCardError) as context:
|
||||
raise_card_error()
|
||||
self.assertIn('not a valid credit card', context.exception.message)
|
||||
self.assertEqual('card error', context.exception.description)
|
||||
|
|
Loading…
Reference in New Issue