diff --git a/cmd/hardlink/main.go b/cmd/hardlink/main.go index df11d4d..daf5ce6 100644 --- a/cmd/hardlink/main.go +++ b/cmd/hardlink/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "encoding/xml" "fmt" "net/http" "os" @@ -34,7 +33,7 @@ import ( ) const ( - buildVersion = "v1.3.5" + buildVersion = "v1.3.6" serviceName = "hardlink" pollingFrequency = 8 * time.Second ) @@ -42,7 +41,6 @@ const ( func main() { // Load config cfg := config.ReadHardlinkConfig() - printer.Layout = readTicketLayout() printer.PrinterName = cfg.PrinterName lockserver.Cert = cfg.Cert lockserver.LockServerURL = cfg.LockserverURL @@ -157,27 +155,29 @@ func main() { fmt.Println("CreditCall payment provider enabled") case cmstypes.PaySystemPayBridge: - if reservationSystem.PaymentGatewayURL == "" { - errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "Payment Gateway URL not found", fmt.Errorf("payment provider paybridge requires paybridge.websocket_url")) + websocketURL := pdqSerialForKiosk(reservationSystem.PDQs, cfg.Kiosk) + + if websocketURL == "" { + errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "PayBridge websocket URL not found", fmt.Errorf("payment provider paybridge requires paybridge.websocket_url")) } if reservationSystem.PaymentGatewayAPIKeyWeb == "" { errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "Payment Gateway API Key not found", fmt.Errorf("payment provider paybridge requires paybridge.api_key")) } provider = paybridge.NewClient( - reservationSystem.PaymentGatewayURL, + websocketURL, reservationSystem.PaymentGatewayAPIKeyWeb, cfg.TimeoutSeconds, ) case cmstypes.PaySystemDojo: - var TerminalID string - for _, item := range reservationSystem.PDQs { - if item.Kiosk != cfg.Kiosk { - continue - } - TerminalID = item.Serial - break + TerminalID := pdqSerialForKiosk(reservationSystem.PDQs, cfg.Kiosk) + + if TerminalID == "" { + errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "Dojo Terminal ID not found", fmt.Errorf("payment provider dojo requires a terminal ID for kiosk %q in the CMS", cfg.Kiosk)) + } + if reservationSystem.PaymentGatewayURL == "" { + errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "Payment Gateway URL not found", fmt.Errorf("payment provider dojo requires dojo.websocket_url")) } dojoClient, err := dojo.NewClient(dojo.Config{ @@ -240,23 +240,23 @@ func main() { } } -func readTicketLayout() printer.LayoutOptions { - const layoutName = "TicketLayout.xml" - var layout printer.LayoutOptions +// func readTicketLayout() printer.LayoutOptions { +// const layoutName = "TicketLayout.xml" +// var layout printer.LayoutOptions - // 1) Read the file - data, err := os.ReadFile(layoutName) - if err != nil { - errorhandlers.FatalError(fmt.Errorf("failed to read %s: %v", layoutName, err)) - } +// // 1) Read the file +// data, err := os.ReadFile(layoutName) +// if err != nil { +// errorhandlers.FatalError(fmt.Errorf("failed to read %s: %v", layoutName, err)) +// } - // 2) Unmarshal into your struct - if err := xml.Unmarshal(data, &layout); err != nil { - errorhandlers.FatalError(fmt.Errorf("failed to parse %s: %v", layoutName, err)) - } +// // 2) Unmarshal into your struct +// if err := xml.Unmarshal(data, &layout); err != nil { +// errorhandlers.FatalError(fmt.Errorf("failed to parse %s: %v", layoutName, err)) +// } - return layout -} +// return layout +// } func startChipDnaClient() { startClient := func() (*exec.Cmd, error) { @@ -316,3 +316,13 @@ func startChipDnaClient() { os.Exit(0) }() } + +func pdqSerialForKiosk(pdqs []cmstypes.PDQRec, kiosk int) string { + for _, item := range pdqs { + if item.Kiosk == kiosk { + return item.Serial + } + } + + return "" +} \ No newline at end of file diff --git a/internal/printer/printer.go b/internal/printer/printer.go index ad0d32c..1881a99 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -13,6 +13,7 @@ import ( "path/filepath" "strings" + "gitea.futuresens.co.uk/futuresens/hardlink/internal/errorhandlers" "github.com/alexbrainman/printer" log "github.com/sirupsen/logrus" imagedraw "golang.org/x/image/draw" @@ -94,7 +95,30 @@ func ParseCardholderReceipt(data []byte) ([]ReceiptEntryXML, error) { return tr.ReceiptEntries.ReceiptEntry, nil } +func readTicketLayout() LayoutOptions { + var layout LayoutOptions + + executablePath, err := os.Executable() + if err != nil { + errorhandlers.FatalError(fmt.Errorf("failed to locate application executable: %v", err)) + } + + layoutName := filepath.Join(filepath.Dir(executablePath), "TicketLayout.xml") + data, err := os.ReadFile(layoutName) + if err != nil { + errorhandlers.FatalError(fmt.Errorf("failed to read %s: %v", layoutName, err)) + } + + if err := xml.Unmarshal(data, &layout); err != nil { + errorhandlers.FatalError(fmt.Errorf("failed to parse %s: %v", layoutName, err)) + } + + return layout +} + func BuildRoomTicket(details RoomDetailsRec) ([]byte, error) { + Layout = readTicketLayout() + var buf bytes.Buffer // shortcuts diff --git a/release notes.md b/release notes.md index 6b4cee5..65f3ed2 100644 --- a/release notes.md +++ b/release notes.md @@ -2,6 +2,10 @@ builtVersion is a const in main.go +#### v1.3.6 - 28 August 2026 +Refactor PDQ lookup for payment providers + + #### v1.3.5 - 23 July 2026 fixed dispenser delivery confirmation