Skip to content
Open
108 changes: 108 additions & 0 deletions api/create_checkout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import sys
import uuid
import requests

TOKEN_FILE = "/var/www/html/config/sumup_token.txt"

ACCESS_TOKEN = ""
MERCHANT_CODE = ""
AMOUNT_CENTS = 0
RETURN_URL = ""

API_BASE_V01 = "https://api.sumup.com/v0.1"


def load_access_token():
global ACCESS_TOKEN

try:
with open(TOKEN_FILE, "r", encoding="utf-8") as f:
ACCESS_TOKEN = f.read().strip()
except Exception as e:
print(f"ERROR: token file unreadable: {e}", file=sys.stderr)
sys.exit(1)

if not ACCESS_TOKEN:
print("ERROR: token file is empty", file=sys.stderr)
sys.exit(1)


def auth_headers():
return {
"Authorization": f"Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
}


def parse_args():
global MERCHANT_CODE, AMOUNT_CENTS, RETURN_URL

if len(sys.argv) < 4:
print(
"Usage: create_checkout.py MERCHANT_CODE AMOUNT_CENTS RETURN_URL",
file=sys.stderr,
)
sys.exit(1)

MERCHANT_CODE = sys.argv[1].strip()

try:
AMOUNT_CENTS = int(sys.argv[2])
except ValueError:
print("ERROR: AMOUNT_CENTS must be an integer", file=sys.stderr)
sys.exit(1)

RETURN_URL = sys.argv[3].strip()

if not MERCHANT_CODE:
print("ERROR: MERCHANT_CODE missing", file=sys.stderr)
sys.exit(1)

if AMOUNT_CENTS <= 0:
print("ERROR: AMOUNT_CENTS invalid", file=sys.stderr)
sys.exit(1)

if not RETURN_URL:
print("ERROR: RETURN_URL missing", file=sys.stderr)
sys.exit(1)


def main():
load_access_token()
parse_args()

checkout_reference = "PHOTO-" + str(uuid.uuid4())[:8]
amount_eur = AMOUNT_CENTS / 100.0

url = f"{API_BASE_V01}/checkouts"

payload = {
"checkout_reference": checkout_reference,
"amount": amount_eur,
"currency": "EUR",
"merchant_code": MERCHANT_CODE,
"description": "Fotobox Ausdruck",
"hosted_checkout": {"enabled": True},
"return_url": RETURN_URL,
}

response = requests.post(url, json=payload, headers=auth_headers(), timeout=30)

print("Status:", response.status_code)
print("Antwort:", response.text)

if response.status_code != 201:
sys.exit(1)

data = response.json()
payment_link = data.get("hosted_checkout_url", "").strip()

if not payment_link:
print("ERROR: hosted_checkout_url missing", file=sys.stderr)
sys.exit(1)

print(payment_link)


if __name__ == "__main__":
main()
38 changes: 38 additions & 0 deletions api/paymentStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

use Photobooth\Utility\PathUtility;

require_once dirname(__DIR__) . '/lib/boot.php';

header('Content-Type: application/json');

$jobFile = PathUtility::getAbsolutePath('private/photobooth_current_print.json');

if (!is_file($jobFile)) {
echo json_encode([
'status' => 'missing',
'paid' => false,
'printed' => false,
]);
exit;
}

$data = json_decode((string)file_get_contents($jobFile), true);

if (!is_array($data)) {
echo json_encode([
'status' => 'invalid',
'paid' => false,
'printed' => false,
]);
exit;
}

echo json_encode([
'status' => 'ok',
'paid' => (bool)($data['paid'] ?? false),
'printed' => (bool)($data['printed'] ?? false),
'filename' => (string)($data['filename'] ?? ''),
]);
94 changes: 94 additions & 0 deletions api/runConfiguredPrint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

declare(strict_types=1);

/**
* Photobooth Payment Print Script (CLI)
* * Dieses Skript wird von den SumUp-Python-Skripten aufgerufen,
* sobald eine Zahlung erfolgreich war. Es nutzt den in der
* Photobooth-Konfiguration hinterlegten Druckbefehl.
*/

use Photobooth\Service\ConfigurationService;
use Photobooth\Service\LoggerService;
use Photobooth\Utility\PathUtility;

require_once dirname(__DIR__) . '/lib/boot.php';

// Sicherstellen, dass das Skript nur über die Konsole gestartet wird
if (PHP_SAPI !== 'cli') {
fwrite(STDERR, "ERROR: CLI only\n");
exit(1);
}

// Argumente einlesen
$filename = $argv[1] ?? '';
$copies = (int)($argv[2] ?? 1);

if ($filename === '') {
fwrite(STDERR, "ERROR: Missing filename\n");
exit(1);
}

// Konfiguration laden
$config = ConfigurationService::getInstance()->getConfiguration();
$printCmd = (string)($config['commands']['print'] ?? '');

if ($printCmd === '') {
fwrite(STDERR, "ERROR: commands.print is empty in Photobooth config\n");
exit(1);
}

// Logger initialisieren (Schreibt in var/log/main.log)
$logger = LoggerService::getInstance()->getLogger('main');

// Pfad zum Bild auflösen
$resolvedFilename = $filename;
if (!str_starts_with($resolvedFilename, '/')) {
$resolvedFilename = PathUtility::getAbsolutePath('data/print/' . ltrim($resolvedFilename, '/'));
}

// Druckbefehl vorbereiten (Platzhalter %s ersetzen)
$cmd = str_replace('%s', escapeshellarg($resolvedFilename), $printCmd);

$output = [];
$returnVar = 1;

// Logge den Start des Vorgangs
$logger->info('Payment Print: Starte System-Druckbefehl', [
'file' => $resolvedFilename,
'copies' => $copies
]);

// Befehl ausführen und Rückgabe sowie Fehler (2>&1) abfangen
exec($cmd . ' 2>&1', $output, $returnVar);

$outputString = implode(' ', $output);

// Ergebnis verarbeiten und loggen
if ($returnVar === 0) {
// Erfolgreich (an das Betriebssystem übergeben)
$logger->info('Payment Print: Druck erfolgreich ausgelöst', [
'output' => $outputString
]);
} else {
// Fehler beim Druckbefehl
$logger->error('Payment Print: Fehler beim Ausführen des Druckbefehls', [
'return_code' => $returnVar,
'cmd' => $cmd,
'output' => $outputString
]);
}

// Backup-Log in private/ (hilfreich für Standalone-Debugging)
$logFile = PathUtility::getAbsolutePath('private/payment-print.log');
$logEntry = sprintf(
"[%s] File: %s | Return: %d | Output: %s\n",
date('c'),
$resolvedFilename,
$returnVar,
$outputString
);
file_put_contents($logFile, $logEntry, FILE_APPEND);

exit($returnVar);
Loading
Loading