33namespace Plugin \MonduPayment \Src \Controllers \Frontend ;
44
55use JTL \Shop ;
6- use Plugin \MonduPayment \PaymentMethod \MonduPayment ;
76use Plugin \MonduPayment \Src \Exceptions \DatabaseQueryException ;
87use Plugin \MonduPayment \Src \Helpers \Response ;
98use Plugin \MonduPayment \Src \Models \MonduInvoice ;
1312class WebhookController
1413{
1514 public const MONDU_JTL_MAPPING = [
16- MonduPayment:: STATE_CONFIRMED => \BESTELLUNG_STATUS_BEZAHLT ,
17- MonduPayment:: STATE_PENDING => \BESTELLUNG_STATUS_IN_BEARBEITUNG ,
18- MonduPayment:: STATE_CANCELED => \BESTELLUNG_STATUS_STORNO ,
19- MonduPayment:: STATE_DECLINED => \BESTELLUNG_STATUS_STORNO ,
15+ ' confirmed ' => \BESTELLUNG_STATUS_BEZAHLT ,
16+ ' pending ' => \BESTELLUNG_STATUS_IN_BEARBEITUNG ,
17+ ' canceled ' => \BESTELLUNG_STATUS_STORNO ,
18+ ' declined ' => \BESTELLUNG_STATUS_STORNO ,
2019 ];
2120
2221 private Request $ request ;
@@ -43,17 +42,26 @@ public function index()
4342 */
4443 private function handleWebhook ()
4544 {
46- $ requestData = $ this ->request ->all ();
47-
48- switch ($ requestData ['topic ' ]) {
49- case 'order/confirmed ' :
50- case 'order/declined ' :
51- case 'order/pending ' :
52- return $ this ->handleOrderStateChanged ($ requestData );
53- case 'invoice/canceled ' :
54- return $ this ->handleInvoiceStateChanged ($ requestData , 'canceled ' );
55- default :
56- return [['message ' => 'Unregistered topic ' ], Response::HTTP_OK ];
45+ try {
46+ $ requestData = $ this ->request ->all ();
47+
48+ // Проверяем наличие topic
49+ if (!isset ($ requestData ['topic ' ])) {
50+ return [['message ' => 'Missing topic parameter ' , 'received_data ' => $ requestData ], Response::HTTP_BAD_REQUEST ];
51+ }
52+
53+ switch ($ requestData ['topic ' ]) {
54+ case 'order/confirmed ' :
55+ case 'order/declined ' :
56+ case 'order/pending ' :
57+ return $ this ->handleOrderStateChanged ($ requestData );
58+ case 'invoice/canceled ' :
59+ return $ this ->handleInvoiceStateChanged ($ requestData , 'canceled ' );
60+ default :
61+ return [['message ' => 'Unregistered topic: ' . $ requestData ['topic ' ], 'available_topics ' => ['order/confirmed ' , 'order/declined ' , 'order/pending ' , 'invoice/canceled ' ]], Response::HTTP_OK ];
62+ }
63+ } catch (\Exception $ e ) {
64+ return [['message ' => 'Error processing webhook ' , 'error ' => $ e ->getMessage ()], Response::HTTP_INTERNAL_SERVER_ERROR ];
5765 }
5866 }
5967
@@ -75,13 +83,50 @@ public function handleOrderStateChanged($requestData)
7583 return [['message ' => 'Order not found ' ], Response::HTTP_NOT_FOUND ];
7684 }
7785
78- $ this ->monduOrder ->update (['state ' => $ params ['order_state ' ]], $ monduOrder ->id );
86+ // If order found via fallback (id is null), create mondu_orders record
87+ if (empty ($ monduOrder ->id )) {
88+ $ monduOrderData = [
89+ 'order_id ' => $ monduOrder ->order_id ,
90+ 'external_reference_id ' => $ monduOrder ->external_reference_id ,
91+ 'order_uuid ' => $ requestData ['order_uuid ' ] ?? null ,
92+ 'state ' => $ params ['order_state ' ]
93+ ];
94+
95+ // Use direct SQL insert
96+ $ pdo = new \PDO (
97+ 'mysql:host= ' . DB_HOST . ';dbname= ' . DB_NAME ,
98+ DB_USER ,
99+ DB_PASS
100+ );
101+
102+ $ stmt = $ pdo ->prepare ("
103+ INSERT INTO mondu_orders
104+ (order_id, external_reference_id, order_uuid, state, created_at, updated_at)
105+ VALUES (?, ?, ?, ?, NOW(), NOW())
106+ " );
107+
108+ $ stmt ->execute ([
109+ $ monduOrderData ['order_id ' ],
110+ $ monduOrderData ['external_reference_id ' ],
111+ $ monduOrderData ['order_uuid ' ],
112+ $ monduOrderData ['state ' ]
113+ ]);
114+
115+ $ newId = $ pdo ->lastInsertId ();
116+
117+ // Update monduOrder with new ID
118+ $ monduOrder ->id = $ newId ;
119+ $ monduOrder ->order_uuid = $ monduOrderData ['order_uuid ' ];
120+ } else {
121+ // Update existing record
122+ $ this ->monduOrder ->update (['state ' => $ params ['order_state ' ]], $ monduOrder ->id );
123+ }
79124
80125 if (isset (self ::MONDU_JTL_MAPPING [$ params ['order_state ' ]])) {
81126 $ this ->updateOrderStatus ($ monduOrder , self ::MONDU_JTL_MAPPING [$ params ['order_state ' ]]);
82127 }
83128
84- if ($ params ['order_state ' ] === MonduPayment:: STATE_CONFIRMED ) {
129+ if ($ params ['order_state ' ] === ' confirmed ' ) {
85130 $ this ->unlockOrderForWawiSync ($ monduOrder );
86131 }
87132
@@ -91,7 +136,6 @@ public function handleOrderStateChanged($requestData)
91136 /**
92137 * @param $requestData
93138 * @param $state
94- *
95139 * @return array
96140 */
97141 public function handleInvoiceStateChanged ($ requestData , $ state ): array
@@ -122,7 +166,55 @@ public function handleInvoiceStateChanged($requestData, $state): array
122166 */
123167 private function getOrder ($ orderUuid )
124168 {
125- return $ this ->monduOrder ->select ('id ' , 'order_uuid ' , 'order_id ' )->where ('external_reference_id ' , $ orderUuid )->first ()[0 ];
169+ // Try to find in mondu_orders by external_reference_id
170+ $ query = $ this ->monduOrder ->select ('id ' , 'order_uuid ' , 'order_id ' )->where ('external_reference_id ' , $ orderUuid );
171+ $ result = $ query ->first ();
172+
173+ if (is_array ($ result ) && isset ($ result [0 ])) {
174+ return $ result [0 ];
175+ }
176+
177+ // Fallback: Search in tbestellung
178+ $ jtlOrderId = null ;
179+
180+ // Extract JTL order ID from external_reference_id (e.g. "JTL5-10005" -> 10005)
181+ if (preg_match ('/^[A-Z0-9]+-(\d+)$/ ' , $ orderUuid , $ matches )) {
182+ $ jtlOrderId = (int )$ matches [1 ];
183+ } elseif (is_numeric ($ orderUuid )) {
184+ $ jtlOrderId = (int )$ orderUuid ;
185+ }
186+
187+ // Search in tbestellung
188+ try {
189+ $ pdo = new \PDO (
190+ 'mysql:host= ' . DB_HOST . ';dbname= ' . DB_NAME . ';charset=utf8mb4 ' ,
191+ DB_USER ,
192+ DB_PASS ,
193+ [\PDO ::ATTR_ERRMODE => \PDO ::ERRMODE_EXCEPTION ]
194+ );
195+
196+ // Search by cBestellNr first (most reliable), then by kBestellung
197+ $ stmt = $ pdo ->prepare ("SELECT kBestellung FROM tbestellung WHERE cBestellNr = ? OR kBestellung = ? " );
198+ $ stmt ->execute ([$ orderUuid , $ jtlOrderId ?: 0 ]);
199+
200+ $ jtlOrder = $ stmt ->fetch (\PDO ::FETCH_ASSOC );
201+
202+ if ($ jtlOrder ) {
203+ // Return a compatible format (object with order_id property)
204+ $ compatibleResult = new \stdClass ();
205+ $ compatibleResult ->id = null ; // No mondu_orders record yet
206+ $ compatibleResult ->order_id = $ jtlOrder ['kBestellung ' ];
207+ $ compatibleResult ->order_uuid = null ;
208+ $ compatibleResult ->external_reference_id = $ orderUuid ;
209+
210+ return $ compatibleResult ;
211+ }
212+
213+ } catch (\Exception $ e ) {
214+ // Silent fail
215+ }
216+
217+ return null ;
126218 }
127219
128220 /**
0 commit comments