diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-04-10 11:18:56 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-04-10 11:18:56 +0200 |
commit | 208dbea1ce964495dbd4ee1b572694a43d8cdb6b (patch) | |
tree | da6ac58120683516da053905224d00ec620dc42f | |
parent | 31babe5cf8e1259b719461fa318db9ae0778ec1a (diff) | |
download | merchant-208dbea1ce964495dbd4ee1b572694a43d8cdb6b.tar.gz merchant-208dbea1ce964495dbd4ee1b572694a43d8cdb6b.tar.bz2 merchant-208dbea1ce964495dbd4ee1b572694a43d8cdb6b.zip |
add implementation of AML status report (#7684)
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c | 110 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-patch-instances-ID.c | 7 | ||||
-rw-r--r-- | src/backenddb/Makefile.am | 3 | ||||
-rw-r--r-- | src/backenddb/merchant-0005.sql | 32 | ||||
-rw-r--r-- | src/include/taler_merchant_service.h | 11 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 5 | ||||
-rw-r--r-- | src/lib/merchant_api_get_kyc.c | 14 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_kyc_get.c | 18 |
8 files changed, 175 insertions, 25 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 c879fbe0..e25da307 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 @@ -488,13 +488,27 @@ exchange_check_cb (void *cls, struct KycContext *kc = ekr->kc; ekr->kyc = NULL; - // FIXME: handle case where exchange returns that account is AML pending/frozen! switch (ks->http_status) { case MHD_HTTP_OK: { enum GNUNET_DB_QueryStatus qs; + if (TALER_AML_NORMAL != ks->details.success.aml_status) + { + GNUNET_assert ( + 0 == + json_array_append_new ( + kc->pending_kycs, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ( + "aml_status", + ks->details.success.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, @@ -503,8 +517,8 @@ exchange_check_cb (void *cls, &ks->details.success.exchange_sig, &ks->details.success.exchange_pub, ks->details.success.timestamp, - true, - TALER_AML_NORMAL); + true, /* KYC OK */ + ks->details.success.aml_status); if (qs < 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -513,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; @@ -539,7 +577,7 @@ exchange_check_cb (void *cls, NULL, NULL, now, - true, + true, /* KYC OK */ TALER_AML_NORMAL); if (qs < 0) { @@ -548,6 +586,42 @@ exchange_check_cb (void *cls, } } 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, + "Failed to store KYC status in database!\n"); + } + } + break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Exchange responded with HTTP status %u (%d) to /kyc-check request!\n", @@ -624,7 +698,7 @@ kyc_with_exchange (void *cls, eh, ekr->exchange_kyc_serial, &h_payto, - /* FIXME: get from settings! */ + /* FIXME-#7796: get from settings! */ TALER_KYCLOGIC_KYC_UT_BUSINESS, kc->timeout, &exchange_check_cb, diff --git a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c index b8e0052d..5bd53a57 100644 --- a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c +++ b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2020-2021 Taler Systems SA + (C) 2020-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as @@ -64,6 +64,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, struct TALER_MERCHANTDB_InstanceSettings is; json_t *payto_uris; const char *name; + // FIXME-#7796: uint32_t ut; struct TMH_WireMethod *wm_head = NULL; struct TMH_WireMethod *wm_tail = NULL; struct GNUNET_JSON_Specification spec[] = { @@ -71,6 +72,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, &payto_uris), GNUNET_JSON_spec_string ("name", &name), + // FIXME-#7796: GNUNET_JSON_spec_uint32 ("user_type", &ut), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("website", (const char **) &is.website), @@ -119,6 +121,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, ? MHD_YES : MHD_NO; } + // FIXME-#7796: is.user_type = (enum TALER_KYCLOGIC_KycUserType) ut; if (! TMH_location_object_valid (is.address)) { GNUNET_break_op (0); @@ -184,6 +187,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, /* Check for equality of settings */ if (! ( (0 == strcmp (mi->settings.name, name)) && + // FIXME-#7796: (mi->settings.user_type == is.user_type) && ((mi->settings.email == is.email) || (NULL != is.email && NULL != mi->settings.email && 0 == strcmp (mi->settings.email, @@ -397,6 +401,7 @@ giveup: json_decref (mi->settings.jurisdiction); is.id = mi->settings.id; mi->settings = is; + // mi->settings.user_type = (enum TALER_KYCLOGIC_KycUserType) is.user_type; mi->settings.address = json_incref (mi->settings.address); mi->settings.jurisdiction = json_incref (mi->settings.jurisdiction); mi->settings.name = GNUNET_strdup (name); diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am index c1080024..d233b95b 100644 --- a/src/backenddb/Makefile.am +++ b/src/backenddb/Makefile.am @@ -18,6 +18,9 @@ sql_DATA = \ merchant-0004.sql \ drop.sql +# merchant-0005.sql \ -- FIXME-#7796 + + if HAVE_POSTGRESQL if HAVE_GNUNETPQ plugin_LTLIBRARIES = \ diff --git a/src/backenddb/merchant-0005.sql b/src/backenddb/merchant-0005.sql new file mode 100644 index 00000000..8006e565 --- /dev/null +++ b/src/backenddb/merchant-0005.sql @@ -0,0 +1,32 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2023 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE. See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +-- + +-- Everything in one big transaction +BEGIN; + +-- Check patch versioning is in place. +SELECT _v.register_patch('merchant-0005', NULL, NULL); + +SET search_path TO merchant; + +ALTER TABLE merchant_instances + ADD COLUMN user_type INT; + +COMMENT ON COLUMN merchant_instances.user_type + IS 'what type of user is this (individual or business)'; + +-- Complete transaction +COMMIT; diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index b2f2f334..3d55e4b0 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -2183,7 +2183,7 @@ struct TALER_MERCHANT_PayResponse * Optional payment confirmation code returned by the service. */ const char *pos_confirmation; - + } success; // TODO: might want to return further details on errors, @@ -3948,7 +3948,9 @@ struct TALER_MERCHANT_AccountKycRedirectDetail /** * URL that the user should open in a browser to * proceed with the KYC process (as returned - * by the exchange's /kyc-check/ endpoint). + * 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; @@ -3961,6 +3963,11 @@ struct TALER_MERCHANT_AccountKycRedirectDetail * Our bank wire account this is about. */ const char *payto_uri; + + /** + * AML state for our account. + */ + enum TALER_AmlDecisionState aml_status; }; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index 1ca27844..68cdf3d7 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -194,6 +194,11 @@ struct TALER_MERCHANTDB_InstanceSettings */ struct GNUNET_TIME_Relative default_pay_delay; + /** + * Type of user this merchant represents. + * FIXME: not yet initialized! + */ + enum TALER_KYCLOGIC_KycUserType ut; }; diff --git a/src/lib/merchant_api_get_kyc.c b/src/lib/merchant_api_get_kyc.c index bc688eed..0b62d2cf 100644 --- a/src/lib/merchant_api_get_kyc.c +++ b/src/lib/merchant_api_get_kyc.c @@ -86,11 +86,19 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc, struct TALER_MERCHANT_ExchangeKycFailureDetail timeout_kycs[GNUNET_NZL ( num_touts)]; + memset (pending_kycs, + 0, + sizeof (pending_kycs)); for (unsigned int i = 0; i<num_pends; i++) { + uint32_t status; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("kyc_url", - &pending_kycs[i].kyc_url), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("kyc_url", + &pending_kycs[i].kyc_url), + NULL), + GNUNET_JSON_spec_uint32 ("aml_status", + &status), GNUNET_JSON_spec_string ("exchange_url", &pending_kycs[i].exchange_url), GNUNET_JSON_spec_string ("payto_uri", @@ -107,6 +115,8 @@ parse_kyc (struct TALER_MERCHANT_KycGetHandle *kyc, GNUNET_break (0); return GNUNET_SYSERR; } + pending_kycs[i].aml_status + = (enum TALER_AmlDecisionState) status; } for (unsigned int i = 0; i<num_touts; i++) { diff --git a/src/testing/testing_api_cmd_kyc_get.c b/src/testing/testing_api_cmd_kyc_get.c index 96d0b58c..d2cb4519 100644 --- a/src/testing/testing_api_cmd_kyc_get.c +++ b/src/testing/testing_api_cmd_kyc_get.c @@ -126,7 +126,7 @@ kyc_get_cb (void *cls, switch (kr->hr.http_status) { case MHD_HTTP_ACCEPTED: - if (0 != kr->details.kyc_status.pending_kycs_length) + for (unsigned int i = 0; i<kr->details.kyc_status.pending_kycs_length; i++) { const char *url; const char *tok; @@ -136,7 +136,21 @@ kyc_get_cb (void *cls, const char *nq; size_t toklen; - url = kr->details.kyc_status.pending_kycs[0].kyc_url; + url = kr->details.kyc_status.pending_kycs[i].kyc_url; + if (NULL == url) + { + /* AML status here must be either pending or frozne */ + switch (kr->details.kyc_status.pending_kycs[i].aml_status) + { + case TALER_AML_NORMAL: + TALER_TESTING_FAIL (cs->is); + case TALER_AML_PENDING: + continue; + case TALER_AML_FROZEN: + continue; + } + TALER_TESTING_FAIL (cs->is); + } tok = strstr (url, "&redirect_uri="); if (NULL == tok) TALER_TESTING_FAIL (cs->is); |