package main import ( "encoding/json" "fmt" "github.com/stripe/stripe-go/v72" "github.com/stripe/stripe-go/v72/paymentintent" "io/ioutil" "log" "net/http" "os" "strconv" "strings" ) func getStripeKey() string { return os.Getenv("STRIPE_KEY") } func getStripePK() string { return os.Getenv("STRIPE_PK") } func getstripepaymentintentHandler(response http.ResponseWriter, request *http.Request) { name := getUserName(request) if name != "" { charge_data, ok := request.URL.Query()["charge_data"] if !ok || len(charge_data[0]) < 1 { log.Println("Url Param 'charge_data' is missing") fmt.Fprintf(response, "{ \"rc\": 1, \"msg\": \"charge_data must be specified in URL\" }") return } trackers := strings.Split(charge_data[0], ",") var abo_years = 0 var items []string amount := 0 for _, tracker := range trackers { items = strings.Split(tracker, ":") if len(items) >= 2 { abo_count, err := strconv.Atoi(items[1]) if err == nil { abo_years += abo_count amount += (abo_count * getYearlyAboCost(items[0])) } } } abo_amount := int64(amount) stripe.Key = getStripeKey() params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(abo_amount), Currency: stripe.String(string(stripe.CurrencyCHF)), ReceiptEmail: stripe.String(name), } params.AddMetadata("charge_data", charge_data[0]) params.AddMetadata("login_user", name) paymentintent, err := paymentintent.New(params) if err != nil { fmt.Fprintf(response, "{ \"rc\": 5, \"stripeclientsecret\": \"%s\" }\n", err) } else { fmt.Fprintf(response, "{ \"rc\": 0, \"stripeclientsecret\": \"%s\" }\n", paymentintent.ClientSecret) } } else { fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"Only available for logged in users\" }") } } func HandlePayment(user string, charge_data string, amount int64) { fmt.Printf("HandlePayment for %s (charge_data: %s, amount: %d)!\n", user, charge_data, amount) charge_data_email_text := fmt.Sprintf("%-30s %20s %10s\n", "Alias", "verlängern bis", "Betrag") charge_data_email_text = charge_data_email_text + strings.Repeat("-", 62) + "\n" for _, token := range strings.Split(charge_data, ",") { res := strings.Split(token, ":") if (len(res)) == 3 { deveui := res[0] years, _ := strconv.Atoi(res[1]) amount, _ := strconv.Atoi(res[2]) fmt.Printf("prolongActivation %s: %d\n", deveui, years) prolongActivation(deveui, years) line := fmt.Sprintf("%-30s %20s %10.2f\n", getDevAlias(deveui), getActiveUntil(deveui), float64(amount/100)) charge_data_email_text = charge_data_email_text + line } } charge_data_email_text = charge_data_email_text + strings.Repeat("-", 62) + "\n" charge_data_email_text = charge_data_email_text + fmt.Sprintf("%-30s %20s %10.2f\n", "Total CHF", "", float64(amount/100)) sendPaymentConfirmationEmail(user, charge_data_email_text, amount) } func stripeWebhookHandler(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) payload, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } event := stripe.Event{} if err := json.Unmarshal(payload, &event); err != nil { fmt.Fprintf(os.Stderr, "Failed to parse webhook body json: %v\n", err.Error()) w.WriteHeader(http.StatusBadRequest) return } // Unmarshal the event data into an appropriate struct depending on its Type switch event.Type { case "payment_intent.succeeded": var paymentIntent stripe.PaymentIntent err := json.Unmarshal(event.Data.Raw, &paymentIntent) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } fmt.Printf("PaymentIntent was successful (charge_data: %s, amount: %d)!\n", paymentIntent.Metadata["charge_data"], paymentIntent.Amount) HandlePayment(paymentIntent.ReceiptEmail, paymentIntent.Metadata["charge_data"], paymentIntent.Amount) // ... handle other event types default: fmt.Fprintf(os.Stderr, "Unexpected event type: %s\n", event.Type) w.WriteHeader(http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) }