Configuration of the Order Printer
The Order Printer offers extensive configuration options to adapt the system to your specific requirements.
Environment Configuration
The main configuration is done via the .env.local file. Here are the most important settings:
Shopware API Configuration
# Shopware API Access
SHOPWARE_HOST=https://your-shopware-domain.de
SHOPWARE_CLIENT_ID=your_client_id
SHOPWARE_CLIENT_SECRET=your_client_secret
# API Timeout (in seconds)
SHOPWARE_API_TIMEOUT=30
# API Rate Limiting
SHOPWARE_API_RATE_LIMIT=100
SHOPWARE_API_RATE_LIMIT_INTERVAL=60
Printer Configuration
# Printer connection: file:///dev/usb/lp0, tcp://<host>:9100 or dummy://
PRINTER_DSN=file:///dev/usb/lp0
# Optional: restaurant name on test receipts (bin/console printer:test), defaults to the SHOPWARE_HOST domain
SHOP_NAME="Masala Mio"
# Printer resolution (DPI)
PRINTER_DPI=203
# Characters per line
PRINTER_CHARACTERS_PER_LINE=42
# Print speed (1-5, 1 = slow, 5 = fast)
PRINTER_SPEED=3
# Printer density (1-15)
PRINTER_DENSITY=10
System Configuration
# Polling interval (in seconds)
POLLING_INTERVAL=10
# Maximum number of concurrent print jobs
MAX_CONCURRENT_PRINTS=5
# Queue timeout (in seconds)
QUEUE_TIMEOUT=300
# Data directory for receipt archive
DATA_DIR="/data/receipts/"
# Log level (debug, info, notice, warning, error, critical, alert, emergency)
LOG_LEVEL=info
Receipt Formatting
Standard Receipt Layout
The Order Printer generates receipts with the following standard layout:
┌────────────────────────────────────────┐
│ YOUR SHOP NAME │
│ Sample Street 123 • 12345 Sample City │
│ Tel: 01234/567890 │
├────────────────────────────────────────┤
│ RECEIPT #1001 │
│ 11.01.2024 14:30 │
├────────────────────────────────────────┤
│ Customer: Max Mustermann │
│ Tel: 0176/12345678 │
├────────────────────────────────────────┤
│ 1x Pizza Margherita 8,99 € │
│ 2x Spaghetti Bolognese 15,98 € │
│ 1x Salad Caesar 5,99 € │
├────────────────────────────────────────┤
│ Subtotal: 30,96 € │
│ Delivery costs: 2,50 € │
│ Total: 33,46 € │
├────────────────────────────────────────┤
│ Payment method: Cash │
│ Delivery type: Pickup │
├────────────────────────────────────────┤
│ Thank you for your │
│ purchase! │
└────────────────────────────────────────┘
Customize Receipt Layout
You can change the receipt layout by adjusting the ReceiptFormatter class:
// In src/Infra/Printer/Epson/ReceiptFormatter.php
public function formatHeader(): self
{
$this->content .= self::ALIGN_CENTER;
$this->content .= self::DOUBLE_WIDTH_ON;
$this->content .= "YOUR SHOP NAME\n";
$this->content .= self::DOUBLE_WIDTH_OFF;
$this->content .= self::ALIGN_CENTER;
$this->content .= "Sample Street 123 • 12345 Sample City\n";
$this->content .= "Tel: 01234/567890\n";
$this->content .= self::FEED;
return $this;
}
Add Logo
To add a logo to the receipt, you need to convert the logo to ESC/POS bitmap:
# Convert logo (requires ImageMagick)
convert logo.png -resize 384x128 -colorspace Gray -dither None logo.bmp
# Convert logo to ESC/POS format
php bin/console order-printer:convert-logo logo.bmp logo.escpos
Then you can include the logo in the ReceiptFormatter class:
public function addLogo(): self
{
$logoPath = __DIR__ . '/../../../public/logo.escpos';
if (file_exists($logoPath)) {
$this->content .= file_get_contents($logoPath);
$this->content .= self::FEED;
}
return $this;
}
Retries on Print Failures
Short outages are normal: the Pi reboots, the restaurant WLAN drops, the printer is out of paper. The Order Printer therefore never gives up after a single failed attempt:
- A failed print job is retried 10 times with increasing delays: 10 s, 20 s, 40 s, 80 s, 160 s and then every 5 minutes, about 30 minutes in total.
- The order stays open in Shopware until the receipt was actually printed. Only a successful print sets it to in progress.
- While a job is waiting for its retry, the poll does not queue the same order again. When the printer is back, every order is printed exactly once.
- After the last retry the job is marked as failed and an
errorlog line with the order number is written, for examplePrinting order 10556 failed permanently after 11 attempt(s): Cannot connect to printer "tcp://…". Use it for monitoring. Because the order is still open, the next poll queues it again and a new retry window starts, so nothing is lost as long as the printer comes back eventually.
Permanently failed jobs can be listed and cleaned up:
bin/console messenger:failed:show
bin/console messenger:failed:remove <id>
To reprint one order by hand:
bin/console app:print-order --order-number=10556
Advanced Configuration
Multiple Printers
One Order Printer instance prints to exactly one PRINTER_DSN. To drive several printers (for example kitchen and counter), run one instance per printer, each with its own .env.local, DATA_DIR and DATABASE_URL, pointing at the same Shopware shop. Because every instance marks printed orders as in progress, only one of them should run with --mark-in-progress; start the others with bin/console app:print-order --all-open --no-mark-in-progress on their own schedule, or filter orders per instance as described below.
Order Filtering
You can filter the orders to be retrieved by adjusting the OrderRepository class:
// In src/Infra/Shopware/OrderRepository.php
public function findNewNumbers(): array
{
// Only orders with certain payment methods
$paymentMethods = ['cash', 'card'];
// Only orders above a certain value
$minOrderValue = 5.00;
// Only orders for certain delivery types
$deliveryTypes = ['delivery', 'takeaway'];
return $this->shopwareClient->getOrders(
$paymentMethods,
$minOrderValue,
$deliveryTypes
);
}
Notifications
You can set up notifications for certain events:
# In config/packages/messenger.yaml
framework:
messenger:
routing:
'Veliu\OrderPrinter\Domain\Event\OrderPrintedEvent': async
'Veliu\OrderPrinter\Domain\Event\PrintFailedEvent': failed
Then you can create event listeners:
#[AsMessageHandler]
final class OrderPrintedNotificationHandler
{
public function __construct(
private MailerInterface $mailer,
private string $adminEmail
) {}
public function __invoke(OrderPrintedEvent $event): void
{
$email = (new Email())
->from('noreply@shopbite.de')
->to($this->adminEmail)
->subject('Order printed: ' . $event->orderNumber)
->text('The order ' . $event->orderNumber . ' has been successfully printed.');
$this->mailer->send($email);
}
}
Performance Optimization
Caching
Enable caching for frequently retrieved data:
# In config/packages/cache.yaml
framework:
cache:
app: cache.adapter.filesystem
default_redis_provider: 'redis://localhost'
pools:
shopware.cache:
adapter: cache.adapter.redis
default_lifetime: 3600
Batch Processing
For high order volumes, you can enable batch processing:
# Batch Configuration
BATCH_SIZE=10
BATCH_INTERVAL=30
Load Distribution
For systems with high throughput, you can set up multiple workers:
# Start multiple workers
bin/console messenger:consume async --limit=10 --time-limit=3600 &
bin/console messenger:consume async --limit=10 --time-limit=3600 &
bin/console messenger:consume async --limit=10 --time-limit=3600 &
Security
API Security
- Enforce HTTPS: Ensure your Shopware instance uses HTTPS
- IP Restriction: Restrict API access to specific IP addresses
- Rate Limiting: Configure appropriate rate limits
Printer Security
- Printer IP Restriction: Restrict access to the printer
- Printer Password: Set up a printer password
- Encryption: Use encrypted connections for network printers
Maintenance Configuration
Log Rotation
Set up log rotation to save disk space:
# Logrotate Configuration (/etc/logrotate.d/order-printer)
/var/log/order-printer-*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 644 www-data www-data
}
Data Cleanup
Set up regular data cleanup:
# Cron job for data cleanup (daily at 3 AM)
0 3 * * * /path/to/project/bin/console order-printer:cleanup --days=30