upd update latest changes

hotfix/hotfix-mysql-error
Ernest Litvinenko 2024-05-03 18:57:53 +10:00
parent b8b4e89bc0
commit cb83eb5ff5
26 changed files with 929 additions and 67 deletions

View File

@ -7,6 +7,8 @@ import (
"github.com/google/uuid"
"github.com/mitchellh/mapstructure"
"github.com/sirupsen/logrus"
"io"
"log"
"net/http"
"os"
"strings"
@ -166,6 +168,7 @@ type BasketResource struct {
type bitrix struct {
EP string
EPCustom string
}
type Bitrix interface {
@ -175,8 +178,9 @@ type Bitrix interface {
CancelOrder(orderId int) error
GetOrderInfo(orderId int) (*OrderResource, error)
CreatePayment(orderId int, sum float64) error
AddProductToOrder(orderId int, productId int, price float64, quantity int) error
AddProductToOrder(orderId int, productId int, price float64, quantity int, productName string) error
UpdateContact(contactId int, email string, name string, phone string) error
GetTotalForProduct(fuserId int, coupon *string) (*GetTotalOrderResponse, error)
}
type createAnonymousUserRequest struct {
@ -231,6 +235,11 @@ type createOrderResponse struct {
} `json:"result"`
}
type GetTotalOrderResponse struct {
Price float64 `json:"price"`
BasePrice float64 `json:"basePrice"`
}
func (b bitrix) CreateOrder(userId int) (int, error) {
req := createOrderRequestWrapper{createOrderRequest{
Lid: "s2",
@ -257,7 +266,10 @@ func (b bitrix) ApprovePayment(paymentId int, paySystemId int) error {
query, _ := json.Marshal(req)
_, err := http.Post(b.EP+"/sale.payment.update", "application/json", bytes.NewBuffer(query))
resp, err := http.Post(b.EP+"/sale.payment.update", "application/json", bytes.NewBuffer(query))
str, _ := io.ReadAll(resp.Body)
log.Println(str)
return err
}
@ -317,20 +329,26 @@ func (b bitrix) CreatePayment(orderId int, sum float64) error {
return err
}
func (b bitrix) AddProductToOrder(orderId int, productId int, price float64, quantity int) error {
func (b bitrix) AddProductToOrder(orderId int, productId int, price float64, quantity int, productName string) error {
req := map[string]interface{}{
"fields": map[string]interface{}{
"name": productName,
"orderId": orderId,
"module": "catalog",
"productId": productId,
"quantity": quantity,
"currency": "RUB",
"price": price,
"vatIncluded": "Y",
"vatRate": 0.2,
"basePrice": price,
"productXmlId": fmt.Sprintf("%d", productId),
"detailPageUrl": fmt.Sprintf("\\/CRM_PRODUCT_CATALOG\\/detail.php?ID=%d", productId),
},
}
query, _ := json.Marshal(req)
_, err := http.Post(b.EP+"/sale.basketitem.addCatalogProduct", "application/json", bytes.NewBuffer(query))
_, err := http.Post(b.EP+"/sale.basketitem.add", "application/json", bytes.NewBuffer(query))
return err
}
@ -361,8 +379,30 @@ func (b bitrix) UpdateContact(contactId int, email string, name string, phone st
return err
}
func (b bitrix) GetTotalForProduct(fuserId int, coupon *string) (*GetTotalOrderResponse, error) {
var result *http.Response
var err error
if coupon != nil {
result, err = http.Get(b.EPCustom + fmt.Sprintf("/order/total?fuserId=%d&coupon=%s", fuserId, *coupon))
} else {
result, err = http.Get(b.EPCustom + fmt.Sprintf("/order/total?fuserId=%d", fuserId))
}
if err != nil {
return nil, err
}
defer result.Body.Close()
returnedValue := new(GetTotalOrderResponse)
json.NewDecoder(result.Body).Decode(returnedValue)
return returnedValue, nil
}
func Initialize() Bitrix {
return &bitrix{
EP: os.Getenv("BITRIX_API_EP"),
EPCustom: os.Getenv("BTIRIX_API_CUSTOM"),
}
}

View File

@ -120,3 +120,21 @@ func CreatePayment(orderId int, sum float64, fullName string, email string, phon
return result, nil
}
func CheckPayment(paymentId uuid.UUID) (*KassaResult, error) {
uid, err := uuid.NewUUID()
client := new(http.Client)
request, _ := http.NewRequest(http.MethodGet, BASE_URL+fmt.Sprintf("/%s", paymentId.String()), nil)
request.Header.Set("Authorization", "Basic "+basicAuth(os.Getenv("YOOKASSA_ACCOUNT_ID"),
os.Getenv("YOOKASSA_ACCOUNT_SECRET")))
request.Header.Set("Idempotence-Key", uid.String())
request.Header.Set("Content-Type", "application/json")
response, err := client.Do(request)
result := new(KassaResult)
json.NewDecoder(response.Body).Decode(&result)
if err != nil {
return nil, err
}
return result, nil
}

124
external/yaGeo/init.go vendored Normal file
View File

@ -0,0 +1,124 @@
package yaGeo
import (
"encoding/json"
"net/http"
"os"
)
type GeoObject struct {
MetaDataProperty struct {
GeocoderMetaData struct {
Precision string `json:"precision"`
Text string `json:"text"`
Kind string `json:"kind"`
Address struct {
CountryCode string `json:"country_code"`
Formatted string `json:"formatted"`
PostalCode string `json:"postal_code,omitempty"`
Components []struct {
Kind string `json:"kind"`
Name string `json:"name"`
} `json:"Components"`
} `json:"Address"`
AddressDetails struct {
Country struct {
AddressLine string `json:"AddressLine"`
CountryNameCode string `json:"CountryNameCode"`
CountryName string `json:"CountryName"`
AdministrativeArea struct {
AdministrativeAreaName string `json:"AdministrativeAreaName"`
SubAdministrativeArea struct {
SubAdministrativeAreaName string `json:"SubAdministrativeAreaName"`
Locality struct {
LocalityName string `json:"LocalityName"`
Thoroughfare struct {
ThoroughfareName string `json:"ThoroughfareName"`
Premise struct {
PremiseNumber string `json:"PremiseNumber"`
PostalCode struct {
PostalCodeNumber string `json:"PostalCodeNumber"`
} `json:"PostalCode,omitempty"`
} `json:"Premise"`
} `json:"Thoroughfare,omitempty"`
DependentLocality struct {
DependentLocalityName string `json:"DependentLocalityName"`
Thoroughfare struct {
ThoroughfareName string `json:"ThoroughfareName"`
Premise struct {
PremiseNumber string `json:"PremiseNumber"`
} `json:"Premise"`
} `json:"Thoroughfare"`
} `json:"DependentLocality,omitempty"`
} `json:"Locality"`
} `json:"SubAdministrativeArea"`
} `json:"AdministrativeArea"`
} `json:"Country"`
} `json:"AddressDetails"`
} `json:"GeocoderMetaData"`
} `json:"metaDataProperty"`
Name string `json:"name"`
Description string `json:"description"`
BoundedBy struct {
Envelope struct {
LowerCorner string `json:"lowerCorner"`
UpperCorner string `json:"upperCorner"`
} `json:"Envelope"`
} `json:"boundedBy"`
Uri string `json:"uri"`
Point struct {
Pos string `json:"pos"`
} `json:"Point"`
}
type geoResponseWrapper struct {
GeoResponse `json:"response"`
}
type geoObjectCollection struct {
FeatureMember []struct {
GeoObject `json:"GeoObject"`
} `json:"featureMember"`
}
type GeoResponse struct {
geoObjectCollection `json:"GeoObjectCollection"`
}
type yaGeo struct {
EP string
apiKey string
}
type YaGeo interface {
GeoCode(q string) (*[]GeoObject, error)
}
func Init() YaGeo {
return &yaGeo{
EP: "https://geocode-maps.yandex.ru/1.x/",
apiKey: os.Getenv("YANDEX_GEOCODER_API_KEY"),
}
}
func (y *yaGeo) GeoCode(q string) (*[]GeoObject, error) {
data := new(geoResponseWrapper)
req, _ := http.NewRequest("GET", y.EP, nil)
params := req.URL.Query()
params.Add("apikey", y.apiKey)
params.Add("geocode", q)
params.Add("lang", "ru_RU")
params.Add("format", "json")
req.URL.RawQuery = params.Encode()
resp, err := http.Get(req.URL.String())
if err != nil {
return nil, err
}
err = json.NewDecoder(resp.Body).Decode(data)
items := []GeoObject{}
for _, d := range data.GeoResponse.geoObjectCollection.FeatureMember {
items = append(items, d.GeoObject)
}
return &items, err
}

43
go.mod
View File

@ -2,49 +2,62 @@ module relynolli-server
go 1.21
require (
github.com/ernesto-jimenez/httplogger v0.0.0-20220128121225-117514c3f345
github.com/geotrace/geo v0.0.0-20160115125640-a9248f7f2ad1
github.com/gin-contrib/cache v1.2.0
github.com/gin-contrib/cors v1.5.0
github.com/gin-gonic/gin v1.9.1
github.com/go-playground/validator/v10 v10.19.0
github.com/go-sql-driver/mysql v1.7.1
github.com/google/go-querystring v1.1.0
github.com/google/uuid v1.6.0
github.com/hashicorp/go-multierror v1.0.0
github.com/joho/godotenv v1.5.1
github.com/mitchellh/mapstructure v1.5.0
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/pkg/errors v0.9.1
github.com/redis/go-redis/v9 v9.5.1
github.com/rs/zerolog v1.31.0
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
github.com/uptrace/bun v1.1.17
github.com/uptrace/bun/dialect/mysqldialect v1.1.17
github.com/uptrace/bun/extra/bundebug v1.1.17
)
require (
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
github.com/bytedance/sonic v1.11.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/cache v1.2.0 // indirect
github.com/gin-contrib/cors v1.5.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.19.0 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gomodule/redigo v1.8.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/memcachier/mc/v3 v3.0.3 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/redis/go-redis/v9 v9.5.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/uptrace/bun v1.1.17 // indirect
github.com/uptrace/bun/dialect/mysqldialect v1.1.17 // indirect
github.com/uptrace/bun/extra/bundebug v1.1.17 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
golang.org/x/arch v0.7.0 // indirect

51
go.sum
View File

@ -1,5 +1,9 @@
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.11.1 h1:JC0+6c9FoWYYxakaoa+c5QTtJeiSZNeByOBhXtAFSn4=
@ -13,14 +17,21 @@ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpV
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/ernesto-jimenez/httplogger v0.0.0-20220128121225-117514c3f345 h1:AZLrCR38RDhsyCQakz1UxCx72As18Ai5mObrKvT8DK8=
github.com/ernesto-jimenez/httplogger v0.0.0-20220128121225-117514c3f345/go.mod h1:pw+gaKQ52Cl/SrERU62yQAiWauPpLgKpuR1hkxwL4tM=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/geotrace/geo v0.0.0-20160115125640-a9248f7f2ad1 h1:t/FumljonSghkl+LUhgKJEhIWC3Zwu9JY7rLrU9YYuU=
github.com/geotrace/geo v0.0.0-20160115125640-a9248f7f2ad1/go.mod h1:5gbC4+PtjSPzYBiq6ANs+3D4SxiPenPozK8jRUORapU=
github.com/gin-contrib/cache v1.2.0 h1:WA+AJR4kmHDTaLLShCHo/IeWVmmGRZ3Lsr3JQ46tFlE=
github.com/gin-contrib/cache v1.2.0/go.mod h1:2KkFL8PSnPF3Tt5E2Jpc3HWuBAUKqGZnClCFMm0tXQI=
github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk=
@ -29,30 +40,35 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@ -61,15 +77,18 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/memcachier/mc/v3 v3.0.3 h1:qii+lDiPKi36O4Xg+HVKwHu6Oq+Gt17b+uEiA0Drwv4=
github.com/memcachier/mc/v3 v3.0.3/go.mod h1:GzjocBahcXPxt2cmqzknrgqCOmMxiSzhVKPOe90Tpug=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@ -83,13 +102,18 @@ github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/
github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 h1:pyecQtsPmlkCsMkYhT5iZ+sUXuwee+OvfuJjinEA3ko=
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62/go.mod h1:65XQgovT59RWatovFwnwocoUxiI/eENTnOY5GK3STuY=
github.com/rvinnie/yookassa-sdk-go v0.0.0-20230904104101-ff7e5be5530c h1:m6dxe045lJQ1tkJeCBwseulCwppUDcdZk+RIxzBjQXQ=
github.com/rvinnie/yookassa-sdk-go v0.0.0-20230904104101-ff7e5be5530c/go.mod h1:flatybkcu+7YLaB7mMnj9JTNKeim4jZ+ZrXNFjVA0pA=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -100,6 +124,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
@ -117,6 +142,8 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/vseinstrumentiru/cdek v0.0.7 h1:73O/Zp0JH/MxPWLHXKoDfrlUAQ9WHYqSPcJlefSMFuI=
github.com/vseinstrumentiru/cdek v0.0.7/go.mod h1:9oNSNbQX0Am56kJcRDpouqlZ77ZJI9Wl4g8HB38ln3Y=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
@ -130,14 +157,18 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -0,0 +1,58 @@
package endpoints
import (
"fmt"
"github.com/gin-gonic/gin"
"relynolli-server/external/yaGeo"
"relynolli-server/models"
"relynolli-server/status"
"time"
)
type handlers struct{}
type Handlers interface {
SearchAddress(c *gin.Context)
}
func GetHandlers() Handlers {
return &handlers{}
}
type searchAddressParams struct {
SearchString string `form:"q"`
}
func (h *handlers) SearchAddress(c *gin.Context) {
query := new(searchAddressParams)
err := c.ShouldBindQuery(query)
meta := models.Meta{
RequestStarted: time.Now().Unix(),
}
response := models.Response{
Status: status.STATUS_OK,
Meta: &meta,
}
if err != nil {
response.Info = fmt.Sprintf("Error: %s", err.Error())
response.Status = status.STATUS_BAD_REQUEST
meta.RequestFinished = time.Now().Unix()
c.JSON(400, response)
return
}
geo := yaGeo.Init()
results, err := geo.GeoCode(query.SearchString)
if err != nil {
response.Info = fmt.Sprintf("Error: %s", err.Error())
response.Status = status.STATUS_SERVER_ERROR
meta.RequestFinished = time.Now().Unix()
c.JSON(500, response)
return
}
response.Data = results
meta.RequestFinished = time.Now().Unix()
c.JSON(200, response)
}

View File

@ -0,0 +1,21 @@
package address
import (
"github.com/gin-contrib/cache"
"github.com/gin-gonic/gin"
"os"
"relynolli-server/handlers/address/endpoints"
"relynolli-server/internal"
"time"
)
func HandleRoutes(parent *gin.RouterGroup) {
h := endpoints.GetHandlers()
addr := parent.Group("/address")
if os.Getenv("IS_PROD") == "1" {
store := internal.InitCacheStore()
addr.GET("/search", cache.CachePage(store, 15*time.Minute, h.SearchAddress))
} else {
addr.GET("/search", h.SearchAddress)
}
}

View File

@ -0,0 +1,113 @@
package endpoints
import (
"context"
"fmt"
"relynolli-server/models"
"relynolli-server/status"
"relynolli-server/storage"
"time"
"github.com/gin-gonic/gin"
)
type handlers struct{}
type Handlers interface {
GetNews(c *gin.Context)
RetrieveNews(c *gin.Context)
}
func GetHandlers() Handlers {
return &handlers{}
}
type ListNewsRequest struct {
Limit int `form:"limit" `
Page int `form:"page"`
}
func (h *handlers) GetNews(c *gin.Context) {
ctx := context.Background()
meta := models.Meta{
RequestStarted: time.Now().Unix(),
}
query := ListNewsRequest{
Limit: 10,
Page: 1,
}
err := c.ShouldBindQuery(&query)
if err != nil {
meta.RequestFinished = time.Now().Unix()
c.JSON(400, models.Response{
Status: status.STATUS_BAD_REQUEST,
Info: fmt.Sprintf("Error: %s", err.Error()),
Meta: &meta,
})
return
}
s := storage.NewStorageArticle()
count, resp, err := s.GetArticles(ctx, int64(query.Limit), int64(query.Limit*(query.Page-1)))
if err != nil {
meta.RequestFinished = time.Now().Unix()
c.JSON(500, models.Response{
Status: status.STATUS_SERVER_ERROR,
Info: fmt.Sprintf("Error: %s", err.Error()),
Meta: &meta,
})
return
}
meta.Count = count
meta.Limit = query.Limit
meta.Page = query.Page
c.JSON(200, models.Response{
Status: status.STATUS_OK,
Data: resp,
Meta: &meta,
})
}
type retireveNewsReq struct {
Code string `uri:"code" binding:"required"`
}
func (h *handlers) RetrieveNews(c *gin.Context) {
ctx := context.Background()
meta := models.Meta{
RequestStarted: time.Now().Unix(),
}
query := new(retireveNewsReq)
err := c.ShouldBindUri(query)
if err != nil {
meta.RequestFinished = time.Now().Unix()
c.JSON(400, models.Response{
Status: status.STATUS_BAD_REQUEST,
Info: fmt.Sprintf("Error: %s", err.Error()),
Meta: &meta,
})
return
}
s := storage.NewStorageArticle()
resp, _ := s.RetrieveArticle(ctx, query.Code)
meta.RequestFinished = time.Now().Unix()
statusResult := status.STATUS_OK
responseCode := 200
if resp == nil {
statusResult = status.STATUS_NOT_FOUND
responseCode = 404
}
c.JSON(responseCode, models.Response{
Status: statusResult,
Data: resp,
Meta: &meta,
})
}

View File

@ -0,0 +1,26 @@
package article
import (
"os"
"relynolli-server/handlers/article/endpoints"
"relynolli-server/internal"
"time"
"github.com/gin-contrib/cache"
"github.com/gin-gonic/gin"
)
func HandleRoutes(parent *gin.RouterGroup) {
h := endpoints.GetHandlers()
cacheStore := internal.InitCacheStore()
catalog := parent.Group("/articles")
if os.Getenv("IS_PROD") == "1" {
// Caching for production usage
catalog.GET("", cache.CachePage(cacheStore, 15*time.Minute, h.GetNews))
catalog.GET("/:code", cache.CachePage(cacheStore, 15*time.Minute, h.RetrieveNews))
} else {
catalog.GET("", h.GetNews)
catalog.GET("/:code", h.RetrieveNews)
}
}

View File

@ -24,11 +24,11 @@ func HandleRoutes(parent *gin.RouterGroup) {
catalog.GET("", cache.CachePage(cacheStore, 15*time.Minute, h.GetCatalogItems))
catalog.GET("/filters", cache.CachePage(cacheStore, 15*time.Minute, h.GetFilters))
catalog.GET("/:code", cache.CachePage(cacheStore, 15*time.Minute, h.GetCatalogItem))
}
} else {
catalog.GET("", h.GetCatalogItems)
catalog.GET("/:code", h.GetCatalogItem)
catalog.GET("/filters", h.GetFilters)
}
// catalog.GET("/filters", cache.CachePage(cacheStore, 15, h.GetFilters))
// catalog.GET("/count", cache.CachePage(cacheStore, 15 * time.Minute, h.Count))

View File

@ -0,0 +1,112 @@
package endpoints
import (
"context"
"encoding/json"
"fmt"
"github.com/geotrace/geo"
"github.com/gin-gonic/gin"
"os"
cdek "relynolli-server/CDEK/v2"
"relynolli-server/internal"
"relynolli-server/models"
"relynolli-server/status"
"time"
)
type handlers struct{}
type Handlers interface {
GetDeliveryPoints(c *gin.Context)
}
func GetHandlers() Handlers {
return &handlers{}
}
type CoordRequest struct {
Lat float64 `form:"lat"`
Lon float64 `form:"lon"`
}
func (h *handlers) GetDeliveryPoints(c *gin.Context) {
query := new(CoordRequest)
ctx := context.Background()
err := c.ShouldBindQuery(&query)
meta := models.Meta{
RequestStarted: time.Now().Unix(),
RequestFinished: 0,
}
resp := models.Response{
Status: status.STATUS_OK,
Info: "",
Data: nil,
Meta: &meta,
}
if err != nil {
meta.RequestFinished = time.Now().Unix()
resp.Info = err.Error()
c.JSON(400, resp)
return
}
client := cdek.NewClient(&cdek.Options{
Endpoint: cdek.EndpointProd,
Credentials: &cdek.Credentials{ClientID: os.Getenv("CDEK_ACCOUNT_ID"),
ClientSecret: os.Getenv("CDEK_API_KEY")},
})
if err != nil {
meta.RequestFinished = time.Now().Unix()
resp.Info = err.Error()
c.JSON(400, resp)
return
}
rdb := internal.InitRedis()
keys, _ := rdb.Keys(ctx, "CDEK_DP:*").Result()
preflightResult := []cdek.DeliveryPoint{}
if len(keys) == 0 {
r1, _ := client.DeliveryPoints(ctx, &cdek.DeliveryPointsRequest{})
pipe := rdb.Pipeline()
for _, d := range *r1 {
str, _ := json.Marshal(d)
pipe.Set(ctx, fmt.Sprintf("CDEK_DP:%s", d.Code), str, -1).Err()
preflightResult = append(preflightResult, d)
}
pipe.Exec(ctx)
} else {
for _, key := range keys {
item := new(cdek.DeliveryPoint)
data, _ := rdb.Get(ctx, key).Result()
json.Unmarshal([]byte(data), item)
preflightResult = append(preflightResult, *item)
}
}
pointOrigin := geo.Point{
query.Lon,
query.Lat,
}
resultedArray := []cdek.DeliveryPoint{}
for _, d := range preflightResult {
p1 := geo.Point{
d.Location.Longitude,
d.Location.Latitude,
}
if pointOrigin.Distance(p1) < 10000 {
resultedArray = append(resultedArray, d)
}
}
meta.RequestFinished = time.Now().Unix()
resp.Data = resultedArray
c.JSON(200, resp)
}

18
handlers/cdek/routes.go Normal file
View File

@ -0,0 +1,18 @@
package cdek
import (
"github.com/gin-gonic/gin"
"os"
"relynolli-server/handlers/cdek/endpoints"
)
func HandleRoutes(parent *gin.RouterGroup) {
h := endpoints.GetHandlers()
cdek := parent.Group("/cdek")
if os.Getenv("IS_PROD") == "1" {
// Caching for production usage
cdek.GET("/points", h.GetDeliveryPoints)
} else {
cdek.GET("/points", h.GetDeliveryPoints)
}
}

View File

@ -18,9 +18,10 @@ func HandleRoutes(parent *gin.RouterGroup) {
// Caching for production usage
catalog.GET("", cache.CachePage(cacheStore, 15*time.Minute, h.GetNews))
catalog.GET("/:code", cache.CachePage(cacheStore, 15*time.Minute, h.RetrieveNews))
}
} else {
catalog.GET("", h.GetNews)
catalog.GET("/:code", h.RetrieveNews)
}
}

View File

@ -19,6 +19,7 @@ type handlers struct{}
type getTotalRequest struct {
FuserId int `json:"fuserId"`
Coupon *string `json:"coupon,omitempty"`
}
type getTotalResponse struct {
@ -55,8 +56,16 @@ func (h handlers) GetTotal(c *gin.Context) {
return
}
data, err := s.GetTotal(ctx, int64(req.FuserId))
data, err := s.GetTotal(ctx, int64(req.FuserId), req.Coupon)
if err != nil {
resp.Status = status.STATUS_SERVER_ERROR
resp.Info = err.Error()
meta.RequestFinished = time.Now().Unix()
c.JSON(500, resp)
}
resp.Data = data
meta.RequestFinished = time.Now().Unix()
c.JSON(200, resp)
}

View File

@ -1,7 +1,10 @@
package handlers
import (
"relynolli-server/handlers/address"
"relynolli-server/handlers/article"
"relynolli-server/handlers/cart"
"relynolli-server/handlers/cdek"
"relynolli-server/handlers/news"
"relynolli-server/handlers/order"
@ -19,4 +22,7 @@ func InitializeRouter(router *gin.Engine) {
cart.HandleRoutes(APIV1Router)
news.HandleRoutes(APIV1Router)
order.HandleRoutes(APIV1Router)
article.HandleRoutes(APIV1Router)
address.HandleRoutes(APIV1Router)
cdek.HandleRoutes(APIV1Router)
}

View File

@ -1,9 +1,7 @@
package endpoints
import (
"fmt"
"net/http"
"relynolli-server/models"
"relynolli-server/services"
"github.com/gin-gonic/gin"
@ -24,8 +22,7 @@ func (_ handlers) Validate(c *gin.Context) {
req := ValidateReq{}
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest,
Info: fmt.Sprintf("Error: %s", err.Error())})
c.JSON(http.StatusBadRequest)
}
services.YookassaValidate(req.Object.Id, req.Object.Status)

View File

@ -6,6 +6,7 @@ import (
"os/signal"
"relynolli-server/handlers"
"relynolli-server/internal"
"relynolli-server/services"
"syscall"
"github.com/gin-contrib/cors"
@ -35,6 +36,7 @@ func main() {
signal.Notify(gracefullyShutDown, syscall.SIGINT, syscall.SIGTERM)
go server.Run("0.0.0.0:8000")
go services.PaymentValidation()
<-gracefullyShutDown

41
models/discount/db.go Normal file
View File

@ -0,0 +1,41 @@
package discount
import "github.com/uptrace/bun"
type DBDiscount struct {
bun.BaseModel `bun:"table:b_sale_discount"`
ID int64
Name string
Actions string
}
type DomainDiscounts struct {
ID int64
Name string
Actions *DomainActions
}
type DomainActions struct {
CLASSID string `json:"CLASS_ID"`
DATA struct {
All string `json:"All"`
} `json:"DATA"`
CHILDREN []struct {
CLASSID string `json:"CLASS_ID"`
DATA struct {
Type string `json:"Type"`
Value int `json:"Value"`
Unit string `json:"Unit"`
Max int `json:"Max"`
All string `json:"All"`
True string `json:"True"`
} `json:"DATA"`
CHILDREN map[string]struct {
CLASSID string `json:"CLASS_ID"`
DATA struct {
Logic string `json:"logic"`
Value string `json:"value"`
} `json:"DATA"`
} `json:"CHILDREN"`
} `json:"CHILDREN"`
}

View File

@ -17,3 +17,15 @@ type DBNews struct {
Picture string `bun:"picture" json:"picture"`
Date time.Time `bun:"date" json:"date"`
}
type DBArticle struct {
bun.BaseModel `bun:"select:api_article"`
ID int64 `bun:"id" json:"id"`
IsActive bool `bun:"is_active" json:"isActive"`
Sort int64 `bun:"sort" json:"sort"`
Name string `bun:"name" json:"name"`
Content string `bun:"content" json:"content"`
Code string `bun:"code" json:"code"`
Picture string `bun:"picture" json:"picture"`
Date time.Time `bun:"date" json:"date"`
}

21
models/order/db.go Normal file
View File

@ -0,0 +1,21 @@
package order
import (
"github.com/google/uuid"
"github.com/uptrace/bun"
)
type DBPayment struct {
bun.BaseModel `bun:"table:api_youkassa_payment"`
ID uuid.UUID `bun:"payment_id,type:char(36),pk" json:"id"`
OrderId int64 `bun:"order_id" json:"orderId"`
Status string `bun:"status" json:"status"`
Link string `bun:"link" json:"link"`
BitrixPayment *DBOrderPayment `bun:"-"`
}
type DBOrderPayment struct {
bun.BaseModel `bun:"table:b_sale_order_payment"`
ID int `bun:"ID,pk"`
OrderId int `bun:"ORDER_ID,pk"`
}

View File

@ -24,7 +24,7 @@ func addProductsToOrder(ctx context.Context, storage storage.StorageCart, api bi
}
for _, product := range *items {
err = api.AddProductToOrder(orderId, int(product.ProductId), product.Product.Price.BASE, int(product.Quantity))
err = api.AddProductToOrder(orderId, int(product.ProductId), product.Product.Price.BASE, int(product.Quantity), product.Product.Name)
if err != nil {
return err
}
@ -35,7 +35,7 @@ func addProductsToOrder(ctx context.Context, storage storage.StorageCart, api bi
//
func MakeOrder(ctx context.Context, fuserId int, email string, fullName string, phone string) (*kassa.KassaResult, error) {
func MakeOrder(ctx context.Context, fuserId int, email string, fullName, phone string) (*kassa.KassaResult, error) {
//
// Инициализируем api
s := storage.NewStorageCart()

View File

@ -1,5 +1,51 @@
package services
import (
"context"
"log"
"relynolli-server/external/bitrix"
"relynolli-server/external/kassa"
"relynolli-server/storage"
"time"
)
func PaymentValidation() {
ctx := context.Background()
s := storage.NewStorageOrder()
api := bitrix.Initialize()
for {
payments, err := s.GetPayments(ctx)
if err != nil {
panic(err.Error())
}
for _, payment := range *payments {
result, _ := kassa.CheckPayment(payment.ID)
if result == nil {
continue
}
payment.Status = result.Status
if result.Status == "succeeded" {
err := api.ApprovePayment(int(payment.BitrixPayment.ID), 8)
if err != nil {
log.Println(err.Error())
continue
}
}
if result.Status == "canceled" {
err := api.CancelOrder(int(payment.OrderId))
if err != nil {
log.Println(err.Error())
}
}
s.UpdatePayment(ctx, &payment)
time.Sleep(1 * time.Second)
}
time.Sleep(5 * time.Second)
}
}
//
//func YookassaValidate(paymentId string, status string) {
// stmt := fmt.Sprintf(`select t1.order_id as order_id, t2.ID as payment_id from api_youkassa_payment t1 join b_sale_order_payment t2 on t1.order_id = t2.ORDER_ID where t1.payment_id = '%s';`, paymentId)

View File

@ -1 +1,43 @@
package storage
import (
"context"
"relynolli-server/internal"
"relynolli-server/models/news"
)
type StorageArticle interface {
GetArticles(ctx context.Context, limit, offset int64) (int, *[]news.DBArticle, error)
RetrieveArticle(ctx context.Context, code string) (*news.DBArticle, error)
}
func NewStorageArticle() StorageArticle {
if instance == nil {
instance = &storage{
db: internal.InitDatabase().GetInstance(),
rdb: internal.InitRedis(),
}
}
return instance
}
func (s *storage) GetArticles(ctx context.Context, limit, offset int64) (int, *[]news.DBArticle, error) {
model := new([]news.DBArticle)
stmt := s.db.NewSelect().Model(model).Where("is_active = 1").OrderExpr("sort ASC, date DESC").Limit(int(limit)).Offset(int(offset))
count, err := stmt.ScanAndCount(ctx)
if err != nil {
return 0, nil, err
}
return count, model, nil
}
func (s *storage) RetrieveArticle(ctx context.Context, code string) (*news.DBArticle, error) {
model := new(news.DBArticle)
stmt := s.db.NewSelect().Model(model).Where("code = ?", code).Where("is_active = 1")
err := stmt.Scan(ctx)
if err != nil {
return nil, err
}
return model, nil
}

View File

@ -1,12 +1,22 @@
package storage
import (
"bytes"
"context"
"encoding/json"
"github.com/uptrace/bun"
"os/exec"
"relynolli-server/external/bitrix"
"relynolli-server/internal"
"relynolli-server/models/cart"
"relynolli-server/models/discount"
"relynolli-server/models/order"
)
type StorageOrder interface {
GetTotal(ctx context.Context, fuserId int64) (*TotalQuery, error)
GetTotal(ctx context.Context, fuserId int64, coupon *string) (*TotalQuery, error)
UpdatePayment(ctx context.Context, payment *order.DBPayment) error
GetPayments(ctx context.Context) (*[]order.DBPayment, error)
}
func NewStorageOrder() StorageOrder {
@ -19,16 +29,108 @@ func NewStorageOrder() StorageOrder {
return instance
}
type TotalQuery struct {
Total float64 `bun:"total" json:"total"`
type DiscountQuery struct {
Name string
Value int64
}
func (s *storage) GetTotal(ctx context.Context, fuserId int64) (*TotalQuery, error) {
model := new(TotalQuery)
stmt := `select sum(price.PRICE * cart.quantity) as total from api_cart cart left join b_catalog_price price on cart.product_id = price.PRODUCT_ID and cart.price_type_id = price.CATALOG_GROUP_ID where fuser_id = ?`
err := s.db.NewRaw(stmt, fuserId).Scan(ctx, model)
type QueryItem struct {
Cart *cart.DBCart `json:"cart"`
Discount *DiscountQuery `json:"discount"`
}
type TotalQuery struct {
Total float64 `bun:"total" json:"total"`
BasePrice float64 `bun:"-" json:"basePrice"`
Items *[]QueryItem `bun:"-" json:"items"`
}
func (s *storage) fetchDiscounts(ctx context.Context) (*[]discount.DBDiscount, error) {
model := new([]discount.DBDiscount)
err := s.db.NewSelect().Model(model).Scan(ctx)
if err != nil {
return nil, err
}
return model, nil
}
type DiscountType struct {
CLASSID string `json:"CLASS_ID"`
DATA struct {
All string `json:"All"`
} `json:"DATA"`
CHILDREN []struct {
CLASSID string `json:"CLASS_ID"`
DATA struct {
Type string `json:"Type"`
Value int `json:"Value"`
Unit string `json:"Unit"`
Max int `json:"Max"`
All string `json:"All"`
True string `json:"True"`
} `json:"DATA"`
CHILDREN []interface{} `json:"CHILDREN"`
} `json:"CHILDREN"`
}
func (s *storage) getDiscountForCoupon(ctx context.Context, coupon string) (*DiscountType, error) {
var couponDiscountPhpQuery string
stmt := "select disc.ACTIONS from b_sale_discount_coupon coupon join b_sale_discount disc on coupon.DISCOUNT_ID = disc.ID where coupon.COUPON = ? and coupon.ACTIVE = 'Y'"
err := s.db.NewRaw(stmt, coupon).Scan(ctx, &couponDiscountPhpQuery)
if err != nil {
return nil, err
}
var out bytes.Buffer
var result DiscountType
cmd := exec.Command("php", "test.php", couponDiscountPhpQuery)
cmd.Stdout = &out
err = cmd.Run()
if err != nil {
return nil, err
}
err = json.Unmarshal(out.Bytes(), &result)
if err != nil {
return nil, err
}
return &result, nil
}
func (s *storage) GetTotal(ctx context.Context, fuserId int64, coupon *string) (*TotalQuery, error) {
model := new(TotalQuery)
api := bitrix.Initialize()
data, err := api.GetTotalForProduct(int(fuserId), coupon)
if err != nil {
return nil, err
}
model.Total = data.Price
model.BasePrice = data.BasePrice
return model, nil
}
func (s *storage) GetPayments(ctx context.Context) (*[]order.DBPayment, error) {
var model []order.DBPayment
err := s.db.NewSelect().Model(&model).Where("status not in (?)", bun.In([]string{"succeeded", "canceled"})).Order("order_id DESC").Scan(ctx)
if err != nil {
return nil, err
}
for idx, item := range model {
bitrixPayment := new(order.DBOrderPayment)
s.db.NewSelect().Model(bitrixPayment).Where("ORDER_ID = ?", item.OrderId).Scan(ctx)
model[idx].BitrixPayment = bitrixPayment
}
return &model, nil
}
func (s *storage) UpdatePayment(ctx context.Context, payment *order.DBPayment) error {
_, err := s.db.NewUpdate().Model(payment).WherePK().Exec(ctx)
return err
}

9
test.php Normal file
View File

@ -0,0 +1,9 @@
<?php
$input = $argv[count($argv) - 1];
$output = unserialize($input);
echo json_encode($output) . "\n";
?>