@@ -272,30 +272,53 @@ def get_order_by_pay_id(
272272 def check_payment_state (
273273 self ,
274274 order_skel : SkeletonInstance ,
275- ) -> tuple [bool , unzer .PaymentGetResponse ]:
276- payment_id = order_skel ["payment" ]["payments" ][- 1 ]["payment_id" ]
277- logger .debug (f"{ payment_id = } " )
278- payment = self .client .getPayment (payment_id )
279- logger .debug (f"{ payment = } " )
280- # payment.charge(order_skel["total"])
281- payment_id = str (order_skel ["key" ].id_or_name )
282- logger .debug (f"{ payment_id = } " )
283- payment = self .client .getPayment (payment_id )
284- logger .debug (f"{ payment = } " )
275+ # TODO: params check_specific_payment_by_uuid
276+ ) -> tuple [bool , unzer .PaymentGetResponse | list [unzer .PaymentGetResponse ]]:
277+ """
278+ Get the payment state for a order.
285279
286- if str ( payment . invoiceId ) != str ( order_skel ["order_uid" ]):
287- raise e . InvalidStateError ( f' { payment . invoiceId } != { order_skel [ "order_uid" ] } ' )
280+ Checks all payments stored in order_skel["payment"]["payments"] for
281+ a completed and full charge.
288282
289- if payment .state == PaymentState .COMPLETED and payment .amountCharged == order_skel ["total" ]:
290- return True , payment
291- return False , payment
283+ In case of a completed charge, only the payment data of the charged payment is returned.
284+ Otherwise (failed or missing payment), data of all payments is returned.
285+
286+ :param order_skel: OrderSkel SkeletonInstance to check
287+ :return: A tuple: [is_paid-boolean, payment-data]
288+ """
289+ payment_results = []
290+ for idx , payment_src in enumerate (order_skel ["payment" ]["payments" ], start = 1 ):
291+ if not (payment_id := payment_src .get ("payment_id" )):
292+ logger .error (f"Payment #{ idx } has no payment_id" )
293+ # Fetch by order short key (orderId)
294+ order_id = str (order_skel ["key" ].id_or_name )
295+ logger .debug (f"{ order_id = } " )
296+ payment = self .client .getPayment (order_id )
297+ logger .debug (f"{ payment = } " )
298+ else :
299+ logger .debug (f"{ payment_id = } " )
300+ payment = self .client .getPayment (payment_id )
301+ logger .debug (f"{ payment = } " )
302+ payment_results .append (payment )
303+
304+ if str (payment .invoiceId ) != str (order_skel ["order_uid" ]):
305+ raise e .InvalidStateError (f'{ payment .invoiceId } != { order_skel ["order_uid" ]} ' )
306+
307+ if payment .state == PaymentState .COMPLETED and payment .amountCharged == order_skel ["total" ]:
308+ return True , payment
309+
310+ return False , payment_results
292311
293312 @exposed
294313 @log_unzer_error
295314 def return_handler (
296315 self ,
297316 order_key : db .Key ,
298317 ) -> t .Any :
318+ """Return Endpoint
319+
320+ Endpoint to which customers are redirected once they have processed a payment on the payment server.
321+ """
299322 order_key = self .shop .api ._normalize_external_key (order_key , "order_key" )
300323 order_skel = self .shop .order .viewSkel ()
301324 if not order_skel .read (order_key ):
@@ -413,6 +436,11 @@ def get_debug_information(
413436 "basket" : basket and dict (basket ),
414437 })
415438
439+ result = {
440+ "payments" : result ,
441+ "payment_state" : self .check_payment_state (self .shop .order .skel ().read (order_key )),
442+ }
443+
416444 return JsonResponse (self .model_to_dict (result ))
417445
418446 @exposed
@@ -495,8 +523,8 @@ def shop_salutation_to_unzer_salutation(
495523 def model_to_dict (cls , obj ):
496524 """Convert any nested unzer model to dict representation"""
497525 if isinstance (obj , BaseModel ):
498- return dict (obj )
499- elif isinstance (obj , dict ):
526+ obj = dict (obj ) # no elif! needs to proceed in depth
527+ if isinstance (obj , dict ):
500528 return {k : cls .model_to_dict (v ) for k , v in obj .items ()}
501529 elif isinstance (obj , list | tuple ):
502530 return [cls .model_to_dict (v ) for v in obj ]
0 commit comments