/*
This file is part of TALER
Copyright (C) 2014-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
*/
/**
* @file test_kyc_api.c
* @brief testcase to test exchange's HTTP API interface
* @author Sree Harsha Totakura
* @author Christian Grothoff
* @author Marcello Stanisci
*/
#include "platform.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "taler_merchant_testing_lib.h"
/**
* Configuration file we use. One (big) configuration is used
* for the various components for this test.
*/
#define CONFIG_FILE "test_kyc_api.conf"
/**
* Exchange base URL. Could also be taken from config.
*/
#define EXCHANGE_URL "http://localhost:8081/"
/**
* Payto URI of the customer (payer).
*/
static struct TALER_FullPayto payer_payto;
/**
* Payto URI of the exchange (escrow account).
*/
static struct TALER_FullPayto exchange_payto;
/**
* Payto URI of the merchant (receiver).
*/
static struct TALER_FullPayto merchant_payto;
/**
* Credentials for the test.
*/
static struct TALER_TESTING_Credentials cred;
/**
* Merchant base URL.
*/
static const char *merchant_url;
/**
* Merchant instance "i1a" base URL.
*/
static char *merchant_url_i1a;
/**
* Account number of the exchange at the bank.
*/
#define EXCHANGE_ACCOUNT_NAME "2"
/**
* Account number of some user.
*/
#define USER_ACCOUNT_NAME "62"
/**
* Account number used by the merchant
*/
#define MERCHANT_ACCOUNT_NAME "3"
/**
* Execute the taler-exchange-aggregator and transfer commands with
* our configuration file.
*
* @param label label to use for the command.
*/
#define CMD_EXEC_AGGREGATOR(label) \
TALER_TESTING_cmd_exec_aggregator_with_kyc (label "-aggregator", \
CONFIG_FILE), \
TALER_TESTING_cmd_exec_transfer (label "-transfer", CONFIG_FILE)
/**
* Execute the taler-exchange-wirewatch command with
* our configuration file.
*
* @param label label to use for the command.
*/
#define CMD_EXEC_WIREWATCH(label) \
TALER_TESTING_cmd_exec_wirewatch2 ( \
label, \
CONFIG_FILE, \
"exchange-account-exchange")
/**
* Run wire transfer of funds from some user's account to the
* exchange.
*
* @param label label to use for the command.
* @param amount amount to transfer, i.e. "EUR:1"
* @param url exchange_url
*/
static struct TALER_TESTING_Command
cmd_transfer_to_exchange (const char *label,
const char *amount)
{
return TALER_TESTING_cmd_admin_add_incoming (label,
amount,
&cred.ba,
payer_payto);
}
/**
* Main function that will tell the interpreter what commands to
* run.
*
* @param cls closure
*/
static void
run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct TALER_TESTING_Command pay[] = {
/**
* Move money to the exchange's bank account.
*/
cmd_transfer_to_exchange (
"create-reserve-1",
"EUR:10.02"),
/**
* Make a reserve exist, according to the previous transfer.
*/
TALER_TESTING_cmd_exec_wirewatch (
"wirewatch-1",
CONFIG_FILE),
TALER_TESTING_cmd_check_bank_admin_transfer (
"check_bank_transfer-2",
"EUR:10.02",
payer_payto,
exchange_payto,
"create-reserve-1"),
TALER_TESTING_cmd_withdraw_amount (
"withdraw-coin-1",
"create-reserve-1",
"EUR:5",
0,
MHD_HTTP_OK),
TALER_TESTING_cmd_withdraw_amount (
"withdraw-coin-2",
"create-reserve-1",
"EUR:5",
0,
MHD_HTTP_OK),
TALER_TESTING_cmd_merchant_get_orders (
"get-orders-empty",
merchant_url,
MHD_HTTP_OK,
NULL),
/**
* Check the reserve is depleted.
*/
TALER_TESTING_cmd_status (
"withdraw-status-1",
"create-reserve-1",
"EUR:0",
MHD_HTTP_OK),
TALER_TESTING_cmd_merchant_post_orders2 (
"create-proposal-1",
cred.cfg,
merchant_url,
MHD_HTTP_OK,
"1", /* order ID */
GNUNET_TIME_UNIT_ZERO_TS,
GNUNET_TIME_UNIT_FOREVER_TS,
true,
"EUR:5.0",
"x-taler-bank",
"",
"",
NULL),
TALER_TESTING_cmd_merchant_claim_order (
"reclaim-1",
merchant_url,
MHD_HTTP_OK,
"create-proposal-1",
NULL),
TALER_TESTING_cmd_merchant_get_instance (
"get-default-instance",
merchant_url,
NULL,
MHD_HTTP_OK,
"instance-create-default-setup"),
TALER_TESTING_cmd_admin_add_kycauth (
"merchant-kyc-auth-transfer",
"EUR:0.01",
&cred.ba,
merchant_payto,
"get-default-instance"),
CMD_EXEC_WIREWATCH (
"import-kyc-account-withdraw"),
TALER_TESTING_cmd_merchant_pay_order (
"deposit-simple",
merchant_url,
MHD_HTTP_OK,
"create-proposal-1",
"withdraw-coin-1",
"EUR:5",
"EUR:4.99",
"session-0"),
TALER_TESTING_cmd_merchant_post_orders_paid (
"verify-order-1-paid",
merchant_url,
"deposit-simple",
"session-1",
MHD_HTTP_OK),
TALER_TESTING_cmd_check_bank_empty (
"check_bank_empty-1"),
CMD_EXEC_AGGREGATOR (
"run-aggregator"),
/* KYC: hence nothing happened at the bank yet: */
TALER_TESTING_cmd_check_bank_empty (
"check_bank_empty-2"),
/* KYC: we don't even know the legitimization UUID yet */
TALER_TESTING_cmd_merchant_kyc_get (
"kyc-pending-early",
merchant_url,
NULL,
NULL,
EXCHANGE_URL,
TALER_EXCHANGE_KLPT_NONE,
MHD_HTTP_OK,
true),
/* now we get the legi UUID by running taler-merchant-depositcheck */
TALER_TESTING_cmd_depositcheck (
"deposit-check",
CONFIG_FILE),
/* Now we should get a status of pending */
TALER_TESTING_cmd_merchant_kyc_get (
"kyc-pending",
merchant_url,
NULL, /* default instance */
"instance-create-default-account", /* h_wire_ref: which account to query */
EXCHANGE_URL,
TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER,
MHD_HTTP_OK,
true),
TALER_TESTING_cmd_get_kyc_info (
"get-kyc-info-deposit",
"kyc-pending",
MHD_HTTP_OK),
TALER_TESTING_cmd_post_kyc_start (
"start-kyc-process-withdraw",
"get-kyc-info-deposit",
0,
MHD_HTTP_OK),
TALER_TESTING_cmd_proof_kyc_oauth2 (
"kyc-do",
"kyc-pending",
"test-oauth2",
"pass",
MHD_HTTP_SEE_OTHER),
CMD_EXEC_AGGREGATOR ("run-aggregator"),
TALER_TESTING_cmd_check_bank_transfer (
"check_bank_transfer-498c",
EXCHANGE_URL,
"EUR:4.98",
exchange_payto,
merchant_payto),
TALER_TESTING_cmd_merchant_post_transfer (
"post-transfer-1",
&cred.ba,
merchant_payto,
merchant_url,
"EUR:4.98",
MHD_HTTP_NO_CONTENT,
"deposit-simple",
NULL),
TALER_TESTING_cmd_run_tme (
"run taler-merchant-reconciliation-1",
CONFIG_FILE),
TALER_TESTING_cmd_merchant_get_transfers (
"get-transfers-1",
merchant_url,
merchant_payto,
MHD_HTTP_OK,
"post-transfer-1",
NULL),
TALER_TESTING_cmd_check_bank_empty (
"check_bank_empty-3"),
TALER_TESTING_cmd_end ()
};
struct TALER_TESTING_Command aml[] = {
TALER_TESTING_cmd_set_officer (
"aml-officer",
NULL,
"Ernest&Young",
true,
false),
cmd_transfer_to_exchange (
"create-reserve-big",
"EUR:100.02"),
TALER_TESTING_cmd_exec_wirewatch (
"wirewatch-big",
CONFIG_FILE),
TALER_TESTING_cmd_sleep (
"sleep to de-collide AML timestamps",
1),
TALER_TESTING_cmd_take_aml_decision (
"freeze",
"aml-officer",
"post-transfer-1",
true /* keep investigating */,
GNUNET_TIME_UNIT_HOURS /* expiration */,
NULL /* successor measure: default */,
"{\"rules\":"
"["
" {"
" \"timeframe\":{\"d_us\":3600000000}"
" ,\"threshold\":\"EUR:1\""
" ,\"operation_type\":\"WITHDRAW\""
" ,\"verboten\":true"
" }"
" ,{"
" \"timeframe\":{\"d_us\":3600000000}"
" ,\"threshold\":\"EUR:1\""
" ,\"operation_type\":\"AGGREGATE\""
" ,\"display_priority\":65536"
" ,\"measures\":[\"form-measure\"]"
" ,\"verboten\":false"
" }"
"]" /* end rules */
",\"new_measure\":\"form-measure\""
",\"custom_measures\":"
" {"
" \"form-measure\":"
" {"
" \"check_name\":\"test-form\""
" ,\"prog_name\":\"test-form-check\""
" }"
" }" /* end custom measures */
"}",
"{}" /* properties */,
"suspicious",
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_check_bank_admin_transfer (
"check_bank_transfer-big",
"EUR:100.02",
payer_payto,
exchange_payto,
"create-reserve-big"),
TALER_TESTING_cmd_withdraw_amount (
"withdraw-coin-aml",
"create-reserve-big",
"EUR:5",
0,
MHD_HTTP_OK),
TALER_TESTING_cmd_merchant_post_orders2 (
"create-proposal-aml",
cred.cfg,
merchant_url,
MHD_HTTP_OK,
"10-aml", /* order ID */
GNUNET_TIME_UNIT_ZERO_TS,
GNUNET_TIME_UNIT_FOREVER_TS,
true,
"EUR:5.0",
"x-taler-bank",
"",
"",
NULL),
TALER_TESTING_cmd_merchant_claim_order (
"reclaim-aml",
merchant_url,
MHD_HTTP_OK,
"create-proposal-aml",
NULL),
TALER_TESTING_cmd_merchant_pay_order (
"deposit-simple",
merchant_url,
MHD_HTTP_OK,
"create-proposal-aml",
"withdraw-coin-aml",
"EUR:5",
"EUR:4.99",
"session-aml"),
TALER_TESTING_cmd_merchant_post_orders_paid (
"verify-order-aml-paid",
merchant_url,
"deposit-simple",
"session-aml",
MHD_HTTP_OK),
TALER_TESTING_cmd_check_bank_empty (
"check_bank_empty-aml-1"),
CMD_EXEC_AGGREGATOR ("run-aggregator-aml-frozen"),
/* AML-frozen: hence nothing happened at the bank yet: */
TALER_TESTING_cmd_check_bank_empty (
"check_bank_empty-aml-2"),
/* Now we should get a status of KYC required */
TALER_TESTING_cmd_merchant_kyc_get (
"aml-frozen-kyc-required",
merchant_url,
NULL, /* no instance ID */
NULL, /* no wire ref */
EXCHANGE_URL,
TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER,
MHD_HTTP_OK,
true),
TALER_TESTING_cmd_sleep (
"sleep to de-collide AML timestamps",
1),
TALER_TESTING_cmd_take_aml_decision (
"unfreeze",
"aml-officer",
"post-transfer-1",
true /* keep investigating */,
GNUNET_TIME_UNIT_HOURS /* expiration */,
NULL /* new measure: none */,
"{\"rules\":["
"{\"timeframe\":{\"d_us\":3600000000},"
" \"threshold\":\"EUR:100\","
" \"operation_type\":\"WITHDRAW\","
" \"verboten\":true"
"}"
"]}" /* new rules */,
"{}" /* properties */,
"fine",
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_merchant_kyc_get (
"aml-unfrozen",
merchant_url,
NULL, /* no instance ID */
NULL, /* no wire ref */
EXCHANGE_URL,
TALER_EXCHANGE_KLPT_KYC_OK,
MHD_HTTP_OK,
true),
CMD_EXEC_AGGREGATOR ("run-aggregator-aml-normal"),
TALER_TESTING_cmd_check_bank_transfer (
"check_bank_transfer-498c-post-unfreeze",
EXCHANGE_URL,
"EUR:4.98",
exchange_payto,
merchant_payto),
TALER_TESTING_cmd_merchant_post_transfer (
"post-transfer-aml",
&cred.ba,
merchant_payto,
merchant_url,
"EUR:4.98",
MHD_HTTP_NO_CONTENT,
"deposit-simple",
NULL),
TALER_TESTING_cmd_run_tme (
"run taler-merchant-reconciliation-2-aml",
CONFIG_FILE),
TALER_TESTING_cmd_merchant_get_transfers (
"get-transfers-aml",
merchant_url,
merchant_payto,
MHD_HTTP_OK,
"post-transfer-1",
"post-transfer-aml",
NULL),
TALER_TESTING_cmd_end ()
}; /* end of aml batch */
struct TALER_TESTING_Command commands[] = {
/* general setup */
TALER_TESTING_cmd_run_fakebank (
"run-fakebank",
cred.cfg,
"exchange-account-exchange"),
TALER_TESTING_cmd_system_start (
"start-taler",
CONFIG_FILE,
"-ema",
"-u", "exchange-account-exchange",
NULL),
TALER_TESTING_cmd_get_exchange (
"get-exchange",
cred.cfg,
NULL,
true,
true),
TALER_TESTING_cmd_oauth_with_birthdate (
"start-oauth-service",
"2005-00-00",
6666),
TALER_TESTING_cmd_merchant_post_instances (
"instance-create-default-setup",
merchant_url,
"default",
MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_merchant_post_account (
"instance-create-default-account",
merchant_url,
merchant_payto,
NULL, NULL,
MHD_HTTP_OK),
TALER_TESTING_cmd_batch ("pay",
pay),
TALER_TESTING_cmd_batch ("aml",
aml),
TALER_TESTING_cmd_end ()
};
TALER_TESTING_run (is,
commands);
}
int
main (int argc,
char *const *argv)
{
payer_payto.full_payto =
(char *) "payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME
"?receiver-name=" USER_ACCOUNT_NAME;
exchange_payto.full_payto =
(char *) "payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME
"?receiver-name=" EXCHANGE_ACCOUNT_NAME;
merchant_payto.full_payto =
(char *) "payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME
"?receiver-name=" MERCHANT_ACCOUNT_NAME;
merchant_url = "http://localhost:8080/";
GNUNET_asprintf (&merchant_url_i1a,
"%sinstances/i1a/",
merchant_url);
return TALER_TESTING_main (argv,
"INFO",
CONFIG_FILE,
"exchange-account-exchange",
TALER_TESTING_BS_FAKEBANK,
&cred,
&run,
NULL);
}
/* end of test_kyc_api.c */