Refactor PDQ lookup for payment providers

This commit is contained in:
yurii 2026-08-28 16:32:51 +01:00
parent 5e99a8e0d4
commit ea578fe03e
3 changed files with 65 additions and 27 deletions

View File

@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
"encoding/xml"
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
@ -34,7 +33,7 @@ import (
) )
const ( const (
buildVersion = "v1.3.5" buildVersion = "v1.3.6"
serviceName = "hardlink" serviceName = "hardlink"
pollingFrequency = 8 * time.Second pollingFrequency = 8 * time.Second
) )
@ -42,7 +41,6 @@ const (
func main() { func main() {
// Load config // Load config
cfg := config.ReadHardlinkConfig() cfg := config.ReadHardlinkConfig()
printer.Layout = readTicketLayout()
printer.PrinterName = cfg.PrinterName printer.PrinterName = cfg.PrinterName
lockserver.Cert = cfg.Cert lockserver.Cert = cfg.Cert
lockserver.LockServerURL = cfg.LockserverURL lockserver.LockServerURL = cfg.LockserverURL
@ -157,27 +155,29 @@ func main() {
fmt.Println("CreditCall payment provider enabled") fmt.Println("CreditCall payment provider enabled")
case cmstypes.PaySystemPayBridge: case cmstypes.PaySystemPayBridge:
if reservationSystem.PaymentGatewayURL == "" { websocketURL := pdqSerialForKiosk(reservationSystem.PDQs, cfg.Kiosk)
errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "Payment Gateway URL not found", fmt.Errorf("payment provider paybridge requires paybridge.websocket_url"))
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 == "" { if reservationSystem.PaymentGatewayAPIKeyWeb == "" {
errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "Payment Gateway API Key not found", fmt.Errorf("payment provider paybridge requires paybridge.api_key")) errorhandlers.FatalErrorWithMail(cfg.Hotel, cfg.Kiosk, "Payment Gateway API Key not found", fmt.Errorf("payment provider paybridge requires paybridge.api_key"))
} }
provider = paybridge.NewClient( provider = paybridge.NewClient(
reservationSystem.PaymentGatewayURL, websocketURL,
reservationSystem.PaymentGatewayAPIKeyWeb, reservationSystem.PaymentGatewayAPIKeyWeb,
cfg.TimeoutSeconds, cfg.TimeoutSeconds,
) )
case cmstypes.PaySystemDojo: case cmstypes.PaySystemDojo:
var TerminalID string TerminalID := pdqSerialForKiosk(reservationSystem.PDQs, cfg.Kiosk)
for _, item := range reservationSystem.PDQs {
if item.Kiosk != cfg.Kiosk { if TerminalID == "" {
continue 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))
} }
TerminalID = item.Serial if reservationSystem.PaymentGatewayURL == "" {
break 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{ dojoClient, err := dojo.NewClient(dojo.Config{
@ -240,23 +240,23 @@ func main() {
} }
} }
func readTicketLayout() printer.LayoutOptions { // func readTicketLayout() printer.LayoutOptions {
const layoutName = "TicketLayout.xml" // const layoutName = "TicketLayout.xml"
var layout printer.LayoutOptions // var layout printer.LayoutOptions
// 1) Read the file // // 1) Read the file
data, err := os.ReadFile(layoutName) // data, err := os.ReadFile(layoutName)
if err != nil { // if err != nil {
errorhandlers.FatalError(fmt.Errorf("failed to read %s: %v", layoutName, err)) // errorhandlers.FatalError(fmt.Errorf("failed to read %s: %v", layoutName, err))
} // }
// 2) Unmarshal into your struct // // 2) Unmarshal into your struct
if err := xml.Unmarshal(data, &layout); err != nil { // if err := xml.Unmarshal(data, &layout); err != nil {
errorhandlers.FatalError(fmt.Errorf("failed to parse %s: %v", layoutName, err)) // errorhandlers.FatalError(fmt.Errorf("failed to parse %s: %v", layoutName, err))
} // }
return layout // return layout
} // }
func startChipDnaClient() { func startChipDnaClient() {
startClient := func() (*exec.Cmd, error) { startClient := func() (*exec.Cmd, error) {
@ -316,3 +316,13 @@ func startChipDnaClient() {
os.Exit(0) os.Exit(0)
}() }()
} }
func pdqSerialForKiosk(pdqs []cmstypes.PDQRec, kiosk int) string {
for _, item := range pdqs {
if item.Kiosk == kiosk {
return item.Serial
}
}
return ""
}

View File

@ -13,6 +13,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"gitea.futuresens.co.uk/futuresens/hardlink/internal/errorhandlers"
"github.com/alexbrainman/printer" "github.com/alexbrainman/printer"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
imagedraw "golang.org/x/image/draw" imagedraw "golang.org/x/image/draw"
@ -94,7 +95,30 @@ func ParseCardholderReceipt(data []byte) ([]ReceiptEntryXML, error) {
return tr.ReceiptEntries.ReceiptEntry, nil 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) { func BuildRoomTicket(details RoomDetailsRec) ([]byte, error) {
Layout = readTicketLayout()
var buf bytes.Buffer var buf bytes.Buffer
// shortcuts // shortcuts

View File

@ -2,6 +2,10 @@
builtVersion is a const in main.go 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 #### v1.3.5 - 23 July 2026
fixed dispenser delivery confirmation fixed dispenser delivery confirmation