[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant] branch master updated: towards new /kyc API: test_kyc_a
From: |
gnunet |
Subject: |
[taler-merchant] branch master updated: towards new /kyc API: test_kyc_api still fails, but getting close |
Date: |
Sun, 08 Sep 2024 23:39:53 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository merchant.
The following commit(s) were added to refs/heads/master by this push:
new fd6e459c towards new /kyc API: test_kyc_api still fails, but getting
close
fd6e459c is described below
commit fd6e459cc7fcad3703c993e812f25a09e1ca9d36
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Sep 8 23:39:50 2024 +0200
towards new /kyc API: test_kyc_api still fails, but getting close
---
...r-merchant-httpd_private-get-instances-ID-kyc.c | 982 ++++++++-------------
src/backend/taler-merchant-kyccheck.c | 32 +-
src/backenddb/pg_account_kyc_get_status.c | 91 +-
src/backenddb/pg_account_kyc_set_status.c | 10 +-
src/backenddb/pg_account_kyc_set_status.sql | 5 +
src/backenddb/pg_get_kyc_status.c | 28 +-
src/backenddb/test_merchantdb.c | 38 +-
src/include/taler_merchant_service.h | 68 +-
src/include/taler_merchant_testing_lib.h | 2 +
src/include/taler_merchantdb_plugin.h | 13 +-
src/lib/merchant_api_get_kyc.c | 237 +++--
src/testing/test_kyc_api.c | 20 +-
src/testing/test_merchant_api.c | 1 +
src/testing/testing_api_cmd_kyc_get.c | 58 +-
src/testing/testing_api_cmd_post_account.c | 4 +-
15 files changed, 713 insertions(+), 876 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 69e962d0..7fb229b2 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
@@ -27,6 +27,7 @@
#include "taler-merchant-httpd_helper.h"
#include "taler-merchant-httpd_exchanges.h"
#include <taler/taler_json_lib.h>
+#include <taler/taler_dbevents.h>
#include <regex.h>
/**
@@ -77,7 +78,8 @@ struct ExchangeKycRequest
/**
* JSON array of payto-URIs with KYC auth wire transfer
- * instructions.
+ * instructions. Provided if @e auth_ok is false and
+ * @e kyc_auth_conflict is false.
*/
json_t *pkaa;
@@ -92,14 +94,10 @@ struct ExchangeKycRequest
struct KycContext *kc;
/**
- * Hash of the wire account (with salt) we are checking.
- */
- struct TALER_MerchantWireHashP h_wire;
-
- /**
- * Handle for the actual HTTP request to the exchange.
+ * JSON array of AccountLimits that apply, NULL if
+ * unknown (and likely defaults apply).
*/
- struct TALER_EXCHANGE_KycCheckHandle *kyc;
+ json_t *jlimits;
/**
* Our account's payto URI.
@@ -111,11 +109,63 @@ struct ExchangeKycRequest
*/
char *exchange_url;
+ /**
+ * Hash of the wire account (with salt) we are checking.
+ */
+ struct TALER_MerchantWireHashP h_wire;
+
+ /**
+ * Current access token for the KYC SPA. Only set
+ * if @e auth_ok is true.
+ */
+ struct TALER_AccountAccessTokenP access_token;
+
/**
* Timestamp when we last got a reply from the exchange.
*/
struct GNUNET_TIME_Timestamp last_check;
+ /**
+ * Last HTTP status code obtained via /kyc-check from
+ * the exchange.
+ */
+ unsigned int last_http_status;
+
+ /**
+ * Last Taler error code returned from /kyc-check.
+ */
+ enum TALER_ErrorCode last_ec;
+
+ /**
+ * True if this account
+ * cannot work at this exchange because KYC auth is
+ * impossible.
+ */
+ bool kyc_auth_conflict;
+
+ /**
+ * We could not get /keys from the exchange.
+ */
+ bool no_keys;
+
+ /**
+ * True if @e access_token is available.
+ */
+ bool auth_ok;
+
+ /**
+ * True if we believe no KYC is currently required
+ * for this account at this exchange.
+ */
+ bool kyc_ok;
+
+ /**
+ * True if the exchange exposed to us that the account
+ * is currently under AML review.
+ */
+ bool in_aml_review;
+
+
};
@@ -149,11 +199,6 @@ struct KycContext
*/
struct TMH_HandlerContext *hc;
- /**
- * Task to trigger on request timeout, or NULL.
- */
- struct GNUNET_SCHEDULER_Task *timeout_task;
-
/**
* Response to return, NULL if we don't have one yet.
*/
@@ -163,19 +208,7 @@ struct KycContext
* JSON array where we are building up the array with
* pending KYC operations.
*/
- json_t *pending_kycs;
-
- /**
- * JSON array where we are building up the array with
- * pending KYC operations.
- */
- json_t *voluntary_kycs;
-
- /**
- * JSON array where we are building up the array with
- * troubled KYC operations.
- */
- json_t *timeout_kycs;
+ json_t *kycs_data;
/**
* Head of DLL of requests we are making to an
@@ -195,6 +228,12 @@ struct KycContext
*/
const char *exchange_url;
+ /**
+ * Notification handler from database on changes
+ * to the KYC status.
+ */
+ struct GNUNET_DB_EventHandler *eh;
+
/**
* Set to the h_wire of the merchant account if
* @a have_h_wire is true, used to filter by account.
@@ -221,6 +260,11 @@ struct KycContext
*/
enum GNUNET_GenericReturnValue suspended;
+ /**
+ * What state are we long-polling for?
+ */
+ enum TALER_EXCHANGE_KycLongPollTarget lpt;
+
/**
* True if @e h_wire was given.
*/
@@ -230,7 +274,7 @@ struct KycContext
* We're still waiting on the exchange to determine
* the KYC status of our deposit(s).
*/
- bool kyc_serial_pending;
+ bool return_immediately;
};
@@ -253,11 +297,6 @@ TMH_force_kyc_resume ()
NULL != kc;
kc = kc->next)
{
- if (NULL != kc->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (kc->timeout_task);
- kc->timeout_task = NULL;
- }
if (GNUNET_YES == kc->suspended)
{
kc->suspended = GNUNET_SYSERR;
@@ -283,27 +322,23 @@ kyc_context_cleanup (void *cls)
GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head,
kc->exchange_pending_tail,
ekr);
- if (NULL != ekr->kyc)
- {
- TALER_EXCHANGE_kyc_check_cancel (ekr->kyc);
- ekr->kyc = NULL;
- }
if (NULL != ekr->fo)
{
TMH_EXCHANGES_keys4exchange_cancel (ekr->fo);
ekr->fo = NULL;
}
json_decref (ekr->pkaa);
+ json_decref (ekr->jlimits);
if (NULL != ekr->keys)
TALER_EXCHANGE_keys_decref (ekr->keys);
GNUNET_free (ekr->exchange_url);
GNUNET_free (ekr->payto_uri);
GNUNET_free (ekr);
}
- if (NULL != kc->timeout_task)
+ if (NULL != kc->eh)
{
- GNUNET_SCHEDULER_cancel (kc->timeout_task);
- kc->timeout_task = NULL;
+ TMH_db->event_listen_cancel (kc->eh);
+ kc->eh = NULL;
}
if (NULL != kc->response)
{
@@ -313,73 +348,42 @@ kyc_context_cleanup (void *cls)
GNUNET_CONTAINER_DLL_remove (kc_head,
kc_tail,
kc);
- json_decref (kc->voluntary_kycs);
- json_decref (kc->pending_kycs);
- json_decref (kc->timeout_kycs);
+ json_decref (kc->kycs_data);
GNUNET_free (kc);
}
/**
- * Resume the given KYC context and send the given response. Stores the
+ * Resume the given KYC context and send the final 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
- * @param response response data to send back
*/
static void
-resume_kyc_with_response (struct KycContext *kc,
- unsigned int response_code,
- struct MHD_Response *response)
+resume_kyc_with_response (struct KycContext *kc)
{
char dat[128];
- kc->response_code = response_code;
- kc->response = response;
- switch (response_code)
- {
- case MHD_HTTP_OK:
- /* KYC failed, cache briefly */
- TALER_MHD_get_date_string (GNUNET_TIME_relative_to_absolute (
- EXPIRATION_KYC_FAILURE),
- dat);
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_EXPIRES,
- dat));
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_CACHE_CONTROL,
- "max-age=300"));
- break;
- case MHD_HTTP_NO_CONTENT:
- /* KYC passed, cache for a long time! */
- TALER_MHD_get_date_string (GNUNET_TIME_relative_to_absolute (
- EXPIRATION_KYC_SUCCESS),
- dat);
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_EXPIRES,
- dat));
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_CACHE_CONTROL,
- "max-age=3600"));
- break;
- case MHD_HTTP_BAD_GATEWAY:
- case MHD_HTTP_GATEWAY_TIMEOUT:
- break; /* no caching */
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ kc->response_code = MHD_HTTP_OK;
+ kc->response = TALER_MHD_MAKE_JSON_PACK (
+ GNUNET_JSON_pack_array_incref ("kyc_data",
+ kc->kycs_data));
+ /* KYC failed, cache briefly */
+ TALER_MHD_get_date_string (GNUNET_TIME_relative_to_absolute (
+ EXPIRATION_KYC_FAILURE),
+ dat);
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (kc->response,
+ MHD_HTTP_HEADER_EXPIRES,
+ dat));
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (kc->response,
+ MHD_HTTP_HEADER_CACHE_CONTROL,
+ "max-age=300"));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Resuming /kyc handling as exchange interaction is done (%u)\n",
- response_code);
- if (NULL != kc->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (kc->timeout_task);
- kc->timeout_task = NULL;
- }
+ MHD_HTTP_OK);
GNUNET_assert (GNUNET_YES == kc->suspended);
kc->suspended = GNUNET_NO;
MHD_resume_connection (kc->connection);
@@ -388,58 +392,26 @@ resume_kyc_with_response (struct KycContext *kc,
/**
- * Handle a timeout for the processing of the kyc request.
+ * Handle a DB event about an update relevant
+ * for the processing of the kyc request.
*
* @param cls our `struct KycContext`
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
*/
static void
-handle_kyc_timeout (void *cls)
+kyc_change_cb (void *cls,
+ const void *extra,
+ size_t extra_size)
{
struct KycContext *kc = cls;
- struct ExchangeKycRequest *ekr;
- kc->timeout_task = NULL;
- while (NULL != (ekr = kc->exchange_pending_head))
- {
- GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head,
- kc->exchange_pending_tail,
- ekr);
- if (NULL != ekr->kyc)
- {
- TALER_EXCHANGE_kyc_check_cancel (ekr->kyc);
- ekr->kyc = NULL;
- }
- if (NULL != ekr->fo)
- {
- TMH_EXCHANGES_keys4exchange_cancel (ekr->fo);
- ekr->fo = NULL;
- }
- 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",
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT),
- GNUNET_JSON_pack_uint64 ("exchange_http_status",
- 0))));
- GNUNET_free (ekr->exchange_url);
- GNUNET_free (ekr->payto_uri);
- GNUNET_free (ekr);
- }
GNUNET_assert (GNUNET_YES == kc->suspended);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Resuming KYC with gateway timeout\n");
- resume_kyc_with_response (
- kc,
- MHD_HTTP_GATEWAY_TIMEOUT,
- TALER_MHD_MAKE_JSON_PACK (
- GNUNET_JSON_pack_array_incref ("pending_kycs",
- kc->pending_kycs),
- GNUNET_JSON_pack_array_incref ("timeout_kycs",
- kc->timeout_kycs)));
+ kc->suspended = GNUNET_NO;
+ MHD_resume_connection (kc->connection);
+ TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
}
@@ -471,107 +443,6 @@ pack_limit (const struct TALER_EXCHANGE_AccountLimit
*limit,
}
-/**
- * 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;
-
- GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head,
- kc->exchange_pending_tail,
- ekr);
- json_decref (ekr->pkaa);
- if (NULL != ekr->keys)
- TALER_EXCHANGE_keys_decref (ekr->keys);
- GNUNET_free (ekr->exchange_url);
- GNUNET_free (ekr->payto_uri);
- GNUNET_free (ekr);
- if (NULL != kc->exchange_pending_head)
- return; /* wait for more */
- /* All exchange requests done, create final
- big response from cumulated replies */
- if ( (0 == json_array_size (kc->pending_kycs)) &&
- (0 == json_array_size (kc->timeout_kycs)) )
- {
- /* special case: all KYC operations did succeed
- after we asked at the exchanges => 204 */
- struct MHD_Response *response;
-
- response = MHD_create_response_from_buffer_static (0,
- "");
- resume_kyc_with_response (kc,
- MHD_HTTP_NO_CONTENT,
- response);
- return;
- }
- resume_kyc_with_response (
- kc,
- kc->response_code, /* MHD_HTTP_OK or MHD_HTTP_ACCEPTED */
- TALER_MHD_MAKE_JSON_PACK (
- GNUNET_JSON_pack_array_incref ("pending_kycs",
- kc->pending_kycs),
- GNUNET_JSON_pack_array_incref ("timeout_kycs",
- kc->timeout_kycs)));
-}
-
-
-/**
- * Store KYC response from the exchange in the
- * local database.
- *
- * @param ekr request context
- * @param ks HTTP response details
- * @param account_kyc_status account KYC status details
- * @return true if the operation was successful
- */
-static bool
-store_kyc_status (
- const struct ExchangeKycRequest *ekr,
- const struct TALER_EXCHANGE_KycStatus *ks,
- const struct TALER_EXCHANGE_AccountKycStatus *account_kyc_status)
-{
- json_t *jlimits;
- enum GNUNET_DB_QueryStatus qs;
-
- jlimits = json_array ();
- GNUNET_assert (NULL != jlimits);
- for (unsigned int i = 0; i<account_kyc_status->limits_length; i++)
- {
- const struct TALER_EXCHANGE_AccountLimit *limit
- = &account_kyc_status->limits[i];
-
- pack_limit (limit,
- jlimits);
- }
-
- qs = TMH_db->account_kyc_set_status (
- TMH_db->cls,
- ekr->kc->mi->settings.id,
- &ekr->h_wire,
- ekr->exchange_url,
- GNUNET_TIME_timestamp_get (),
- ks->hr.http_status,
- ks->hr.ec,
- &account_kyc_status->access_token,
- jlimits,
- account_kyc_status->aml_review,
- false);
- json_decref (jlimits);
- if (qs < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to store KYC status in database!\n");
- return false;
- }
- return true;
-}
-
-
/**
* Return JSON array with AccountLimit objects giving
* the current limits for this exchange.
@@ -581,297 +452,141 @@ store_kyc_status (
*/
static json_t *
get_exchange_limits (
- struct ExchangeKycRequest *ekr,
- const struct TALER_EXCHANGE_AccountKycStatus *account_kyc_status)
+ struct ExchangeKycRequest *ekr)
{
+ const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
json_t *limits;
+ if (NULL != ekr->jlimits)
+ return json_incref (ekr->jlimits);
+ if (NULL == keys)
+ return NULL;
limits = json_array ();
GNUNET_assert (NULL != limits);
- if (NULL == account_kyc_status)
+ for (unsigned int i = 0; i<keys->hard_limits_length; i++)
{
- const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
-
- GNUNET_assert (NULL != keys);
- for (unsigned int i = 0; i<keys->hard_limits_length; i++)
- {
- const struct TALER_EXCHANGE_AccountLimit *limit
- = &keys->hard_limits[i];
-
- pack_limit (limit,
- limits);
- }
- for (unsigned int i = 0; i<keys->zero_limits_length; i++)
- {
- const struct TALER_EXCHANGE_ZeroLimitedOperation *zlimit
- = &keys->zero_limits[i];
- json_t *jl;
- struct TALER_Amount zero;
+ const struct TALER_EXCHANGE_AccountLimit *limit
+ = &keys->hard_limits[i];
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (keys->currency,
- &zero));
- jl = GNUNET_JSON_PACK (
- TALER_JSON_pack_kycte ("operation_type",
- zlimit->operation_type),
- GNUNET_JSON_pack_time_rel ("timeframe",
- GNUNET_TIME_UNIT_ZERO),
- TALER_JSON_pack_amount ("threshold",
- &zero),
- GNUNET_JSON_pack_bool ("soft_limit",
- true)
- );
- GNUNET_assert (0 ==
- json_array_append_new (limits,
- jl));
- }
+ pack_limit (limit,
+ limits);
}
- else
+ for (unsigned int i = 0; i<keys->zero_limits_length; i++)
{
- for (unsigned int i = 0; i<account_kyc_status->limits_length; i++)
- {
- const struct TALER_EXCHANGE_AccountLimit *limit
- = &account_kyc_status->limits[i];
-
- pack_limit (limit,
- limits);
- }
+ const struct TALER_EXCHANGE_ZeroLimitedOperation *zlimit
+ = &keys->zero_limits[i];
+ json_t *jl;
+ struct TALER_Amount zero;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (keys->currency,
+ &zero));
+ jl = GNUNET_JSON_PACK (
+ TALER_JSON_pack_kycte ("operation_type",
+ zlimit->operation_type),
+ GNUNET_JSON_pack_time_rel ("timeframe",
+ GNUNET_TIME_UNIT_ZERO),
+ TALER_JSON_pack_amount ("threshold",
+ &zero),
+ GNUNET_JSON_pack_bool ("soft_limit",
+ true)
+ );
+ GNUNET_assert (0 ==
+ json_array_append_new (limits,
+ jl));
}
return limits;
}
/**
- * Update exchange KYC account status, storing it
- * in the database and returning it in the response.
+ * Take data from @a ekr to expand our response.
*
- * @param[in,out] ekr our request context
- * @param ks overall HTTP response
- * @param account_kyc_status specific KYC status
+ * @param ekr exchange we are done inspecting
*/
static void
-update_account_status (
- struct ExchangeKycRequest *ekr,
- const struct TALER_EXCHANGE_KycStatus *ks,
- const struct TALER_EXCHANGE_AccountKycStatus *account_kyc_status)
+ekr_expand_response (struct ExchangeKycRequest *ekr)
{
- char *kyc_url;
-
- GNUNET_break (store_kyc_status (ekr,
- ks,
- account_kyc_status));
- {
- char *ats;
-
- ats = GNUNET_STRINGS_data_to_string_alloc (
- &account_kyc_status->access_token,
- sizeof (account_kyc_status->access_token));
- GNUNET_asprintf (&kyc_url,
- "%s/kyc-spa/%s",
- ekr->exchange_url,
- ats);
- GNUNET_free (ats);
- }
-
GNUNET_assert (
0 ==
json_array_append_new (
- ekr->kc->pending_kycs,
+ ekr->kc->kycs_data,
GNUNET_JSON_PACK (
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_array_steal (
- "limits",
- get_exchange_limits (ekr,
- account_kyc_status))),
- (TALER_EC_NONE == ks->hr.ec)
- ? GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string (
- "dummy",
- NULL))
- : GNUNET_JSON_pack_uint64 ("exchange_code",
- ks->hr.ec),
- GNUNET_JSON_pack_uint64 ("exchange_http_status",
- ks->hr.http_status),
- GNUNET_JSON_pack_data_auto (
- "access_token",
- &account_kyc_status->access_token),
GNUNET_JSON_pack_string (
- "kyc_url",
- kyc_url),
+ "payto_uri",
+ ekr->payto_uri),
GNUNET_JSON_pack_string (
"exchange_url",
ekr->exchange_url),
- GNUNET_JSON_pack_string (
- "payto_uri",
- ekr->payto_uri))));
- GNUNET_free (kyc_url);
-}
-
-
-/**
- * Return exchange KYC account status when KYC auth
- * is required for authorization to the KYC state.
- *
- * @param[in,out] ekr our request context
- * @param ks overall HTTP response
- */
-static void
-return_auth_required (
- struct ExchangeKycRequest *ekr,
- const struct TALER_EXCHANGE_KycStatus *ks)
-{
- struct KycContext *kc = ekr->kc;
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TMH_db->account_kyc_set_status (
- TMH_db->cls,
- kc->mi->settings.id,
- &ekr->h_wire,
- ekr->exchange_url,
- GNUNET_TIME_timestamp_get (),
- ks->hr.http_status,
- ks->hr.ec,
- NULL,
- NULL,
- false,
- true);
- if (qs < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to store KYC status in database!\n");
- }
-
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- kc->pending_kycs,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_array_steal (
- "limits",
- get_exchange_limits (ekr,
- NULL))),
- (TALER_EC_NONE == ks->hr.ec)
+ GNUNET_JSON_pack_bool ("no_keys",
+ ekr->no_keys),
+ GNUNET_JSON_pack_bool ("auth_conflict",
+ ekr->kyc_auth_conflict),
+ GNUNET_JSON_pack_uint64 ("exchange_http_status",
+ ekr->last_http_status),
+ (TALER_EC_NONE == ekr->last_ec)
? GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string (
"dummy",
NULL))
: GNUNET_JSON_pack_uint64 ("exchange_code",
- ks->hr.ec),
- GNUNET_JSON_pack_uint64 ("exchange_http_status",
- ks->hr.http_status),
- GNUNET_JSON_pack_array_incref ("payto_kycauths",
- ekr->pkaa),
- GNUNET_JSON_pack_string ("exchange_url",
- ekr->exchange_url),
- GNUNET_JSON_pack_string ("payto_uri",
- ekr->payto_uri))));
+ ekr->last_ec),
+ ekr->auth_ok
+ ? GNUNET_JSON_pack_data_auto (
+ "access_token",
+ &ekr->access_token)
+ : GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string (
+ "dummy",
+ NULL)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_array_steal (
+ "limits",
+ get_exchange_limits (ekr))),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_array_incref ("payto_kycauths",
+ ekr->pkaa))
+ )));
}
/**
- * Function called with the result of a KYC check.
+ * We are done with the KYC request @a ekr. Remove it from the work list and
+ * check if we are done overall.
*
- * @param cls a `struct ExchangeKycRequest *`
- * @param ks the account's KYC status details
+ * @param[in] ekr key request that is done (and will be freed)
*/
static void
-exchange_check_cb (
- void *cls,
- const struct TALER_EXCHANGE_KycStatus *ks)
+ekr_finished (struct ExchangeKycRequest *ekr)
{
- struct ExchangeKycRequest *ekr = cls;
struct KycContext *kc = ekr->kc;
- ekr->kyc = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Checking KYC status of `%s' at `%s' is %u\n",
- ekr->payto_uri,
- ekr->exchange_url,
- ks->hr.http_status);
- switch (ks->hr.http_status)
+ 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);
+ GNUNET_free (ekr);
+
+ if (NULL != kc->exchange_pending_head)
+ return; /* wait for more */
+
+ if ( (! kc->return_immediately) &&
+ (! GNUNET_TIME_absolute_is_past (kc->timeout)) )
{
- case MHD_HTTP_OK:
- update_account_status (ekr,
- ks,
- &ks->details.ok);
- break;
- case MHD_HTTP_ACCEPTED:
- kc->response_code = MHD_HTTP_ACCEPTED;
- update_account_status (ekr,
- ks,
- &ks->details.accepted);
- break;
- case MHD_HTTP_NO_CONTENT:
- {
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TMH_db->account_kyc_set_status (
- TMH_db->cls,
- kc->mi->settings.id,
- &ekr->h_wire,
- ekr->exchange_url,
- GNUNET_TIME_timestamp_get (),
- MHD_HTTP_NO_CONTENT,
- TALER_EC_NONE,
- NULL,
- NULL,
- false,
- true);
- if (qs < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to store KYC status in database!\n");
- }
- }
- break;
- case MHD_HTTP_FORBIDDEN: /* bad signature */
- case MHD_HTTP_NOT_FOUND: /* account unknown */
- case MHD_HTTP_CONFLICT: /* no account_pub known */
- return_auth_required (ekr,
- ks);
- break;
- default:
- {
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Exchange responded with HTTP status %u (%d) to /kyc-check
request!\n",
- ks->hr.http_status,
- ks->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",
- ks->hr.ec),
- GNUNET_JSON_pack_uint64 ("exchange_http_status",
- ks->hr.http_status))));
- qs = TMH_db->account_kyc_set_status (
- TMH_db->cls,
- kc->mi->settings.id,
- &ekr->h_wire,
- ekr->exchange_url,
- GNUNET_TIME_timestamp_get (),
- ks->hr.http_status,
- ks->hr.ec,
- NULL,
- NULL,
- false,
- true);
- if (qs < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to store KYC status in database!\n");
- }
- break;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Remaining suspended: long poll target %d not reached\n",
+ kc->lpt);
+ return;
}
- ekr_finished (ekr);
+ /* All exchange requests done, create final
+ big response from cumulated replies */
+ resume_kyc_with_response (kc);
}
@@ -882,14 +597,13 @@ exchange_check_cb (
* in @a ekr.
*
* @param[in,out] request we are processing
- * @param keys exchange keys
*/
static void
determine_eligible_accounts (
- struct ExchangeKycRequest *ekr,
- const struct TALER_EXCHANGE_Keys *keys)
+ struct ExchangeKycRequest *ekr)
{
struct KycContext *kc = ekr->kc;
+ const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
struct TALER_Amount kyc_amount;
char *merchant_pub_str;
@@ -1022,58 +736,35 @@ kyc_with_exchange (void *cls,
struct TMH_Exchange *exchange)
{
struct ExchangeKycRequest *ekr = cls;
- struct KycContext *kc = ekr->kc;
- struct TALER_PaytoHashP h_payto;
- union TALER_AccountPrivateKeyP ap;
(void) exchange;
ekr->fo = NULL;
if (NULL == keys)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to download `%s/keys`\n",
+ "Failed to download `%skeys`\n",
ekr->exchange_url);
- kc->response_code = MHD_HTTP_BAD_GATEWAY;
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- kc->timeout_kycs,
- GNUNET_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE))));
+ ekr->no_keys = true;
ekr_finished (ekr);
return;
}
- determine_eligible_accounts (ekr,
- keys);
- if (0 == json_array_size (ekr->pkaa))
+ ekr->keys = TALER_EXCHANGE_keys_incref (keys);
+ if (! ekr->auth_ok)
{
- /* No KYC auth wire transfers are possible to this exchange from
- our merchant bank account, so we cannot use this account with
- this exchange if it has any KYC requirements! */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "KYC auth to `%s' impossible for merchant account `%s'\n",
- ekr->exchange_url,
- ekr->payto_uri);
- ekr_finished (ekr);
- return;
+ determine_eligible_accounts (ekr);
+ if (0 == json_array_size (ekr->pkaa))
+ {
+ /* No KYC auth wire transfers are possible to this exchange from
+ our merchant bank account, so we cannot use this account with
+ this exchange if it has any KYC requirements! */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC auth to `%s' impossible for merchant account `%s'\n",
+ ekr->exchange_url,
+ ekr->payto_uri);
+ ekr->kyc_auth_conflict = true;
+ }
}
- ekr->keys = TALER_EXCHANGE_keys_incref (keys);
- TALER_payto_hash (ekr->payto_uri,
- &h_payto);
- ap.merchant_priv = kc->mi->merchant_priv;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Checking KYC status of `%s' at `%s'\n",
- ekr->payto_uri,
- ekr->exchange_url);
- ekr->kyc = TALER_EXCHANGE_kyc_check (
- TMH_curl_ctx,
- ekr->exchange_url,
- &h_payto,
- &ap,
- GNUNET_TIME_absolute_get_remaining (kc->timeout),
- &exchange_check_cb,
- ekr);
+ ekr_finished (ekr);
}
@@ -1083,46 +774,84 @@ kyc_with_exchange (void *cls,
*
* @param cls our `struct KycContext *`
* @param h_wire hash of the wire account
- * @param exchange_kyc_serial serial number for the KYC process at the
exchange, 0 if unknown
* @param payto_uri payto:// URI of the merchant's bank account
* @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 access_token access token for the KYC SPA, NULL if we cannot access
it yet (need KYC auth wire transfer)
+ * @param last_http_status last HTTP status from /kyc-check
+ * @param last_ec last Taler error code from /kyc-check
+ * @param in_aml_review true if the account is pending review
+ * @param jlimits JSON array of applicable AccountLimits, or NULL if unknown
(like defaults apply)
*/
static void
kyc_status_cb (
void *cls,
const struct TALER_MerchantWireHashP *h_wire,
- uint64_t exchange_kyc_serial,
const char *payto_uri,
const char *exchange_url,
struct GNUNET_TIME_Timestamp last_check,
- bool kyc_ok)
+ bool kyc_ok,
+ const struct TALER_AccountAccessTokenP *access_token,
+ unsigned int last_http_status,
+ enum TALER_ErrorCode last_ec,
+ bool in_aml_review,
+ const json_t *jlimits)
{
struct KycContext *kc = cls;
struct ExchangeKycRequest *ekr;
- if (kyc_ok &&
- (GNUNET_TIME_relative_cmp (
- GNUNET_TIME_absolute_get_duration (last_check.abs_time),
- <,
- STALE_KYC_TIMEOUT)) )
- return; /* KYC ok, ignore! */
- kc->response_code = MHD_HTTP_OK;
+ switch (kc->lpt)
+ {
+ case TALER_EXCHANGE_KLPT_NONE:
+ break;
+ case TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER:
+ if (NULL != access_token)
+ kc->return_immediately = true;
+ break;
+ case TALER_EXCHANGE_KLPT_INVESTIGATION_DONE:
+ if (! in_aml_review)
+ kc->return_immediately = true;
+ break;
+ case TALER_EXCHANGE_KLPT_KYC_OK:
+ if (kyc_ok)
+ kc->return_immediately = true;
+ break;
+ }
ekr = GNUNET_new (struct ExchangeKycRequest);
GNUNET_CONTAINER_DLL_insert (kc->exchange_pending_head,
kc->exchange_pending_tail,
ekr);
+ ekr->last_http_status = last_http_status;
+ ekr->last_ec = last_ec;
+ if (NULL != jlimits)
+ ekr->jlimits = json_incref ((json_t *) jlimits);
ekr->h_wire = *h_wire;
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_keys4exchange (
- exchange_url,
- false,
- &kyc_with_exchange,
- ekr);
+ ekr->in_aml_review = in_aml_review;
+ ekr->auth_ok = (NULL != access_token);
+ if ( (! ekr->auth_ok) ||
+ (NULL == ekr->jlimits) )
+ {
+ /* Figure out wire transfer instructions */
+ if (GNUNET_NO == kc->suspended)
+ {
+ MHD_suspend_connection (kc->connection);
+ kc->suspended = GNUNET_YES;
+ }
+ ekr->fo = TMH_EXCHANGES_keys4exchange (
+ exchange_url,
+ false,
+ &kyc_with_exchange,
+ ekr);
+ return;
+ }
+ ekr->access_token = *access_token;
+ ekr_finished (ekr);
}
@@ -1153,32 +882,38 @@ get_instances_ID_kyc (
kc);
kc->connection = connection;
kc->hc = hc;
- kc->pending_kycs = json_array ();
- GNUNET_assert (NULL != kc->pending_kycs);
- kc->timeout_kycs = json_array ();
- GNUNET_assert (NULL != kc->timeout_kycs);
-
+ kc->kycs_data = json_array ();
+ GNUNET_assert (NULL != kc->kycs_data);
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);
-
+ {
+ uint64_t num = 0;
+ int val;
+
+ TALER_MHD_parse_request_number (connection,
+ "lpt",
+ &num);
+ val = (int) num;
+ if ( (val < 0) ||
+ (val > TALER_EXCHANGE_KLPT_MAX) )
+ {
+ /* Protocol violation, but we can be graceful and
+ just ignore the long polling! */
+ GNUNET_break_op (0);
+ val = TALER_EXCHANGE_KLPT_NONE;
+ }
+ kc->lpt = (enum TALER_EXCHANGE_KycLongPollTarget) val;
+ }
+ kc->return_immediately
+ = (TALER_EXCHANGE_KLPT_NONE == kc->lpt);
/* process 'exchange_url' argument */
kc->exchange_url = MHD_lookup_connection_value (
connection,
MHD_GET_ARGUMENT_KIND,
"exchange_url");
if ( (NULL != kc->exchange_url) &&
- (! TALER_url_valid_charset (kc->exchange_url) ||
- ( (0 != strncasecmp (kc->exchange_url,
- "http://",
- strlen ("http://"))) &&
- (0 != strncasecmp (kc->exchange_url,
- "https://",
- strlen ("https://"))) ) ) )
+ ( (! TALER_url_valid_charset (kc->exchange_url)) ||
+ (! TALER_is_web_url (kc->exchange_url)) ) )
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (
@@ -1192,68 +927,101 @@ get_instances_ID_kyc (
"h_wire",
&kc->h_wire,
kc->have_h_wire);
- /* Check our database */
+
+ if ( (TALER_EXCHANGE_KLPT_NONE != kc->lpt) &&
+ (! GNUNET_TIME_absolute_is_past (kc->timeout)) )
{
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TMH_db->account_kyc_get_status (
- TMH_db->cls,
- mi->settings.id,
- kc->have_h_wire
- ? &kc->h_wire
- : NULL,
- kc->exchange_url,
- &kyc_status_cb,
- kc);
- if (qs < 0)
+ if (kc->have_h_wire)
{
- GNUNET_break (0);
- return TALER_MHD_reply_with_ec (
- connection,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "account_kyc_get_status");
+ struct TALER_MERCHANTDB_MerchantKycStatusChangeEventP ev = {
+ .header.size = htons (sizeof (ev)),
+ .header.type = htons (
+ TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_STATUS_CHANGED
+ ),
+ .h_wire = kc->h_wire
+ };
+
+ kc->eh = TMH_db->event_listen (
+ TMH_db->cls,
+ &ev.header,
+ GNUNET_TIME_absolute_get_remaining (kc->timeout),
+ &kyc_change_cb,
+ kc);
}
- }
- if (kc->kyc_serial_pending)
+ else
+ {
+ struct GNUNET_DB_EventHeaderP hdr = {
+ .size = htons (sizeof (hdr)),
+ .type = htons (TALER_DBEVENT_MERCHANT_KYC_STATUS_CHANGED)
+ };
+
+ kc->eh = TMH_db->event_listen (
+ TMH_db->cls,
+ &hdr,
+ GNUNET_TIME_absolute_get_remaining (kc->timeout),
+ &kyc_change_cb,
+ kc);
+ }
+ } /* end register LISTEN hooks */
+ } /* end 1st time initialization */
+
+ if (GNUNET_SYSERR == kc->suspended)
+ return MHD_NO; /* during shutdown, we don't generate any more replies */
+ GNUNET_assert (GNUNET_NO == kc->suspended);
+
+ if (NULL != kc->response)
+ return MHD_queue_response (connection,
+ kc->response_code,
+ kc->response);
+
+ /* Check our database */
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_break (0 ==
+ json_array_clear (kc->kycs_data));
+ qs = TMH_db->account_kyc_get_status (
+ TMH_db->cls,
+ mi->settings.id,
+ kc->have_h_wire
+ ? &kc->h_wire
+ : NULL,
+ kc->exchange_url,
+ &kyc_status_cb,
+ kc);
+ if (qs < 0)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Exchange legitimization UUID unknown, assuming KYC
pending\n");
- return TALER_MHD_REPLY_JSON_PACK (
+ /* Database error */
+ GNUNET_break (0);
+ if (GNUNET_YES == kc->suspended)
+ {
+ /* must have suspended before DB error, resume! */
+ MHD_resume_connection (connection);
+ kc->suspended = GNUNET_NO;
+ }
+ return TALER_MHD_reply_with_ec (
connection,
- MHD_HTTP_SERVICE_UNAVAILABLE,
- GNUNET_JSON_pack_string ("hint",
- "awaiting legitimization UUID"));
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "account_kyc_get_status");
}
- if (NULL == kc->exchange_pending_head)
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ /* no matching accounts, could not have suspended */
+ GNUNET_assert (GNUNET_NO == kc->suspended);
return TALER_MHD_reply_static (connection,
MHD_HTTP_NO_CONTENT,
NULL,
NULL,
0);
- MHD_suspend_connection (connection);
- kc->suspended = GNUNET_YES;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Suspending KYC request handling while checking with the
exchange(s)\n");
- return MHD_YES;
- }
- if (GNUNET_SYSERR == kc->suspended)
- return MHD_NO; /* during shutdown, we don't generate any more replies */
- GNUNET_assert (GNUNET_NO == kc->suspended);
- if (0 != kc->response_code)
- {
- /* We are *done* processing the request, just queue the response (!) */
- if (UINT_MAX == kc->response_code)
- {
- GNUNET_break (0);
- return MHD_NO; /* hard error */
}
- return MHD_queue_response (connection,
- kc->response_code,
- kc->response);
}
- /* we should never get here */
- GNUNET_break (0);
- return MHD_NO;
+ if (GNUNET_YES == kc->suspended)
+ return MHD_YES;
+ /* Should have generated a response */
+ GNUNET_break (NULL != kc->response);
+ return MHD_queue_response (connection,
+ kc->response_code,
+ kc->response);
}
diff --git a/src/backend/taler-merchant-kyccheck.c
b/src/backend/taler-merchant-kyccheck.c
index 279be891..f001285c 100644
--- a/src/backend/taler-merchant-kyccheck.c
+++ b/src/backend/taler-merchant-kyccheck.c
@@ -38,6 +38,14 @@
GNUNET_TIME_UNIT_MINUTES, \
30)
+/**
+ * How long do we wait between requests if all we wait
+ * for is a change in the AML investigation status?
+ */
+#define AML_FREQ GNUNET_TIME_relative_multiply ( \
+ GNUNET_TIME_UNIT_HOURS, \
+ 6)
+
/**
* How many inquiries do we process concurrently at most.
*/
@@ -467,8 +475,15 @@ exchange_check_cb (
store_kyc_status (i,
&ks->details.ok);
i->backoff = GNUNET_TIME_UNIT_ZERO;
- /* KYC is OK, only check again if triggered */
- i->due = GNUNET_TIME_UNIT_FOREVER_ABS;
+ if (i->aml_review)
+ {
+ i->due = GNUNET_TIME_relative_to_absolute (AML_FREQ);
+ }
+ else
+ {
+ /* KYC is OK, only check again if triggered */
+ i->due = GNUNET_TIME_UNIT_FOREVER_ABS;
+ }
break;
case MHD_HTTP_ACCEPTED:
i->last_kyc_check = GNUNET_TIME_timestamp_get ();
@@ -573,6 +588,7 @@ static void
inquiry_work (void *cls)
{
struct Inquiry *i = cls;
+ enum TALER_EXCHANGE_KycLongPollTarget lpt;
i->task = NULL;
if (! GNUNET_TIME_absolute_is_past (i->due))
@@ -600,11 +616,19 @@ inquiry_work (void *cls)
i->e->keys->exchange_url);
i->timeout
= GNUNET_TIME_relative_to_absolute (EXCHANGE_TIMEOUT);
+ lpt = TALER_EXCHANGE_KLPT_NONE;
+ if (! i->auth_ok)
+ lpt = TALER_EXCHANGE_KLPT_NONE;
+ else if (! i->kyc_ok)
+ lpt = TALER_EXCHANGE_KLPT_KYC_OK;
+ else if (i->aml_review)
+ lpt = TALER_EXCHANGE_KLPT_INVESTIGATION_DONE;
i->kyc = TALER_EXCHANGE_kyc_check (
ctx,
i->e->keys->exchange_url,
&i->a->h_payto,
&i->a->ap,
+ lpt,
EXCHANGE_TIMEOUT,
&exchange_check_cb,
i);
@@ -997,7 +1021,9 @@ find_keys (const char *exchange_url)
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
- GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "No %s/keys yet!\n",
+ exchange_url);
return;
}
for (e = e_head; NULL != e; e = e->next)
diff --git a/src/backenddb/pg_account_kyc_get_status.c
b/src/backenddb/pg_account_kyc_get_status.c
index 1eee0416..0a89189c 100644
--- a/src/backenddb/pg_account_kyc_get_status.c
+++ b/src/backenddb/pg_account_kyc_get_status.c
@@ -40,16 +40,6 @@ struct KycStatusContext
*/
void *kyc_cb_cls;
- /**
- * Filter, NULL to not filter.
- */
- const struct TALER_MerchantWireHashP *h_wire;
-
- /**
- * Filter, NULL to not filter.
- */
- const char *exchange_url;
-
/**
* Number of results found.
*/
@@ -80,11 +70,16 @@ kyc_status_cb (void *cls,
for (unsigned int i = 0; i < num_results; i++)
{
struct TALER_MerchantWireHashP h_wire;
- uint64_t kyc_serial = 0; /* deprecated */
char *exchange_url;
char *payto_uri;
struct GNUNET_TIME_Timestamp last_check;
bool kyc_ok;
+ struct TALER_AccountAccessTokenP access_token;
+ bool no_auth;
+ uint32_t h32;
+ uint32_t e32;
+ bool in_aml_review;
+ json_t *jlimits = NULL;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&h_wire),
@@ -96,8 +91,24 @@ kyc_status_cb (void *cls,
&last_check),
GNUNET_PQ_result_spec_bool ("kyc_ok",
&kyc_ok),
+ 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 (
+ TALER_PQ_result_spec_json ("jaccount_limits",
+ &jlimits),
+ NULL),
GNUNET_PQ_result_spec_end
};
+ unsigned int last_http_status;
+ enum TALER_ErrorCode last_ec;
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
@@ -108,28 +119,22 @@ kyc_status_cb (void *cls,
ksc->failure = true;
return;
}
- if ( (NULL != ksc->exchange_url) &&
- (0 != strcmp (ksc->exchange_url,
- exchange_url)) )
- {
- GNUNET_PQ_cleanup_result (rs);
- continue;
- }
- if ( (NULL != ksc->h_wire) &&
- (0 != GNUNET_memcmp (ksc->h_wire,
- &h_wire)) )
- {
- GNUNET_PQ_cleanup_result (rs);
- continue;
- }
+ last_http_status = (unsigned int) h32;
+ last_ec = (enum TALER_ErrorCode) (int) e32;
ksc->count++;
ksc->kyc_cb (ksc->kyc_cb_cls,
&h_wire,
- kyc_serial,
payto_uri,
exchange_url,
last_check,
- kyc_ok);
+ kyc_ok,
+ (no_auth)
+ ? NULL
+ : &access_token,
+ last_http_status,
+ last_ec,
+ in_aml_review,
+ jlimits);
GNUNET_PQ_cleanup_result (rs);
}
}
@@ -147,12 +152,16 @@ TMH_PG_account_kyc_get_status (
struct PostgresClosure *pg = cls;
struct KycStatusContext ksc = {
.kyc_cb = kyc_cb,
- .kyc_cb_cls = kyc_cb_cls,
- .exchange_url = exchange_url,
- .h_wire = h_wire
+ .kyc_cb_cls = kyc_cb_cls
};
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (merchant_id),
+ NULL == exchange_url
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (exchange_url),
+ NULL == h_wire
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (h_wire),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
@@ -166,17 +175,27 @@ TMH_PG_account_kyc_get_status (
",exchange_url"
",kyc_timestamp"
",kyc_ok"
+ ",access_token"
+ ",exchange_http_status"
+ ",exchange_ec_code"
+ ",aml_review"
+ ",jaccount_limits"
" FROM merchant_instances"
" JOIN merchant_accounts"
" USING (merchant_serial)"
" JOIN merchant_kyc"
" USING (account_serial)"
- " WHERE merchant_instances.merchant_id=$1");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_kyc_status",
- params,
- &kyc_status_cb,
- &ksc);
+ " WHERE (merchant_instances.merchant_id=$1)"
+ " AND ( ($2::TEXT IS NULL)"
+ " OR (exchange_url=$2) )"
+ " AND ( ($3::BYTEA IS NULL)"
+ " OR (h_wire=$3) );");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "lookup_kyc_status",
+ params,
+ &kyc_status_cb,
+ &ksc);
if (ksc.failure)
{
GNUNET_break (0);
diff --git a/src/backenddb/pg_account_kyc_set_status.c
b/src/backenddb/pg_account_kyc_set_status.c
index ecd63fb3..f2a3e51e 100644
--- a/src/backenddb/pg_account_kyc_set_status.c
+++ b/src/backenddb/pg_account_kyc_set_status.c
@@ -47,8 +47,14 @@ TMH_PG_account_kyc_set_status (
.header.type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_STATUS_CHANGED),
.h_wire = *h_wire
};
+ struct GNUNET_DB_EventHeaderP hdr = {
+ .size = htons (sizeof (hdr)),
+ .type = htons (TALER_DBEVENT_MERCHANT_KYC_STATUS_CHANGED)
+ };
char *notify_s
= GNUNET_PQ_get_event_notify_channel (&ev.header);
+ char *notify2_s
+ = GNUNET_PQ_get_event_notify_channel (&hdr);
uint32_t http_status32 = (uint32_t) exchange_http_status;
uint32_t ec_code32 = (uint32_t) exchange_ec_code;
struct GNUNET_PQ_QueryParam params[] = {
@@ -67,6 +73,7 @@ TMH_PG_account_kyc_set_status (
GNUNET_PQ_query_param_bool (in_aml_review),
GNUNET_PQ_query_param_bool (kyc_ok),
GNUNET_PQ_query_param_string (notify_s),
+ GNUNET_PQ_query_param_string (notify2_s),
GNUNET_PQ_query_param_end
};
bool no_instance;
@@ -87,13 +94,14 @@ TMH_PG_account_kyc_set_status (
" out_no_instance AS no_instance"
" ,out_no_account AS no_account"
" FROM merchant_do_account_kyc_set_status"
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);");
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
"account_kyc_set_status",
params,
rs);
GNUNET_free (notify_s);
+ GNUNET_free (notify2_s);
if (qs <= 0)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
diff --git a/src/backenddb/pg_account_kyc_set_status.sql
b/src/backenddb/pg_account_kyc_set_status.sql
index 2d752167..dcb26a44 100644
--- a/src/backenddb/pg_account_kyc_set_status.sql
+++ b/src/backenddb/pg_account_kyc_set_status.sql
@@ -29,6 +29,7 @@ CREATE FUNCTION merchant_do_account_kyc_set_status (
IN in_aml_active BOOL,
IN in_kyc_ok BOOL,
IN in_notify_str TEXT,
+ IN in_notify2_str TEXT,
OUT out_no_instance BOOL,
OUT out_no_account BOOL)
LANGUAGE plpgsql
@@ -105,6 +106,10 @@ EXECUTE FORMAT (
'NOTIFY %s'
,in_notify_str);
+EXECUTE FORMAT (
+ 'NOTIFY %s'
+ ,in_notify2_str);
+
-- Success!
END $$;
diff --git a/src/backenddb/pg_get_kyc_status.c
b/src/backenddb/pg_get_kyc_status.c
index 5c980bfd..3a216d83 100644
--- a/src/backenddb/pg_get_kyc_status.c
+++ b/src/backenddb/pg_get_kyc_status.c
@@ -77,27 +77,23 @@ TMH_PG_get_kyc_status (
PREPARE (pg,
"get_kyc_status",
"SELECT"
- " access_token"
- ",exchange_http_status"
- ",exchange_ec_code"
- ",kyc_ok"
- ",kyc_timestamp"
- ",aml_review"
- ",jaccount_limits"
+ " mk.access_token"
+ ",mk.exchange_http_status"
+ ",mk.exchange_ec_code"
+ ",mk.kyc_ok"
+ ",mk.kyc_timestamp"
+ ",mk.aml_review"
+ ",mk.jaccount_limits"
" FROM merchant_kyc mk"
- " JOIN merchant_accounts"
- " USING (merchant_serial)"
- " JOIN merchant_kyc"
- " USING (account_serial)"
- " WHERE exchange_url=$3"
- " AND account_serial="
+ " WHERE mk.exchange_url=$3"
+ " AND mk.account_serial="
" (SELECT account_serial"
" FROM merchant_accounts"
" WHERE payto_uri=$1"
" AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$2));");
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$2));");
*jlimits = NULL;
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"get_kyc_status",
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 392511e1..f1d6e392 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -5570,13 +5570,18 @@ test_lookup_orders_all_filters (void)
static void
-kyc_status_ok (void *cls,
- const struct TALER_MerchantWireHashP *h_wire,
- uint64_t exchange_kyc_serial,
- const char *payto_uri,
- const char *exchange_url,
- struct GNUNET_TIME_Timestamp last_check,
- bool kyc_ok)
+kyc_status_ok (
+ void *cls,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const char *payto_uri,
+ const char *exchange_url,
+ struct GNUNET_TIME_Timestamp last_check,
+ bool kyc_ok,
+ const struct TALER_AccountAccessTokenP *access_token,
+ unsigned int last_http_status,
+ enum TALER_ErrorCode last_ec,
+ bool in_aml_review,
+ const json_t *jlimits)
{
bool *fail = cls;
@@ -5586,13 +5591,18 @@ kyc_status_ok (void *cls,
static void
-kyc_status_fail (void *cls,
- const struct TALER_MerchantWireHashP *h_wire,
- uint64_t exchange_kyc_serial,
- const char *payto_uri,
- const char *exchange_url,
- struct GNUNET_TIME_Timestamp last_check,
- bool kyc_ok)
+kyc_status_fail (
+ void *cls,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const char *payto_uri,
+ const char *exchange_url,
+ struct GNUNET_TIME_Timestamp last_check,
+ bool kyc_ok,
+ const struct TALER_AccountAccessTokenP *access_token,
+ unsigned int last_http_status,
+ enum TALER_ErrorCode last_ec,
+ bool in_aml_review,
+ const json_t *jlimits)
{
bool *fail = cls;
diff --git a/src/include/taler_merchant_service.h
b/src/include/taler_merchant_service.h
index b1840ea8..05ea273b 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -4386,15 +4386,6 @@ struct TALER_MERCHANT_AccountKycRedirectDetail
*/
struct TALER_AccountAccessTokenP access_token;
- /**
- * URL that the user should open in a browser to
- * proceed with the KYC process (as returned
- * by the exchange's /kyc-check/ endpoint). Can
- * be NULL, specifically if KYC is satisfied but
- * the transactions are hanging in AML.
- */
- const char *kyc_url;
-
/**
* Base URL of the exchange this is about.
*/
@@ -4442,31 +4433,25 @@ struct TALER_MERCHANT_AccountKycRedirectDetail
*/
enum TALER_ErrorCode exchange_code;
-};
-
-
-/**
- * Information about KYC status failures at the exchange.
- */
-struct TALER_MERCHANT_ExchangeKycFailureDetail
-{
/**
- * Base URL of the exchange this is about.
+ * Set to true if @e access_token was not given.
*/
- const char *exchange_url;
+ bool no_access_token;
/**
- * Error code indicating errors the exchange
- * returned, or #TALER_EC_INVALID for none.
+ * Set to true if the merchant backend could not
+ * get the exchanges ``/keys`` and thus could not
+ * determine default limits or determine an
+ * @e auth_conflict.
*/
- enum TALER_ErrorCode exchange_code;
+ bool no_keys;
/**
- * HTTP status code returned by the exchange when we asked for
- * information about the KYC status.
- * 0 if there was no response at all.
+ * Set to true if the given account cannot to KYC at the given exchange
+ * because no wire method exists that could be used to do the KYC auth wire
+ * transfer.
*/
- unsigned int exchange_http_status;
+ bool auth_conflict;
};
@@ -4486,32 +4471,22 @@ struct TALER_MERCHANT_KycResponse
union
{
/**
- * Information returned if the status was #MHD_HTTP_ACCEPTED,
- * #MHD_HTTP_BAD_GATEWAY or #MHD_HTTP_GATEWAY_TIMEOUT.
+ * Information returned if the status was #MHD_HTTP_OK.
*/
struct
{
/**
- * Array with information about KYC actions the merchant still must
perform.
+ * Array with information about KYC actions the merchant may perform.
*/
- struct TALER_MERCHANT_AccountKycRedirectDetail *pending_kycs;
-
- /**
- * Array with information about KYC failures at the exchange.
- */
- struct TALER_MERCHANT_ExchangeKycFailureDetail *timeout_kycs;
+ struct TALER_MERCHANT_AccountKycRedirectDetail *kycs;
/**
* Length of the @e pending_kycs array.
*/
- unsigned int pending_kycs_length;
+ unsigned int kycs_length;
- /**
- * Length of the @e timeout_kycs array.
- */
- unsigned int timeout_kycs_length;
- } kyc_status;
+ } ok;
} details;
@@ -4538,7 +4513,11 @@ typedef void
* @param backend_url base URL of the merchant backend
* @param h_wire which bank account to query, NULL for all
* @param exchange_url which exchange to query, NULL for all
- * @param timeout how long to wait for a (positive) reply
+ * @param lpt target for long polling
+ * @param timeout how long to wait for an answer, including possibly long
polling for the desired @a lpt status;
+ * note that when pulling for multiple accounts, any
+ * account reaching this status will cause the
+ * response to be returned
* @param cb function to call with the result
* @param cb_cls closure for @a cb
* @return handle for this operation, NULL upon errors
@@ -4549,6 +4528,7 @@ TALER_MERCHANT_kyc_get (
const char *backend_url,
const struct TALER_MerchantWireHashP *h_wire,
const char *exchange_url,
+ enum TALER_EXCHANGE_KycLongPollTarget lpt,
struct GNUNET_TIME_Relative timeout,
TALER_MERCHANT_KycGetCallback cb,
void *cb_cls);
@@ -4563,7 +4543,8 @@ TALER_MERCHANT_kyc_get (
* @param instance_id specific instance to query
* @param h_wire which bank account to query, NULL for all
* @param exchange_url which exchange to query, NULL for all
- * @param timeout how long to wait for a (positive) reply
+ * @param lpt target for long polling
+ * @param timeout how long to wait for a reply
* @param cb function to call with the result
* @param cb_cls closure for @a cb
* @return handle for this operation, NULL upon errors
@@ -4575,6 +4556,7 @@ TALER_MERCHANT_management_kyc_get (
const char *instance_id,
const struct TALER_MerchantWireHashP *h_wire,
const char *exchange_url,
+ enum TALER_EXCHANGE_KycLongPollTarget lpt,
struct GNUNET_TIME_Relative timeout,
TALER_MERCHANT_KycGetCallback cb,
void *cb_cls);
diff --git a/src/include/taler_merchant_testing_lib.h
b/src/include/taler_merchant_testing_lib.h
index 4833e4fe..c18274dc 100644
--- a/src/include/taler_merchant_testing_lib.h
+++ b/src/include/taler_merchant_testing_lib.h
@@ -1259,6 +1259,7 @@ TALER_TESTING_cmd_merchant_delete_transfer (const char
*label,
* @param h_wire_ref label of command with a merchant wire hash trait
* of the bank account to check KYC for; NULL to check all accounts
* @param exchange_url base URL of the exchange to check KYC status for
+ * @param lpt target for long polling
* @param expected_http_status expected HTTP status
* @param expected_kyc_state expected KYC state (only effective if @e
expected_http_status is #MHD_HTTP_OK/#MHD_HTTP_ACCEPTED)
* @return the command
@@ -1270,6 +1271,7 @@ TALER_TESTING_cmd_merchant_kyc_get (
const char *instance_id,
const char *h_wire_ref,
const char *exchange_url,
+ enum TALER_EXCHANGE_KycLongPollTarget lpt,
unsigned int expected_http_status,
bool expected_kyc_state);
diff --git a/src/include/taler_merchantdb_plugin.h
b/src/include/taler_merchantdb_plugin.h
index 5e50845c..41d7570d 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -854,16 +854,25 @@ typedef void
* @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 access_token access token for the KYC SPA, NULL if we cannot access
it yet (need KYC auth wire transfer)
+ * @param last_http_status last HTTP status from /kyc-check
+ * @param last_ec last Taler error code from /kyc-check
+ * @param in_aml_review true if the account is pending review
+ * @param jlimits JSON array of applicable AccountLimits, or NULL if unknown
(like defaults apply)
*/
typedef void
(*TALER_MERCHANTDB_KycCallback)(
void *cls,
const struct TALER_MerchantWireHashP *h_wire,
- uint64_t exchange_kyc_serial,
const char *payto_uri,
const char *exchange_url,
struct GNUNET_TIME_Timestamp last_check,
- bool kyc_ok);
+ bool kyc_ok,
+ const struct TALER_AccountAccessTokenP *access_token,
+ unsigned int last_http_status,
+ enum TALER_ErrorCode last_ec,
+ bool in_aml_review,
+ const json_t *jlimits);
/**
diff --git a/src/lib/merchant_api_get_kyc.c b/src/lib/merchant_api_get_kyc.c
index bf5d4300..8e441647 100644
--- a/src/lib/merchant_api_get_kyc.c
+++ b/src/lib/merchant_api_get_kyc.c
@@ -75,36 +75,27 @@ struct TALER_MERCHANT_KycGetHandle
* @param kyc operation handle
* @param[in,out] kr response details
* @param pends pending_kycs array from the reply
- * @param touts timeout_kycs array from the reply
* @return #GNUNET_OK on success (callback was called)
*/
static enum GNUNET_GenericReturnValue
parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
struct TALER_MERCHANT_KycResponse *kr,
- const json_t *pends,
- const json_t *touts)
+ const json_t *jkyc)
{
- unsigned int num_pends = (unsigned int) json_array_size (pends);
- unsigned int num_touts = (unsigned int) json_array_size (touts);
+ unsigned int num_kycs = (unsigned int) json_array_size (jkyc);
unsigned int num_limits = 0;
unsigned int num_kycauths = 0;
unsigned int pos_limits = 0;
unsigned int pos_kycauths = 0;
- if ( (json_array_size (pends) != (size_t) num_pends) ||
- (num_pends > MAX_KYC) )
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if ( (json_array_size (touts) != (size_t) num_touts) ||
- (num_touts > MAX_KYC) )
+ if ( (json_array_size (jkyc) != (size_t) num_kycs) ||
+ (num_kycs > MAX_KYC) )
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
- for (unsigned int i = 0; i<num_pends; i++)
+ for (unsigned int i = 0; i<num_kycs; i++)
{
const json_t *jlimits = NULL;
const json_t *jkycauths = NULL;
@@ -123,13 +114,13 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
};
if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (pends,
+ GNUNET_JSON_parse (json_array_get (jkyc,
i),
spec,
NULL, NULL))
{
GNUNET_break (0);
- json_dumpf (json_array_get (pends,
+ json_dumpf (json_array_get (jkyc,
i),
stderr,
JSON_INDENT (2));
@@ -141,25 +132,49 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
{
- struct TALER_MERCHANT_AccountKycRedirectDetail pending_kycs[
- GNUNET_NZL (num_pends)];
- struct TALER_MERCHANT_ExchangeKycFailureDetail timeout_kycs[
- GNUNET_NZL (num_touts)];
+ struct TALER_MERCHANT_AccountKycRedirectDetail kycs[
+ GNUNET_NZL (num_kycs)];
struct TALER_EXCHANGE_AccountLimit limits[
GNUNET_NZL (num_limits)];
const char *payto_kycauths[
GNUNET_NZL (num_kycauths)];
- memset (pending_kycs,
+ memset (kycs,
0,
- sizeof (pending_kycs));
- for (unsigned int i = 0; i<num_pends; i++)
+ sizeof (kycs));
+ for (unsigned int i = 0; i<num_kycs; i++)
{
struct TALER_MERCHANT_AccountKycRedirectDetail *rd
- = &pending_kycs[i];
+ = &kycs[i];
const json_t *jlimits = NULL;
const json_t *jkycauths = NULL;
+ uint32_t hs;
struct GNUNET_JSON_Specification spec[] = {
+ TALER_JSON_spec_payto_uri (
+ "payto_uri",
+ &rd->payto_uri),
+ TALER_JSON_spec_web_url (
+ "exchange_url",
+ &rd->exchange_url),
+ GNUNET_JSON_spec_uint32 (
+ "exchange_http_status",
+ &hs),
+ GNUNET_JSON_spec_bool (
+ "no_keys",
+ &rd->no_keys),
+ GNUNET_JSON_spec_bool (
+ "auth_conflict",
+ &rd->auth_conflict),
+ GNUNET_JSON_spec_mark_optional (
+ TALER_JSON_spec_ec (
+ "exchange_code",
+ &rd->exchange_code),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_fixed_auto (
+ "access_token",
+ &rd->access_token),
+ &rd->no_access_token),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_array_const (
"limits",
@@ -170,18 +185,6 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
"payto_kycauths",
&jkycauths),
NULL),
- GNUNET_JSON_spec_fixed_auto (
- "access_token",
- &rd->access_token),
- TALER_JSON_spec_web_url (
- "kyc_url",
- &rd->kyc_url),
- TALER_JSON_spec_web_url (
- "exchange_url",
- &rd->exchange_url),
- TALER_JSON_spec_payto_uri (
- "payto_uri",
- &rd->payto_uri),
GNUNET_JSON_spec_end ()
};
size_t j;
@@ -189,18 +192,19 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
json_t *jkycauth;
if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (pends,
+ GNUNET_JSON_parse (json_array_get (jkyc,
i),
spec,
NULL, NULL))
{
GNUNET_break (0);
- json_dumpf (json_array_get (pends,
+ json_dumpf (json_array_get (jkyc,
i),
stderr,
JSON_INDENT (2));
return GNUNET_SYSERR;
}
+ rd->exchange_http_status = (unsigned int) hs;
rd->limits = &limits[pos_limits];
rd->limits_length = json_array_size (jlimits);
json_array_foreach (jlimits, j, jlimit)
@@ -233,7 +237,7 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
NULL, NULL))
{
GNUNET_break (0);
- json_dumpf (json_array_get (pends,
+ json_dumpf (json_array_get (jkyc,
i),
stderr,
JSON_INDENT (2));
@@ -251,7 +255,7 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
if (NULL == payto_kycauths[pos_kycauths])
{
GNUNET_break (0);
- json_dumpf (json_array_get (pends,
+ json_dumpf (json_array_get (jkyc,
i),
stderr,
JSON_INDENT (2));
@@ -260,38 +264,8 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
pos_kycauths++;
}
}
- for (unsigned int i = 0; i<num_touts; i++)
- {
- uint32_t hs;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_web_url (
- "exchange_url",
- &timeout_kycs[i].exchange_url),
- TALER_JSON_spec_ec (
- "exchange_code",
- &timeout_kycs[i].exchange_code),
- GNUNET_JSON_spec_uint32 (
- "exchange_http_status",
- &hs),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (touts,
- i),
- spec,
- NULL, NULL))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- timeout_kycs[i].exchange_http_status
- = (unsigned int) hs;
- }
- kr->details.kyc_status.pending_kycs = pending_kycs;
- kr->details.kyc_status.timeout_kycs = timeout_kycs;
- kr->details.kyc_status.pending_kycs_length = num_pends;
- kr->details.kyc_status.timeout_kycs_length = num_touts;
+ kr->details.ok.kycs = kycs;
+ kr->details.ok.kycs_length = num_kycs;
kyc->cb (kyc->cb_cls,
kr);
}
@@ -325,19 +299,12 @@ handle_get_kyc_finished (void *cls,
(unsigned int) response_code);
switch (response_code)
{
- case MHD_HTTP_NO_CONTENT:
- break;
- case MHD_HTTP_ACCEPTED:
- case MHD_HTTP_BAD_GATEWAY:
- case MHD_HTTP_GATEWAY_TIMEOUT:
+ case MHD_HTTP_OK:
{
- const json_t *pends;
- const json_t *touts;
+ const json_t *jkyc;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("pending_kycs",
- &pends),
- GNUNET_JSON_spec_array_const ("timeout_kycs",
- &touts),
+ GNUNET_JSON_spec_array_const ("kyc_data",
+ &jkyc),
GNUNET_JSON_spec_end ()
};
@@ -353,8 +320,7 @@ handle_get_kyc_finished (void *cls,
if (GNUNET_OK !=
parse_kyc (kyc,
&kr,
- pends,
- touts))
+ jkyc))
{
kr.hr.http_status = 0;
kr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
@@ -364,6 +330,8 @@ handle_get_kyc_finished (void *cls,
TALER_MERCHANT_kyc_get_cancel (kyc);
return;
}
+ case MHD_HTTP_NO_CONTENT:
+ break;
case MHD_HTTP_UNAUTHORIZED:
kr.hr.ec = TALER_JSON_get_error_code (json);
kr.hr.hint = TALER_JSON_get_error_hint (json);
@@ -395,7 +363,8 @@ handle_get_kyc_finished (void *cls,
* @param[in] url URL to use for the request, consumed!
* @param h_wire which bank account to query, NULL for all
* @param exchange_url which exchange to query, NULL for all
- * @param timeout how long to wait for a (positive) reply
+ * @param lpt target for long polling
+ * @param timeout how long to wait for a reply
* @param cb function to call with the result
* @param cb_cls closure for @a cb
* @return handle for this operation, NULL upon errors
@@ -405,6 +374,7 @@ kyc_get (struct GNUNET_CURL_Context *ctx,
char *url,
const struct TALER_MerchantWireHashP *h_wire,
const char *exchange_url,
+ enum TALER_EXCHANGE_KycLongPollTarget lpt,
struct GNUNET_TIME_Relative timeout,
TALER_MERCHANT_KycGetCallback cb,
void *cb_cls)
@@ -412,34 +382,44 @@ kyc_get (struct GNUNET_CURL_Context *ctx,
struct TALER_MERCHANT_KycGetHandle *kyc;
CURL *eh;
char timeout_ms[32];
- unsigned int tms;
+ char lpt_str[32];
+ unsigned long long tms;
kyc = GNUNET_new (struct TALER_MERCHANT_KycGetHandle);
kyc->ctx = ctx;
kyc->cb = cb;
kyc->cb_cls = cb_cls;
- tms = (unsigned int) (timeout.rel_value_us
- / GNUNET_TIME_UNIT_MILLISECONDS.
- rel_value_us);
+ GNUNET_snprintf (lpt_str,
+ sizeof (lpt_str),
+ "%d",
+ (int) lpt);
+ tms = timeout.rel_value_us
+ / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
GNUNET_snprintf (timeout_ms,
sizeof (timeout_ms),
- "%u",
+ "%llu",
tms);
- kyc->url = TALER_url_join (url,
- "kyc",
- "h_wire",
- NULL == h_wire
- ? NULL
- : GNUNET_h2s_full (&h_wire->hash),
- "exchange_url",
- NULL == exchange_url
- ? NULL
- : exchange_url,
- "timeout_ms",
- GNUNET_TIME_relative_is_zero (timeout)
- ? NULL
- : timeout_ms,
- NULL);
+ kyc->url
+ = TALER_url_join (
+ url,
+ "kyc",
+ "h_wire",
+ NULL == h_wire
+ ? NULL
+ : GNUNET_h2s_full (&h_wire->hash),
+ "exchange_url",
+ NULL == exchange_url
+ ? NULL
+ : exchange_url,
+ "timeout_ms",
+ GNUNET_TIME_relative_is_zero (timeout)
+ ? NULL
+ : timeout_ms,
+ "lpt",
+ TALER_EXCHANGE_KLPT_NONE == lpt
+ ? NULL
+ : lpt_str,
+ NULL);
GNUNET_free (url);
if (NULL == kyc->url)
{
@@ -459,22 +439,25 @@ kyc_get (struct GNUNET_CURL_Context *ctx,
CURLOPT_TIMEOUT_MS,
(long) (tms + 100L)));
}
- kyc->job = GNUNET_CURL_job_add (ctx,
- eh,
- &handle_get_kyc_finished,
- kyc);
+ kyc->job
+ = GNUNET_CURL_job_add (ctx,
+ eh,
+ &handle_get_kyc_finished,
+ kyc);
return kyc;
}
struct TALER_MERCHANT_KycGetHandle *
-TALER_MERCHANT_kyc_get (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const struct TALER_MerchantWireHashP *h_wire,
- const char *exchange_url,
- struct GNUNET_TIME_Relative timeout,
- TALER_MERCHANT_KycGetCallback cb,
- void *cb_cls)
+TALER_MERCHANT_kyc_get (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const char *exchange_url,
+ enum TALER_EXCHANGE_KycLongPollTarget lpt,
+ struct GNUNET_TIME_Relative timeout,
+ TALER_MERCHANT_KycGetCallback cb,
+ void *cb_cls)
{
char *url;
@@ -485,6 +468,7 @@ TALER_MERCHANT_kyc_get (struct GNUNET_CURL_Context *ctx,
url, /* consumed! */
h_wire,
exchange_url,
+ lpt,
timeout,
cb,
cb_cls);
@@ -492,14 +476,16 @@ TALER_MERCHANT_kyc_get (struct GNUNET_CURL_Context *ctx,
struct TALER_MERCHANT_KycGetHandle *
-TALER_MERCHANT_management_kyc_get (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *instance_id,
- const struct TALER_MerchantWireHashP
*h_wire,
- const char *exchange_url,
- struct GNUNET_TIME_Relative timeout,
- TALER_MERCHANT_KycGetCallback cb,
- void *cb_cls)
+TALER_MERCHANT_management_kyc_get (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *instance_id,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const char *exchange_url,
+ enum TALER_EXCHANGE_KycLongPollTarget lpt,
+ struct GNUNET_TIME_Relative timeout,
+ TALER_MERCHANT_KycGetCallback cb,
+ void *cb_cls)
{
char *url;
@@ -511,6 +497,7 @@ TALER_MERCHANT_management_kyc_get (struct
GNUNET_CURL_Context *ctx,
url, /* consumed! */
h_wire,
exchange_url,
+ lpt,
timeout,
cb,
cb_cls);
diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c
index 5f34995a..53e2818f 100644
--- a/src/testing/test_kyc_api.c
+++ b/src/testing/test_kyc_api.c
@@ -240,8 +240,9 @@ run (void *cls,
NULL,
NULL,
EXCHANGE_URL,
- MHD_HTTP_NO_CONTENT,
- false),
+ TALER_EXCHANGE_KLPT_NONE,
+ MHD_HTTP_OK,
+ true),
/* now we get the legi UUID by running taler-merchant-depositcheck */
TALER_TESTING_cmd_depositcheck (
"deposit-check",
@@ -260,16 +261,15 @@ run (void *cls,
"get-default-instance"),
CMD_EXEC_WIREWATCH (
"import-kyc-account-withdraw"),
-
-
/* Now we should get a status of pending */
TALER_TESTING_cmd_merchant_kyc_get (
"kyc-pending",
merchant_url,
- NULL, /* instance */
- NULL, /* h_wire_ref: which account to query */
+ NULL, /* default instance */
+ "instance-create-default-account", /* h_wire_ref: which account to query
*/
EXCHANGE_URL,
- MHD_HTTP_ACCEPTED,
+ TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER,
+ MHD_HTTP_OK,
true),
TALER_TESTING_cmd_get_kyc_info (
"get-kyc-info-deposit",
@@ -426,7 +426,8 @@ run (void *cls,
NULL, /* no instance ID */
NULL, /* no wire ref */
EXCHANGE_URL,
- MHD_HTTP_ACCEPTED,
+ TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER,
+ MHD_HTTP_OK,
true),
TALER_TESTING_cmd_sleep (
"sleep to de-collide AML timestamps",
@@ -454,6 +455,7 @@ run (void *cls,
NULL, /* no instance ID */
NULL, /* no wire ref */
EXCHANGE_URL,
+ TALER_EXCHANGE_KLPT_KYC_OK,
MHD_HTTP_OK,
false),
CMD_EXEC_AGGREGATOR ("run-aggregator-aml-normal"),
@@ -521,10 +523,8 @@ run (void *cls,
MHD_HTTP_OK),
TALER_TESTING_cmd_batch ("pay",
pay),
-#if FIXME_FUTURE_WORK || 1
TALER_TESTING_cmd_batch ("aml",
aml),
-#endif
TALER_TESTING_cmd_end ()
};
diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c
index f5cd61ab..72546e4c 100644
--- a/src/testing/test_merchant_api.c
+++ b/src/testing/test_merchant_api.c
@@ -225,6 +225,7 @@ run (void *cls,
NULL,
NULL,
EXCHANGE_URL,
+ TALER_EXCHANGE_KLPT_NONE,
MHD_HTTP_NO_CONTENT,
false),
TALER_TESTING_cmd_merchant_post_orders_no_claim (
diff --git a/src/testing/testing_api_cmd_kyc_get.c
b/src/testing/testing_api_cmd_kyc_get.c
index bca4fbd8..f58b091d 100644
--- a/src/testing/testing_api_cmd_kyc_get.c
+++ b/src/testing/testing_api_cmd_kyc_get.c
@@ -16,13 +16,11 @@
License along with TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
-
/**
* @file testing_api_cmd_kyc_get.c
* @brief command to test kyc_get request
* @author Christian Grothoff
*/
-
#include "platform.h"
#include <taler/taler_exchange_service.h>
#include <taler/taler_testing_lib.h>
@@ -77,11 +75,21 @@ struct KycGetState
*/
unsigned int expected_http_status;
+ /**
+ * Target for long-polling.
+ */
+ enum TALER_EXCHANGE_KycLongPollTarget lpt;
+
/**
* Expected KYC state.
*/
bool expected_kyc_state;
+ /**
+ * Expected KYC state.
+ */
+ bool have_access_token;
+
/**
* Interpreter state.
*/
@@ -135,28 +143,32 @@ kyc_get_cb (void *cls,
}
switch (kr->hr.http_status)
{
- case MHD_HTTP_ACCEPTED:
+ case MHD_HTTP_OK:
if (! cs->expected_kyc_state)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Expected KYC state %u, got %u\n",
cs->expected_kyc_state,
- kr->details.kyc_status.pending_kycs_length);
+ kr->details.ok.kycs_length);
TALER_TESTING_FAIL (cs->is);
}
- for (unsigned int i = 0; i<kr->details.kyc_status.pending_kycs_length; i++)
+ for (unsigned int i = 0; i<kr->details.ok.kycs_length; i++)
{
const char *payto_uri;
- payto_uri = kr->details.kyc_status.pending_kycs[i].payto_uri;
+ payto_uri = kr->details.ok.kycs[i].payto_uri;
if (NULL == payto_uri)
{
continue;
}
TALER_payto_hash (payto_uri,
&cs->h_payto);
- cs->access_token
- = kr->details.kyc_status.pending_kycs[i].access_token;
+ if (! kr->details.ok.kycs[i].no_access_token)
+ {
+ cs->access_token
+ = kr->details.ok.kycs[i].access_token;
+ cs->have_access_token = true;
+ }
break;
}
break;
@@ -190,7 +202,6 @@ kyc_get_run (void *cls,
TALER_TESTING_interpreter_lookup_command (cs->is,
cs->h_wire_ref)))
{
- GNUNET_break (0);
TALER_TESTING_FAIL (cs->is);
}
/* Note: at the time of writing, no command offers an h_wire trait,
@@ -199,7 +210,6 @@ kyc_get_run (void *cls,
TALER_TESTING_get_trait_h_wire (wire_cmd,
&h_wire))
{
- GNUNET_break (0);
TALER_TESTING_FAIL (cs->is);
}
}
@@ -209,7 +219,10 @@ kyc_get_run (void *cls,
cs->merchant_url,
h_wire,
cs->exchange_url,
- GNUNET_TIME_UNIT_ZERO,
+ cs->lpt,
+ TALER_EXCHANGE_KLPT_NONE == cs->lpt
+ ? GNUNET_TIME_UNIT_ZERO
+ : GNUNET_TIME_UNIT_MINUTES,
&kyc_get_cb,
cs);
else
@@ -219,7 +232,10 @@ kyc_get_run (void *cls,
cs->instance_id,
h_wire,
cs->exchange_url,
- GNUNET_TIME_UNIT_ZERO,
+ cs->lpt,
+ TALER_EXCHANGE_KLPT_NONE == cs->lpt
+ ? GNUNET_TIME_UNIT_ZERO
+ : GNUNET_TIME_UNIT_MINUTES,
&kyc_get_cb,
cs);
@@ -244,17 +260,21 @@ kyc_get_traits (void *cls,
{
struct KycGetState *cs = cls;
struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_h_payto (
- &cs->h_payto),
+ /* Must be first, skipped if we have no token! */
TALER_TESTING_make_trait_account_access_token (
&cs->access_token),
+ TALER_TESTING_make_trait_h_payto (
+ &cs->h_payto),
TALER_TESTING_trait_end ()
};
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
+ return TALER_TESTING_get_trait (
+ &traits[cs->have_access_token
+ ? 0
+ : 1],
+ ret,
+ trait,
+ index);
}
@@ -265,6 +285,7 @@ TALER_TESTING_cmd_merchant_kyc_get (
const char *instance_id,
const char *h_wire_ref,
const char *exchange_url,
+ enum TALER_EXCHANGE_KycLongPollTarget lpt,
unsigned int expected_http_status,
bool expected_kyc_state)
{
@@ -275,6 +296,7 @@ TALER_TESTING_cmd_merchant_kyc_get (
cs->instance_id = instance_id;
cs->h_wire_ref = h_wire_ref;
cs->exchange_url = exchange_url;
+ cs->lpt = lpt;
cs->expected_http_status = expected_http_status;
cs->expected_kyc_state = expected_kyc_state;
{
diff --git a/src/testing/testing_api_cmd_post_account.c
b/src/testing/testing_api_cmd_post_account.c
index 8ddad94c..057ab060 100644
--- a/src/testing/testing_api_cmd_post_account.c
+++ b/src/testing/testing_api_cmd_post_account.c
@@ -167,11 +167,13 @@ post_account_traits (void *cls,
const char *trait,
unsigned int index)
{
- struct PostAccountState *pps = cls;
+ struct PostAccountState *pps = cls;
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_h_wires (
0,
&pps->h_wire),
+ TALER_TESTING_make_trait_h_wire (
+ &pps->h_wire),
TALER_TESTING_make_trait_payto_uris (
0,
pps->payto_uri),
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-merchant] branch master updated: towards new /kyc API: test_kyc_api still fails, but getting close,
gnunet <=