summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-04-10 11:18:56 +0200
committerChristian Grothoff <christian@grothoff.org>2023-04-10 11:18:56 +0200
commit208dbea1ce964495dbd4ee1b572694a43d8cdb6b (patch)
treeda6ac58120683516da053905224d00ec620dc42f /src
parent31babe5cf8e1259b719461fa318db9ae0778ec1a (diff)
downloadmerchant-208dbea1ce964495dbd4ee1b572694a43d8cdb6b.tar.gz
merchant-208dbea1ce964495dbd4ee1b572694a43d8cdb6b.tar.bz2
merchant-208dbea1ce964495dbd4ee1b572694a43d8cdb6b.zip
add implementation of AML status report (#7684)
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c110
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-instances-ID.c7
-rw-r--r--src/backenddb/Makefile.am3
-rw-r--r--src/backenddb/merchant-0005.sql32
-rw-r--r--src/include/taler_merchant_service.h11
-rw-r--r--src/include/taler_merchantdb_plugin.h5
-rw-r--r--src/lib/merchant_api_get_kyc.c14
-rw-r--r--src/testing/testing_api_cmd_kyc_get.c18
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);