585 lines
22 KiB
Go
585 lines
22 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/labstack/echo/v5"
|
|
|
|
"github.com/pocketbase/pocketbase"
|
|
"github.com/pocketbase/pocketbase/core"
|
|
"github.com/pocketbase/pocketbase/forms"
|
|
"github.com/pocketbase/pocketbase/models"
|
|
"github.com/pocketbase/pocketbase/plugins/jsvm"
|
|
|
|
"github.com/stripe/stripe-go/v78"
|
|
"github.com/stripe/stripe-go/v78/billingportal/session"
|
|
checkoutSession "github.com/stripe/stripe-go/v78/checkout/session"
|
|
"github.com/stripe/stripe-go/v78/customer"
|
|
"github.com/stripe/stripe-go/v78/webhook"
|
|
)
|
|
|
|
func coalesce(value *string, defaultValue string) string {
|
|
if value != nil {
|
|
return *value
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func int64ToISODate(timestamp int64) string {
|
|
// Convert the Unix timestamp to a time.Time
|
|
t := time.Unix(timestamp, 0)
|
|
|
|
// Format the time as an ISO 8601 date string (in UTC)
|
|
return t.Format(time.RFC3339)
|
|
}
|
|
|
|
func main() {
|
|
// Retreive stripe generated webhook secret
|
|
// SECRET_TXT, err := os.ReadFile("secret.txt")
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
// WHSEC := strings.ReplaceAll(string(SECRET_TXT), "\n", "")
|
|
// log.Print(WHSEC)
|
|
app := pocketbase.New()
|
|
|
|
// Retreive your STRIPE_SECRET_KEY from environment variables
|
|
stripe.Key = os.Getenv("STRIPE_SECRET_KEY")
|
|
stripeSuccessURL := os.Getenv("STRIPE_SUCCESS_URL")
|
|
stripeCancelURL := os.Getenv("STRIPE_CANCEL_URL")
|
|
stripeBillingReturnURL := os.Getenv("STRIPE_BILLING_RETURN_URL")
|
|
WHSEC := os.Getenv("STRIPE_WHSEC")
|
|
|
|
jsvm.MustRegister(app, jsvm.Config{
|
|
HooksWatch: true,
|
|
HooksPoolSize: 25,
|
|
})
|
|
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
|
e.Router.POST("/create-checkout-session", func(c echo.Context) error {
|
|
// 1. Destructure the price and quantity from the POST body
|
|
body := c.Request().Body
|
|
defer body.Close()
|
|
payload, _ := io.ReadAll(body)
|
|
var data map[string]interface{}
|
|
json.Unmarshal([]byte(payload), &data)
|
|
|
|
price, _ := data["price"].(map[string]interface{})
|
|
quantity, _ := data["quantity"].(float64)
|
|
|
|
// 2. Get the user from pocketbase auth
|
|
token := c.Request().Header.Get("Authorization")
|
|
record, err := app.Dao().FindAuthRecordByToken(token, app.Settings().RecordAuthToken.Secret)
|
|
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not get user"})
|
|
}
|
|
|
|
// 3. Retrieve or create the customer in Stripe
|
|
existingCustomerRecord, err := app.Dao().FindFirstRecordByData("customer", "user_id", record.Id)
|
|
if err != nil {
|
|
//create new customer if none exists
|
|
customerEmail := record.GetString("email")
|
|
customerParams := &stripe.CustomerParams{
|
|
Email: &customerEmail,
|
|
Metadata: map[string]string{
|
|
"pocketbaseUUID": record.GetString("id"),
|
|
},
|
|
}
|
|
|
|
stripeCustomer, _ := customer.New(customerParams)
|
|
|
|
//upload customer to pocketbase
|
|
collection, err := app.Dao().FindCollectionByNameOrId("customer")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var form *forms.RecordUpsert
|
|
newCustomerRecord := models.NewRecord(collection)
|
|
|
|
if err == nil {
|
|
form = forms.NewRecordUpsert(app, newCustomerRecord)
|
|
}
|
|
|
|
form.LoadData(map[string]any{
|
|
"user_id": record.Id,
|
|
"stripe_customer_id": stripeCustomer.ID,
|
|
})
|
|
|
|
if err := form.Submit(); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not create new customer"})
|
|
}
|
|
|
|
//Do Pricing New Customer
|
|
if price["type"] == "recurring" {
|
|
//create new session
|
|
lineParams := []*stripe.CheckoutSessionLineItemParams{
|
|
{
|
|
Price: stripe.String(price["id"].(string)),
|
|
Quantity: stripe.Int64(int64(quantity)),
|
|
},
|
|
}
|
|
customerUpdateParams := &stripe.CheckoutSessionCustomerUpdateParams{
|
|
Address: stripe.String("auto"),
|
|
}
|
|
subscriptionParams := &stripe.CheckoutSessionSubscriptionDataParams{
|
|
Metadata: map[string]string{},
|
|
}
|
|
|
|
sessionParams := &stripe.CheckoutSessionParams{
|
|
Customer: &stripeCustomer.ID,
|
|
PaymentMethodTypes: stripe.StringSlice([]string{"card"}),
|
|
BillingAddressCollection: stripe.String("required"),
|
|
CustomerUpdate: customerUpdateParams,
|
|
Mode: stripe.String("subscription"),
|
|
AllowPromotionCodes: stripe.Bool(true),
|
|
SuccessURL: &stripeSuccessURL,
|
|
CancelURL: &stripeCancelURL,
|
|
LineItems: lineParams,
|
|
SubscriptionData: subscriptionParams,
|
|
}
|
|
sesh, _ := checkoutSession.New(sessionParams)
|
|
return c.JSON(http.StatusOK, sesh)
|
|
} else if price["type"] == "one_time" {
|
|
//create new session
|
|
lineParams := []*stripe.CheckoutSessionLineItemParams{
|
|
{
|
|
Price: stripe.String(price["id"].(string)),
|
|
Quantity: stripe.Int64(int64(quantity)),
|
|
},
|
|
}
|
|
customerUpdateParams := &stripe.CheckoutSessionCustomerUpdateParams{
|
|
Address: stripe.String("auto"),
|
|
}
|
|
|
|
sessionParams := &stripe.CheckoutSessionParams{
|
|
Customer: &stripeCustomer.ID,
|
|
PaymentMethodTypes: stripe.StringSlice([]string{"card"}),
|
|
BillingAddressCollection: stripe.String("required"),
|
|
CustomerUpdate: customerUpdateParams,
|
|
Mode: stripe.String("payment"),
|
|
AllowPromotionCodes: stripe.Bool(true),
|
|
SuccessURL: &stripeSuccessURL,
|
|
CancelURL: &stripeCancelURL,
|
|
LineItems: lineParams,
|
|
}
|
|
sesh, _ := checkoutSession.New(sessionParams)
|
|
return c.JSON(http.StatusOK, sesh)
|
|
} else {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not create new session"})
|
|
}
|
|
} else {
|
|
//Do Pricing Existing
|
|
if price["type"] == "recurring" {
|
|
//create new session
|
|
lineParams := []*stripe.CheckoutSessionLineItemParams{
|
|
{
|
|
Price: stripe.String(price["id"].(string)),
|
|
Quantity: stripe.Int64(int64(quantity)),
|
|
},
|
|
}
|
|
customerUpdateParams := &stripe.CheckoutSessionCustomerUpdateParams{
|
|
Address: stripe.String("auto"),
|
|
}
|
|
subscriptionParams := &stripe.CheckoutSessionSubscriptionDataParams{
|
|
Metadata: map[string]string{},
|
|
}
|
|
|
|
sessionParams := &stripe.CheckoutSessionParams{
|
|
Customer: stripe.String(existingCustomerRecord.GetString("stripe_customer_id")),
|
|
PaymentMethodTypes: stripe.StringSlice([]string{"card"}),
|
|
BillingAddressCollection: stripe.String("required"),
|
|
CustomerUpdate: customerUpdateParams,
|
|
Mode: stripe.String("subscription"),
|
|
AllowPromotionCodes: stripe.Bool(true),
|
|
SuccessURL: &stripeSuccessURL,
|
|
CancelURL: &stripeCancelURL,
|
|
LineItems: lineParams,
|
|
SubscriptionData: subscriptionParams,
|
|
}
|
|
sesh, _ := checkoutSession.New(sessionParams)
|
|
return c.JSON(http.StatusOK, sesh)
|
|
} else if price["type"] == "one_time" {
|
|
//create new session
|
|
lineParams := []*stripe.CheckoutSessionLineItemParams{
|
|
{
|
|
Price: stripe.String(price["id"].(string)),
|
|
Quantity: stripe.Int64(int64(quantity)),
|
|
},
|
|
}
|
|
customerUpdateParams := &stripe.CheckoutSessionCustomerUpdateParams{
|
|
Address: stripe.String("auto"),
|
|
}
|
|
|
|
sessionParams := &stripe.CheckoutSessionParams{
|
|
Customer: stripe.String(existingCustomerRecord.GetString("stripe_customer_id")),
|
|
PaymentMethodTypes: stripe.StringSlice([]string{"card"}),
|
|
BillingAddressCollection: stripe.String("required"),
|
|
CustomerUpdate: customerUpdateParams,
|
|
Mode: stripe.String("payment"),
|
|
AllowPromotionCodes: stripe.Bool(true),
|
|
SuccessURL: &stripeSuccessURL,
|
|
CancelURL: &stripeCancelURL,
|
|
LineItems: lineParams,
|
|
}
|
|
sesh, _ := checkoutSession.New(sessionParams)
|
|
return c.JSON(http.StatusOK, sesh)
|
|
} else {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not create new session for stripe"})
|
|
}
|
|
}
|
|
})
|
|
return nil
|
|
})
|
|
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
|
e.Router.POST("/create-portal-link", func(c echo.Context) error {
|
|
// 1. Get the user from pocketbase auth
|
|
token := c.Request().Header.Get("Authorization")
|
|
record, err := app.Dao().FindAuthRecordByToken(token, app.Settings().RecordAuthToken.Secret)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not get user"})
|
|
}
|
|
|
|
// 2. Retrieve or create the customer in Stripe
|
|
existingCustomerRecord, err := app.Dao().FindFirstRecordByData("customer", "user_id", record.Id)
|
|
if err != nil {
|
|
//create new customer if none exists
|
|
customerParams := &stripe.CustomerParams{
|
|
Metadata: map[string]string{
|
|
"pocketbaseUUID": record.GetString("id"),
|
|
},
|
|
}
|
|
|
|
stripeCustomer, _ := customer.New(customerParams)
|
|
|
|
//upload customer to pocketbase
|
|
collection, err := app.Dao().FindCollectionByNameOrId("customer")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var form *forms.RecordUpsert
|
|
newCustomerRecord := models.NewRecord(collection)
|
|
|
|
if err == nil {
|
|
form = forms.NewRecordUpsert(app, newCustomerRecord)
|
|
}
|
|
|
|
form.LoadData(map[string]any{
|
|
"user_id": record.Id,
|
|
"stripe_customer_id": stripeCustomer.ID,
|
|
})
|
|
|
|
if err := form.Submit(); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not create new customer"})
|
|
}
|
|
|
|
//create new session
|
|
sessionParams := &stripe.BillingPortalSessionParams{
|
|
Customer: stripe.String(stripeCustomer.ID),
|
|
ReturnURL: &stripeBillingReturnURL,
|
|
}
|
|
sesh, err := session.New(sessionParams)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not create new session"})
|
|
} else {
|
|
return c.JSON(http.StatusOK, sesh)
|
|
}
|
|
|
|
} else {
|
|
//create new session
|
|
sessionParams := &stripe.BillingPortalSessionParams{
|
|
Customer: stripe.String(existingCustomerRecord.GetString("stripe_customer_id")),
|
|
ReturnURL: &stripeBillingReturnURL,
|
|
}
|
|
sesh, err := session.New(sessionParams)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "Could not create new session"})
|
|
} else {
|
|
return c.JSON(http.StatusOK, sesh)
|
|
}
|
|
}
|
|
})
|
|
return nil
|
|
})
|
|
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
|
e.Router.POST("/stripe", func(c echo.Context) error {
|
|
// Read the request body into a byte slice
|
|
body := c.Request().Body
|
|
defer body.Close() // Close the body when done
|
|
payload, err := io.ReadAll(body)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "failed to read body"})
|
|
}
|
|
|
|
event := stripe.Event{}
|
|
err = json.Unmarshal(payload, &event)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "failed to parse JSON"})
|
|
}
|
|
signatureHeader := c.Request().Header.Get("Stripe-Signature")
|
|
event, err = webhook.ConstructEvent(payload, signatureHeader, WHSEC)
|
|
if err != nil {
|
|
failureMessage := fmt.Sprintf("webhook verification failed: payload=%q, signatureHeader=%q, err=%q",
|
|
payload, signatureHeader, err)
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": failureMessage})
|
|
}
|
|
|
|
switch event.Type {
|
|
case "product.created", "product.updated":
|
|
var product stripe.Product
|
|
err := json.Unmarshal(event.Data.Raw, &product)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "failed to marshall the stripe event"})
|
|
}
|
|
// Then define and call a func to handle the successful payment intent.
|
|
|
|
collection, err := app.Dao().FindCollectionByNameOrId("product")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
existingRecord, err := app.Dao().FindFirstRecordByData("product", "product_id", product.ID)
|
|
record := models.NewRecord(collection)
|
|
|
|
var form *forms.RecordUpsert
|
|
|
|
if err == nil && existingRecord != nil {
|
|
// Existing record found, update it
|
|
// You might need to map data from product to your record
|
|
// Assuming UpdateRecord updates the existing record with new data
|
|
form = forms.NewRecordUpsert(app, existingRecord)
|
|
} else {
|
|
// Existing record not found, insert a new record
|
|
// You might need to map data from product to your record
|
|
// Assuming InsertRecord inserts a new record
|
|
form = forms.NewRecordUpsert(app, record)
|
|
}
|
|
|
|
form.LoadData(map[string]any{
|
|
"product_id": product.ID,
|
|
"active": product.Active,
|
|
"name": product.Name,
|
|
"description": coalesce(&product.Description, ""),
|
|
"metadata": product.Metadata,
|
|
})
|
|
|
|
// validate and submit (internally it calls app.Dao().SaveRecord(record) in a transaction)
|
|
if err := form.Submit(); err != nil {
|
|
return err
|
|
}
|
|
case "price.created", "price.updated":
|
|
var price stripe.Price
|
|
err := json.Unmarshal(event.Data.Raw, &price)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "failed to marshall the stripe event"})
|
|
}
|
|
// Then define and call a func to handle the successful payment intent.
|
|
|
|
collection, err := app.Dao().FindCollectionByNameOrId("price")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
existingRecord, err := app.Dao().FindFirstRecordByData("product", "price_id", price.ID)
|
|
record := models.NewRecord(collection)
|
|
|
|
var form *forms.RecordUpsert
|
|
|
|
if err == nil && existingRecord != nil {
|
|
// Existing record found, update it
|
|
// You might need to map data from product to your record
|
|
// Assuming UpdateRecord updates the existing record with new data
|
|
form = forms.NewRecordUpsert(app, existingRecord)
|
|
} else {
|
|
// Existing record not found, insert a new record
|
|
// You might need to map data from product to your record
|
|
// Assuming InsertRecord inserts a new record
|
|
form = forms.NewRecordUpsert(app, record)
|
|
}
|
|
|
|
data := map[string]any{
|
|
"price_id": price.ID,
|
|
"product_id": price.Product.ID,
|
|
"active": price.Active,
|
|
"currency": price.Currency,
|
|
"description": price.Nickname,
|
|
"type": price.Type,
|
|
"unit_amount": price.UnitAmount,
|
|
"metadata": price.Metadata,
|
|
}
|
|
// Check if Recurring is not nil before accessing its fields
|
|
if price.Recurring != nil {
|
|
data["interval"] = price.Recurring.Interval
|
|
data["interval_count"] = price.Recurring.IntervalCount
|
|
data["trial_period_days"] = price.Recurring.TrialPeriodDays
|
|
}
|
|
|
|
form.LoadData(data)
|
|
|
|
// validate and submit (internally it calls app.Dao().SaveRecord(record) in a transaction)
|
|
if err := form.Submit(); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "failed to submit to pocketbase"})
|
|
}
|
|
case "customer.subscription.created", "customer.subscription.updated", "customer.subscription.deleted":
|
|
var subscription stripe.Subscription
|
|
err := json.Unmarshal(event.Data.Raw, &subscription)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "failed to marshall the stripe event"})
|
|
}
|
|
//Get customer's UUID from mapping table in order to update users billing address and payment method
|
|
existingCustomer, err := app.Dao().FindFirstRecordByData("customer", "stripe_customer_id", subscription.Customer.ID)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "no customer"})
|
|
}
|
|
|
|
var uuid = existingCustomer.GetString("user_id")
|
|
collection, err := app.Dao().FindCollectionByNameOrId("subscription")
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "collection doesn't exist"})
|
|
}
|
|
|
|
//Update Subscription Details
|
|
existingRecord, err := app.Dao().FindFirstRecordByData("subscription", "subscription_id", subscription.ID)
|
|
record := models.NewRecord(collection)
|
|
|
|
var form *forms.RecordUpsert
|
|
|
|
if err == nil && existingRecord != nil {
|
|
// Existing record found, update it
|
|
// You might need to map data from product to your record
|
|
// Assuming UpdateRecord updates the existing record with new data
|
|
form = forms.NewRecordUpsert(app, existingRecord)
|
|
} else {
|
|
// Existing record not found, insert a new record
|
|
// You might need to map data from product to your record
|
|
// Assuming InsertRecord inserts a new record
|
|
form = forms.NewRecordUpsert(app, record)
|
|
}
|
|
|
|
form.LoadData(map[string]any{
|
|
"subscription_id": subscription.ID,
|
|
"user_id": uuid,
|
|
"metadata": subscription.Metadata,
|
|
"status": subscription.Status,
|
|
"price_id": subscription.Items.Data[0].Price.ID,
|
|
"quantity": subscription.Items.Data[0].Quantity,
|
|
"cancel_at_period_end": subscription.CancelAtPeriodEnd,
|
|
"cancel_at": int64ToISODate(subscription.CancelAt),
|
|
"canceled_at": int64ToISODate(subscription.CanceledAt),
|
|
"current_period_start": int64ToISODate(subscription.CurrentPeriodStart),
|
|
"current_period_end": int64ToISODate(subscription.CurrentPeriodEnd),
|
|
"created": int64ToISODate(subscription.Items.Data[0].Created),
|
|
"ended_at": int64ToISODate(subscription.EndedAt),
|
|
"trial_start": int64ToISODate(subscription.TrialStart),
|
|
"trial_end": int64ToISODate(subscription.TrialEnd),
|
|
})
|
|
if err := form.Submit(); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "couldn't submit subscription update"})
|
|
}
|
|
|
|
//Update User Details If Subscription Created
|
|
if event.Type == "customer.subscription.created" {
|
|
existingUserRecord, _ := app.Dao().FindFirstRecordByData("user", "id", uuid)
|
|
var userForm = forms.NewRecordUpsert(app, existingUserRecord)
|
|
|
|
userForm.LoadData(map[string]any{
|
|
"billing_address": subscription.DefaultPaymentMethod.Customer.Address,
|
|
"payment_method": subscription.DefaultPaymentMethod.Type,
|
|
})
|
|
// validate and submit (internally it calls app.Dao().SaveRecord(record) in a transaction)
|
|
if err := userForm.Submit(); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "couldn't submit user update"})
|
|
}
|
|
}
|
|
case "checkout.session.completed":
|
|
var session stripe.CheckoutSession
|
|
err := json.Unmarshal(event.Data.Raw, &session)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "failed to marshall the stripe event"})
|
|
}
|
|
if session.Mode == "subscription" {
|
|
//Get customer's UUID from mapping table in order to update users billing address and payment method
|
|
existingCustomer, err := app.Dao().FindFirstRecordByData("customer", "stripe_customer_id", session.Subscription.Customer.ID)
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "no customer"})
|
|
}
|
|
|
|
var uuid = existingCustomer.GetString("user_id")
|
|
collection, err := app.Dao().FindCollectionByNameOrId("subscription")
|
|
if err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "collection doesn't exist"})
|
|
}
|
|
|
|
//Update Subscription Details
|
|
existingRecord, err := app.Dao().FindFirstRecordByData("subscription", "subscription_id", session.Subscription.ID)
|
|
record := models.NewRecord(collection)
|
|
|
|
var form *forms.RecordUpsert
|
|
|
|
if err == nil && existingRecord != nil {
|
|
// Existing record found, update it
|
|
// You might need to map data from product to your record
|
|
// Assuming UpdateRecord updates the existing record with new data
|
|
form = forms.NewRecordUpsert(app, existingRecord)
|
|
} else {
|
|
// Existing record not found, insert a new record
|
|
// You might need to map data from product to your record
|
|
// Assuming InsertRecord inserts a new record
|
|
form = forms.NewRecordUpsert(app, record)
|
|
}
|
|
|
|
form.LoadData(map[string]any{
|
|
"subscription_id": session.Subscription.ID,
|
|
"user_id": uuid,
|
|
"metadata": session.Subscription.Metadata,
|
|
"status": session.Subscription.Status,
|
|
"price_id": session.Subscription.Items.Data[0].Price.ID,
|
|
"quantity": session.Subscription.Items.Data[0].Quantity,
|
|
"cancel_at_period_end": session.Subscription.CancelAtPeriodEnd,
|
|
"cancel_at": int64ToISODate(session.Subscription.CancelAt),
|
|
"canceled_at": int64ToISODate(session.Subscription.CanceledAt),
|
|
"current_period_start": int64ToISODate(session.Subscription.CurrentPeriodStart),
|
|
"current_period_end": int64ToISODate(session.Subscription.CurrentPeriodEnd),
|
|
"created": int64ToISODate(session.Subscription.Items.Data[0].Created),
|
|
"ended_at": int64ToISODate(session.Subscription.EndedAt),
|
|
"trial_start": int64ToISODate(session.Subscription.TrialStart),
|
|
"trial_end": int64ToISODate(session.Subscription.TrialEnd),
|
|
})
|
|
if err := form.Submit(); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "couldn't submit subscription update"})
|
|
}
|
|
|
|
//Update User Details
|
|
existingUserRecord, _ := app.Dao().FindFirstRecordByData("user", "id", uuid)
|
|
var userForm = forms.NewRecordUpsert(app, existingUserRecord)
|
|
|
|
userForm.LoadData(map[string]any{
|
|
"billing_address": session.Subscription.DefaultPaymentMethod.Customer.Address,
|
|
"payment_method": session.Subscription.DefaultPaymentMethod.Type,
|
|
})
|
|
|
|
// validate and submit (internally it calls app.Dao().SaveRecord(record) in a transaction)
|
|
if err := userForm.Submit(); err != nil {
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "couldn't submit user update"})
|
|
}
|
|
}
|
|
default:
|
|
return c.JSON(http.StatusBadRequest, map[string]string{"failure": "didn't receive a valid event"})
|
|
}
|
|
|
|
return c.JSON(http.StatusOK, map[string]interface{}{"success": "data was received"})
|
|
} /* optional middlewares */)
|
|
|
|
return nil
|
|
})
|
|
|
|
if err := app.Start(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|