aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-07-31 19:01:45 +0200
committerChristian Grothoff <christian@grothoff.org>2024-07-31 19:01:45 +0200
commit854bad7d7c220c9ea9f4d61eb8fd46548a160da2 (patch)
tree7acb0f2077df215ab4128fbf721196cb09465e08
parent4a312017e07335a7285d6a984f4a2a3882877288 (diff)
DB schema change for storing more KYC status data
-rw-r--r--src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c150
-rw-r--r--src/backenddb/merchant-0010.sql26
-rw-r--r--src/include/taler_merchant_service.h19
-rw-r--r--src/lib/merchant_api_get_kyc.c38
-rw-r--r--src/testing/testing_api_cmd_kyc_get.c21
5 files changed, 176 insertions, 78 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 7c2081a6..3cf4b161 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-2023 Taler Systems SA
+ (C) 2021-2024 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
@@ -481,8 +481,9 @@ ekr_finished (struct ExchangeKycRequest *ekr)
* @param ks the account's KYC status details
*/
static void
-exchange_check_cb (void *cls,
- const struct TALER_EXCHANGE_KycStatus *ks)
+exchange_check_cb (
+ void *cls,
+ const struct TALER_EXCHANGE_KycStatus *ks)
{
struct ExchangeKycRequest *ekr = cls;
struct KycContext *kc = ekr->kc;
@@ -493,7 +494,11 @@ exchange_check_cb (void *cls,
case MHD_HTTP_OK:
{
enum GNUNET_DB_QueryStatus qs;
+ const struct TALER_EXCHANGE_AccountKycStatus *aks;
+ aks = &ks->details.ok;
+ // FIXME: also store aks->access_token, limits,
+ // aml_review, etc.!
qs = TMH_db->account_kyc_set_status (
TMH_db->cls,
kc->mi->settings.id,
@@ -513,17 +518,36 @@ exchange_check_cb (void *cls,
{
struct GNUNET_TIME_Timestamp now;
enum GNUNET_DB_QueryStatus qs;
-
+ const struct TALER_EXCHANGE_AccountKycStatus *aks;
+ char *kyc_url;
+ char *ats;
+
+ aks = &ks->details.accepted;
+ ats = GNUNET_STRINGS_data_to_string_alloc (
+ &aks->access_token,
+ sizeof (aks->access_token));
+ GNUNET_asprintf (&kyc_url,
+ "%s/kyc-spa/%s",
+ ekr->exchange_url,
+ ats);
+ GNUNET_free (ats);
GNUNET_assert (
0 ==
json_array_append_new (
kc->pending_kycs,
GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_data_auto ("access_token",
+ &aks->access_token),
+ GNUNET_JSON_pack_string ("kyc_url",
+ kyc_url),
GNUNET_JSON_pack_string ("exchange_url",
ekr->exchange_url),
GNUNET_JSON_pack_string ("payto_uri",
ekr->payto_uri))));
+ GNUNET_free (kyc_url);
now = GNUNET_TIME_timestamp_get ();
+ // FIXME: also store aks->access_token, limits,
+ // aml_review, etc.!
qs = TMH_db->account_kyc_set_status (
TMH_db->cls,
kc->mi->settings.id,
@@ -545,13 +569,14 @@ exchange_check_cb (void *cls,
enum GNUNET_DB_QueryStatus qs;
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,
- now,
- true);
+ qs = TMH_db->account_kyc_set_status (
+ TMH_db->cls,
+ kc->mi->settings.id,
+ &ekr->h_wire,
+ ekr->exchange_url,
+ ekr->exchange_kyc_serial,
+ now,
+ true);
if (qs < 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -559,6 +584,9 @@ exchange_check_cb (void *cls,
}
}
break;
+ case MHD_HTTP_FORBIDDEN:
+ case MHD_HTTP_NOT_FOUND:
+ case MHD_HTTP_CONFLICT:
case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
{
struct GNUNET_TIME_Timestamp now;
@@ -571,9 +599,14 @@ exchange_check_cb (void *cls,
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),
GNUNET_JSON_pack_string ("payto_uri",
ekr->payto_uri))));
now = GNUNET_TIME_timestamp_get ();
+ // FIXME: also store HTTP status code + EC in DB!
qs = TMH_db->account_kyc_set_status (
TMH_db->cls,
kc->mi->settings.id,
@@ -629,7 +662,6 @@ kyc_with_exchange (void *cls,
struct TALER_PaytoHashP h_payto;
union TALER_AccountPrivateKeyP ap;
-
(void) exchange;
ekr->fo = NULL;
if (NULL == keys)
@@ -672,13 +704,14 @@ kyc_with_exchange (void *cls,
* @param kyc_ok true if we satisfied the KYC requirements
*/
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)
+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)
{
struct KycContext *kc = cls;
struct ExchangeKycRequest *ekr;
@@ -705,10 +738,11 @@ kyc_status_cb (void *cls,
ekr->payto_uri = GNUNET_strdup (payto_uri);
ekr->last_check = last_check;
ekr->kc = kc;
- ekr->fo = TMH_EXCHANGES_keys4exchange (exchange_url,
- false,
- &kyc_with_exchange,
- ekr);
+ ekr->fo = TMH_EXCHANGES_keys4exchange (
+ exchange_url,
+ false,
+ &kyc_with_exchange,
+ ekr);
}
@@ -721,9 +755,10 @@ kyc_status_cb (void *cls,
* @return MHD result code
*/
static MHD_RESULT
-get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
- struct MHD_Connection *connection,
- struct TMH_HandlerContext *hc)
+get_instances_ID_kyc (
+ struct TMH_MerchantInstance *mi,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
{
struct KycContext *kc = hc->ctx;
@@ -752,9 +787,10 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
kc);
/* process 'exchange_url' argument */
- kc->exchange_url = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "exchange_url");
+ 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,
@@ -765,10 +801,11 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
strlen ("https://"))) ) ) )
{
GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "exchange_url must be a valid HTTP(s) URL");
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "exchange_url must be a valid HTTP(s) URL");
}
TALER_MHD_parse_request_arg_auto (connection,
@@ -779,20 +816,22 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
{
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);
+ 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_break (0);
- return TALER_MHD_reply_with_ec (connection,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "account_kyc_get_status");
+ return TALER_MHD_reply_with_ec (
+ connection,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "account_kyc_get_status");
}
}
if (kc->kyc_serial_pending)
@@ -839,9 +878,10 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi,
MHD_RESULT
-TMH_private_get_instances_ID_kyc (const struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- struct TMH_HandlerContext *hc)
+TMH_private_get_instances_ID_kyc (
+ const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
{
struct TMH_MerchantInstance *mi = hc->instance;
@@ -853,9 +893,10 @@ TMH_private_get_instances_ID_kyc (const struct TMH_RequestHandler *rh,
MHD_RESULT
-TMH_private_get_instances_default_ID_kyc (const struct TMH_RequestHandler *rh,
- struct MHD_Connection *connection,
- struct TMH_HandlerContext *hc)
+TMH_private_get_instances_default_ID_kyc (
+ const struct TMH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ struct TMH_HandlerContext *hc)
{
struct TMH_MerchantInstance *mi;
@@ -863,10 +904,11 @@ TMH_private_get_instances_default_ID_kyc (const struct TMH_RequestHandler *rh,
mi = TMH_lookup_instance (hc->infix);
if (NULL == mi)
{
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
- hc->infix);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
+ hc->infix);
}
return get_instances_ID_kyc (mi,
connection,
diff --git a/src/backenddb/merchant-0010.sql b/src/backenddb/merchant-0010.sql
index e7ac0dc3..7f3504e9 100644
--- a/src/backenddb/merchant-0010.sql
+++ b/src/backenddb/merchant-0010.sql
@@ -29,7 +29,31 @@ SET search_path TO merchant;
ALTER TABLE merchant_kyc
DROP COLUMN aml_decision
,DROP COLUMN exchange_sig
- ,DROP COLUMN exchange_pub;
+ ,DROP COLUMN exchange_pub
+ ,ADD COLUMN access_token BLOB DEFAULT NULL
+ ,ADD COLUMN exchange_http_status INT4 DEFAULT(0)
+ ,ADD COLUMN exchange_ec_code INT4 DEFAULT(0)
+ ,ADD COLUMN aml_review BOOL DEFAULT(FALSE)
+ ,ADD COLUMN deposit_threshold taler_amount_currency[] DEFAULT NULL
+ ,ADD COLUMN deposit_timeframe INT8[] DEFAULT NULL
+ ,ADD COLUMN deposit_limit_is_soft BOOL[] DEFAULT NULL
+ ,ADD CONSTRAINT access_token_length_check CHECK (LENGTH(access_token) = 32);
+
+COMMENT ON COLUMN merchant_kyc.access_token
+ IS 'Access token required to begin the KYC process';
+COMMENT ON COLUMN merchant_kyc.exchange_http_status
+ IS 'Last HTTP status returned by the exchange when inquiring about our KYC status.';
+COMMENT ON COLUMN merchant_kyc.exchange_ec_code
+ IS 'Last Taler error code returned by the exchange when inquiring about our KYC status.';
+COMMENT ON COLUMN merchant_kyc.aml_review
+ IS 'True if our account is under AML review according to the exchange.';
+COMMENT ON COLUMN merchant_kyc.deposit_threshold
+ IS 'Maximum amount we are allowed to deposit in a given timeframe under current rules.';
+COMMENT ON COLUMN merchant_kyc.deposit_timeframe
+ IS 'Timeframe for which the deposit_threshold applies.';
+COMMENT ON COLUMN merchant_kyc.deposit_limit_is_soft
+ IS 'True if this is a soft limit';
+
-- Complete transaction
COMMIT;
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index 15c1f759..0b5cf232 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -4383,6 +4383,11 @@ struct TALER_MERCHANT_AccountKycRedirectDetail
{
/**
+ * Access token the user needs to start a KYC process.
+ */
+ 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
@@ -4401,6 +4406,20 @@ struct TALER_MERCHANT_AccountKycRedirectDetail
*/
const char *payto_uri;
+ /**
+ * Array of length @e limits_array with (exposed) limits that apply to the
+ * account.
+ *
+ * FIXME: not yet returned.
+ */
+ struct TALER_EXCHANGE_AccountLimit *limits;
+
+ /**
+ * Length of the @e limits array.
+ */
+ unsigned int limits_length;
+
+
};
diff --git a/src/lib/merchant_api_get_kyc.c b/src/lib/merchant_api_get_kyc.c
index a6048fc6..f8cf932f 100644
--- a/src/lib/merchant_api_get_kyc.c
+++ b/src/lib/merchant_api_get_kyc.c
@@ -112,14 +112,18 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
for (unsigned int i = 0; i<num_pends; i++)
{
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_mark_optional (
- TALER_JSON_spec_web_url ("kyc_url",
- &pending_kycs[i].kyc_url),
- NULL),
- TALER_JSON_spec_web_url ("exchange_url",
- &pending_kycs[i].exchange_url),
- TALER_JSON_spec_payto_uri ("payto_uri",
- &pending_kycs[i].payto_uri),
+ GNUNET_JSON_spec_fixed_auto (
+ "access_token",
+ &pending_kycs[i].access_token),
+ TALER_JSON_spec_web_url (
+ "kyc_url",
+ &pending_kycs[i].kyc_url),
+ TALER_JSON_spec_web_url (
+ "exchange_url",
+ &pending_kycs[i].exchange_url),
+ TALER_JSON_spec_payto_uri (
+ "payto_uri",
+ &pending_kycs[i].payto_uri),
GNUNET_JSON_spec_end ()
};
@@ -137,12 +141,15 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
{
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),
+ 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 ()
};
@@ -155,7 +162,8 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- timeout_kycs[i].exchange_http_status = (unsigned int) hs;
+ 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;
diff --git a/src/testing/testing_api_cmd_kyc_get.c b/src/testing/testing_api_cmd_kyc_get.c
index 416423b1..58be93e9 100644
--- a/src/testing/testing_api_cmd_kyc_get.c
+++ b/src/testing/testing_api_cmd_kyc_get.c
@@ -68,6 +68,11 @@ struct KycGetState
struct TALER_PaytoHashP h_payto;
/**
+ * Access token the user needs to start a KYC process.
+ */
+ struct TALER_AccountAccessTokenP access_token;
+
+ /**
* Expected HTTP response code.
*/
unsigned int expected_http_status;
@@ -249,14 +254,14 @@ kyc_get_run (void *cls,
}
}
if (NULL == cs->instance_id)
- cs->kgh = TALER_MERCHANT_kyc_get (TALER_TESTING_interpreter_get_context (
- is),
- cs->merchant_url,
- h_wire,
- cs->exchange_url,
- GNUNET_TIME_UNIT_ZERO,
- &kyc_get_cb,
- cs);
+ cs->kgh = TALER_MERCHANT_kyc_get (
+ TALER_TESTING_interpreter_get_context (is),
+ cs->merchant_url,
+ h_wire,
+ cs->exchange_url,
+ GNUNET_TIME_UNIT_ZERO,
+ &kyc_get_cb,
+ cs);
else
cs->kgh = TALER_MERCHANT_management_kyc_get (
TALER_TESTING_interpreter_get_context (is),