Beispiel #1
0
func (sp *StripePayment) handle(w http.ResponseWriter, r *http.Request, session *lobster.Session, frameParams lobster.FrameParams) {
	if !lobster.AntifloodCheck(lobster.ExtractIP(r.RemoteAddr), "payment_stripe_handle", 5) {
		lobster.RedirectMessage(w, r, "/panel/billing", lobster.L.FormattedError("try_again_later"))
		return
	}
	lobster.AntifloodAction(lobster.ExtractIP(r.RemoteAddr), "payment_stripe_handle")

	stripeToken := r.PostFormValue("stripeToken")
	amount, amountErr := strconv.Atoi(r.PostFormValue("amount"))
	currency := r.PostFormValue("currency")

	if stripeToken == "" || amount <= 0 || amountErr != nil || currency == "" {
		lobster.RedirectMessage(w, r, "/panel/billing", lobster.L.FormatError(fmt.Errorf("credit card payment failed due to form submission error")))
		return
	}

	// duplicate amount range check here since user might tamper with the amount in the form
	cfg := lobster.GetConfig()
	if amount < int(cfg.Billing.DepositMinimum*100) || amount > int(cfg.Billing.DepositMaximum*100) {
		lobster.RedirectMessage(w, r, "/panel/billing", lobster.L.FormattedErrorf("amount_between", cfg.Billing.DepositMinimum, cfg.Billing.DepositMaximum))
		return
	}

	chargeParams := &stripe.ChargeParams{
		Amount:   uint64(amount),
		Currency: stripe.Currency(currency),
		Source:   &stripe.SourceParams{Token: stripeToken},
		Desc:     "Lobster credit",
	}
	charge, err := sp.client.Charges.New(chargeParams)

	if err != nil {
		emailParams := StripeErrorEmail{
			fmt.Sprintf("error creating charge for user %d", session.UserId),
			err,
		}
		lobster.MailWrap(-1, "stripeError", emailParams, false)
		lobster.RedirectMessage(w, r, "/panel/billing", lobster.L.FormatError(fmt.Errorf("credit card payment error; make sure that you have entered your credit card details correctly")))
		return
	} else if !charge.Paid {
		emailParams := StripeErrorEmail{
			fmt.Sprintf("created charge for user %d but paid is false", session.UserId),
			nil,
		}
		lobster.MailWrap(-1, "stripeError", emailParams, false)
		lobster.RedirectMessage(w, r, "/panel/billing", lobster.L.FormatError(fmt.Errorf("credit card payment error; make sure that you have entered your credit card details correctly")))
		return
	}

	transaction := charge.Tx
	lobster.TransactionAdd(
		session.UserId,
		"stripe",
		charge.ID,
		"Stripe payment: "+charge.ID,
		int64(charge.Amount)*lobster.BILLING_PRECISION/100,
		transaction.Fee*lobster.BILLING_PRECISION/100,
	)
	lobster.RedirectMessage(w, r, "/panel/billing", lobster.L.Success("payment_made"))
}
Beispiel #2
0
func (this *PaypalPayment) Payment(w http.ResponseWriter, r *http.Request, frameParams lobster.FrameParams, userId int, username string, amount float64) {
	cfg := lobster.GetConfig()
	frameParams.Scripts = append(frameParams.Scripts, "paypal")
	params := &PaypalTemplateParams{
		Frame:     frameParams,
		Business:  this.business,
		Amount:    amount,
		UserId:    userId,
		NotifyUrl: cfg.Default.UrlBase + PAYPAL_CALLBACK,
		ReturnUrl: this.returnUrl,
		Currency:  cfg.Billing.Currency,
	}
	lobster.RenderTemplate(w, "panel", "paypal", params)
}
Beispiel #3
0
func (sp *StripePayment) form(w http.ResponseWriter, r *http.Request, session *lobster.Session, frameParams lobster.FrameParams) {
	cents, _ := strconv.ParseInt(r.URL.Query().Get("cents"), 10, 64)
	user := lobster.UserDetails(session.UserId)
	cfg := lobster.GetConfig()
	params := &StripeTemplateParams{
		Frame:    frameParams,
		Token:    lobster.CSRFGenerate(session),
		Key:      sp.publishableKey,
		Cents:    cents,
		Currency: cfg.Billing.Currency,
		Amount:   float64(cents) / 100,
		Email:    user.Email,
	}
	lobster.RenderTemplate(w, "panel", "stripe", params)
}
Beispiel #4
0
func (this *CoinbasePayment) callback(w http.ResponseWriter, r *http.Request) {
	cfg := lobster.GetConfig()

	requestBytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		lobster.ReportError(err, "coinbase callback read error", fmt.Sprintf("ip: %s", r.RemoteAddr))
		w.WriteHeader(500)
		return
	}

	var data CoinbaseData
	err = json.Unmarshal(requestBytes, &data)
	if err != nil {
		lobster.ReportError(err, "coinbase callback decoding error", fmt.Sprintf("ip: %s; raw request: %s", r.RemoteAddr, requestBytes))
		w.WriteHeader(400)
		return
	}

	if data.Order.TotalNative.CurrencyIso != cfg.Billing.Currency {
		lobster.ReportError(fmt.Errorf("invalid currency %s", data.Order.TotalNative.CurrencyIso), "coinbase callback error", fmt.Sprintf("ip: %s; raw request: %s", r.RemoteAddr, requestBytes))
		w.WriteHeader(200)
		return
	} else if !strings.HasPrefix(data.Order.Custom, "lobster") {
		lobster.ReportError(fmt.Errorf("invalid payment with custom=%s", data.Order.Custom), "coinbase callback error", fmt.Sprintf("ip: %s; raw request: %s", r.RemoteAddr, requestBytes))
		w.WriteHeader(200)
		return
	}

	userIdStr := strings.Split(data.Order.Custom, "lobster")[1]
	userId, err := strconv.Atoi(userIdStr)
	if err != nil {
		lobster.ReportError(fmt.Errorf("invalid payment with custom=%s", data.Order.Custom), "coinbase callback error", fmt.Sprintf("ip: %s; raw request: %s", r.RemoteAddr, requestBytes))
		w.WriteHeader(200)
		return
	}

	if data.Order.Status == "completed" {
		lobster.TransactionAdd(userId, "coinbase", data.Order.Id, "Bitcoin transaction: "+data.Order.Transaction.Id, int64(data.Order.TotalNative.Cents)*lobster.BILLING_PRECISION/100, 0)
	} else if data.Order.Status == "mispaid" {
		lobster.MailWrap(-1, "coinbaseMispaid", CoinbaseMispaidEmail{OrderId: data.Order.Id}, false)
	}

	w.WriteHeader(200)
}
Beispiel #5
0
func Setup() {
	decoder = lobster.GetDecoder()
	L = lobster.L
	cfg = lobster.GetConfig()
	db = lobster.GetDatabase()

	lobster.RegisterPanelHandler("/panel/support", panelSupport, false)
	lobster.RegisterPanelHandler("/panel/support/open", panelSupportOpen, false)
	lobster.RegisterPanelHandler("/panel/support/{id:[0-9]+}", panelSupportTicket, false)
	lobster.RegisterPanelHandler("/panel/support/{id:[0-9]+}/reply", panelSupportTicketReply, true)
	lobster.RegisterPanelHandler("/panel/support/{id:[0-9]+}/close", panelSupportTicketClose, true)

	lobster.RegisterAdminHandler("/admin/support", adminSupport, false)
	lobster.RegisterAdminHandler("/admin/support/open/{id:[0-9]+}", adminSupportOpen, false)
	lobster.RegisterAdminHandler("/admin/support/{id:[0-9]+}", adminSupportTicket, false)
	lobster.RegisterAdminHandler("/admin/support/{id:[0-9]+}/reply", adminSupportTicketReply, true)
	lobster.RegisterAdminHandler("/admin/support/{id:[0-9]+}/close", adminSupportTicketClose, true)

	lobster.RegisterPanelWidget("Support", lobster.PanelWidgetFunc(func(session *lobster.Session) interface{} {
		return TicketListActive(session.UserId)
	}))
}
Beispiel #6
0
func (this *CoinbasePayment) Payment(w http.ResponseWriter, r *http.Request, frameParams lobster.FrameParams, userId int, username string, amount float64) {
	cfg := lobster.GetConfig()
	if cfg.Default.Debug {
		log.Printf("Creating Coinbase button for %s (id=%d) with amount $%.2f", username, userId, amount)
	}
	params := &coinbase.Button{
		Name:             lobster.L.T("credit_for_username", username),
		PriceString:      fmt.Sprintf("%.2f", amount),
		PriceCurrencyIso: cfg.Billing.Currency,
		Custom:           fmt.Sprintf("lobster%d", userId),
		Description:      fmt.Sprintf("Credit %s", lobster.L.T("currency_format", fmt.Sprintf("%.2f", amount))),
		Type:             "buy_now",
		Style:            "buy_now_large",
		CallbackUrl:      cfg.Default.UrlBase + "/coinbase_callback_" + this.callbackSecret,
	}
	cli := coinbase.ApiKeyClient(this.apiKey, this.apiSecret)
	button, err := cli.CreateButton(params)
	if err != nil {
		lobster.ReportError(err, "failed to create Coinbase button", fmt.Sprintf("username=%s, amount=%.2f", username, amount))
		lobster.RedirectMessage(w, r, "/panel/billing", lobster.L.FormattedError("try_again_later"))
		return
	}
	http.Redirect(w, r, "https://coinbase.com/checkouts/"+button.Code, 303)
}
Beispiel #7
0
func (this *PaypalPayment) Callback(w http.ResponseWriter, r *http.Request) {
	cfg := lobster.GetConfig()
	requestBytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		lobster.ReportError(err, "paypal callback read error", fmt.Sprintf("ip: %s", r.RemoteAddr))
		w.WriteHeader(403)
		return
	}

	// decode the post data manually since there may be encoding issues
	requestParts := strings.Split(string(requestBytes), "&")
	myPost := make(map[string]string)
	for _, part := range requestParts {
		keyval := strings.Split(part, "=")
		if len(keyval) == 2 {
			myPost[keyval[0]], _ = url.QueryUnescape(keyval[1])
		}
	}

	// post back to Paypal system to validate the IPN data
	validateReq := "cmd=_notify-validate"
	for key, value := range myPost {
		validateReq += fmt.Sprintf("&%s=%s", key, url.QueryEscape(value))
	}

	resp, err := http.Post(PAYPAL_URL, "application/x-www-form-urlencoded", bytes.NewBufferString(validateReq))
	if err != nil {
		lobster.ReportError(err, "paypal callback validation error", fmt.Sprintf("ip: %s; requestmap: %v", r.RemoteAddr, myPost))
		w.WriteHeader(403)
		return
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		lobster.ReportError(err, "paypal callback validation error", fmt.Sprintf("ip: %s; requestmap: %v", r.RemoteAddr, myPost))
		w.WriteHeader(403)
		return
	}

	if string(body) != "VERIFIED" || myPost["payment_status"] == "" || myPost["mc_gross"] == "" || myPost["mc_currency"] == "" || myPost["txn_id"] == "" || myPost["receiver_email"] == "" || myPost["payment_status"] == "" || myPost["payer_email"] == "" || myPost["custom"] == "" {
		lobster.ReportError(errors.New("missing field or not verified"), "paypal callback bad input or validation", fmt.Sprintf("ip: %s; verify body: %s; requestmap: %v", r.RemoteAddr, body, myPost))
		w.WriteHeader(403)
		return
	}

	w.WriteHeader(200)

	if myPost["payment_status"] != "Completed" {
		return
	} else if !strings.HasPrefix(myPost["custom"], "lobster") {
		lobster.ReportError(fmt.Errorf("invalid payment with custom=%s", myPost["custom"]), "paypal callback error", fmt.Sprintf("ip: %s; requestmap: %v", r.RemoteAddr, myPost))
		return
	} else if strings.TrimSpace(strings.ToLower(myPost["receiver_email"])) != strings.TrimSpace(strings.ToLower(this.business)) {
		lobster.ReportError(fmt.Errorf("invalid payment with receiver_email=%s", myPost["receiver_email"]), "paypal callback error", fmt.Sprintf("ip: %s; requestmap: %v", r.RemoteAddr, myPost))
		return
	} else if myPost["mc_currency"] != cfg.Billing.Currency {
		lobster.ReportError(fmt.Errorf("invalid payment with currency=%s", myPost["mc_currency"]), "paypal callback error", fmt.Sprintf("ip: %s; requestmap: %v", r.RemoteAddr, myPost))
		return
	}

	paymentAmount, _ := strconv.ParseFloat(myPost["mc_gross"], 64)
	transactionId := myPost["txn_id"]
	userIdStr := strings.Split(myPost["custom"], "lobster")[1]
	userId, err := strconv.Atoi(userIdStr)
	if err != nil {
		lobster.ReportError(fmt.Errorf("invalid payment with custom=%s", myPost["custom"]), "paypal callback error", fmt.Sprintf("ip: %s; requestmap: %v", r.RemoteAddr, myPost))
		return
	}

	lobster.TransactionAdd(userId, "paypal", transactionId, "Transaction "+transactionId, int64(paymentAmount*lobster.BILLING_PRECISION), 0)
}