Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
devxpy committed Sep 5, 2024
2 parents 3919754 + 5438af8 commit cc64265
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 4 deletions.
4 changes: 4 additions & 0 deletions daras_ai_v2/bot_integration_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ def web_widget_config(bi: BotIntegration, user: AppUser | None):
enablePhotoUpload=False,
autoPlayResponses=True,
enableAudioMessage=True,
enableConversations=True,
branding=(
dict(showPoweredByGooey=True)
| bi.web_config_extras.get("branding", {})
Expand All @@ -442,6 +443,9 @@ def web_widget_config(bi: BotIntegration, user: AppUser | None):
config["enablePhotoUpload"] = gui.checkbox(
"Allow Photo Upload", value=config["enablePhotoUpload"]
)
config["enableConversations"] = gui.checkbox(
'Show "New Chat"', value=config["enableConversations"]
)
with scol2:
config["enableAudioMessage"] = gui.checkbox(
"Enable Audio Message", value=config["enableAudioMessage"]
Expand Down
2 changes: 1 addition & 1 deletion daras_ai_v2/send_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def send_email_via_postmark(
html_body: str = "",
text_body: str = "",
message_stream: typing.Literal[
"outbound", "gooey-ai-workflows", "announcements"
"outbound", "gooey-ai-workflows", "announcements", "billing"
] = "outbound",
):
if is_running_pytest:
Expand Down
2 changes: 1 addition & 1 deletion daras_ai_v2/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"""

import os
import json
from pathlib import Path

import sentry_sdk
Expand Down Expand Up @@ -265,6 +264,7 @@
ADMIN_EMAILS = config("ADMIN_EMAILS", cast=Csv(), default="")
SUPPORT_EMAIL = "Gooey.AI Support <[email protected]>"
SALES_EMAIL = "Gooey.AI Sales <[email protected]>"
PAYMENT_EMAIL = "Gooey.AI Payments <[email protected]>"
SEND_RUN_EMAIL_AFTER_SEC = config("SEND_RUN_EMAIL_AFTER_SEC", 5)

DISALLOWED_TITLE_SLUGS = config("DISALLOWED_TITLE_SLUGS", cast=Csv(), default="") + [
Expand Down
28 changes: 28 additions & 0 deletions payments/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,34 @@ def send_monthly_spending_notification_email(user_id: int):
user.subscription.save(update_fields=["monthly_spending_notification_sent_at"])


@app.task
def send_payment_failed_email_with_invoice(
uid: str,
invoice_url: str,
dollar_amt: float,
subject: str,
):
from routers.account import account_route

user = AppUser.objects.get(uid=uid)
if not user.email:
logger.error(f"User doesn't have an email: {user=}")
return

send_email_via_postmark(
from_address=settings.PAYMENT_EMAIL,
to_address=user.email,
subject=subject,
html_body=templates.get_template("auto_payment_failed_email.html").render(
user=user,
dollar_amt=f"{dollar_amt:.2f}",
invoice_url=invoice_url,
account_url=get_app_route_url(account_route),
),
message_stream="billing",
)


def send_monthly_budget_reached_email(user: AppUser):
from routers.account import account_route

Expand Down
27 changes: 26 additions & 1 deletion payments/webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
from daras_ai_v2 import paypal
from .models import Subscription
from .plans import PricingPlan
from .tasks import send_monthly_spending_notification_email
from .tasks import (
send_monthly_spending_notification_email,
send_payment_failed_email_with_invoice,
)


class PaypalWebhookHandler:
Expand Down Expand Up @@ -189,6 +192,28 @@ def handle_subscription_cancelled(cls, uid: str):
external_id=None,
)

@classmethod
def handle_invoice_failed(cls, uid: str, data: dict):
if stripe.Charge.list(payment_intent=data["payment_intent"], limit=1).has_more:
# we must have already sent an invoice for this to the user. so we should just ignore this event
logger.info("Charge already exists for this payment intent")
return

if data.get("metadata", {}).get("auto_recharge"):
send_payment_failed_email_with_invoice.delay(
uid=uid,
invoice_url=data["hosted_invoice_url"],
dollar_amt=data["amount_due"] / 100,
subject="Payment failure on your Gooey.AI auto-recharge",
)
elif data.get("subscription_details", {}):
send_payment_failed_email_with_invoice.delay(
uid=uid,
invoice_url=data["hosted_invoice_url"],
dollar_amt=data["amount_due"] / 100,
subject="Payment failure on your Gooey.AI subscription",
)


def add_balance_for_payment(
*,
Expand Down
2 changes: 1 addition & 1 deletion routers/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ class RecipeTabs(TabData, Enum):
route=history_route,
)
integrations = TabData(
title=f'<img width="24" height="24" style="margin-right: 4px" src="{icons.integrations_img}" alt="Facebook, Whatsapp, Slack, Instagram Icons"> Integrations',
title=f'<img width="24" height="24" style="margin-right: 4px;margin-top: -3px" src="{icons.integrations_img}" alt="Facebook, Whatsapp, Slack, Instagram Icons"> Integrations',
label="Integrations",
route=integrations_route,
)
Expand Down
2 changes: 2 additions & 0 deletions routers/stripe.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ def webhook_received(request: Request, payload: bytes = fastapi_request_body):
match event["type"]:
case "invoice.paid":
StripeWebhookHandler.handle_invoice_paid(uid, data)
case "invoice.payment_failed":
StripeWebhookHandler.handle_invoice_failed(uid, data)
case "checkout.session.completed":
StripeWebhookHandler.handle_checkout_session_completed(uid, data)
case "customer.subscription.created" | "customer.subscription.updated":
Expand Down
38 changes: 38 additions & 0 deletions templates/auto_payment_failed_email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>

<body class="d-flex flex-column min-vh-100">
<div class="flex-fill">

<p>Hi {{ user.first_name() }},</p>

<p>We attempted to process your payment for ${{ dollar_amt }} but your payment method was declined.</p>

<p>
Please <a href="{{ invoice_url }}">make a payment</a> on Gooey.AI for continued service or update
your payment method on <a href="{{ account_url }}">your account</a>.
</p>

<p>
<a href="{{ invoice_url }}">
<button class="btn btn-dark text-light">Make Payment</button>
</a>
</p>

<p>
Cheers,<br />
The Gooey.AI team
</p>

</div>

</body>

</html>

0 comments on commit cc64265

Please sign in to comment.