work on kycaid attribute extraction
This commit is contained in:
parent
59716ffdc4
commit
85e44ceea6
@ -291,7 +291,9 @@ libtalerexchangedb_la_LDFLAGS = \
|
|||||||
|
|
||||||
|
|
||||||
check_PROGRAMS = \
|
check_PROGRAMS = \
|
||||||
test-exchangedb-postgres \
|
test-exchangedb-postgres
|
||||||
|
|
||||||
|
noinst_PROGRAMS = \
|
||||||
bench-db-postgres\
|
bench-db-postgres\
|
||||||
perf-exchangedb-reserves-in-insert-postgres\
|
perf-exchangedb-reserves-in-insert-postgres\
|
||||||
test-exchangedb-by-j-postgres\
|
test-exchangedb-by-j-postgres\
|
||||||
|
@ -34,6 +34,17 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legal name of the business/company.
|
||||||
|
*/
|
||||||
|
#define TALER_ATTRIBUTE_COMPANY_NAME "company_name"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legal country of registration of the business/company,
|
||||||
|
* 2-letter country code using ISO 3166-2.
|
||||||
|
*/
|
||||||
|
#define TALER_ATTRIBUTE_REGISTRATION_COUNTRY "registration_country"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full name, when known/possible using "Lastname, Firstname(s)" format,
|
* Full name, when known/possible using "Lastname, Firstname(s)" format,
|
||||||
* but "Firstname(s) Lastname" or "Firstname M. Lastname" should also be
|
* but "Firstname(s) Lastname" or "Firstname M. Lastname" should also be
|
||||||
@ -43,6 +54,22 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define TALER_ATTRIBUTE_FULL_NAME "full_name"
|
#define TALER_ATTRIBUTE_FULL_NAME "full_name"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True/false indicator if the individual is a politically
|
||||||
|
* exposed person.
|
||||||
|
*/
|
||||||
|
#define TALER_ATTRIBUTE_PEP "pep"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phone number (of business or individual).
|
||||||
|
*/
|
||||||
|
#define TALER_ATTRIBUTE_PHONE "phone"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email address (of business or individual).
|
||||||
|
*/
|
||||||
|
#define TALER_ATTRIBUTE_EMAIL "email"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Birthdate of the person, as far as known. YYYY-MM-DD, a value
|
* Birthdate of the person, as far as known. YYYY-MM-DD, a value
|
||||||
* of 0 (for DD, MM or even YYYY) is to be used for 'unknown'
|
* of 0 (for DD, MM or even YYYY) is to be used for 'unknown'
|
||||||
@ -63,6 +90,15 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define TALER_ATTRIBUTE_NATIONALITIES "nationalities"
|
#define TALER_ATTRIBUTE_NATIONALITIES "nationalities"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Residence countries(s) of the person using 2-letter country codes ("US",
|
||||||
|
* "DE", "FR", "IT", etc.) separated by commas if multiple residences are
|
||||||
|
* confirmed ("EN,US,DE"). Note that in the latter case it is not guaranteed
|
||||||
|
* that all residences were necessarily recorded. Empty string for
|
||||||
|
* international nomads. NULL for not collected.
|
||||||
|
*/
|
||||||
|
#define TALER_ATTRIBUTE_RESIDENCES "residences"
|
||||||
|
|
||||||
|
|
||||||
#if 0 /* keep Emacsens' auto-indent happy */
|
#if 0 /* keep Emacsens' auto-indent happy */
|
||||||
{
|
{
|
||||||
|
@ -77,8 +77,6 @@ enum TALER_KYCLOGIC_KycStatus
|
|||||||
* The provider is still checking.
|
* The provider is still checking.
|
||||||
*/
|
*/
|
||||||
TALER_KYCLOGIC_STATUS_PROVIDER_PENDING
|
TALER_KYCLOGIC_STATUS_PROVIDER_PENDING
|
||||||
|
|
||||||
|
|
||||||
= TALER_KYCLOGIC_STATUS_PROVIDER
|
= TALER_KYCLOGIC_STATUS_PROVIDER
|
||||||
| TALER_KYCLOGIC_STATUS_PENDING,
|
| TALER_KYCLOGIC_STATUS_PENDING,
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of GNU Taler
|
This file is part of GNU Taler
|
||||||
Copyright (C) 2022 Taler Systems SA
|
Copyright (C) 2022, 2023 Taler Systems SA
|
||||||
|
|
||||||
Taler is free software; you can redistribute it and/or modify it under the
|
Taler is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the GNU Affero General Public License as published by the Free Software
|
terms of the GNU Affero General Public License as published by the Free Software
|
||||||
@ -19,6 +19,8 @@
|
|||||||
* @author Christian Grothoff
|
* @author Christian Grothoff
|
||||||
*/
|
*/
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include "taler_attributes.h"
|
||||||
|
#include "taler_kyclogic_lib.h"
|
||||||
#include "taler_kyclogic_plugin.h"
|
#include "taler_kyclogic_plugin.h"
|
||||||
#include "taler_mhd_lib.h"
|
#include "taler_mhd_lib.h"
|
||||||
#include "taler_curl_lib.h"
|
#include "taler_curl_lib.h"
|
||||||
@ -749,7 +751,7 @@ log_failure (json_t *verifications)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called when we're done processing the
|
* Function called when we're done processing the
|
||||||
* HTTP "/verifications/{verification_id}" request.
|
* HTTP "/applicants/{verification_id}" request.
|
||||||
*
|
*
|
||||||
* @param cls the `struct TALER_KYCLOGIC_WebhookHandle`
|
* @param cls the `struct TALER_KYCLOGIC_WebhookHandle`
|
||||||
* @param response_code HTTP response code, 0 on error
|
* @param response_code HTTP response code, 0 on error
|
||||||
@ -769,30 +771,116 @@ handle_webhook_finished (void *cls,
|
|||||||
{
|
{
|
||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
{
|
{
|
||||||
const char *applicant_id;
|
const char *type;
|
||||||
const char *verification_id;
|
const char *profile_status;
|
||||||
const char *status;
|
const char *first_name = NULL;
|
||||||
bool verified;
|
const char *last_name = NULL;
|
||||||
json_t *verifications;
|
const char *middle_name = NULL;
|
||||||
|
const char *dob = NULL;
|
||||||
|
const char *residence_country = NULL;
|
||||||
|
const char *gender = NULL;
|
||||||
|
bool pep = false;
|
||||||
|
bool no_pep = false;
|
||||||
|
const char *company_name = NULL;
|
||||||
|
const char *business_activity_id = NULL;
|
||||||
|
const char *registration_country = NULL;
|
||||||
|
const char *email = NULL;
|
||||||
|
const char *phone = NULL;
|
||||||
|
json_t *addresses = NULL;
|
||||||
|
json_t *documents = NULL;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_string ("applicant_id",
|
GNUNET_JSON_spec_string ("type",
|
||||||
&applicant_id),
|
&type),
|
||||||
GNUNET_JSON_spec_string ("verification_id",
|
GNUNET_JSON_spec_string ("profile_status",
|
||||||
&verification_id),
|
&profile_status), /* valid, invalid, pending */
|
||||||
GNUNET_JSON_spec_string ("status",
|
GNUNET_JSON_spec_mark_optional (
|
||||||
&status), /* completed, pending, ... */
|
GNUNET_JSON_spec_string ("email",
|
||||||
GNUNET_JSON_spec_bool ("verified",
|
&email),
|
||||||
&verified),
|
NULL),
|
||||||
GNUNET_JSON_spec_json ("verifications",
|
GNUNET_JSON_spec_mark_optional (
|
||||||
&verifications),
|
GNUNET_JSON_spec_string ("phone",
|
||||||
|
&phone),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_json ("addresses",
|
||||||
|
&addresses),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_json ("documents",
|
||||||
|
&documents),
|
||||||
|
NULL),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
struct GNUNET_JSON_Specification bspec[] = {
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("company_name",
|
||||||
|
&company_name),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("business_activity_id",
|
||||||
|
&business_activity_id),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("registration_country",
|
||||||
|
®istration_country),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_end ()
|
||||||
|
};
|
||||||
|
struct GNUNET_JSON_Specification pspec[] = {
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("first_name",
|
||||||
|
&first_name),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("middle_name",
|
||||||
|
&middle_name),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("last_name",
|
||||||
|
&last_name),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("dob",
|
||||||
|
&dob),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("residence_country",
|
||||||
|
&residence_country),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_string ("gender",
|
||||||
|
&gender),
|
||||||
|
NULL),
|
||||||
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
GNUNET_JSON_spec_bool ("pep",
|
||||||
|
&pep),
|
||||||
|
&no_pep),
|
||||||
|
GNUNET_JSON_spec_end ()
|
||||||
|
};
|
||||||
|
struct GNUNET_JSON_Specification *ispec = NULL;
|
||||||
struct GNUNET_TIME_Absolute expiration;
|
struct GNUNET_TIME_Absolute expiration;
|
||||||
|
bool no_parse;
|
||||||
|
enum TALER_KYCLOGIC_KycUserType ut;
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
no_parse = (GNUNET_OK !=
|
||||||
GNUNET_JSON_parse (j,
|
GNUNET_JSON_parse (j,
|
||||||
spec,
|
spec,
|
||||||
NULL, NULL))
|
NULL, NULL));
|
||||||
|
if (! no_parse)
|
||||||
|
{
|
||||||
|
ut = (0 == strcasecmp ("person",
|
||||||
|
type))
|
||||||
|
? TALER_KYCLOGIC_KYC_UT_INDIVIDUAL
|
||||||
|
: TALER_KYCLOGIC_KYC_UT_BUSINESS;
|
||||||
|
ispec = (ut == TALER_KYCLOGIC_KYC_UT_INDIVIDUAL)
|
||||||
|
? pspec
|
||||||
|
: bspec;
|
||||||
|
no_parse = (GNUNET_OK !=
|
||||||
|
GNUNET_JSON_parse (j,
|
||||||
|
ispec,
|
||||||
|
NULL, NULL));
|
||||||
|
}
|
||||||
|
if (no_parse)
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
json_dumpf (j,
|
json_dumpf (j,
|
||||||
@ -816,20 +904,94 @@ handle_webhook_finished (void *cls,
|
|||||||
resp);
|
resp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (! verified)
|
if (0 == strcasecmp ("valid",
|
||||||
|
profile_status))
|
||||||
{
|
{
|
||||||
log_failure (verifications);
|
log_failure (json_object_get (j,
|
||||||
|
"decline_reasons"));
|
||||||
}
|
}
|
||||||
resp = MHD_create_response_from_buffer (0,
|
resp = MHD_create_response_from_buffer (0,
|
||||||
"",
|
"",
|
||||||
MHD_RESPMEM_PERSISTENT);
|
MHD_RESPMEM_PERSISTENT);
|
||||||
if (verified)
|
if (0 == strcasecmp ("valid",
|
||||||
|
profile_status))
|
||||||
{
|
{
|
||||||
json_t *attr;
|
json_t *attr;
|
||||||
|
|
||||||
attr = json_object ();
|
if (ut == TALER_KYCLOGIC_KYC_UT_INDIVIDUAL)
|
||||||
// FIXME: initialize attributes!
|
{
|
||||||
GNUNET_assert (NULL != attr);
|
char *name = NULL;
|
||||||
|
|
||||||
|
if ( (NULL != last_name) ||
|
||||||
|
(NULL != first_name) ||
|
||||||
|
(NULL != middle_name) )
|
||||||
|
{
|
||||||
|
GNUNET_asprintf (&name,
|
||||||
|
"%s, %s %s",
|
||||||
|
(NULL != last_name)
|
||||||
|
? last_name
|
||||||
|
: "",
|
||||||
|
(NULL != first_name)
|
||||||
|
? first_name
|
||||||
|
: "",
|
||||||
|
(NULL != middle_name)
|
||||||
|
? middle_name
|
||||||
|
: "");
|
||||||
|
}
|
||||||
|
attr = GNUNET_JSON_PACK (
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_BIRTHDATE,
|
||||||
|
dob)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
no_pep
|
||||||
|
? GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_PEP,
|
||||||
|
NULL)
|
||||||
|
: GNUNET_JSON_pack_bool (
|
||||||
|
TALER_ATTRIBUTE_PEP,
|
||||||
|
pep)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_FULL_NAME,
|
||||||
|
name)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_PHONE,
|
||||||
|
phone)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_EMAIL,
|
||||||
|
email)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_RESIDENCES,
|
||||||
|
residence_country))
|
||||||
|
);
|
||||||
|
GNUNET_free (name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attr = GNUNET_JSON_PACK (
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_COMPANY_NAME,
|
||||||
|
company_name)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_PHONE,
|
||||||
|
phone)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_EMAIL,
|
||||||
|
email)),
|
||||||
|
GNUNET_JSON_pack_allow_null (
|
||||||
|
GNUNET_JSON_pack_string (
|
||||||
|
TALER_ATTRIBUTE_REGISTRATION_COUNTRY,
|
||||||
|
residence_country))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// FIXME: do something about addresses & documents!
|
||||||
expiration = GNUNET_TIME_relative_to_absolute (wh->pd->validity);
|
expiration = GNUNET_TIME_relative_to_absolute (wh->pd->validity);
|
||||||
wh->cb (wh->cb_cls,
|
wh->cb (wh->cb_cls,
|
||||||
wh->process_row,
|
wh->process_row,
|
||||||
@ -846,18 +1008,25 @@ handle_webhook_finished (void *cls,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
enum TALER_KYCLOGIC_KycStatus ks;
|
||||||
|
|
||||||
|
ks = (0 == strcasecmp ("pending",
|
||||||
|
profile_status))
|
||||||
|
? TALER_KYCLOGIC_STATUS_PENDING
|
||||||
|
: TALER_KYCLOGIC_STATUS_USER_ABORTED;
|
||||||
wh->cb (wh->cb_cls,
|
wh->cb (wh->cb_cls,
|
||||||
wh->process_row,
|
wh->process_row,
|
||||||
&wh->h_payto,
|
&wh->h_payto,
|
||||||
wh->pd->section,
|
wh->pd->section,
|
||||||
wh->applicant_id,
|
wh->applicant_id,
|
||||||
wh->verification_id,
|
wh->verification_id,
|
||||||
TALER_KYCLOGIC_STATUS_USER_ABORTED,
|
ks,
|
||||||
GNUNET_TIME_UNIT_ZERO_ABS,
|
GNUNET_TIME_UNIT_ZERO_ABS,
|
||||||
NULL,
|
NULL,
|
||||||
MHD_HTTP_NO_CONTENT,
|
MHD_HTTP_NO_CONTENT,
|
||||||
resp);
|
resp);
|
||||||
}
|
}
|
||||||
|
GNUNET_JSON_parse_free (ispec);
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1201,7 +1370,7 @@ kycaid_webhook (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_asprintf (&wh->url,
|
GNUNET_asprintf (&wh->url,
|
||||||
"https://api.kycaid.com/verifications/%s",
|
"https://api.kycaid.com/applicants/%s",
|
||||||
verification_id);
|
verification_id);
|
||||||
GNUNET_break (CURLE_OK ==
|
GNUNET_break (CURLE_OK ==
|
||||||
curl_easy_setopt (eh,
|
curl_easy_setopt (eh,
|
||||||
|
Loading…
Reference in New Issue
Block a user