/* This file is part of TALER (C) 2014-2024 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 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 taler-merchant-httpd_private-get-transfers.c * @brief implement API for obtaining a list of wire transfers * @author Marcello Stanisci * @author Christian Grothoff */ #include "platform.h" #include #include #include "taler-merchant-httpd_private-get-transfers.h" /** * Function called with information about a wire transfer. * Generate a response (array entry) based on the given arguments. * * @param cls closure with a `json_t *` array to build up the response * @param credit_amount how much was wired to the merchant (minus fees) * @param wtid wire transfer identifier * @param payto_uri target account that received the wire transfer * @param exchange_url base URL of the exchange that made the wire transfer * @param transfer_serial_id serial number identifying the transfer in the backend * @param execution_time when did the exchange make the transfer, #GNUNET_TIME_UNIT_FOREVER_ABS * if it did not yet happen * @param verified YES if we checked the exchange's answer and liked it, * NO if we checked the exchange's answer and it is problematic, * ALL if we did not yet check * @param confirmed true if the merchant acknowledged the wire transfer reception */ static void transfer_cb (void *cls, const struct TALER_Amount *credit_amount, const struct TALER_WireTransferIdentifierRawP *wtid, struct TALER_FullPayto payto_uri, const char *exchange_url, uint64_t transfer_serial_id, struct GNUNET_TIME_Timestamp execution_time, bool verified, bool confirmed) { json_t *ja = cls; json_t *r; r = GNUNET_JSON_PACK ( TALER_JSON_pack_amount ("credit_amount", credit_amount), GNUNET_JSON_pack_data_auto ("wtid", wtid), TALER_JSON_pack_full_payto ("payto_uri", payto_uri), GNUNET_JSON_pack_string ("exchange_url", exchange_url), GNUNET_JSON_pack_uint64 ("transfer_serial_id", transfer_serial_id), GNUNET_JSON_pack_bool ("verified", verified), GNUNET_JSON_pack_bool ("confirmed", confirmed), GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_timestamp ( "execution_time", GNUNET_TIME_absolute_is_never (execution_time.abs_time) ? GNUNET_TIME_UNIT_ZERO_TS /* => field omitted */ : execution_time)) ); GNUNET_assert (0 == json_array_append_new (ja, r)); } /** * Manages a GET /private/transfers call. * * @param rh context of the handler * @param connection the MHD connection to handle * @param[in,out] hc context with further information about the request * @return MHD result code */ MHD_RESULT TMH_private_get_transfers (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { struct TALER_FullPayto payto_uri = { .full_payto = NULL }; struct GNUNET_TIME_Timestamp before = GNUNET_TIME_UNIT_FOREVER_TS; struct GNUNET_TIME_Timestamp after = GNUNET_TIME_UNIT_ZERO_TS; int64_t limit = -20; uint64_t offset; enum TALER_EXCHANGE_YesNoAll verified; (void) rh; { const char *esc_payto; esc_payto = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "payto_uri"); if (NULL != esc_payto) { payto_uri.full_payto = GNUNET_strdup (esc_payto); MHD_http_unescape (payto_uri.full_payto); } } { const char *before_s; before_s = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "before"); if ( (NULL != before_s) && (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_timestamp (before_s, &before)) ) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PARAMETER_MALFORMED, "before"); } { const char *after_s; after_s = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "after"); if ( (NULL != after_s) && (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_timestamp (after_s, &after)) ) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PARAMETER_MALFORMED, "after"); } TALER_MHD_parse_request_snumber (connection, "limit", &limit); if (limit < 0) offset = INT64_MAX; else offset = 0; TALER_MHD_parse_request_number (connection, "offset", &offset); if (! (TALER_arg_to_yna (connection, "verified", TALER_EXCHANGE_YNA_ALL, &verified)) ) return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PARAMETER_MALFORMED, "verified"); TMH_db->preflight (TMH_db->cls); { json_t *ja; enum GNUNET_DB_QueryStatus qs; ja = json_array (); GNUNET_assert (NULL != ja); qs = TMH_db->lookup_transfers (TMH_db->cls, hc->instance->settings.id, payto_uri, before, after, limit, offset, verified, &transfer_cb, ja); GNUNET_free (payto_uri.full_payto); if (0 > qs) { /* Simple select queries should not cause serialization issues */ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); /* Always report on hard error as well to enable diagnostics */ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, "transfers"); } return TALER_MHD_REPLY_JSON_PACK ( connection, MHD_HTTP_OK, GNUNET_JSON_pack_array_steal ("transfers", ja)); } } /* end of taler-merchant-httpd_track-transfer.c */