go fmt; email message after payment

This commit is contained in:
Joerg Lehmann 2020-04-09 14:41:41 +02:00
parent 2cac4d56e2
commit 5548949e9d
9 changed files with 791 additions and 795 deletions

View File

@ -1,11 +1,11 @@
package main
import (
"github.com/gorilla/securecookie"
"net/http"
"fmt"
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/gorilla/securecookie"
"net/http"
)
// cookie handling
@ -67,34 +67,33 @@ func loginHandler(response http.ResponseWriter, request *http.Request) {
pass := request.FormValue("password")
redirectTarget := "/invalid_login.html"
// .. check credentials ..
if checkLoginCredentials(name,pass) {
if checkLoginCredentials(name, pass) {
redirectTarget = "/scales.html"
logit(fmt.Sprintf("loginHandler: successful login for User %s",name))
logit(fmt.Sprintf("loginHandler: successful login for User %s", name))
setSession(name, response)
updateLoginTime(name)
} else {
logit(fmt.Sprintf("loginHandler: invalid login for User %s",name))
logit(fmt.Sprintf("loginHandler: invalid login for User %s", name))
}
http.Redirect(response, request, redirectTarget, 302)
}
// resetPassword handler
func resetPasswordHandler(response http.ResponseWriter, request *http.Request) {
name := request.FormValue("email")
pass := request.FormValue("password")
redirectTarget := "/"
logit(fmt.Sprintf("resetPasswordHandler: request for User %s",name))
logit(fmt.Sprintf("resetPasswordHandler: request for User %s", name))
if name != "" && pass != "" {
if checkUserAvailable(name) {
http.Redirect(response, request, "/user_does_not_exist.html", 302)
} else {
updateUser(name,pass)
updateUser(name, pass)
http.Redirect(response, request, redirectTarget, 302)
}
}
http.Redirect(response, request, "/error_reset_password.html",302)
http.Redirect(response, request, "/error_reset_password.html", 302)
}
// setPassword handler
@ -106,7 +105,7 @@ func setPasswordHandler(response http.ResponseWriter, request *http.Request) {
if checkUserAvailable(name) {
http.Redirect(response, request, "/user_does_not_exist.html", 302)
} else {
updateUser(name,pass)
updateUser(name, pass)
}
}
}
@ -122,7 +121,7 @@ func logoutHandler(response http.ResponseWriter, request *http.Request) {
func confirmHandler(response http.ResponseWriter, request *http.Request) {
confirm_id := request.URL.Query().Get("id")
logit(fmt.Sprintf("Confirm ID: %s\n",confirm_id))
logit(fmt.Sprintf("Confirm ID: %s\n", confirm_id))
confirmUser(confirm_id)
http.Redirect(response, request, "/", 302)
}

View File

@ -6,9 +6,9 @@ import (
// Contains tells whether a contains x.
func Contains(a []string, x string) bool {
log.Println("Search for: "+x)
log.Println("Search for: " + x)
for _, n := range a {
log.Println("Piece of Array: "+n)
log.Println("Piece of Array: " + n)
if x == n {
return true
}

View File

@ -1,12 +1,12 @@
package main
import (
"log"
"bytes"
"log"
"net/smtp"
)
func sendEmail(username,confirm_id string) {
func sendEmail(username, confirm_id string) {
c, err := smtp.Dial("127.0.0.1:25")
if err != nil {
log.Fatal(err)
@ -43,7 +43,7 @@ mini-beieli.ch`
}
}
func sendPaymentConfirmationEmail(username,charge_data string, amount int64) {
func sendPaymentConfirmationEmail(username, charge_data string, amount int64) {
c, err := smtp.Dial("127.0.0.1:25")
if err != nil {
log.Fatal(err)

View File

@ -9,7 +9,7 @@ import (
)
func serveTemplate(w http.ResponseWriter, r *http.Request) {
logit("Called URL: "+r.URL.Path)
logit("Called URL: " + r.URL.Path)
// wennn kein File angegeben ist: index.html
if r.URL.Path == "/" {
r.URL.Path = "/index.html"
@ -44,7 +44,7 @@ func serveTemplate(w http.ResponseWriter, r *http.Request) {
query_values := r.URL.Query()
if (r.URL.Path == "/scales.html") {
if r.URL.Path == "/scales.html" {
// wir holen noch die letzten Metriken
for _, v := range scales {
last_metric := getLastMetrics(v)
@ -58,7 +58,7 @@ func serveTemplate(w http.ResponseWriter, r *http.Request) {
Scales []string
LastMetrics []OneMetric
QueryValues map[string][]string
} {
}{
userName,
datetimestring,
scales,

View File

@ -1,15 +1,15 @@
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"io/ioutil"
"bufio"
"strings"
"strconv"
"strings"
"time"
)
type OneMetric struct {
@ -28,7 +28,6 @@ type OneMetric struct {
DaysUntilDeactivated int // berechneter Wert
}
// metrics handler
func metricsHandler(response http.ResponseWriter, request *http.Request) {
@ -53,7 +52,7 @@ func metricsHandler(response http.ResponseWriter, request *http.Request) {
// we only want the single item.
mydeveui := deveui[0]
if !(Contains(getMyDevs(name),mydeveui)) {
if !(Contains(getMyDevs(name), mydeveui)) {
log.Println("specified 'deveui' does not belong to this user")
fmt.Fprintf(response, "{ \"msg\": \"specified deveui does not belong to this user\" }")
return
@ -91,7 +90,7 @@ func metricsHandler(response http.ResponseWriter, request *http.Request) {
var mystart string
if !ok || len(start[0]) < 1 {
log.Println("Url Param 'start' is missing, set it to stop minus one day")
t := stopDate.AddDate(0,0,-1)
t := stopDate.AddDate(0, 0, -1)
mystart = t.Format("2006-01-02T15:04:05Z")
}
@ -100,7 +99,7 @@ func metricsHandler(response http.ResponseWriter, request *http.Request) {
}
url := "http://localhost:9999/api/v2/query?org=beieliorg"
data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") |> range(start: %s, stop: %s) |> filter(fn: (r) => r._measurement == "measurement") |> filter(fn: (r) => r._field == "%s") |> filter(fn: (r) => r.deveui == "%s")`,mystart,mystop,property[0],mydeveui))
data := []byte(fmt.Sprintf(`from(bucket:"beielibucket") |> range(start: %s, stop: %s) |> filter(fn: (r) => r._measurement == "measurement") |> filter(fn: (r) => r._field == "%s") |> filter(fn: (r) => r.deveui == "%s")`, mystart, mystop, property[0], mydeveui))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil {
@ -130,27 +129,27 @@ func metricsHandler(response http.ResponseWriter, request *http.Request) {
log.Fatal("Error reading body. ", err)
}
fmt.Fprintf(response,"[\n")
fmt.Fprintf(response, "[\n")
scanner := bufio.NewScanner(strings.NewReader(string(body)))
first := true
for scanner.Scan() {
s := strings.Split(scanner.Text(),",")
if ((len(s) >= 7) && !(strings.HasPrefix(s[5],"_"))) {
t,err := time.Parse(time.RFC3339,s[5])
s := strings.Split(scanner.Text(), ",")
if (len(s) >= 7) && !(strings.HasPrefix(s[5], "_")) {
t, err := time.Parse(time.RFC3339, s[5])
if err != nil {
continue
}
a := t.Unix()
b := s[6]
if !(first) {
fmt.Fprintf(response,",")
fmt.Fprintf(response, ",")
} else {
first = false
}
fmt.Fprintf(response,"[%d000,%s]\n",a,b)
fmt.Fprintf(response, "[%d000,%s]\n", a, b)
}
}
fmt.Fprintf(response,"]\n")
fmt.Fprintf(response, "]\n")
} else {
fmt.Fprintf(response, "{ \"msg\": \"Only available for logged in users\" }")
@ -172,7 +171,7 @@ func lastmetricsHandler(response http.ResponseWriter, request *http.Request) {
// we only want the single item.
mydeveui := deveui[0]
if !(Contains(getMyDevs(name),mydeveui)) {
if !(Contains(getMyDevs(name), mydeveui)) {
log.Println("specified 'deveui' does not belong to this user")
fmt.Fprintf(response, "{ \"msg\": \"specified deveui does not belong to this user\" }")
return
@ -186,7 +185,7 @@ func lastmetricsHandler(response http.ResponseWriter, request *http.Request) {
|> range(start:-365d)
|> filter(fn: (r) => r.deveui == "%s")
|> filter(fn: (r) => r._field == "t" or r._field == "h" or r._field == "w" or r._field == "p" or r._field == "vp")
|> last() |> yield(name: "last")`,mydeveui))
|> last() |> yield(name: "last")`, mydeveui))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil {
@ -226,9 +225,9 @@ func lastmetricsHandler(response http.ResponseWriter, request *http.Request) {
vp := ""
location, err := time.LoadLocation("Europe/Zurich")
for scanner.Scan() {
s := strings.Split(scanner.Text(),",")
if ((len(s) >= 7) && !(strings.HasPrefix(s[5],"_"))) {
mytime,err := time.Parse(time.RFC3339,s[5])
s := strings.Split(scanner.Text(), ",")
if (len(s) >= 7) && !(strings.HasPrefix(s[5], "_")) {
mytime, err := time.Parse(time.RFC3339, s[5])
if err != nil {
continue
}
@ -248,14 +247,14 @@ func lastmetricsHandler(response http.ResponseWriter, request *http.Request) {
}
}
}
fmt.Fprintf(response,`{
fmt.Fprintf(response, `{
"ts": "%s",
"t": "%s",
"h": "%s",
"w": "%s",
"p": "%s",
"vp": "%s"
}`,ts,t,h,w,p,vp)
}`, ts, t, h, w, p, vp)
} else {
fmt.Fprintf(response, "{ \"msg\": \"Only available for logged in users\" }")
@ -283,7 +282,7 @@ func getLastMetrics(deveui string) OneMetric {
|> range(start:-365d)
|> filter(fn: (r) => r.deveui == "%s")
|> filter(fn: (r) => r._field == "t" or r._field == "h" or r._field == "w" or r._field == "p" or r._field == "vp")
|> last() |> yield(name: "last")`,deveui))
|> last() |> yield(name: "last")`, deveui))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil {
@ -317,9 +316,9 @@ func getLastMetrics(deveui string) OneMetric {
scanner := bufio.NewScanner(strings.NewReader(string(body)))
location, err := time.LoadLocation("Europe/Zurich")
for scanner.Scan() {
s := strings.Split(scanner.Text(),",")
if ((len(s) >= 7) && !(strings.HasPrefix(s[5],"_"))) {
mytime,err := time.Parse(time.RFC3339,s[5])
s := strings.Split(scanner.Text(), ",")
if (len(s) >= 7) && !(strings.HasPrefix(s[5], "_")) {
mytime, err := time.Parse(time.RFC3339, s[5])
if err != nil {
continue
}
@ -333,8 +332,8 @@ func getLastMetrics(deveui string) OneMetric {
} else if field == "w" {
res.Weight = value
i, err := strconv.Atoi(value)
if (err == nil) {
res.Weight_kg = fmt.Sprintf("%.2f",float64(i) / 1000.0)
if err == nil {
res.Weight_kg = fmt.Sprintf("%.2f", float64(i)/1000.0)
} else {
res.Weight_kg = "ERR"
}

View File

@ -1,13 +1,13 @@
package main
import (
"time"
"strings"
"fmt"
"log"
"crypto/rand"
"golang.org/x/crypto/bcrypt"
"fmt"
"github.com/gomodule/redigo/redis"
"golang.org/x/crypto/bcrypt"
"log"
"strings"
"time"
)
var globalPool *redis.Pool
@ -44,7 +44,7 @@ func ping(c redis.Conn) error {
return err
}
logit("PING Response = "+s)
logit("PING Response = " + s)
// Output: PONG
return nil
@ -73,7 +73,7 @@ func initDB() {
// Wir legen einen initialen Admin User an, falls es diesen noch nicht gibt
if checkUserAvailable("joerg.lehmann@nbit.ch") {
insertUser("joerg.lehmann@nbit.ch","changeme123","Y");
insertUser("joerg.lehmann@nbit.ch", "changeme123", "Y")
}
}
@ -82,7 +82,6 @@ func closeDB() {
globalPool.Close()
}
func updateScaleSettings(scaleSettings Dev) error {
conn := globalPool.Get()
defer conn.Close()
@ -96,15 +95,14 @@ func updateScaleSettings(scaleSettings Dev) error {
return nil
}
func checkUserAvailable(username string) bool {
logit("checkUserAvailable: User: "+username)
logit("checkUserAvailable: User: " + username)
conn := globalPool.Get()
defer conn.Close()
_, err := redis.String(conn.Do("GET", userPrefix+username))
if (err == redis.ErrNil) {
logit("User does not exist and is therefore available:"+username)
if err == redis.ErrNil {
logit("User does not exist and is therefore available:" + username)
return true
} else if err != nil {
logit("checkUserAvailable: Error to query Key Value Store")
@ -120,14 +118,13 @@ func getMyDevs(username string) []string {
return res
}
conn := globalPool.Get()
defer conn.Close()
logit("getMyDevs: User: "+username)
logit("getMyDevs: User: " + username)
mydevs, err := redis.String(conn.Do("HGET", userPrefix+username, "my_devs"))
if err == nil {
logit("getMyDevs: mydevs: "+mydevs)
logit("getMyDevs: mydevs: " + mydevs)
res = strings.Split(mydevs, ",")
} else {
log.Print(err)
@ -143,14 +140,13 @@ func getDevAlias(deveui string) string {
return res
}
conn := globalPool.Get()
defer conn.Close()
logit("getDevAlias: Deveui: "+deveui)
logit("getDevAlias: Deveui: " + deveui)
alias, err := redis.String(conn.Do("HGET", devPrefix+deveui, "alias"))
if err == nil {
logit("getDevAlias: alias: "+alias)
logit("getDevAlias: alias: " + alias)
res = alias
} else {
log.Print(err)
@ -166,14 +162,13 @@ func getDevAlarmactive(deveui string) string {
return res
}
conn := globalPool.Get()
defer conn.Close()
logit("getDevAlarmactive: Deveui: "+deveui)
logit("getDevAlarmactive: Deveui: " + deveui)
alarmactive, err := redis.String(conn.Do("HGET", devPrefix+deveui, "alarmactive"))
if err == nil {
logit("getDevAlarmactive: alarmactive: "+alarmactive)
logit("getDevAlarmactive: alarmactive: " + alarmactive)
res = alarmactive
} else {
log.Print(err)
@ -189,14 +184,13 @@ func getDevSmsnumber(deveui string) string {
return res
}
conn := globalPool.Get()
defer conn.Close()
logit("getDevSmsnumber: Deveui: "+deveui)
logit("getDevSmsnumber: Deveui: " + deveui)
smsnumber, err := redis.String(conn.Do("HGET", devPrefix+deveui, "smsnumber"))
if err == nil {
logit("getDevAlarmactive: smsnumber: "+smsnumber)
logit("getDevAlarmactive: smsnumber: " + smsnumber)
res = smsnumber
} else {
log.Print(err)
@ -212,14 +206,13 @@ func getActiveUntil(deveui string) string {
return res
}
conn := globalPool.Get()
defer conn.Close()
logit("getActiveUntil: Deveui: "+deveui)
logit("getActiveUntil: Deveui: " + deveui)
activeuntil, err := redis.String(conn.Do("HGET", devPrefix+deveui, "active_until"))
if err == nil {
logit("getActiveUntil: activeuntil: "+activeuntil)
logit("getActiveUntil: activeuntil: " + activeuntil)
res = activeuntil
} else {
log.Print(err)
@ -229,7 +222,7 @@ func getActiveUntil(deveui string) string {
}
func AboExpired(deveui string) bool {
active_until := getActiveUntil(deveui);
active_until := getActiveUntil(deveui)
layout := "02.01.2006"
t, _ := time.Parse(layout, active_until)
@ -243,7 +236,7 @@ func prolongActivation(deveui string, years int) (string, error) {
active_until_old, err := redis.String(conn.Do("HGET", devPrefix+deveui, "active_until"))
if err == nil {
logit("prolongActivation: active_until: " +active_until_old)
logit("prolongActivation: active_until: " + active_until_old)
} else {
log.Print(err)
}
@ -267,7 +260,7 @@ func prolongActivation(deveui string, years int) (string, error) {
// SET object
_, err1 := conn.Do("HMSET", devPrefix+deveui, "active_until", active_until_new)
if err1 != nil {
return "",err1
return "", err1
}
return active_until_new, nil
@ -278,70 +271,70 @@ func randString(n int) string {
var bytes = make([]byte, n)
rand.Read(bytes)
for i, b := range bytes {
bytes[i] = alphanum[b % byte(len(alphanum))]
bytes[i] = alphanum[b%byte(len(alphanum))]
}
return string(bytes)
}
func insertUser(username,password,is_admin string) {
func insertUser(username, password, is_admin string) {
conn := globalPool.Get()
defer conn.Close()
logit("insertUser: "+username)
logit("insertUser: " + username)
pwd := []byte(password)
hashedPassword,err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
hashedPassword, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
if err != nil {
logit("insertUser: Error with bcrypt.GenerateFromPassword, User: "+username)
logit("insertUser: Error with bcrypt.GenerateFromPassword, User: " + username)
return
}
confirm_id := ""
_, err = conn.Do("HMSET", userPrefix+username, "password", string(hashedPassword), "new_password", string(hashedPassword), "confirm_id", confirm_id, "last_login", "", "my_devs","")
_, err = conn.Do("HMSET", userPrefix+username, "password", string(hashedPassword), "new_password", string(hashedPassword), "confirm_id", confirm_id, "last_login", "", "my_devs", "")
if err != nil {
logit("insertUser: Error inserting User: "+username)
logit("insertUser: Error inserting User: " + username)
return
}
}
func updateUser(username,password string) {
func updateUser(username, password string) {
conn := globalPool.Get()
defer conn.Close()
logit("updateUser: "+username)
logit("updateUser: " + username)
pwd := []byte(password)
hashedPassword,err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
hashedPassword, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
if err != nil {
logit("updateUser: Error with bcrypt.GenerateFromPassword, User: "+username)
logit("updateUser: Error with bcrypt.GenerateFromPassword, User: " + username)
return
}
confirm_id := randString(30)
_, err = conn.Do("HMSET", userPrefix+username, "new_password", string(hashedPassword), "confirm_id", confirm_id)
if err != nil {
logit("updateUser: Error updateing User: "+username)
logit("updateUser: Error updateing User: " + username)
return
}
_, err = conn.Do("SET", confirmPrefix+confirm_id,username)
_, err = conn.Do("SET", confirmPrefix+confirm_id, username)
if err != nil {
logit("updateUser: Error inserting confirm_id: "+confirm_id+": "+username)
logit("updateUser: Error inserting confirm_id: " + confirm_id + ": " + username)
return
}
sendEmail(username,confirm_id)
sendEmail(username, confirm_id)
}
func checkLoginCredentials(username,password string) bool {
func checkLoginCredentials(username, password string) bool {
conn := globalPool.Get()
defer conn.Close()
logit("checkLoginCredentials: called with username,password: "+username+","+password)
logit("checkLoginCredentials: called with username,password: " + username + "," + password)
pwd, err := redis.String(conn.Do("HGET", userPrefix+username, "password"))
if err == nil {
logit("checkLoginCredentials: pwd: "+pwd+" CMD: HGET "+userPrefix+username+userPrefix+username+" confirm_id")
logit("checkLoginCredentials: pwd: " + pwd + " CMD: HGET " + userPrefix + username + userPrefix + username + " confirm_id")
cid, err := redis.String(conn.Do("HGET", userPrefix+username, "confirm_id"))
if err == nil {
logit("checkLoginCredentials: cid: "+cid)
logit("checkLoginCredentials: cid: " + cid)
if !(err != nil && cid != "") {
logit("checkLoginCredentials: pwd: "+pwd)
logit("checkLoginCredentials: pwd: " + pwd)
if err != nil {
return false
}
@ -363,7 +356,7 @@ func updateLoginTime(username string) {
_, err := conn.Do("HSET", userPrefix+username, "last_login", time.Now().UTC().Format("2006-01-02 15:04:05"))
if err != nil {
logit("updateUser: Error updateing User: "+username)
logit("updateUser: Error updateing User: " + username)
return
}
}
@ -374,23 +367,22 @@ func confirmUser(confirm_id string) {
u, err := redis.String(conn.Do("GET", confirmPrefix+confirm_id))
if err != nil {
logit("confirmUser: Error with searching confirm_id: "+confirm_id)
logit("confirmUser: Error with searching confirm_id: " + confirm_id)
return
}
new_password, err := redis.String(conn.Do("HGET", userPrefix+u, "new_password"))
if err != nil {
logit("confirmUser: Error with getting new_password: "+u)
logit("confirmUser: Error with getting new_password: " + u)
return
}
_, err = conn.Do("HMSET", userPrefix+u, "confirm_id", "", "password", new_password)
if err != nil {
logit("confirmUser: Error updateing User: "+u)
logit("confirmUser: Error updateing User: " + u)
return
}
_, err = conn.Do("DEL", confirmPrefix+confirm_id)
if err != nil {
logit("confirmUser: Error deleting confirm_id: "+confirm_id)
logit("confirmUser: Error deleting confirm_id: " + confirm_id)
return
}
}

View File

@ -3,8 +3,8 @@ package main
import (
"fmt"
"log"
"regexp"
"net/http"
"regexp"
)
// scales handler
@ -24,13 +24,13 @@ func save_scale_settingsHandler(response http.ResponseWriter, request *http.Requ
// we only want the single item.
mydeveui := deveui[0]
if (len(mydeveui) != 16) {
if len(mydeveui) != 16 {
log.Println("specified 'deveui' has invalid length")
fmt.Fprintf(response, "{ \"rc\": 8, \"msg\": \"specified deveui has invalid length\" }")
return
}
if !(Contains(getMyDevs(name),mydeveui)) {
if !(Contains(getMyDevs(name), mydeveui)) {
log.Println("specified 'deveui' does not belong to this user")
fmt.Fprintf(response, "{ \"rc\": 2, \"msg\": \"specified deveui does not belong to this user\" }")
return

View File

@ -1,16 +1,16 @@
package main
import (
"fmt"
"log"
"os"
"io/ioutil"
"encoding/json"
"net/http"
"strings"
"strconv"
"fmt"
"github.com/stripe/stripe-go"
"github.com/stripe/stripe-go/paymentintent"
"io/ioutil"
"log"
"net/http"
"os"
"strconv"
"strings"
)
func getStripeKey() string {
@ -28,13 +28,13 @@ func getstripepaymentintentHandler(response http.ResponseWriter, request *http.R
return
}
scales := strings.Split(charge_data[0],",")
scales := strings.Split(charge_data[0], ",")
var abo_years = 0
var items []string
for _,scale := range scales {
items = strings.Split(scale,":")
if (len(items) == 2) {
for _, scale := range scales {
items = strings.Split(scale, ":")
if len(items) == 2 {
abo_count, err := strconv.Atoi(items[1])
if err == nil {
abo_years += abo_count
@ -54,9 +54,9 @@ func getstripepaymentintentHandler(response http.ResponseWriter, request *http.R
paymentintent, err := paymentintent.New(params)
if err != nil {
fmt.Fprintf(response,"{ \"rc\": 5, \"stripeclientsecret\": \"%s\" }\n",err)
fmt.Fprintf(response, "{ \"rc\": 5, \"stripeclientsecret\": \"%s\" }\n", err)
} else {
fmt.Fprintf(response,"{ \"rc\": 0, \"stripeclientsecret\": \"%s\" }\n",paymentintent.ClientSecret)
fmt.Fprintf(response, "{ \"rc\": 0, \"stripeclientsecret\": \"%s\" }\n", paymentintent.ClientSecret)
}
} else {
@ -66,16 +66,22 @@ func getstripepaymentintentHandler(response http.ResponseWriter, request *http.R
func HandlePayment(user string, charge_data string, amount int64) {
fmt.Printf("HandlePayment for %s (charge_data: %s, amount: %d)!\n", user, charge_data, amount)
for _, token := range strings.Split(charge_data,",") {
res := strings.Split(token,":")
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)) == 2 {
deveui := res[0]
years, _ := strconv.Atoi(res[1])
fmt.Printf("prolongActivation %s: %d\n", deveui, years)
prolongActivation(deveui, years)
line := fmt.Sprintf("%-30s %20s %10.2f\n", getDevAlias(deveui), getActiveUntil(deveui), float64(24*years))
charge_data_email_text = charge_data_email_text + line
}
}
sendPaymentConfirmationEmail(user,charge_data,amount)
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) {