Код:
package main
import (
"encoding/json"
"fmt"
"html/template"
"io/ioutil"
"log"
"net/http"
"github.com/gorilla/mux"
"donateform/DashPaymentAPI"
)
const (
LISTENIP = "127.0.0.1"
PORT = "8080"
SUCCESS_URL = "https://example.com/success"
CANCEL_URL = "https://example.com/cancel"
WEBHOOK_URL = "https://example.com/webhook"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/", createPaymentHandler).Methods("GET", "POST")
r.HandleFunc("/success", showSuccessHandler).Methods("GET")
r.HandleFunc("/cancel", showCancelHandler).Methods("GET")
r.HandleFunc("/webhook", webhookHandler).Methods("POST")
ADDR := LISTENIP+":"+PORT
log.Printf("Listen on Addr = %s", ADDR)
log.Fatal(http.ListenAndServe(ADDR, r))
}
func createPaymentHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
tmpl := template.Must(template.ParseFiles("pages/form.html"))
tmpl.Execute(w, nil)
return
}
amountStr := r.FormValue("amount")
amount := 5.0
if amountStr != "" {
fmt.Sscanf(amountStr, "%f", &amount)
}
if amount <= 0 {
http.Error(w, "Некорректная сумма", http.StatusBadRequest)
return
}
paymentURL, err := DashPaymentAPI.CreateDashPayment(
amount,
SUCCESS_URL,
CANCEL_URL,
WEBHOOK_URL,
)
if err != nil {
http.Error(w, fmt.Sprintf("Ошибка создания платежа: %v", err), http.StatusInternalServerError)
return
}
http.Redirect(w, r, paymentURL, http.StatusSeeOther)
}
func showSuccessHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
tmpl := template.Must(template.ParseFiles("pages/success.html"))
tmpl.Execute(w, nil)
return
}
}
func showCancelHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
tmpl := template.Must(template.ParseFiles("pages/cancel.html"))
tmpl.Execute(w, nil)
return
}
}
func webhookHandler(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, `{"error": "Некорректные данные"}`, http.StatusBadRequest)
return
}
defer r.Body.Close()
var data DashPaymentAPI.WebhookData
if err := json.Unmarshal(body, &data); err != nil {
http.Error(w, `{"error": "Некорректные данные"}`, http.StatusBadRequest)
return
}
log.Printf("Получен вебхук: %+v", data)
switch data.Status {
case "confirmed":
handlePaymentSuccess(data)
case "expired":
handlePaymentExpired(data)
case "cancelled":
handlePaymentCancelled(data)
default:
log.Printf("Неизвестный статус: %s", data.Status)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
func handlePaymentSuccess(data DashPaymentAPI.WebhookData) {
log.Printf("Обработка успешного платежа: %s", data.PaymentID)
}
func handlePaymentExpired(data DashPaymentAPI.WebhookData) {
log.Printf("Обработка истекшего платежа: %s", data.PaymentID)
}
func handlePaymentCancelled(data DashPaymentAPI.WebhookData) {
log.Printf("Обработка отмененного платежа: %s", data.PaymentID)
}
form.html:
HTML:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Клуб ZXCPM</title>
<style>
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container {
background: white;
padding: 40px;
border-radius: 15px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
text-align: center;
max-width: 500px;
width: 90%%;
}
h1 {
color: #333;
margin-bottom: 20px;
font-size: 28px;
}
.club-logo {
font-size: 60px;
margin-bottom: 20px;
}
.description {
color: #666;
line-height: 1.6;
margin-bottom: 30px;
font-size: 18px;
}
.amount {
background: #f8f9fa;
padding: 20px;
border-radius: 10px;
margin: 20px 0;
font-size: 24px;
font-weight: bold;
color: #28a745;
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 25px;
cursor: pointer;
transition: transform 0.2s;
text-decoration: none;
display: inline-block;
margin-top: 10px;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.features {
margin: 30px 0;
text-align: left;
}
.feature {
margin: 10px 0;
display: flex;
align-items: center;
}
.feature::before {
content: "✓";
color: #28a745;
font-weight: bold;
margin-right: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="club-logo">🏆</div>
<h1>Добро пожаловать в клуб ZXCPM</h1>
<div class="description">
<p>Для вступления в клуб необходимо совершить единоразовый взнос в размере:</p>
</div>
<div class="amount">5.00 USD</div>
<div class="features">
<div class="feature">Доступ к эксклюзивным материалам</div>
<div class="feature">Участие в закрытых мероприятиях</div>
<div class="feature">Поддержка разработчиков</div>
</div>
<form action="/" method="POST">
<input type="hidden" name="amount" value="5.00">
<button type="submit" class="btn">Оплатить 5.00 USD</button>
</form>
<p style="margin-top: 20px; color: #888; font-size: 14px;">
После оплаты вы получите доступ в Клуб
</p>
</div>
</body>
</html>
success.html:
HTML:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Успешно!</title>
<style>
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container {
background: white;
padding: 40px;
border-radius: 15px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
text-align: center;
max-width: 500px;
width: 90%%;
}
h1 {
color: #28a745;
margin-bottom: 20px;
}
.checkmark {
font-size: 60px;
color: #28a745;
margin-bottom: 20px;
}
.message {
color: #666;
line-height: 1.6;
margin-bottom: 30px;
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 25px;
cursor: pointer;
text-decoration: none;
display: inline-block;
}
</style>
</head>
<body>
<div class="container">
<div class="checkmark">✓</div>
<h1>Платеж успешно выполнен!</h1>
<div class="message">
<p>Поздравляем! Вы успешно вступили в клуб ZXCPM.</p>
<p>Теперь у вас есть доступ ко всем привилегиям клуба.</p>
</div>
<a href="/" class="btn">Вернуться на главную</a>
</div>
</body>
</html>
cancel.html:
HTML:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Платеж отменен</title>
<style>
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container {
background: white;
padding: 40px;
border-radius: 15px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
text-align: center;
max-width: 500px;
width: 90%%;
}
h1 {
color: #dc3545;
margin-bottom: 20px;
}
.warning {
font-size: 60px;
color: #dc3545;
margin-bottom: 20px;
}
.message {
color: #666;
line-height: 1.6;
margin-bottom: 30px;
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 25px;
cursor: pointer;
text-decoration: none;
display: inline-block;
}
</style>
</head>
<body>
<div class="container">
<div class="warning">⚠️</div>
<h1>Платеж отменен</h1>
<div class="message">
<p>Платеж был отменен или не завершен.</p>
<p>Вы можете попробовать снова.</p>
</div>
<a href="/" class="btn">Попробовать снова</a>
</div>
</body>
</html>