summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c')
-rw-r--r--src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c271
1 files changed, 140 insertions, 131 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
index 10c76013..8a338e7d 100644
--- a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
+++ b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c
@@ -1,6 +1,6 @@
/*
This file is part of GNU Taler
- (C) 2021 Taler Systems SA
+ (C) 2021-2023 Taler Systems SA
GNU Taler is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@@ -39,13 +39,13 @@
* How long should clients cache a KYC failure response?
*/
#define EXPIRATION_KYC_FAILURE GNUNET_TIME_relative_multiply ( \
- GNUNET_TIME_UNIT_MINUTES, 5)
+ GNUNET_TIME_UNIT_MINUTES, 5)
/**
* How long should clients cache a KYC success response?
*/
#define EXPIRATION_KYC_SUCCESS GNUNET_TIME_relative_multiply ( \
- GNUNET_TIME_UNIT_HOURS, 1)
+ GNUNET_TIME_UNIT_HOURS, 1)
/**
@@ -73,7 +73,7 @@ struct ExchangeKycRequest
/**
* Find operation where we connect to the respective exchange.
*/
- struct TMH_EXCHANGES_FindOperation *fo;
+ struct TMH_EXCHANGES_KeysOperation *fo;
/**
* KYC request this exchange request is made for.
@@ -110,11 +110,6 @@ struct ExchangeKycRequest
*/
struct GNUNET_TIME_Timestamp last_check;
- /**
- * Last KYC status returned by the exchange.
- */
- bool kyc_ok;
-
};
@@ -197,7 +192,7 @@ struct KycContext
/**
* How long are we willing to wait for the exchange(s)?
*/
- struct GNUNET_TIME_Relative timeout;
+ struct GNUNET_TIME_Absolute timeout;
/**
* HTTP status code to use for the reply, i.e 200 for "OK".
@@ -283,7 +278,7 @@ kyc_context_cleanup (void *cls)
}
if (NULL != ekr->fo)
{
- TMH_EXCHANGES_find_exchange_cancel (ekr->fo);
+ TMH_EXCHANGES_keys4exchange_cancel (ekr->fo);
ekr->fo = NULL;
}
GNUNET_free (ekr->exchange_url);
@@ -310,9 +305,9 @@ kyc_context_cleanup (void *cls)
/**
- * Resume the given KYC context and send the given response.
- * Stores the response in the @a kc and signals MHD to resume
- * the connection. Also ensures MHD runs immediately.
+ * Resume the given KYC context and send the given response. Stores the
+ * response in the @a kc and signals MHD to resume the connection. Also
+ * ensures MHD runs immediately.
*
* @param kc KYC context
* @param response_code response code to use
@@ -400,7 +395,7 @@ handle_kyc_timeout (void *cls)
}
if (NULL != ekr->fo)
{
- TMH_EXCHANGES_find_exchange_cancel (ekr->fo);
+ TMH_EXCHANGES_keys4exchange_cancel (ekr->fo);
ekr->fo = NULL;
}
GNUNET_assert (
@@ -433,9 +428,8 @@ handle_kyc_timeout (void *cls)
/**
- * 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 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)
*/
@@ -453,7 +447,7 @@ ekr_finished (struct ExchangeKycRequest *ekr)
if (NULL != kc->exchange_pending_head)
return; /* wait for more */
/* All exchange requests done, create final
- big response from cummulated replies */
+ big response from cumulated replies */
if ( (0 == json_array_size (kc->pending_kycs)) &&
(0 == json_array_size (kc->timeout_kycs)) )
{
@@ -500,15 +494,31 @@ exchange_check_cb (void *cls,
{
enum GNUNET_DB_QueryStatus qs;
+ if (TALER_AML_NORMAL != ks->details.ok.aml_status)
+ {
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ kc->pending_kycs,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_uint64 (
+ "aml_status",
+ ks->details.ok.aml_status),
+ GNUNET_JSON_pack_string ("exchange_url",
+ ekr->exchange_url),
+ GNUNET_JSON_pack_string ("payto_uri",
+ ekr->payto_uri))));
+ }
qs = TMH_db->account_kyc_set_status (TMH_db->cls,
kc->mi->settings.id,
&ekr->h_wire,
ekr->exchange_url,
ekr->exchange_kyc_serial,
- &ks->details.success.exchange_sig,
- &ks->details.success.exchange_pub,
- ks->details.success.timestamp,
- true);
+ &ks->details.ok.exchange_sig,
+ &ks->details.ok.exchange_pub,
+ ks->details.ok.timestamp,
+ true, /* KYC OK */
+ ks->details.ok.aml_status);
if (qs < 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -517,18 +527,42 @@ exchange_check_cb (void *cls,
}
break;
case MHD_HTTP_ACCEPTED:
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- kc->pending_kycs,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("kyc_url",
- ks->details.accepted.kyc_url),
- GNUNET_JSON_pack_string ("exchange_url",
- ekr->exchange_url),
- GNUNET_JSON_pack_string ("payto_uri",
- ekr->payto_uri))));
- break;
+ {
+ struct GNUNET_TIME_Timestamp now;
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ kc->pending_kycs,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("kyc_url",
+ ks->details.accepted.kyc_url),
+ GNUNET_JSON_pack_uint64 ("aml_status",
+ ks->details.accepted.aml_status),
+ GNUNET_JSON_pack_string ("exchange_url",
+ ekr->exchange_url),
+ GNUNET_JSON_pack_string ("payto_uri",
+ ekr->payto_uri))));
+ now = GNUNET_TIME_timestamp_get ();
+ qs = TMH_db->account_kyc_set_status (
+ TMH_db->cls,
+ kc->mi->settings.id,
+ &ekr->h_wire,
+ ekr->exchange_url,
+ ekr->exchange_kyc_serial,
+ NULL,
+ NULL,
+ now,
+ false, /* KYC not OK */
+ ks->details.accepted.aml_status);
+ if (qs < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to store KYC status in database!\n");
+ }
+ break;
+ }
case MHD_HTTP_NO_CONTENT:
{
struct GNUNET_TIME_Timestamp now;
@@ -543,7 +577,44 @@ exchange_check_cb (void *cls,
NULL,
NULL,
now,
- true);
+ true, /* KYC OK */
+ TALER_AML_NORMAL);
+ if (qs < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to store KYC status in database!\n");
+ }
+ }
+ break;
+ case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ {
+ struct GNUNET_TIME_Timestamp now;
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ kc->pending_kycs,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_uint64 (
+ "aml_status",
+ ks->details.unavailable_for_legal_reasons.aml_status),
+ GNUNET_JSON_pack_string ("exchange_url",
+ ekr->exchange_url),
+ GNUNET_JSON_pack_string ("payto_uri",
+ ekr->payto_uri))));
+ now = GNUNET_TIME_timestamp_get ();
+ qs = TMH_db->account_kyc_set_status (
+ TMH_db->cls,
+ kc->mi->settings.id,
+ &ekr->h_wire,
+ ekr->exchange_url,
+ ekr->exchange_kyc_serial,
+ NULL,
+ NULL,
+ now,
+ true, /* KYC is OK, AML not... */
+ ks->details.unavailable_for_legal_reasons.aml_status);
if (qs < 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -574,70 +645,55 @@ exchange_check_cb (void *cls,
/**
- * Function called with the result of a #TMH_EXCHANGES_find_exchange()
+ * Function called with the result of a #TMH_EXCHANGES_keys4exchange()
* operation. Runs the KYC check against the exchange.
*
* @param cls closure with our `struct ExchangeKycRequest *`
- * @param hr HTTP response details
- * @param eh handle to the exchange context
- * @param payto_uri payto://-URI of the exchange
- * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available
- * @param exchange_trusted true if this exchange is trusted by config
+ * @param keys keys of the exchange context
+ * @param exchange representation of the exchange
*/
static void
kyc_with_exchange (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- struct TALER_EXCHANGE_Handle *eh,
- const char *payto_uri,
- const struct TALER_Amount *wire_fee,
- bool exchange_trusted)
+ struct TALER_EXCHANGE_Keys *keys,
+ struct TMH_Exchange *exchange)
{
struct ExchangeKycRequest *ekr = cls;
struct KycContext *kc = ekr->kc;
struct TALER_PaytoHashP h_payto;
- (void) payto_uri;
- (void) wire_fee;
- (void) exchange_trusted;
+ (void) exchange;
ekr->fo = NULL;
- if (MHD_HTTP_OK != hr->http_status)
+ if (NULL == keys)
{
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Exchange responded with HTTP status %u (%d) to /kyc-check request!\n",
- hr->http_status,
- hr->ec);
kc->response_code = MHD_HTTP_BAD_GATEWAY;
GNUNET_assert (
0 ==
json_array_append_new (
kc->timeout_kycs,
GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("exchange_url",
- ekr->exchange_url),
- GNUNET_JSON_pack_uint64 ("exchange_code",
- hr->ec),
- GNUNET_JSON_pack_uint64 ("exchange_http_status",
- hr->http_status))));
+ TALER_JSON_pack_ec (
+ TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE))));
ekr_finished (ekr);
return;
}
TALER_payto_hash (ekr->payto_uri,
&h_payto);
ekr->kyc = TALER_EXCHANGE_kyc_check (
- eh,
+ TMH_curl_ctx,
+ ekr->exchange_url,
+ keys,
ekr->exchange_kyc_serial,
&h_payto,
- /* FIXME: get from settings! */
- TALER_KYCLOGIC_KYC_UT_BUSINESS,
- kc->timeout,
+ ekr->kc->mi->settings.ut,
+ GNUNET_TIME_absolute_get_remaining (kc->timeout),
&exchange_check_cb,
ekr);
}
/**
- * Function called from ``account_kyc_get_status``
- * with KYC status information for this merchant.
+ * Function called from account_kyc_get_status() with KYC status information
+ * for this merchant.
*
* @param cls our `struct KycContext *`
* @param h_wire hash of the wire account
@@ -646,6 +702,7 @@ kyc_with_exchange (void *cls,
* @param exchange_url base URL of the exchange for which this is a status
* @param last_check when did we last get an update on our KYC status from the exchange
* @param kyc_ok true if we satisfied the KYC requirements
+ * @param aml_decision latest AML decision known to us
*/
static void
kyc_status_cb (void *cls,
@@ -654,12 +711,14 @@ kyc_status_cb (void *cls,
const char *payto_uri,
const char *exchange_url,
struct GNUNET_TIME_Timestamp last_check,
- bool kyc_ok)
+ bool kyc_ok,
+ enum TALER_AmlDecisionState aml_decision)
{
struct KycContext *kc = cls;
struct ExchangeKycRequest *ekr;
if (kyc_ok &&
+ (TALER_AML_PENDING != aml_decision) &&
(GNUNET_TIME_relative_cmp (
GNUNET_TIME_absolute_get_duration (last_check.abs_time),
<,
@@ -680,11 +739,9 @@ kyc_status_cb (void *cls,
ekr->exchange_url = GNUNET_strdup (exchange_url);
ekr->payto_uri = GNUNET_strdup (payto_uri);
ekr->last_check = last_check;
- ekr->kyc_ok = kyc_ok;
ekr->kc = kc;
- ekr->fo = TMH_EXCHANGES_find_exchange (exchange_url,
- NULL,
- GNUNET_NO,
+ ekr->fo = TMH_EXCHANGES_keys4exchange (exchange_url,
+ false,
&kyc_with_exchange,
ekr);
}
@@ -721,39 +778,13 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
kc->timeout_kycs = json_array ();
GNUNET_assert (NULL != kc->timeout_kycs);
- /* process 'timeout_ms' argument */
- {
- const char *long_poll_timeout_s;
-
- long_poll_timeout_s
- = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "timeout_ms");
- if (NULL != long_poll_timeout_s)
- {
- unsigned int timeout_ms;
- char dummy;
-
- if (1 != sscanf (long_poll_timeout_s,
- "%u%c",
- &timeout_ms,
- &dummy))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "timeout_ms must be non-negative number");
- }
- kc->timeout = GNUNET_TIME_relative_multiply (
- GNUNET_TIME_UNIT_MILLISECONDS,
- timeout_ms);
- kc->timeout_task
- = GNUNET_SCHEDULER_add_delayed (kc->timeout,
- &handle_kyc_timeout,
- kc);
- }
- } /* end timeout processing */
+ TALER_MHD_parse_request_timeout (connection,
+ &kc->timeout);
+ if (! GNUNET_TIME_absolute_is_past (kc->timeout))
+ kc->timeout_task
+ = GNUNET_SCHEDULER_add_at (kc->timeout,
+ &handle_kyc_timeout,
+ kc);
/* process 'exchange_url' argument */
kc->exchange_url = MHD_lookup_connection_value (connection,
@@ -775,32 +806,10 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
"exchange_url must be a valid HTTP(s) URL");
}
- /* process 'h_wire' argument */
- {
- const char *h_wire_s;
-
- h_wire_s
- = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "h_wire");
- if (NULL != h_wire_s)
- {
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (h_wire_s,
- strlen (h_wire_s),
- &kc->h_wire,
- sizeof (kc->h_wire)))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "h_wire must be Crockford base32 encoded hash");
- }
- kc->have_h_wire = true;
- }
- } /* end of h_wire processing */
-
+ TALER_MHD_parse_request_arg_auto (connection,
+ "h_wire",
+ &kc->h_wire,
+ kc->have_h_wire);
/* Check our database */
{
enum GNUNET_DB_QueryStatus qs;