add fix for widget and add rouer for create donat

This commit is contained in:
harold 2025-03-09 18:15:11 +05:00
parent bf74330beb
commit f5e143c044
14 changed files with 393 additions and 74 deletions

View File

@ -3,10 +3,10 @@ package donat
import (
"context"
"donat-widget/internal/model"
_ "donat-widget/internal/model/api"
"donat-widget/pkg/custom_response"
"donat-widget/pkg/validator"
"fmt"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
"log/slog"
"mime/multipart"
@ -14,36 +14,39 @@ import (
"strconv"
)
// CreateDonat godoc
// @Summary Create donat
// @Description Create donat
// @Tags Donate
// @Accept json
// @Produce json
// @Param streamer-login path string true "Login стримера"
// @Param request body model.CreateDonatBody true "Create donat body json"
// @Success 200 {object} api.CreatePaymentResponse "Donat page updated successfully"
// @Failure 400 {object} echo.HTTPError "Bad request"
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
// @Failure 422 {object} echo.HTTPError "Validation error"
// @Router /donat/{streamer-login} [post]
func CreateDonat(donatService model.DonatService) echo.HandlerFunc {
type CreateDonatBody struct {
StreamerID model.StreamerID `json:"streamerID"`
TargetID model.TargetID `json:"targetID"`
Amount model.DonatAmount `json:"amount"`
Text string `json:"text"`
DonatUser string `json:"donatUser"`
}
return func(request echo.Context) error {
ctx := context.Background()
var body CreateDonatBody
if err := request.Bind(&body); err != nil {
var body model.CreateDonatBody
err := validator.ParseAndValidate(&body, request)
if err != nil {
slog.Error(err.Error())
return request.JSON(http.StatusInternalServerError, err.Error())
}
if err := request.Validate(&body); err != nil {
slog.Error(err.Error())
return request.JSON(http.StatusInternalServerError, err.Error())
return echo.NewHTTPError(http.StatusUnprocessableEntity, "Unprocessable Entity")
}
orderID := model.OrderID(uuid.New().String())
streamerLogin := request.Param("streamer-login")
order, err := donatService.CreateDonat(
ctx,
body.StreamerID,
orderID,
body.TargetID,
body.Amount,
streamerLogin,
body.Text,
body.DonatUser,
body.TargetID,
body.Amount,
)
if err != nil {
return request.JSON(http.StatusInternalServerError, err.Error())

View File

@ -247,7 +247,7 @@ func UpdateWidget(widgetService model.WidgetService) echo.HandlerFunc {
// slog.Info("set " + mediaType + " file successfully")
// return request.String(200, "File successfully uploaded")
// }
//}
//}e
//
//func GetMediaFile(widgetService model.WidgetService) echo.HandlerFunc {
// return func(request echo.Context) error {

View File

@ -69,7 +69,7 @@ func IncludeDonatHandlers(
donatService model.DonatService,
fileService model.FileService,
) {
server.POST(PREFIX+"/donat/create", CreateDonat(donatService))
server.POST(PREFIX+"/donat/:streamer-login", CreateDonat(donatService))
server.GET(PREFIX+"/inner-donate-page", GetInnerDonatePage(donatService))
server.GET(PREFIX+"/outer-donate-page/:streamer-login", GetOuterDonatePage(donatService))

View File

@ -93,6 +93,65 @@ const docTemplate = `{
}
}
},
"/donat/{streamer-login}": {
"post": {
"description": "Create donat",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Donate"
],
"summary": "Create donat",
"parameters": [
{
"type": "string",
"description": "Login стримера",
"name": "streamer-login",
"in": "path",
"required": true
},
{
"description": "Create donat body json",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/donat-widget_internal_model.CreateDonatBody"
}
}
],
"responses": {
"200": {
"description": "Donat page updated successfully",
"schema": {
"$ref": "#/definitions/donat-widget_internal_model_api.CreatePaymentResponse"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"401": {
"description": "Unauthorized or expired token",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"422": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
}
}
}
},
"/files": {
"post": {
"security": [
@ -827,6 +886,23 @@ const docTemplate = `{
}
},
"definitions": {
"donat-widget_internal_model.CreateDonatBody": {
"type": "object",
"properties": {
"amount": {
"type": "integer"
},
"donatUser": {
"type": "string"
},
"targetID": {
"type": "integer"
},
"text": {
"type": "string"
}
}
},
"donat-widget_internal_model.CreateWidgetBody": {
"type": "object",
"required": [
@ -990,6 +1066,11 @@ const docTemplate = `{
"format": "int64",
"example": 100
},
"name": {
"type": "string",
"format": "string",
"example": "Мой виджет 10"
},
"streamer_id": {
"type": "integer",
"format": "int64",
@ -1237,6 +1318,35 @@ const docTemplate = `{
}
}
},
"donat-widget_internal_model_api.CreatePaymentResponse": {
"type": "object",
"properties": {
"Amount": {
"type": "integer"
},
"ErrorCode": {
"type": "string"
},
"OrderId": {
"type": "string"
},
"PaymentId": {
"type": "string"
},
"PaymentURL": {
"type": "string"
},
"Status": {
"type": "string"
},
"Success": {
"type": "boolean"
},
"TerminalKey": {
"type": "string"
}
}
},
"echo.HTTPError": {
"type": "object",
"properties": {

View File

@ -86,6 +86,65 @@
}
}
},
"/donat/{streamer-login}": {
"post": {
"description": "Create donat",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Donate"
],
"summary": "Create donat",
"parameters": [
{
"type": "string",
"description": "Login стримера",
"name": "streamer-login",
"in": "path",
"required": true
},
{
"description": "Create donat body json",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/donat-widget_internal_model.CreateDonatBody"
}
}
],
"responses": {
"200": {
"description": "Donat page updated successfully",
"schema": {
"$ref": "#/definitions/donat-widget_internal_model_api.CreatePaymentResponse"
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"401": {
"description": "Unauthorized or expired token",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
},
"422": {
"description": "Validation error",
"schema": {
"$ref": "#/definitions/echo.HTTPError"
}
}
}
}
},
"/files": {
"post": {
"security": [
@ -820,6 +879,23 @@
}
},
"definitions": {
"donat-widget_internal_model.CreateDonatBody": {
"type": "object",
"properties": {
"amount": {
"type": "integer"
},
"donatUser": {
"type": "string"
},
"targetID": {
"type": "integer"
},
"text": {
"type": "string"
}
}
},
"donat-widget_internal_model.CreateWidgetBody": {
"type": "object",
"required": [
@ -983,6 +1059,11 @@
"format": "int64",
"example": 100
},
"name": {
"type": "string",
"format": "string",
"example": "Мой виджет 10"
},
"streamer_id": {
"type": "integer",
"format": "int64",
@ -1230,6 +1311,35 @@
}
}
},
"donat-widget_internal_model_api.CreatePaymentResponse": {
"type": "object",
"properties": {
"Amount": {
"type": "integer"
},
"ErrorCode": {
"type": "string"
},
"OrderId": {
"type": "string"
},
"PaymentId": {
"type": "string"
},
"PaymentURL": {
"type": "string"
},
"Status": {
"type": "string"
},
"Success": {
"type": "boolean"
},
"TerminalKey": {
"type": "string"
}
}
},
"echo.HTTPError": {
"type": "object",
"properties": {

View File

@ -1,5 +1,16 @@
basePath: /api/widget
definitions:
donat-widget_internal_model.CreateDonatBody:
properties:
amount:
type: integer
donatUser:
type: string
targetID:
type: integer
text:
type: string
type: object
donat-widget_internal_model.CreateWidgetBody:
properties:
audio:
@ -121,6 +132,10 @@ definitions:
example: 100
format: int64
type: integer
name:
example: Мой виджет 10
format: string
type: string
streamer_id:
example: 1001
format: int64
@ -290,6 +305,25 @@ definitions:
$ref: '#/definitions/donat-widget_internal_model.GetWidgetDb'
type: array
type: object
donat-widget_internal_model_api.CreatePaymentResponse:
properties:
Amount:
type: integer
ErrorCode:
type: string
OrderId:
type: string
PaymentId:
type: string
PaymentURL:
type: string
Status:
type: string
Success:
type: boolean
TerminalKey:
type: string
type: object
echo.HTTPError:
properties:
message: {}
@ -351,6 +385,45 @@ paths:
summary: Update personal streamer donate page
tags:
- Donate
/donat/{streamer-login}:
post:
consumes:
- application/json
description: Create donat
parameters:
- description: Login стримера
in: path
name: streamer-login
required: true
type: string
- description: Create donat body json
in: body
name: request
required: true
schema:
$ref: '#/definitions/donat-widget_internal_model.CreateDonatBody'
produces:
- application/json
responses:
"200":
description: Donat page updated successfully
schema:
$ref: '#/definitions/donat-widget_internal_model_api.CreatePaymentResponse'
"400":
description: Bad request
schema:
$ref: '#/definitions/echo.HTTPError'
"401":
description: Unauthorized or expired token
schema:
$ref: '#/definitions/echo.HTTPError'
"422":
description: Validation error
schema:
$ref: '#/definitions/echo.HTTPError'
summary: Create donat
tags:
- Donate
/files:
post:
consumes:

View File

@ -73,7 +73,7 @@ type WidgetRepo interface {
type DonatService interface {
CheckToken(request echo.Context) (api.CheckTokenResponse, error)
CreateDonat(ctx context.Context, streamerID StreamerID, orderID OrderID, targetID TargetID, amount DonatAmount, text string, donatUser string) (api.CreatePaymentResponse, error)
CreateDonat(ctx context.Context, streamerLogin, text, donatUser string, targetID, amount int) (api.CreatePaymentResponse, error)
GetDonatByStreamerID(ctx context.Context, streamerID StreamerID) ([]*Donat, error)
GetDonatByOrderID(ctx context.Context, orderID OrderID) (*Donat, error)
@ -101,7 +101,16 @@ type DonatService interface {
}
type DonatRepo interface {
CreateDonat(ctx context.Context, streamerID StreamerID, widgetID WidgetID, orderID OrderID, targetID TargetID, amount DonatAmount, text string, donatUser string) error
CreateDonat(
ctx context.Context,
streamerID int,
targetID int,
widgetID int,
orderID uuid.UUID,
amount int,
text string,
donatUser string,
) error
GetDonatByStreamerID(ctx context.Context, streamerID StreamerID) ([]*Donat, error)
GetDonatByOrderID(ctx context.Context, orderID OrderID) (*Donat, error)
@ -166,7 +175,7 @@ type Storage interface {
}
type PaymentClient interface {
CreatePayment(streamerID StreamerID, amount DonatAmount, orderID OrderID) (api.CreatePaymentResponse, error)
CreatePayment(streamerID int, amount int, orderID uuid.UUID) (api.CreatePaymentResponse, error)
}
type Db interface {
Insert(ctx context.Context, query string, args ...interface{}) (any, error)

View File

@ -21,6 +21,7 @@ type GetWidgetDb struct {
ID int `db:"id" json:"id" example:"1" format:"int64" description:"Unique identifier of the widget"`
StreamerID int `db:"streamer_id" json:"streamer_id" example:"1001" format:"int64" description:"ID of the streamer"`
TemplateID int `db:"template_id" json:"template_id" example:"5" format:"int64" description:"ID of the template"`
Name string `db:"name" json:"name" example:"Мой виджет 10" format:"string" description:"Имя виджета"`
Duration int `db:"duration" json:"duration" example:"30" format:"int64" description:"Duration of the widget"`
MinAmount int `db:"min_amount" json:"min_amount" example:"100" format:"int64" description:"Minimum donation amount"`
MaxAmount int `db:"max_amount" json:"max_amount" example:"1000" format:"int64" description:"Maximum donation amount"`
@ -68,8 +69,7 @@ type Donat struct {
DonatUser string `db:"donat_user"`
Amount DonatAmount `db:"amount"`
Paid bool `db:"paid"`
View bool `db:"view"`
status string `db:"status"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
@ -248,6 +248,13 @@ type DonatAndWidget struct {
Display Display
}
type CreateDonatBody struct {
TargetID int `json:"targetID"`
Amount int `json:"amount"`
Text string `json:"text"`
DonatUser string `json:"donatUser"`
}
//func (widget *GetWidgetDb) GetMediaUrl(mediaType MediaType) MediaUrl {
// var mediaUrl MediaUrl
// if mediaType == "background_url" {

View File

@ -34,18 +34,16 @@ CREATE TABLE IF NOT EXISTS files (
CREATE TABLE IF NOT EXISTS donats (
id SERIAL PRIMARY KEY,
streamer_id INTEGER NOT NULL,
widget_id INTEGER NOT NULL,
order_id TEXT NOT NULL,
target_id INTEGER NOT NULL,
size FLOAT NOT NULL,
widget_id INTEGER REFERENCES widgets(id) NOT NULL,
order_id UUID NOT NULL,
target_id INTEGER,
status VARCHAR(50) NOT NULL DEFAULT 'pending',
text TEXT NOT NULL,
amount INTEGER NOT NULL,
donat_user TEXT NOT NULL,
paid BOOLEAN DEFAULT FALSE,
view BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@ -155,6 +155,7 @@ SELECT
w.streamer_id,
w.template_id,
w.group_id,
w.name,
img.id AS image_id,
img.file_name AS image_file_name,
img.file_type AS image_type,

View File

@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"github.com/georgysavva/scany/v2/pgxscan"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"log/slog"
"strings"
@ -24,11 +25,11 @@ type RepoDonat struct {
func (repoDonat *RepoDonat) CreateDonat(
ctx context.Context,
streamerID model.StreamerID,
widgetID model.WidgetID,
orderID model.OrderID,
targetID model.TargetID,
amount model.DonatAmount,
streamerID int,
targetID int,
widgetID int,
orderID uuid.UUID,
amount int,
text string,
donatUser string,
) error {
@ -39,6 +40,7 @@ func (repoDonat *RepoDonat) CreateDonat(
"target_id": targetID,
"text": text,
"amount": amount,
"status": "pending",
"donat_user": donatUser,
}
_, err := repoDonat.db.Insert(ctx, sql.CreateDonat, args)

View File

@ -4,6 +4,7 @@ import (
"context"
"donat-widget/internal/model"
"donat-widget/internal/model/api"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
"log/slog"
"mime/multipart"
@ -66,42 +67,48 @@ func (donatService *ServiceDonat) CheckToken(
func (donatService *ServiceDonat) CreateDonat(
ctx context.Context,
streamerID model.StreamerID,
orderID model.OrderID,
targetID model.TargetID,
amount model.DonatAmount,
streamerLogin string,
text string,
donatUser string,
targetID int,
amount int,
) (api.CreatePaymentResponse, error) {
return api.CreatePaymentResponse{}, nil
//widgets, err := donatService.widgetRepo.GetAllWidget(ctx, streamerID)
//if err != nil {
// slog.Error(err.Error())
// return api.CreatePaymentResponse{}, err
//}
//
//var widgetID model.WidgetID
//for _, widget := range widgets {
// if widget.MinAmount <= amount {
// widgetID = widget.ID
// }
//}
//
//err = donatService.donatRepo.CreateDonat(
// ctx, streamerID, widgetID, orderID, targetID, amount, text, donatUser,
//)
//if err != nil {
// slog.Error(err.Error())
// return api.CreatePaymentResponse{}, err
//}
//
donatePage, err := donatService.donatRepo.GetDonatPageByLogin(ctx, streamerLogin)
if err != nil {
slog.Error("Failed to get donate page", "error", err.Error())
return api.CreatePaymentResponse{}, err
}
widgets, err := donatService.widgetRepo.GetWidgetsByStreamerID(ctx, donatePage.StreamerID)
if err != nil {
slog.Error(err.Error())
return api.CreatePaymentResponse{}, err
}
orderID := uuid.New()
var widgetID int
for _, widget := range widgets {
if widget.MinAmount <= amount && widget.MaxAmount <= amount {
widgetID = widget.ID
}
}
err = donatService.donatRepo.CreateDonat(
ctx, donatePage.StreamerID, targetID, widgetID, orderID, amount, text, donatUser,
)
if err != nil {
slog.Error(err.Error())
return api.CreatePaymentResponse{}, err
}
//createPaymentResponse, err := donatService.paymentClient.CreatePayment(streamerID, amount, orderID)
//if err != nil {
// slog.Error(err.Error())
// return api.CreatePaymentResponse{}, err
//}
//
//return createPaymentResponse, nil
return api.CreatePaymentResponse{}, err
}
func (donatService *ServiceDonat) GetDonatByStreamerID(

View File

@ -2,10 +2,10 @@ package payment
import (
"bytes"
"donat-widget/internal/model"
"donat-widget/internal/model/api"
"encoding/json"
"errors"
"github.com/google/uuid"
"io"
"log/slog"
"net/http"
@ -24,9 +24,9 @@ type ClientPayment struct {
}
func (c *ClientPayment) CreatePayment(
streamerID model.StreamerID,
amount model.DonatAmount,
orderID model.OrderID,
streamerID int,
amount int,
orderID uuid.UUID,
) (api.CreatePaymentResponse, error) {
requestBody := map[string]any{
"sellerID": streamerID,

View File

@ -42,8 +42,7 @@ CREATE TABLE IF NOT EXISTS donats (
text TEXT NOT NULL,
amount INTEGER NOT NULL,
donat_user TEXT NOT NULL,
paid BOOLEAN DEFAULT FALSE,
view BOOLEAN DEFAULT FALSE,
status VARCHAR(50) NOT NULL DEFAULT 'pending',
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);