mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
215 lines
5.0 KiB
Go
215 lines
5.0 KiB
Go
package services
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"fotbal-club/internal/config"
|
|
"fotbal-club/internal/models"
|
|
)
|
|
|
|
type PacketaService struct {
|
|
ApiPassword string
|
|
ApiUrl string
|
|
EshopName string
|
|
}
|
|
|
|
func NewPacketaService(cfg *config.Config) *PacketaService {
|
|
// Defaults
|
|
apiUrl := "https://www.zasilkovna.cz/api/rest"
|
|
eshopName := "MyClubEshop"
|
|
|
|
if cfg.PacketaEshopName != "" {
|
|
eshopName = cfg.PacketaEshopName
|
|
}
|
|
|
|
return &PacketaService{
|
|
ApiPassword: cfg.PacketaAPIPassword,
|
|
ApiUrl: apiUrl,
|
|
EshopName: eshopName,
|
|
}
|
|
}
|
|
|
|
// XML Structures
|
|
type CreatePacketRequest struct {
|
|
XMLName xml.Name `xml:"createPacket"`
|
|
ApiPassword string `xml:"apiPassword"`
|
|
PacketAttributes PacketAttributes `xml:"packetAttributes"`
|
|
}
|
|
|
|
type PacketAttributes struct {
|
|
Number string `xml:"number"`
|
|
Name string `xml:"name"`
|
|
Surname string `xml:"surname"`
|
|
Email string `xml:"email"`
|
|
Phone string `xml:"phone"`
|
|
AddressId string `xml:"addressId"`
|
|
Value string `xml:"value"`
|
|
Currency string `xml:"currency"`
|
|
Weight string `xml:"weight"`
|
|
Eshop string `xml:"eshop"`
|
|
}
|
|
|
|
type CreatePacketResponse struct {
|
|
XMLName xml.Name `xml:"response"`
|
|
Status string `xml:"status"`
|
|
Result PacketResult `xml:"result"`
|
|
Fault *PacketFault `xml:"fault"`
|
|
}
|
|
|
|
type PacketResult struct {
|
|
PacketId string `xml:"packetId"`
|
|
LabelUrl string `xml:"labelUrl"` // Not standard, usually requires separate call
|
|
Barcode string `xml:"barcode"`
|
|
}
|
|
|
|
type PacketFault struct {
|
|
String string `xml:"string"`
|
|
Detail string `xml:"detail"`
|
|
}
|
|
|
|
// CreatePacket calls Packeta API to register the shipment
|
|
func (s *PacketaService) CreatePacket(order *models.EshopOrder, addressId string) (string, error) {
|
|
if s.ApiPassword == "" {
|
|
return "", fmt.Errorf("Packeta API password not configured")
|
|
}
|
|
|
|
req := CreatePacketRequest{
|
|
ApiPassword: s.ApiPassword,
|
|
PacketAttributes: PacketAttributes{
|
|
Number: order.OrderNumber,
|
|
Name: order.FirstName,
|
|
Surname: order.LastName,
|
|
Email: order.Email,
|
|
Phone: "", // Add phone to order model if needed
|
|
AddressId: addressId,
|
|
Value: fmt.Sprintf("%.2f", float64(order.TotalAmountCents)/100.0),
|
|
Currency: order.Currency,
|
|
Weight: "1.0", // Default weight, should come from product sum
|
|
Eshop: s.EshopName,
|
|
},
|
|
}
|
|
|
|
xmlData, err := xml.Marshal(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
resp, err := http.Post(s.ApiUrl, "text/xml", bytes.NewBuffer(xmlData))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
|
|
var xmlResp CreatePacketResponse
|
|
if err := xml.Unmarshal(body, &xmlResp); err != nil {
|
|
return "", fmt.Errorf("failed to parse response: %v", err)
|
|
}
|
|
|
|
if xmlResp.Status != "ok" {
|
|
msg := "unknown error"
|
|
if xmlResp.Fault != nil {
|
|
msg = xmlResp.Fault.String + ": " + xmlResp.Fault.Detail
|
|
}
|
|
return "", fmt.Errorf("packeta error: %s", msg)
|
|
}
|
|
|
|
return xmlResp.Result.PacketId, nil
|
|
}
|
|
|
|
// Helper struct for packet status
|
|
type PacketStatusRequest struct {
|
|
XMLName xml.Name `xml:"packetStatus"`
|
|
ApiPassword string `xml:"apiPassword"`
|
|
PacketId string `xml:"packetId"`
|
|
}
|
|
|
|
type PacketStatusResponse struct {
|
|
XMLName xml.Name `xml:"response"`
|
|
Status string `xml:"status"`
|
|
Result PacketStatusResult `xml:"result"`
|
|
}
|
|
|
|
type PacketStatusResult struct {
|
|
StatusCode string `xml:"statusCode"`
|
|
StatusText string `xml:"statusText"`
|
|
}
|
|
|
|
func (s *PacketaService) GetPacketLabel(packetId string) ([]byte, error) {
|
|
if s.ApiPassword == "" {
|
|
return nil, fmt.Errorf("Packeta API password not configured")
|
|
}
|
|
|
|
type PacketLabelPdfRequest struct {
|
|
XMLName xml.Name `xml:"packetLabelPdf"`
|
|
ApiPassword string `xml:"apiPassword"`
|
|
PacketId string `xml:"packetId"`
|
|
Format string `xml:"format"`
|
|
Offset int `xml:"offset"`
|
|
}
|
|
|
|
req := PacketLabelPdfRequest{
|
|
ApiPassword: s.ApiPassword,
|
|
PacketId: packetId,
|
|
Format: "A6 on A4",
|
|
Offset: 0,
|
|
}
|
|
|
|
xmlData, err := xml.Marshal(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := http.Post(s.ApiUrl, "text/xml", bytes.NewBuffer(xmlData))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("label request failed with status %d", resp.StatusCode)
|
|
}
|
|
|
|
return body, nil
|
|
}
|
|
|
|
func (s *PacketaService) GetPacketStatus(packetId string) (string, error) {
|
|
req := PacketStatusRequest{
|
|
ApiPassword: s.ApiPassword,
|
|
PacketId: packetId,
|
|
}
|
|
|
|
xmlData, err := xml.Marshal(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
resp, err := http.Post(s.ApiUrl, "text/xml", bytes.NewBuffer(xmlData))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
var xmlResp PacketStatusResponse
|
|
if err := xml.Unmarshal(body, &xmlResp); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if xmlResp.Status != "ok" {
|
|
return "", fmt.Errorf("status check failed")
|
|
}
|
|
|
|
return xmlResp.Result.StatusText, nil
|
|
}
|