Skip to content

Commit 8a2f85e

Browse files
frogroandi34
authored andcommitted
Add SumUp payment integration
Change-Id: I6144c0db0c2541d89ba926ba071f3a491ea12a1d
1 parent 3c17a04 commit 8a2f85e

19 files changed

+6407
-568
lines changed

api/create_checkout.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import sys
2+
import uuid
3+
import requests
4+
5+
TOKEN_FILE = "/var/www/html/config/sumup_token.txt"
6+
7+
ACCESS_TOKEN = ""
8+
MERCHANT_CODE = ""
9+
AMOUNT_CENTS = 0
10+
RETURN_URL = ""
11+
12+
API_BASE_V01 = "https://api.sumup.com/v0.1"
13+
14+
15+
def load_access_token():
16+
global ACCESS_TOKEN
17+
18+
try:
19+
with open(TOKEN_FILE, "r", encoding="utf-8") as f:
20+
ACCESS_TOKEN = f.read().strip()
21+
except Exception as e:
22+
print(f"ERROR: token file unreadable: {e}", file=sys.stderr)
23+
sys.exit(1)
24+
25+
if not ACCESS_TOKEN:
26+
print("ERROR: token file is empty", file=sys.stderr)
27+
sys.exit(1)
28+
29+
30+
def auth_headers():
31+
return {
32+
"Authorization": f"Bearer {ACCESS_TOKEN}",
33+
"Content-Type": "application/json",
34+
}
35+
36+
37+
def parse_args():
38+
global MERCHANT_CODE, AMOUNT_CENTS, RETURN_URL
39+
40+
if len(sys.argv) < 4:
41+
print("Usage: create_checkout.py MERCHANT_CODE AMOUNT_CENTS RETURN_URL", file=sys.stderr)
42+
sys.exit(1)
43+
44+
MERCHANT_CODE = sys.argv[1].strip()
45+
46+
try:
47+
AMOUNT_CENTS = int(sys.argv[2])
48+
except ValueError:
49+
print("ERROR: AMOUNT_CENTS must be an integer", file=sys.stderr)
50+
sys.exit(1)
51+
52+
RETURN_URL = sys.argv[3].strip()
53+
54+
if not MERCHANT_CODE:
55+
print("ERROR: MERCHANT_CODE missing", file=sys.stderr)
56+
sys.exit(1)
57+
58+
if AMOUNT_CENTS <= 0:
59+
print("ERROR: AMOUNT_CENTS invalid", file=sys.stderr)
60+
sys.exit(1)
61+
62+
if not RETURN_URL:
63+
print("ERROR: RETURN_URL missing", file=sys.stderr)
64+
sys.exit(1)
65+
66+
67+
def main():
68+
load_access_token()
69+
parse_args()
70+
71+
checkout_reference = "PHOTO-" + str(uuid.uuid4())[:8]
72+
amount_eur = AMOUNT_CENTS / 100.0
73+
74+
url = f"{API_BASE_V01}/checkouts"
75+
76+
payload = {
77+
"checkout_reference": checkout_reference,
78+
"amount": amount_eur,
79+
"currency": "EUR",
80+
"merchant_code": MERCHANT_CODE,
81+
"description": "Fotobox Ausdruck",
82+
"hosted_checkout": {
83+
"enabled": True
84+
},
85+
"return_url": RETURN_URL
86+
}
87+
88+
response = requests.post(url, json=payload, headers=auth_headers(), timeout=30)
89+
90+
print("Status:", response.status_code)
91+
print("Antwort:", response.text)
92+
93+
if response.status_code != 201:
94+
sys.exit(1)
95+
96+
data = response.json()
97+
payment_link = data.get("hosted_checkout_url", "").strip()
98+
99+
if not payment_link:
100+
print("ERROR: hosted_checkout_url missing", file=sys.stderr)
101+
sys.exit(1)
102+
103+
print(payment_link)
104+
105+
106+
if __name__ == "__main__":
107+
main()

api/paymentStatus.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Photobooth\Utility\PathUtility;
6+
7+
require_once dirname(__DIR__) . '/lib/boot.php';
8+
9+
header('Content-Type: application/json');
10+
11+
$jobFile = PathUtility::getAbsolutePath('private/photobooth_current_print.json');
12+
13+
if (!is_file($jobFile)) {
14+
echo json_encode([
15+
'status' => 'missing',
16+
'paid' => false,
17+
'printed' => false,
18+
]);
19+
exit;
20+
}
21+
22+
$data = json_decode((string)file_get_contents($jobFile), true);
23+
24+
if (!is_array($data)) {
25+
echo json_encode([
26+
'status' => 'invalid',
27+
'paid' => false,
28+
'printed' => false,
29+
]);
30+
exit;
31+
}
32+
33+
echo json_encode([
34+
'status' => 'ok',
35+
'paid' => (bool)($data['paid'] ?? false),
36+
'printed' => (bool)($data['printed'] ?? false),
37+
'filename' => (string)($data['filename'] ?? ''),
38+
]);

api/runConfiguredPrint.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Photobooth Payment Print Script (CLI)
7+
* * Dieses Skript wird von den SumUp-Python-Skripten aufgerufen,
8+
* sobald eine Zahlung erfolgreich war. Es nutzt den in der
9+
* Photobooth-Konfiguration hinterlegten Druckbefehl.
10+
*/
11+
12+
use Photobooth\Service\ConfigurationService;
13+
use Photobooth\Service\LoggerService;
14+
use Photobooth\Utility\PathUtility;
15+
16+
require_once dirname(__DIR__) . '/lib/boot.php';
17+
18+
// Sicherstellen, dass das Skript nur über die Konsole gestartet wird
19+
if (PHP_SAPI !== 'cli') {
20+
fwrite(STDERR, "ERROR: CLI only\n");
21+
exit(1);
22+
}
23+
24+
// Argumente einlesen
25+
$filename = $argv[1] ?? '';
26+
$copies = (int)($argv[2] ?? 1);
27+
28+
if ($filename === '') {
29+
fwrite(STDERR, "ERROR: Missing filename\n");
30+
exit(1);
31+
}
32+
33+
// Konfiguration laden
34+
$config = ConfigurationService::getInstance()->getConfiguration();
35+
$printCmd = (string)($config['commands']['print'] ?? '');
36+
37+
if ($printCmd === '') {
38+
fwrite(STDERR, "ERROR: commands.print is empty in Photobooth config\n");
39+
exit(1);
40+
}
41+
42+
// Logger initialisieren (Schreibt in var/log/main.log)
43+
$logger = LoggerService::getInstance()->getLogger('main');
44+
45+
// Pfad zum Bild auflösen
46+
$resolvedFilename = $filename;
47+
if (!str_starts_with($resolvedFilename, '/')) {
48+
$resolvedFilename = PathUtility::getAbsolutePath('data/print/' . ltrim($resolvedFilename, '/'));
49+
}
50+
51+
// Druckbefehl vorbereiten (Platzhalter %s ersetzen)
52+
$cmd = str_replace('%s', escapeshellarg($resolvedFilename), $printCmd);
53+
54+
$output = [];
55+
$returnVar = 1;
56+
57+
// Logge den Start des Vorgangs
58+
$logger->info('Payment Print: Starte System-Druckbefehl', [
59+
'file' => $resolvedFilename,
60+
'copies' => $copies
61+
]);
62+
63+
// Befehl ausführen und Rückgabe sowie Fehler (2>&1) abfangen
64+
exec($cmd . ' 2>&1', $output, $returnVar);
65+
66+
$outputString = implode(' ', $output);
67+
68+
// Ergebnis verarbeiten und loggen
69+
if ($returnVar === 0) {
70+
// Erfolgreich (an das Betriebssystem übergeben)
71+
$logger->info('Payment Print: Druck erfolgreich ausgelöst', [
72+
'output' => $outputString
73+
]);
74+
} else {
75+
// Fehler beim Druckbefehl
76+
$logger->error('Payment Print: Fehler beim Ausführen des Druckbefehls', [
77+
'return_code' => $returnVar,
78+
'cmd' => $cmd,
79+
'output' => $outputString
80+
]);
81+
}
82+
83+
// Backup-Log in private/ (hilfreich für Standalone-Debugging)
84+
$logFile = PathUtility::getAbsolutePath('private/payment-print.log');
85+
$logEntry = sprintf(
86+
"[%s] File: %s | Return: %d | Output: %s\n",
87+
date('c'),
88+
$resolvedFilename,
89+
$returnVar,
90+
$outputString
91+
);
92+
file_put_contents($logFile, $logEntry, FILE_APPEND);
93+
94+
exit($returnVar);

0 commit comments

Comments
 (0)