commit 508b748f8e0e4817b04cf57bae0c5f528f3377a6
parent a3b07879bb98d6f6b4c9a833467cbfb5fb74cfb3
Author: Christian Grothoff <christian@grothoff.org>
Date: Fri, 6 Sep 2024 09:40:08 +0200
pass on 451 replies from exchange to wallets on /pay
Diffstat:
1 file changed, 81 insertions(+), 0 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -137,6 +137,12 @@ enum PayPhase
PP_RETURN_RESPONSE,
/**
+ * An exchange denied a deposit, fail for
+ * legal reasons.
+ */
+ PP_FAIL_LEGAL_REASONS,
+
+ /**
* Return #MHD_YES to end processing.
*/
PP_END_YES,
@@ -346,6 +352,11 @@ struct ExchangeGroup
* true if we already tried a forced /keys download.
*/
bool tried_force_keys;
+
+ /**
+ * Did this exchange deny the transaction for legal reasons?
+ */
+ bool got_451;
};
@@ -651,6 +662,10 @@ struct PayContext
*/
bool refund_currency_mismatch;
+ /**
+ * Did any exchange deny a deposit for legal reasons?
+ */
+ bool got_451;
};
@@ -810,6 +825,43 @@ phase_return_response (struct PayContext *pc)
/**
+ * Return a response indicating failure for legal reasons.
+ *
+ * @param[in,out] pc payment context we are processing
+ */
+static void
+phase_fail_for_legal_reasons (struct PayContext *pc)
+{
+ json_t *exchanges;
+
+ GNUNET_assert (0 == pc->pending);
+ GNUNET_assert (pc->got_451);
+ exchanges = json_array ();
+ GNUNET_assert (NULL != exchanges);
+ for (unsigned int i = 0; i<pc->num_exchanges; i++)
+ {
+ struct ExchangeGroup *eg = pc->egs[i];
+
+ GNUNET_assert (NULL == eg->fo);
+ GNUNET_assert (NULL == eg->bdh);
+ if (! eg->got_451)
+ continue;
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ exchanges,
+ json_string (eg->exchange_url)));
+ }
+ pay_end (pc,
+ TALER_MHD_REPLY_JSON_PACK (
+ pc->connection,
+ MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
+ GNUNET_JSON_pack_array_steal ("exchange_base_urls",
+ exchanges)));
+}
+
+
+/**
* Do database transaction for a completed batch deposit.
*
* @param eg group that completed
@@ -1018,6 +1070,27 @@ batch_deposit_cb (
pay_resume (pc);
}
return;
+ case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ eg->got_451 = true;
+ pc->got_451 = true;
+ /* update pc->pending */
+ for (size_t i = 0; i<pc->coins_cnt; i++)
+ {
+ struct DepositConfirmation *dc = &pc->dc[i];
+
+ if (0 != strcmp (eg->exchange_url,
+ pc->dc[i].exchange_url))
+ continue;
+ if (dc->found_in_db)
+ continue;
+ pc->pending--;
+ }
+ if (0 == pc->pending_at_eg)
+ {
+ pc->phase = PP_PAY_TRANSACTION;
+ pay_resume (pc);
+ }
+ return;
default:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Deposit operation failed with HTTP code %u/%d\n",
@@ -2034,6 +2107,11 @@ phase_execute_pay_transaction (struct PayContext *pc)
struct TMH_HandlerContext *hc = pc->hc;
const char *instance_id = hc->instance->settings.id;
+ if (pc->got_451)
+ {
+ pc->phase = PP_FAIL_LEGAL_REASONS;
+ return;
+ }
/* Avoid re-trying transactions on soft errors forever! */
if (pc->retry_counter++ > MAX_RETRIES)
{
@@ -3651,6 +3729,9 @@ TMH_post_orders_ID_pay (const struct TMH_RequestHandler *rh,
case PP_RETURN_RESPONSE:
phase_return_response (pc);
break;
+ case PP_FAIL_LEGAL_REASONS:
+ phase_fail_for_legal_reasons (pc);
+ break;
case PP_END_YES:
return MHD_YES;
case PP_END_NO: