commit 24227de303ceeecd73c447bd1058851081d23352
parent 0301428cc8d1cc3bc0006003a9abbdf9bcdfdb0b
Author: Iván Ávalos <avalos@disroot.org>
Date: Sun, 9 Aug 2026 17:16:54 +0200
create a fresh payment order when the merchant lost the pending one
Diffstat:
1 file changed, 57 insertions(+), 10 deletions(-)
diff --git a/src/sync/sync-httpd2_payments.c b/src/sync/sync-httpd2_payments.c
@@ -242,8 +242,11 @@ ongoing_payment_cb (void *cls,
*
* @param bpc our payment context
* @param osr order status
+ * @return true if the caller should resume the request, false if a
+ * fresh order creation was initiated instead (the request was
+ * re-suspended and will be resumed once that order exists)
*/
-static void
+static bool
set_payment_response (
struct BackupPaymentContext *bpc,
const struct TALER_MERCHANT_GetPrivateOrderResponse *osr)
@@ -257,7 +260,48 @@ set_payment_response (
bpc->resp = TALER_MHD2_make_error (
TALER_EC_SYNC_GENERIC_BACKEND_TIMEOUT,
NULL);
- return;
+ return true;
+ case MHD_HTTP_STATUS_NOT_FOUND:
+ /* The merchant no longer knows the order we stored as pending (it
+ expired, or the merchant's data was reset). The stored order is
+ stale and can never be paid: forget it and create a fresh one, so
+ the account payment can still be set up instead of failing every
+ upload with a 502 until the order expires from our own database. */
+ if (NULL != bpc->existing_order_id)
+ {
+ bool suspend;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Pending order `%s' no longer exists at the merchant,"
+ " creating a fresh order\n",
+ bpc->existing_order_id);
+ GNUNET_free (bpc->existing_order_id);
+ bpc->existing_order_id = NULL;
+ bpc->force_fresh_order = true;
+ bpc->resp = SH_begin_payment (bpc,
+ GNUNET_NO,
+ &suspend);
+ if (suspend)
+ return false; /* fresh order is being created; do not resume yet */
+ return true;
+ }
+ /* The order the client promised to pay (`paying') is gone; tell
+ them to start over. */
+ bpc->resp = TALER_MHD2_MAKE_JSON_PACK (
+ MHD_HTTP_STATUS_BAD_GATEWAY,
+ GNUNET_JSON_pack_uint64 ("code",
+ TALER_EC_SYNC_GENERIC_BACKEND_ERROR),
+ GNUNET_JSON_pack_string ("hint",
+ TALER_ErrorCode_get_hint (
+ TALER_EC_SYNC_GENERIC_BACKEND_ERROR)),
+ GNUNET_JSON_pack_uint64 ("backend-ec",
+ (json_int_t) hr->ec),
+ GNUNET_JSON_pack_uint64 ("backend-http-status",
+ (json_int_t) hr->http_status),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_object_incref ("backend-reply",
+ (json_t *) hr->reply)));
+ return true;
case MHD_HTTP_STATUS_OK:
break; /* handled below */
default:
@@ -276,7 +320,7 @@ set_payment_response (
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_object_incref ("backend-reply",
(json_t *) hr->reply)));
- return;
+ return true;
}
GNUNET_assert (MHD_HTTP_STATUS_OK == hr->http_status);
@@ -294,12 +338,12 @@ set_payment_response (
bpc->order_id,
GNUNET_TIME_UNIT_YEARS); /* always annual */
if (0 <= qs)
- return; /* continue as planned */
+ return true; /* continue as planned */
GNUNET_break (0);
bpc->resp = TALER_MHD2_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
"increment lifetime");
GNUNET_assert (NULL != bpc->resp);
- return; /* continue as planned */
+ return true; /* continue as planned */
}
case TALER_MERCHANT_OSC_UNPAID:
case TALER_MERCHANT_OSC_CLAIMED:
@@ -316,13 +360,14 @@ set_payment_response (
? NULL
: &bpc->token);
GNUNET_assert (NULL != bpc->resp);
- return;
+ return true;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Timeout waiting for payment\n");
bpc->resp = TALER_MHD2_make_error (TALER_EC_SYNC_PAYMENT_GENERIC_TIMEOUT,
"Timeout awaiting promised payment");
GNUNET_assert (NULL != bpc->resp);
+ return true;
}
@@ -341,10 +386,12 @@ check_payment_cb (
GNUNET_CONTAINER_DLL_remove (bpc_head,
bpc_tail,
bpc);
- /* Set the response before resuming, MHD needs it in place */
- set_payment_response (bpc,
- osr);
- resume_request (bpc);
+ /* Set the response before resuming, MHD needs it in place. A 404 from
+ the merchant for a stale order re-runs the payment initiation (which
+ re-suspends the request); only resume when a final response is set. */
+ if (set_payment_response (bpc,
+ osr))
+ resume_request (bpc);
}