/* This file is part of TALER (C) 2014-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 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_get-rewards-ID.c * @brief implementation of GET /rewards/$ID * @author Marcello Stanisci * @author Christian Grothoff */ #include "platform.h" #include #include #include #include #include "taler-merchant-httpd_get-rewards-ID.h" #include "taler-merchant-httpd_helper.h" #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_qr.h" char * TMH_make_taler_reward_uri (struct MHD_Connection *con, const struct TALER_RewardIdentifierP *reward_id, const char *instance_id) { struct GNUNET_Buffer buf = { 0 }; GNUNET_assert (NULL != instance_id); GNUNET_assert (NULL != reward_id); if (GNUNET_OK != TMH_taler_uri_by_connection (con, "reward", instance_id, &buf)) { GNUNET_break (0); return NULL; } /* Ensure previous part is slash-terminated */ GNUNET_buffer_write_path (&buf, ""); GNUNET_buffer_write_data_encoded (&buf, reward_id, sizeof (*reward_id)); return GNUNET_buffer_reap_str (&buf); } char * TMH_make_reward_status_url (struct MHD_Connection *con, const struct TALER_RewardIdentifierP *reward_id, const char *instance_id) { struct GNUNET_Buffer buf; GNUNET_assert (NULL != instance_id); GNUNET_assert (NULL != reward_id); if (GNUNET_OK != TMH_base_url_by_connection (con, instance_id, &buf)) { GNUNET_break (0); return NULL; } GNUNET_buffer_write_path (&buf, "rewards/"); GNUNET_buffer_write_data_encoded (&buf, reward_id, sizeof (*reward_id)); return GNUNET_buffer_reap_str (&buf); } MHD_RESULT TMH_get_rewards_ID (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { struct TALER_RewardIdentifierP reward_id; enum GNUNET_DB_QueryStatus qs; struct TALER_Amount total_authorized; struct TALER_Amount total_picked_up; struct GNUNET_TIME_Timestamp expiration; char *exchange_url; char *next_url; struct TALER_ReservePrivateKeyP reserve_priv; (void) rh; if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (hc->infix, &reward_id.hash)) { /* reward_id has wrong encoding */ GNUNET_break_op (0); return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PARAMETER_MALFORMED, hc->infix); } TMH_db->preflight (TMH_db->cls); qs = TMH_db->lookup_reward (TMH_db->cls, hc->instance->settings.id, &reward_id, &total_authorized, &total_picked_up, &expiration, &exchange_url, &next_url, &reserve_priv); if (0 > qs) { /* single, read-only SQL statements should never cause serialization problems */ 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, NULL); } if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Unknown reward id given: `%s'\n", hc->infix); return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, TALER_EC_MERCHANT_GENERIC_REWARD_ID_UNKNOWN, hc->infix); } /* Build response */ { struct TALER_Amount remaining; MHD_RESULT ret; GNUNET_break (0 <= TALER_amount_subtract (&remaining, &total_authorized, &total_picked_up)); if (TMH_MHD_test_html_desired (connection)) { char *qr; char *uri; char *reward_status_url; uri = TMH_make_taler_reward_uri (connection, &reward_id, hc->instance->settings.id); reward_status_url = TMH_make_reward_status_url (connection, &reward_id, hc->instance->settings.id); qr = TMH_create_qrcode (uri); if (NULL == qr) { GNUNET_break (0); GNUNET_free (uri); ret = TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_ALLOCATION_FAILURE, "during QR code generation"); } else { json_t *context; context = GNUNET_JSON_PACK ( TALER_JSON_pack_amount ("remaining_reward", &remaining), GNUNET_JSON_pack_string ("taler_reward_uri", uri), GNUNET_JSON_pack_string ("next_url", next_url), GNUNET_JSON_pack_string ("taler_reward_qrcode_svg", qr)); ret = TALER_TEMPLATING_reply (connection, ( (0 == remaining.value) && (0 == remaining.fraction) ) ? MHD_HTTP_GONE : MHD_HTTP_OK, ( (0 == remaining.value) && (0 == remaining.fraction) ) ? "depleted_reward" : "offer_reward", hc->instance->settings.id, uri, context); json_decref (context); } GNUNET_free (reward_status_url); GNUNET_free (uri); GNUNET_free (qr); } else { ret = TALER_MHD_REPLY_JSON_PACK ( connection, TALER_amount_is_zero (&remaining) ? MHD_HTTP_GONE : MHD_HTTP_OK, GNUNET_JSON_pack_string ("exchange_url", exchange_url), GNUNET_JSON_pack_string ("next_url", next_url), TALER_JSON_pack_amount ("reward_amount", &remaining), GNUNET_JSON_pack_timestamp ("expiration", expiration)); } GNUNET_free (exchange_url); GNUNET_free (next_url); return ret; } } /* end of taler-merchant-httpd_get-rewards-ID.c */