merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit f1af21e4537dd59e31d532f9495a0bd7a0020ad0
parent 914358f414ba29195ff7972e7e2875457af2d566
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu, 30 Oct 2025 21:39:05 +0100

fix #10541

Diffstat:
Msrc/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c | 135++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/backenddb/pg_account_kyc_get_status.c | 51++++++++++++++++++++++++++++++++-------------------
2 files changed, 146 insertions(+), 40 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c @@ -685,31 +685,14 @@ ekr_expand_response (struct ExchangeKycRequest *ekr) /** - * We are done with the KYC request @a ekr. Remove it from the work list and - * check if we are done overall. + * We are done with asynchronous processing, generate the + * response for the @e kc. * - * @param[in] ekr key request that is done (and will be freed) + * @param[in,out] kc KYC context to respond for */ static void -ekr_finished (struct ExchangeKycRequest *ekr) +kc_respond (struct KycContext *kc) { - struct KycContext *kc = ekr->kc; - - ekr_expand_response (ekr); - GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head, - kc->exchange_pending_tail, - ekr); - json_decref (ekr->jlimits); - json_decref (ekr->pkaa); - if (NULL != ekr->keys) - TALER_EXCHANGE_keys_decref (ekr->keys); - GNUNET_free (ekr->exchange_url); - GNUNET_free (ekr->payto_uri.full_payto); - GNUNET_free (ekr); - - if (NULL != kc->exchange_pending_head) - return; /* wait for more */ - if ( (! kc->return_immediately) && (! GNUNET_TIME_absolute_is_past (kc->timeout)) ) { @@ -736,6 +719,35 @@ ekr_finished (struct ExchangeKycRequest *ekr) /** + * We are done with the KYC request @a ekr. Remove it from the work list and + * check if we are done overall. + * + * @param[in] ekr key request that is done (and will be freed) + */ +static void +ekr_finished (struct ExchangeKycRequest *ekr) +{ + struct KycContext *kc = ekr->kc; + + ekr_expand_response (ekr); + GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head, + kc->exchange_pending_tail, + ekr); + json_decref (ekr->jlimits); + json_decref (ekr->pkaa); + if (NULL != ekr->keys) + TALER_EXCHANGE_keys_decref (ekr->keys); + GNUNET_free (ekr->exchange_url); + GNUNET_free (ekr->payto_uri.full_payto); + GNUNET_free (ekr); + + if (NULL != kc->exchange_pending_head) + return; /* wait for more */ + kc_respond (kc); +} + + +/** * Figure out which exchange accounts from @a keys could * be used for a KYC auth wire transfer from the account * that @a ekr is checking. Will set the "pkaa" array @@ -879,6 +891,72 @@ kyc_with_exchange (void *cls, /** + * Closure for add_unreachable_status(). + */ +struct UnreachableContext +{ + /** + * Where we are building the response. + */ + struct KycContext *kc; + + /** + * Pointer to our account hash. + */ + const struct TALER_MerchantWireHashP *h_wire; + + /** + * Bank account for which we have no status from any exchange. + */ + struct TALER_FullPayto payto_uri; + +}; + +/** + * Add all trusted exchanges with "unknown" status for the + * bank account given in the context. + * + * @param cls a `struct UnreachableContext` + * @param url base URL of the exchange + * @param exchange internal handle for the exchange + */ +static void +add_unreachable_status (void *cls, + const char *url, + const struct TMH_Exchange *exchange) +{ + struct UnreachableContext *uc = cls; + struct KycContext *kc = uc->kc; + + GNUNET_assert ( + 0 == + json_array_append_new ( + kc->kycs_data, + GNUNET_JSON_PACK ( + TALER_JSON_pack_full_payto ( + "payto_uri", + uc->payto_uri), + GNUNET_JSON_pack_data_auto ( + "h_wire", + uc->h_wire), + GNUNET_JSON_pack_string ( + "status", + "exchange-unreachable"), + GNUNET_JSON_pack_string ( + "exchange_url", + url), + GNUNET_JSON_pack_bool ("no_keys", + true), + GNUNET_JSON_pack_bool ("auth_conflict", + false), + GNUNET_JSON_pack_uint64 ("exchange_http_status", + 0) + ))); + +} + + +/** * Function called from account_kyc_get_status() with KYC status information * for this merchant. * @@ -911,6 +989,21 @@ kyc_status_cb ( struct KycContext *kc = cls; struct ExchangeKycRequest *ekr; + if (NULL == exchange_url) + { + struct UnreachableContext uc = { + .kc = kc, + .h_wire = h_wire, + .payto_uri = payto_uri + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Account has unknown KYC status for all exchanges.\n"); + TMH_exchange_get_trusted (&add_unreachable_status, + &uc); + kc_respond (kc); + return; + } if (! TMH_EXCHANGES_check_trusted (exchange_url)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/backenddb/pg_account_kyc_get_status.c b/src/backenddb/pg_account_kyc_get_status.c @@ -73,37 +73,50 @@ kyc_status_cb (void *cls, for (unsigned int i = 0; i < num_results; i++) { struct TALER_MerchantWireHashP h_wire; - char *exchange_url; + char *exchange_url = NULL; struct TALER_FullPayto payto_uri; struct GNUNET_TIME_Timestamp last_check; - bool kyc_ok; + bool kyc_ok = false; struct TALER_AccountAccessTokenP access_token; - bool no_auth; - uint32_t h32; - uint32_t e32; - bool in_aml_review; + bool no_auth = false; + uint32_t h32 = 0; + uint32_t e32 = 0; + bool in_aml_review = false; + bool no_mk; /* left join on merchant_kyc table yielded nothing */ json_t *jlimits = NULL; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("h_wire", &h_wire), GNUNET_PQ_result_spec_string ("payto_uri", &payto_uri.full_payto), - GNUNET_PQ_result_spec_string ("exchange_url", - &exchange_url), - GNUNET_PQ_result_spec_timestamp ("kyc_timestamp", - &last_check), - GNUNET_PQ_result_spec_bool ("kyc_ok", - &kyc_ok), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), + &no_mk), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_timestamp ("kyc_timestamp", + &last_check), + &no_mk), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_bool ("kyc_ok", + &kyc_ok), + &no_mk), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("access_token", &access_token), &no_auth), - GNUNET_PQ_result_spec_uint32 ("exchange_http_status", - &h32), - GNUNET_PQ_result_spec_uint32 ("exchange_ec_code", - &e32), - GNUNET_PQ_result_spec_bool ("aml_review", - &in_aml_review), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint32 ("exchange_http_status", + &h32), + &no_mk), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_uint32 ("exchange_ec_code", + &e32), + &no_mk), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_bool ("aml_review", + &in_aml_review), + &no_mk), GNUNET_PQ_result_spec_allow_null ( TALER_PQ_result_spec_json ("jaccount_limits", &jlimits), @@ -186,7 +199,7 @@ TMH_PG_account_kyc_get_status ( " FROM merchant_instances mi" " JOIN merchant_accounts ma" " USING (merchant_serial)" - " JOIN merchant_kyc mk" + " LEFT JOIN merchant_kyc mk" " USING (account_serial)" " WHERE (mi.merchant_id=$1)" " AND ma.active"