diff --git a/api4/cloud.go b/api4/cloud.go
index 93ca4c4a22..acd629e60d 100644
--- a/api4/cloud.go
+++ b/api4/cloud.go
@@ -353,7 +353,11 @@ func handleCWSWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = nErr
return
}
-
+ case model.EventTypeFailedPaymentNoCard:
+ if nErr := c.App.SendNoCardPaymentFailedEmail(); nErr != nil {
+ c.Err = nErr
+ return
+ }
}
ReturnStatusOK(w)
diff --git a/app/app_iface.go b/app/app_iface.go
index f16eeb87ef..a83f7f0acc 100644
--- a/app/app_iface.go
+++ b/app/app_iface.go
@@ -265,6 +265,8 @@ type AppIface interface {
SearchAllChannels(term string, opts model.ChannelSearchOpts) (*model.ChannelListWithTeamData, int64, *model.AppError)
// SearchAllTeams returns a team list and the total count of the results
SearchAllTeams(searchOpts *model.TeamSearch) ([]*model.Team, int64, *model.AppError)
+ // SendNoCardPaymentFailedEmail
+ SendNoCardPaymentFailedEmail() *model.AppError
// ServePluginPublicRequest serves public plugin files
// at the URL http(s)://$SITE_URL/plugins/$PLUGIN_ID/public/{anything}
ServePluginPublicRequest(w http.ResponseWriter, r *http.Request)
diff --git a/app/cloud.go b/app/cloud.go
index a34799d0f3..bf79a52e8f 100644
--- a/app/cloud.go
+++ b/app/cloud.go
@@ -75,3 +75,19 @@ func (a *App) SendPaymentFailedEmail(failedPayment *model.FailedPayment) *model.
}
return nil
}
+
+// SendNoCardPaymentFailedEmail
+func (a *App) SendNoCardPaymentFailedEmail() *model.AppError {
+ sysAdmins, err := a.getSysAdminsEmailRecipients()
+ if err != nil {
+ return err
+ }
+
+ for _, admin := range sysAdmins {
+ err := a.Srv().EmailService.SendNoCardPaymentFailedEmail(admin.Email, admin.Locale, *a.Config().ServiceSettings.SiteURL)
+ if err != nil {
+ a.Log().Error("Error sending payment failed email", mlog.Err(err))
+ }
+ }
+ return nil
+}
diff --git a/app/email.go b/app/email.go
index 2236f5ac04..fe4a44c7e5 100644
--- a/app/email.go
+++ b/app/email.go
@@ -779,6 +779,7 @@ func (es *EmailService) SendPaymentFailedEmail(email string, locale string, fail
bodyPage.Props["Info2"] = T("api.templates.payment_failed.info2")
bodyPage.Props["Info3"] = T("api.templates.payment_failed.info3")
bodyPage.Props["Button"] = T("api.templates.over_limit_fix_now")
+ bodyPage.Props["EmailUs"] = T("api.templates.email_us_anytime_at")
bodyPage.Props["FailedReason"] = failedPayment.FailureMessage
@@ -788,3 +789,23 @@ func (es *EmailService) SendPaymentFailedEmail(email string, locale string, fail
return true, nil
}
+
+func (es *EmailService) SendNoCardPaymentFailedEmail(email string, locale string, siteURL string) *model.AppError {
+ T := utils.GetUserTranslations(locale)
+
+ subject := T("api.templates.payment_failed_no_card.subject")
+
+ bodyPage := es.newEmailTemplate("payment_failed_no_card_body", locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = T("api.templates.payment_failed_no_card.title")
+ bodyPage.Props["Info1"] = T("api.templates.payment_failed_no_card.info1")
+ bodyPage.Props["Info3"] = T("api.templates.payment_failed_no_card.info3")
+ bodyPage.Props["Button"] = T("api.templates.payment_failed_no_card.button")
+ bodyPage.Props["EmailUs"] = T("api.templates.email_us_anytime_at")
+
+ if err := es.sendMail(email, subject, bodyPage.Render()); err != nil {
+ return model.NewAppError("SendPaymentFailedEmail", "api.user.send_password_reset.send.app_error", nil, "err="+err.Message, http.StatusInternalServerError)
+ }
+
+ return nil
+}
diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go
index f033a9e9da..1fb2f8747f 100644
--- a/app/opentracing/opentracing_layer.go
+++ b/app/opentracing/opentracing_layer.go
@@ -13110,6 +13110,28 @@ func (a *OpenTracingAppLayer) SendEphemeralPost(userId string, post *model.Post)
return resultVar0
}
+func (a *OpenTracingAppLayer) SendNoCardPaymentFailedEmail() *model.AppError {
+ origCtx := a.ctx
+ span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendNoCardPaymentFailedEmail")
+
+ a.ctx = newCtx
+ a.app.Srv().Store.SetContext(newCtx)
+ defer func() {
+ a.app.Srv().Store.SetContext(origCtx)
+ a.ctx = origCtx
+ }()
+
+ defer span.Finish()
+ resultVar0 := a.app.SendNoCardPaymentFailedEmail()
+
+ if resultVar0 != nil {
+ span.LogFields(spanlog.Error(resultVar0))
+ ext.Error.Set(span, true)
+ }
+
+ return resultVar0
+}
+
func (a *OpenTracingAppLayer) SendNotifications(post *model.Post, team *model.Team, channel *model.Channel, sender *model.User, parentPostList *model.PostList, setOnline bool) ([]string, error) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SendNotifications")
diff --git a/i18n/en.json b/i18n/en.json
index f8cfbe6304..2513fe5f30 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -2882,6 +2882,26 @@
"id": "api.templates.payment_failed.title",
"translation": "Failed Payment"
},
+ {
+ "id": "api.templates.payment_failed_no_card.button",
+ "translation": "Pay now"
+ },
+ {
+ "id": "api.templates.payment_failed_no_card.info1",
+ "translation": "Your Mattermost Cloud invoice for the most recent billing period has been processed. However, we don't have your payment details on file."
+ },
+ {
+ "id": "api.templates.payment_failed_no_card.info3",
+ "translation": "To review your invoice and add a payment method, select Pay now."
+ },
+ {
+ "id": "api.templates.payment_failed_no_card.subject",
+ "translation": "Payment is due for your Mattermost Cloud subscription"
+ },
+ {
+ "id": "api.templates.payment_failed_no_card.title",
+ "translation": "Your Mattermost Cloud Invoice is due"
+ },
{
"id": "api.templates.post_body.button",
"translation": "Go To Post"
diff --git a/model/cloud.go b/model/cloud.go
index efd89762f7..21402895fd 100644
--- a/model/cloud.go
+++ b/model/cloud.go
@@ -4,7 +4,8 @@
package model
const (
- EventTypeFailedPayment = "failed-payment"
+ EventTypeFailedPayment = "failed-payment"
+ EventTypeFailedPaymentNoCard = "failed-payment-no-card"
)
// Product model represents a product on the cloud system.
diff --git a/templates/payment_failed_no_card_body.html b/templates/payment_failed_no_card_body.html
new file mode 100644
index 0000000000..445752025e
--- /dev/null
+++ b/templates/payment_failed_no_card_body.html
@@ -0,0 +1,92 @@
+{{define "payment_failed_no_card_body"}}
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ .Props.Title }}
+ |
+
+
+
+ {{ .Props.Info1 }}
+ {{.Props.Info3}}
+
+ {{ .Props.Button }}
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+ |
+
+ {{.Props.Organization}}
+ {{.Props.Footer}}
+
+ |
+
+
+
+ |
+
+
+ |
+
+
+
+{{end}}