2026-03-29 11:55:53 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2026-04-28 20:26:52 +08:00
|
|
|
"context"
|
|
|
|
|
"encoding/json"
|
2026-03-29 11:55:53 +08:00
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"net"
|
2026-04-28 20:26:52 +08:00
|
|
|
"net/http"
|
2026-03-29 11:55:53 +08:00
|
|
|
"os"
|
|
|
|
|
"os/signal"
|
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
|
|
"github.com/cloudprint/cloudprint-backend/config"
|
|
|
|
|
"github.com/cloudprint/cloudprint-backend/internal/grpc/interceptor"
|
2026-04-28 20:26:52 +08:00
|
|
|
grpcService "github.com/cloudprint/cloudprint-backend/internal/grpc/service"
|
2026-03-29 11:55:53 +08:00
|
|
|
"github.com/cloudprint/cloudprint-backend/internal/repository"
|
|
|
|
|
"github.com/cloudprint/cloudprint-backend/internal/service"
|
|
|
|
|
"github.com/cloudprint/cloudprint-backend/pkg/jwt"
|
|
|
|
|
"github.com/cloudprint/cloudprint-backend/pkg/pay"
|
|
|
|
|
"github.com/cloudprint/cloudprint-backend/pkg/upload"
|
|
|
|
|
pb "github.com/cloudprint/cloudprint-backend/proto/generated"
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
"google.golang.org/grpc"
|
2026-04-28 20:26:52 +08:00
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
|
"google.golang.org/grpc/metadata"
|
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
|
"gorm.io/driver/postgres"
|
2026-03-29 11:55:53 +08:00
|
|
|
"gorm.io/gorm"
|
|
|
|
|
"gorm.io/gorm/logger"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
configPath := flag.String("config", "config.yaml", "path to config file")
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
|
|
// Load configuration
|
|
|
|
|
cfg, err := config.LoadConfig(*configPath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("Failed to load config: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize logger
|
|
|
|
|
zapLogger, _ := zap.NewProduction()
|
|
|
|
|
defer zapLogger.Sync()
|
|
|
|
|
|
|
|
|
|
// Initialize database
|
|
|
|
|
db, err := initDB(cfg)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("Failed to initialize database: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize repositories
|
|
|
|
|
userRepo := repository.NewUserRepository(db)
|
|
|
|
|
adminRepo := repository.NewAdminRepository(db)
|
|
|
|
|
fileRepo := repository.NewFileRepository(db)
|
|
|
|
|
orderRepo := repository.NewOrderRepository(db)
|
|
|
|
|
orderItemRepo := repository.NewOrderItemRepository(db)
|
|
|
|
|
printerRepo := repository.NewPrinterRepository(db)
|
|
|
|
|
printJobRepo := repository.NewPrintJobRepository(db)
|
|
|
|
|
libraryRepo := repository.NewLibraryRepository(db)
|
|
|
|
|
priceRepo := repository.NewPriceRepository(db)
|
|
|
|
|
paymentRepo := repository.NewPaymentRepository(db)
|
|
|
|
|
|
|
|
|
|
// Initialize JWT manager
|
|
|
|
|
jwtManager := jwt.NewJWTManager(
|
|
|
|
|
cfg.JWT.Secret,
|
|
|
|
|
cfg.JWT.AccessTokenTTL,
|
|
|
|
|
cfg.JWT.RefreshTokenTTL,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Initialize file uploader
|
|
|
|
|
fileUploader := upload.NewFileUploader(
|
|
|
|
|
cfg.Upload.Path,
|
|
|
|
|
cfg.Upload.ChunkPath,
|
|
|
|
|
cfg.Upload.MaxSize,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Initialize WeChat pay
|
|
|
|
|
weChatPay := pay.NewWeChatPay(&cfg.WeChat)
|
|
|
|
|
|
|
|
|
|
// Initialize services
|
|
|
|
|
authService := service.NewAuthService(userRepo, adminRepo, jwtManager, nil, &cfg.WeChat)
|
|
|
|
|
fileService := service.NewFileService(fileRepo, fileUploader, cfg.Upload.Path)
|
|
|
|
|
orderService := service.NewOrderService(orderRepo, orderItemRepo, fileRepo, priceRepo, userRepo, printerRepo, printJobRepo)
|
|
|
|
|
printService := service.NewPrintService(printerRepo, printJobRepo, orderRepo)
|
|
|
|
|
|
|
|
|
|
// Initialize gRPC server
|
|
|
|
|
grpcServer := grpc.NewServer(
|
|
|
|
|
grpc.UnaryInterceptor(interceptor.NewAuthInterceptor(jwtManager).UnaryServerInterceptor()),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Register gRPC services
|
2026-04-28 20:26:52 +08:00
|
|
|
pb.RegisterAuthServiceServer(grpcServer, grpcService.NewAuthServiceServer(authService))
|
|
|
|
|
pb.RegisterFileServiceServer(grpcServer, grpcService.NewFileServiceServer(fileService))
|
|
|
|
|
pb.RegisterOrderServiceServer(grpcServer, grpcService.NewOrderServiceServer(orderService))
|
|
|
|
|
pb.RegisterPrintServiceServer(grpcServer, grpcService.NewPrintServiceServer(printService))
|
|
|
|
|
pb.RegisterLibraryServiceServer(grpcServer, grpcService.NewLibraryServiceServer(libraryRepo, fileRepo))
|
|
|
|
|
pb.RegisterPriceServiceServer(grpcServer, grpcService.NewPriceServiceServer(priceRepo))
|
|
|
|
|
pb.RegisterPayServiceServer(grpcServer, grpcService.NewPayServiceServer(orderService, paymentRepo, weChatPay, userRepo))
|
|
|
|
|
pb.RegisterAdminServiceServer(grpcServer, grpcService.NewAdminServiceServer(authService, orderRepo, printerRepo))
|
|
|
|
|
|
|
|
|
|
// Initialize HTTP gateway
|
|
|
|
|
gateway := newHTTPGateway(grpcServer, jwtManager)
|
2026-03-29 11:55:53 +08:00
|
|
|
|
|
|
|
|
// Start server
|
|
|
|
|
addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)
|
|
|
|
|
lis, err := net.Listen("tcp", addr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("Failed to listen: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Graceful shutdown
|
|
|
|
|
sigCh := make(chan os.Signal, 1)
|
|
|
|
|
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
|
|
2026-04-28 20:26:52 +08:00
|
|
|
// HTTP server for gateway
|
|
|
|
|
httpServer := &http.Server{
|
|
|
|
|
Handler: gateway,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start HTTP server in goroutine
|
2026-03-29 11:55:53 +08:00
|
|
|
go func() {
|
2026-04-28 20:26:52 +08:00
|
|
|
zapLogger.Info("Starting HTTP gateway", zap.String("address", addr))
|
|
|
|
|
if err := httpServer.Serve(lis); err != nil && err != http.ErrServerClosed {
|
|
|
|
|
log.Fatalf("Failed to serve HTTP: %v", err)
|
|
|
|
|
}
|
2026-03-29 11:55:53 +08:00
|
|
|
}()
|
|
|
|
|
|
2026-04-28 20:26:52 +08:00
|
|
|
// Wait for shutdown signal
|
|
|
|
|
<-sigCh
|
|
|
|
|
zapLogger.Info("Shutting down servers...")
|
|
|
|
|
|
|
|
|
|
// Graceful stop gRPC server
|
|
|
|
|
grpcServer.GracefulStop()
|
|
|
|
|
|
|
|
|
|
// Shutdown HTTP server
|
|
|
|
|
if err := httpServer.Close(); err != nil {
|
|
|
|
|
zapLogger.Error("Failed to close HTTP server", zap.Error(err))
|
2026-03-29 11:55:53 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func initDB(cfg *config.Config) (*gorm.DB, error) {
|
|
|
|
|
gormLogger := logger.New(
|
|
|
|
|
log.New(os.Stdout, "\r\n", log.LstdFlags),
|
|
|
|
|
logger.Config{
|
|
|
|
|
LogLevel: logger.Info,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
2026-04-28 20:26:52 +08:00
|
|
|
db, err := gorm.Open(postgres.Open(cfg.Database.DSN()), &gorm.Config{
|
2026-03-29 11:55:53 +08:00
|
|
|
Logger: gormLogger,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sqlDB, err := db.DB()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sqlDB.SetMaxOpenConns(cfg.Database.MaxOpenConns)
|
|
|
|
|
sqlDB.SetMaxIdleConns(cfg.Database.MaxIdleConns)
|
|
|
|
|
|
|
|
|
|
return db, nil
|
|
|
|
|
}
|
2026-04-28 20:26:52 +08:00
|
|
|
|
|
|
|
|
// HTTP Gateway
|
|
|
|
|
|
|
|
|
|
type httpGateway struct {
|
|
|
|
|
grpcServer *grpc.Server
|
|
|
|
|
jwtManager *jwt.JWTManager
|
|
|
|
|
mux *http.ServeMux
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newHTTPGateway(grpcServer *grpc.Server, jwtManager *jwt.JWTManager) *httpGateway {
|
|
|
|
|
g := &httpGateway{
|
|
|
|
|
grpcServer: grpcServer,
|
|
|
|
|
jwtManager: jwtManager,
|
|
|
|
|
mux: http.NewServeMux(),
|
|
|
|
|
}
|
|
|
|
|
g.registerHandlers()
|
|
|
|
|
return g
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
g.mux.ServeHTTP(w, r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) registerHandlers() {
|
|
|
|
|
// Health check
|
|
|
|
|
g.mux.HandleFunc("/health", g.healthHandler)
|
|
|
|
|
|
|
|
|
|
// Auth endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/auth/login", g.handleLogin)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/auth/refresh", g.handleRefreshToken)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/auth/userinfo", g.handleGetUserInfo)
|
|
|
|
|
|
|
|
|
|
// File endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/file/upload", g.handleFileUpload)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/file/", g.handleFileOps)
|
|
|
|
|
|
|
|
|
|
// Order endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/order/create", g.handleCreateOrder)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/order/", g.handleOrderOps)
|
|
|
|
|
|
|
|
|
|
// Print endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/print/printers", g.handleGetPrinters)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/print/submit", g.handleSubmitPrintJob)
|
|
|
|
|
|
|
|
|
|
// Library endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/library/categories", g.handleGetCategories)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/library/files", g.handleGetLibraryFiles)
|
|
|
|
|
|
|
|
|
|
// Price endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/price/list", g.handleGetPriceList)
|
|
|
|
|
|
|
|
|
|
// Pay endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/pay/wxpay", g.handleCreateWxPayOrder)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/pay/callback", g.handlePayCallback)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/pay/balance", g.handlePayByBalance)
|
|
|
|
|
|
|
|
|
|
// Admin endpoints
|
|
|
|
|
g.mux.HandleFunc("/api/v1/admin/login", g.handleAdminLogin)
|
|
|
|
|
g.mux.HandleFunc("/api/v1/admin/stats", g.handleGetStatistics)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) healthHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(`{"status":"ok"}`))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) writeJSON(w http.ResponseWriter, statusCode int, data interface{}) {
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.WriteHeader(statusCode)
|
|
|
|
|
json.NewEncoder(w).Encode(data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleError(w http.ResponseWriter, err error) {
|
|
|
|
|
st, ok := status.FromError(err)
|
|
|
|
|
if !ok {
|
|
|
|
|
g.writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
code := http.StatusInternalServerError
|
|
|
|
|
switch st.Code() {
|
|
|
|
|
case codes.OK:
|
|
|
|
|
code = http.StatusOK
|
|
|
|
|
case codes.InvalidArgument:
|
|
|
|
|
code = http.StatusBadRequest
|
|
|
|
|
case codes.NotFound:
|
|
|
|
|
code = http.StatusNotFound
|
|
|
|
|
case codes.Unauthenticated:
|
|
|
|
|
code = http.StatusUnauthorized
|
|
|
|
|
case codes.PermissionDenied:
|
|
|
|
|
code = http.StatusForbidden
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, code, map[string]string{"error": st.Message()})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) parseToken(r *http.Request) (context.Context, error) {
|
|
|
|
|
token := r.Header.Get("Authorization")
|
|
|
|
|
if token == "" {
|
|
|
|
|
return nil, status.Error(codes.Unauthenticated, "missing token")
|
|
|
|
|
}
|
|
|
|
|
if len(token) > 7 && token[:7] == "Bearer " {
|
|
|
|
|
token = token[7:]
|
|
|
|
|
}
|
|
|
|
|
claims, err := g.jwtManager.ValidateToken(token)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, status.Error(codes.Unauthenticated, "invalid token")
|
|
|
|
|
}
|
|
|
|
|
return metadata.NewOutgoingContext(r.Context(), metadata.Pairs(
|
|
|
|
|
"user_id", fmt.Sprintf("%d", claims.UserID),
|
|
|
|
|
"user_type", claims.UserType,
|
|
|
|
|
)), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleLogin(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
var req pb.LoginRequest
|
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
|
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// gRPC call would go here - returning placeholder for now
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "Use gRPC directly for login"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleRefreshToken(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleGetUserInfo(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleFileUpload(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleFileOps(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
switch r.Method {
|
|
|
|
|
case http.MethodGet:
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
case http.MethodDelete:
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
default:
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleCreateOrder(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleOrderOps(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
switch r.Method {
|
|
|
|
|
case http.MethodGet:
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
default:
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleGetPrinters(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleSubmitPrintJob(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleGetCategories(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleGetLibraryFiles(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleGetPriceList(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleCreateWxPayOrder(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handlePayCallback(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handlePayByBalance(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleAdminLogin(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (g *httpGateway) handleGetStatistics(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
_, err := g.parseToken(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
g.handleError(w, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
g.writeJSON(w, http.StatusOK, map[string]string{"message": "not implemented"})
|
|
|
|
|
}
|