diff --git a/endpoints/webhooks.py b/endpoints/webhooks.py
index b5815bf0d..d8fa1e7e4 100644
--- a/endpoints/webhooks.py
+++ b/endpoints/webhooks.py
@@ -8,7 +8,7 @@ from data import model
from auth.auth import process_auth
from auth.permissions import ModifyRepositoryPermission
from util.invoice import renderInvoiceToHtml
-from util.email import send_invoice_email, send_subscription_change
+from util.email import send_invoice_email, send_subscription_change, send_payment_failed
from util.names import parse_repository_name
from util.http import abort
from endpoints.trigger import BuildTrigger, ValidationRequestException
@@ -25,27 +25,23 @@ def stripe_webhook():
request_data = request.get_json()
logger.debug('Stripe webhook call: %s' % request_data)
+ customer_id = request_data.get('data', {}).get('object', {}).get('customer', None)
+ user = model.get_user_or_org_by_customer_id(customer_id) if customer_id else None
+
event_type = request_data['type'] if 'type' in request_data else None
if event_type == 'charge.succeeded':
- data = request_data['data'] if 'data' in request_data else {}
- obj = data['object'] if 'object' in data else {}
- invoice_id = obj['invoice'] if 'invoice' in obj else None
- customer_id = obj['customer'] if 'customer' in obj else None
+ invoice_id = ['data']['object']['invoice']
+
+ if user and user.invoice_email:
+ # Lookup the invoice.
+ invoice = stripe.Invoice.retrieve(invoice_id)
+ if invoice:
+ invoice_html = renderInvoiceToHtml(invoice, user)
+ send_invoice_email(user.email, invoice_html)
- if invoice_id and customer_id:
- # Find the user associated with the customer ID.
- user = model.get_user_or_org_by_customer_id(customer_id)
- if user and user.invoice_email:
- # Lookup the invoice.
- invoice = stripe.Invoice.retrieve(invoice_id)
- if invoice:
- invoice_html = renderInvoiceToHtml(invoice, user)
- send_invoice_email(user.email, invoice_html)
elif event_type.startswith('customer.subscription.'):
- customer_id = request_data['data']['object']['customer']
- cust = model.get_user_or_org_by_customer_id(customer_id)
- cust_email = cust.email if cust is not None else 'unknown@domain.com'
- quay_username = cust.username if cust is not None else 'unknown'
+ cust_email = user.email if user is not None else 'unknown@domain.com'
+ quay_username = user.username if user is not None else 'unknown'
change_type = ''
if event_type.endswith('.deleted'):
@@ -64,6 +60,10 @@ def stripe_webhook():
change_type = 'switched %s -> %s' % (old_plan, new_plan)
send_subscription_change(change_type, customer_id, cust_email, quay_username)
+ elif event_type == 'invoice.payment_failed':
+ if user:
+ send_payment_failed(user.email, user.username)
+
return make_response('Okay')
diff --git a/util/email.py b/util/email.py
index 14159b325..e9fadea97 100644
--- a/util/email.py
+++ b/util/email.py
@@ -41,6 +41,22 @@ Customer email: {2}
Quay user or org name: {3}
"""
+
+PAYMENT_FAILED = """
+Hi {0},
+
+Your recent payment for Quay.io failed, which usually results in our payments processorcanceling
+your subscription automatically. If you would like to continue to use Quay.io without interruption,
+please add a new card to Quay.io and re-subscribe to your plan.
+
+You can find the card and subscription management features under your account settings.
+
+Thanks and have a great day!
+
+-Quay.io Support
+"""
+
+
SUBSCRIPTION_CHANGE_TITLE = 'Subscription Change - {0} {1}'
@@ -82,3 +98,10 @@ def send_subscription_change(change_description, customer_id, customer_email, qu
msg.html = SUBSCRIPTION_CHANGE.format(change_description, customer_id, customer_email,
quay_username)
mail.send(msg)
+
+
+def send_payment_failed(customer_email, quay_username):
+ msg = Message('Quay.io Subscription Payment Failure', sender='support@quay.io',
+ recipients=[customer_email])
+ msg.html = PAYMENT_FAILED.format(quay_username)
+ mail.send(msg)