package main import ( "encoding/json" "fmt" "github.com/stripe/stripe-go/v74" "github.com/stripe/stripe-go/v74/customer" "github.com/stripe/stripe-go/v74/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 getCustomerid(name string) string { // if customer does not already exist, create it... var cid = "" params := &stripe.CustomerSearchParams{} params.Query = *stripe.String("name:'" + name + "'") customers := customer.Search(params) for customers.Next() { fmt.Printf("%s\n", customers.Current().(*stripe.Customer).ID) cid = customers.Current().(*stripe.Customer).ID } if cid == "" { // create new customer paramsc := &stripe.CustomerParams{ Name: stripe.String(name), } customer, err := customer.New(paramsc) if err != nil { log.Println("Error Creating Customer: " + name) } cid = customer.ID } return cid } 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() // if customer does not already exist, create it... customerid := getCustomerid(name) // define payment params := &stripe.PaymentIntentParams{ Customer: stripe.String(customerid), Amount: stripe.Int64(abo_amount), Currency: stripe.String(string(stripe.CurrencyCHF)), } 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) }