dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
shop_integrity_test.php
Go to the documentation of this file.
1<?php
2
3$root = dirname(__DIR__);
4$repo = file_get_contents($root . '/include/dbxShopRepository.class.php');
5$service = file_get_contents($root . '/include/dbxShopService.class.php');
6
7$fail = static function (string $message, int $code): void {
8 fwrite(STDERR, "FAIL: $message\n");
9 exit($code);
10};
11
12if (!is_string($repo) || !is_string($service)) {
13 $fail('Shop-Quellen konnten nicht gelesen werden.', 1);
14}
15if (strpos($repo, 'AND trash = 0 AND stock >= ') === false
16 || strpos($repo, 'stock = stock - ') === false) {
17 $fail('Bestand wird nicht atomar und ohne Unterlauf reserviert.', 2);
18}
19if (substr_count($repo, "begin(\$this->dd('shopOrder'))") < 3
20 || strpos($repo, 'order_item_insert_failed') === false
21 || strpos($repo, 'order_history_insert_failed') === false) {
22 $fail('Bestellung, Positionen, Bestand und Historie bilden keine Transaktion.', 3);
23}
24if (strpos($repo, 'channel_import_lock_failed') === false
25 || strpos($repo, 'Zweite Idempotenzpruefung nach dem serialisierenden Channel-Lock.') === false) {
26 $fail('Parallele Channel-Importe werden nicht datenbankweit vor der Duplikatpruefung serialisiert.', 10);
27}
28if (strpos($repo, 'private function decorateProducts(array $rows): array') === false
29 || strpos($repo, 'return $this->decorateProducts($rows);') === false
30 || strpos($repo, 'foreach ($this->decorateProducts(is_array($rows) ? $rows : array()) as $row)') === false) {
31 $fail('Produktlisten verwenden nicht einheitlich die gebuendelte Repository-Datensicht.', 11);
32}
33if (strpos($service, 'private function shopTemplateFields(string $template): array') === false
34 || strpos($service, '$this->productTemplateData($product, $channel, false, $this->shopTemplateFields($template))') === false
35 || strpos($service, '$this->productTemplateData(' . "\n" . ' $product,' . "\n" . ' $channel,' . "\n" . ' true,') === false) {
36 $fail('Produktkarten und -details berechnen nicht nur die vom Template verwendeten Werte.', 12);
37}
38$allImages = preg_match('/public function allImages\\(\\): array \\{([\\s\\S]*?)\\n \\}/', $repo, $match)
39 ? $match[1]
40 : '';
41if (strpos($allImages, '$productById = $this->rowsById') === false
42 || strpos($allImages, '$groupById = $this->rowsById') === false
43 || strpos($allImages, '->select1(') !== false) {
44 $fail('Die Admin-Bildliste laedt Produkt- und Gruppentitel nicht gebuendelt.', 13);
45}
46if (strpos($repo, 'claimOrderPayment') === false
47 || strpos($repo, "'payment_status' => 'processing'") === false
48 || strpos($repo, '(int)$db->_update_count !== 1') === false) {
49 $fail('Provider-Abschluesse sind nicht gegen parallele Wiederholung beansprucht.', 4);
50}
51if (strpos($repo, 'isStalePaymentProcessing') === false
52 || strpos($repo, 'payment_processing_retry_seconds') === false
53 || strpos($repo, "' AND update_date = '") === false) {
54 $fail('Verwaiste processing-Claims besitzen keinen zeitlich und atomar begrenzten Wiederanlauf.', 9);
55}
56if (strpos($service, "providerReturnOrder('paypal'") === false
57 || strpos($service, "providerReturnOrder('amazon_pay'") === false
58 || strpos($service, 'validateCapture(') === false
59 || strpos($service, 'validateCompletion(') === false) {
60 $fail('Provider-Ruecklaeufe werden nicht vollstaendig gebunden und verifiziert.', 5);
61}
62if (strpos($service, 'checkoutRequestOrder($requestId)') === false
63 || strpos($service, 'rememberCheckoutRequest($requestId, $order)') === false) {
64 $fail('Wiederholte Checkout-POSTs sind nicht an eine idempotente Request-ID gebunden.', 6);
65}
66
67$paypalCancel = preg_match('/public function paypalCancel\\(\\): string \\{([\\s\\S]*?)\\n \\}/', $service, $match)
68 ? $match[1]
69 : '';
70$amazonCancel = preg_match('/public function amazonPayCancel\\(\\): string \\{([\\s\\S]*?)\\n \\}/', $service, $match)
71 ? $match[1]
72 : '';
73if (strpos($paypalCancel, 'updateOrderPayment') !== false || strpos($amazonCancel, 'updateOrderPayment') !== false) {
74 $fail('Ein nicht verifizierter Browser-Cancel veraendert weiterhin den Zahlungsstatus.', 7);
75}
76
77if (strpos($service, "if (\$secret === '')") === false
78 || strpos($service, 'Webhook-Authentifizierung ist nicht konfiguriert.') === false
79 || strpos($service, "\$_GET['secret']") !== false) {
80 $fail('Der oeffentliche Channel-Webhook ist nicht fail-closed oder akzeptiert Secrets aus GET-URLs.', 8);
81}
82
83echo "OK shop integrity\n";
exit
Definition index.php:146
if(strpos($allImages, ' $productById=$this->rowsById')===false||strpos($allImages, ' $groupById=$this->rowsById')===false||strpos($allImages, '->select1(') !==false) if(strpos( $repo, 'claimOrderPayment')===false||strpos( $repo, "'payment_status' => 'processing'")===false||strpos( $repo, '(int) $db->_update_count !==1')===false) if(strpos($repo, 'isStalePaymentProcessing')===false||strpos($repo, 'payment_processing_retry_seconds')===false||strpos($repo, "' AND update_date = '")===false) if(strpos( $service, "providerReturnOrder('paypal'")===false||strpos( $service, "providerReturnOrder('amazon_pay'")===false||strpos( $service, 'validateCapture(')===false||strpos( $service, 'validateCompletion(')===false) if(strpos($service, 'checkoutRequestOrder($requestId)')===false||strpos($service, 'rememberCheckoutRequest($requestId, $order)')===false) $paypalCancel