/* This file is part of TALER Copyright (C) 2021 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 */ /** * @file testing_api_cmd_kyc_get.c * @brief command to test kyc_get request * @author Christian Grothoff */ #include "platform.h" #include #include #include "taler_merchant_service.h" #include "taler_merchant_testing_lib.h" /** * State for a "/kyc" GET CMD. */ struct KycGetState { /** * Operation handle for a GET /private/kyc GET request. */ struct TALER_MERCHANT_KycGetHandle *kgh; /** * Base URL of the merchant serving the request. */ const char *merchant_url; /** * Instance to query, NULL if part of @e merchant_url */ const char *instance_id; /** * Reference to command providing wire hash, NULL to * query all accounts. */ const char *h_wire_ref; /** * URL of exchange to query. */ const char *exchange_url; /** * Set to the payto hash of the first account * for which we failed to pass the KYC check. */ struct TALER_PaytoHashP h_payto; /** * Expected HTTP response code. */ unsigned int expected_http_status; /** * Interpreter state. */ struct TALER_TESTING_Interpreter *is; }; /** * Free the state of a "/kyc" GET CMD, and * possibly cancel a pending "kyc" GET operation. * * @param cls closure with the `struct KycGetState` * @param cmd command currently being freed. */ static void kyc_get_cleanup (void *cls, const struct TALER_TESTING_Command *cmd) { struct KycGetState *cs = cls; if (NULL != cs->kgh) { TALER_LOG_WARNING ("/kyc GET operation did not complete\n"); TALER_MERCHANT_kyc_get_cancel (cs->kgh); } GNUNET_free (cs); } /** * Process "GET /public/kyc_get" (lookup) response. * * @param cls closure * @param kr response we got */ static void kyc_get_cb (void *cls, const struct TALER_MERCHANT_KycResponse *kr) { struct KycGetState *cs = cls; cs->kgh = NULL; if (kr->hr.http_status != cs->expected_http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected status %u, got %u\n", cs->expected_http_status, kr->hr.http_status); TALER_TESTING_FAIL (cs->is); } switch (kr->hr.http_status) { case MHD_HTTP_ACCEPTED: if (0 != kr->details.kyc_status.pending_kycs_length) { const char *url; const char *tok; const char *end; char *dec; const char *eq; size_t toklen; url = kr->details.kyc_status.pending_kycs[0].kyc_url; tok = strstr (url, "&redirect_uri="); if (NULL == tok) TALER_TESTING_FAIL (cs->is); tok += strlen ("&redirect_uri="); end = strchr (tok, '&'); if (NULL == end) toklen = strlen (tok); else toklen = end - tok; (void) GNUNET_STRINGS_urldecode (tok, toklen, &dec); eq = strrchr (dec, '/'); if (NULL == eq) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received unexpected KYC URL `%s' (%s)\n", url, dec); GNUNET_free (dec); TALER_TESTING_FAIL (cs->is); } eq++; if (GNUNET_OK != GNUNET_STRINGS_string_to_data (eq, strlen (eq), &cs->h_payto, sizeof (cs->h_payto))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received unexpected KYC URL `%s' (%s)\n", url, dec); GNUNET_free (dec); TALER_TESTING_FAIL (cs->is); } GNUNET_free (dec); } break; } TALER_TESTING_interpreter_next (cs->is); } /** * Run the "kyc_get" CMD. * * @param cls closure. * @param cmd command being currently run. * @param is interpreter state. */ static void kyc_get_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) { struct KycGetState *cs = cls; const struct TALER_MerchantWireHashP *h_wire = NULL; cs->is = is; if (NULL != cs->h_wire_ref) { const struct TALER_TESTING_Command *wire_cmd; if (NULL == (wire_cmd = 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, so for now this code is dead and 'h_wire_ref' must always be NULL... */ if (GNUNET_OK != TALER_TESTING_get_trait_h_wire (wire_cmd, &h_wire)) { GNUNET_break (0); TALER_TESTING_FAIL (cs->is); } } if (NULL == cs->instance_id) cs->kgh = TALER_MERCHANT_kyc_get (is->ctx, cs->merchant_url, h_wire, cs->exchange_url, GNUNET_TIME_UNIT_ZERO, &kyc_get_cb, cs); else cs->kgh = TALER_MERCHANT_management_kyc_get (is->ctx, cs->merchant_url, cs->instance_id, h_wire, cs->exchange_url, GNUNET_TIME_UNIT_ZERO, &kyc_get_cb, cs); GNUNET_assert (NULL != cs->kgh); } /** * Offer internal data from "KYC" GET CMD. * * @param cls closure. * @param[out] ret result (could be anything). * @param trait name of the trait. * @param index index number of the object to offer. * @return #GNUNET_OK on success. */ static enum GNUNET_GenericReturnValue kyc_get_traits (void *cls, const void **ret, const char *trait, unsigned int index) { struct KycGetState *cs = cls; struct TALER_TESTING_Trait traits[] = { TALER_TESTING_make_trait_h_payto ( &cs->h_payto), TALER_TESTING_trait_end () }; return TALER_TESTING_get_trait (traits, ret, trait, index); } struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_kyc_get (const char *label, const char *merchant_url, const char *instance_id, const char *h_wire_ref, const char *exchange_url, unsigned int expected_http_status) { struct KycGetState *cs; cs = GNUNET_new (struct KycGetState); cs->merchant_url = merchant_url; cs->instance_id = instance_id; cs->h_wire_ref = h_wire_ref; cs->exchange_url = exchange_url; cs->expected_http_status = expected_http_status; { struct TALER_TESTING_Command cmd = { .cls = cs, .label = label, .run = &kyc_get_run, .cleanup = &kyc_get_cleanup, .traits = &kyc_get_traits }; return cmd; } } /* end of testing_api_cmd_kyc_get.c */