taler-merchant-httpd_get-private-incoming-ID.c (8452B)
1 /* 2 This file is part of TALER 3 (C) 2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file taler-merchant-httpd_get-private-incoming-ID.c 18 * @brief implement API for obtaining details about an expected incoming wire transfer 19 * @author Christian Grothoff 20 */ 21 #include "taler/platform.h" 22 #include <jansson.h> 23 #include <taler/taler_json_lib.h> 24 #include "taler-merchant-httpd_get-private-incoming-ID.h" 25 26 27 /** 28 * Function called with information about orders aggregated into 29 * a wire transfer. 30 * Generate a response (array entry) based on the given arguments. 31 * 32 * @param cls closure with a `json_t *` array to build up the response 33 * @param order_id ID of the order that was paid and aggregated 34 * @param remaining_deposit deposited amount minus any refunds 35 * @param deposit_fee deposit fees paid to the exchange for the order 36 */ 37 static void 38 reconciliation_cb (void *cls, 39 const char *order_id, 40 const struct TALER_Amount *remaining_deposit, 41 const struct TALER_Amount *deposit_fee) 42 { 43 json_t *rd = cls; 44 json_t *r; 45 46 r = GNUNET_JSON_PACK ( 47 GNUNET_JSON_pack_string ("order_id", 48 order_id), 49 TALER_JSON_pack_amount ("remaining_deposit", 50 remaining_deposit), 51 TALER_JSON_pack_amount ("deposit_fee", 52 deposit_fee)); 53 GNUNET_assert (0 == 54 json_array_append_new (rd, 55 r)); 56 } 57 58 59 /** 60 * Manages a GET /private/incoming call. 61 * 62 * @param rh context of the handler 63 * @param connection the MHD connection to handle 64 * @param[in,out] hc context with further information about the request 65 * @return MHD result code 66 */ 67 MHD_RESULT 68 TMH_private_get_incoming_ID (const struct TMH_RequestHandler *rh, 69 struct MHD_Connection *connection, 70 struct TMH_HandlerContext *hc) 71 { 72 unsigned long long serial_id; 73 struct TALER_Amount wire_fee; 74 bool no_fee; 75 struct GNUNET_TIME_Timestamp expected_time; 76 struct TALER_Amount expected_credit_amount; 77 struct TALER_WireTransferIdentifierRawP wtid; 78 struct TALER_FullPayto payto_uri; 79 char *exchange_url = NULL; 80 struct GNUNET_TIME_Timestamp execution_time; 81 bool confirmed; 82 83 { 84 char dummy; 85 86 if (1 != 87 sscanf (hc->infix, 88 "%llu%c", 89 &serial_id, 90 &dummy)) 91 { 92 GNUNET_break_op (0); 93 return TALER_MHD_reply_with_error ( 94 connection, 95 MHD_HTTP_BAD_REQUEST, 96 TALER_EC_GENERIC_PARAMETER_MALFORMED, 97 "transfer ID must be a number"); 98 } 99 } 100 101 TMH_db->preflight (TMH_db->cls); 102 { 103 struct TALER_MasterPublicKeyP master_pub; 104 enum GNUNET_DB_QueryStatus qs; 105 106 qs = TMH_db->lookup_expected_transfer (TMH_db->cls, 107 hc->instance->settings.id, 108 serial_id, 109 &expected_time, 110 &expected_credit_amount, 111 &wtid, 112 &payto_uri, 113 &exchange_url, 114 &execution_time, 115 &confirmed, 116 &master_pub); 117 if (0 > qs) 118 { 119 /* Simple select queries should not cause serialization issues */ 120 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 121 /* Always report on hard error as well to enable diagnostics */ 122 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 123 return TALER_MHD_reply_with_error (connection, 124 MHD_HTTP_INTERNAL_SERVER_ERROR, 125 TALER_EC_GENERIC_DB_FETCH_FAILED, 126 "lookup_expected_transfer"); 127 } 128 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 129 { 130 GNUNET_break_op (0); 131 return TALER_MHD_reply_with_error ( 132 connection, 133 MHD_HTTP_NOT_FOUND, 134 TALER_EC_MERCHANT_GENERIC_EXPECTED_TRANSFER_UNKNOWN, 135 hc->infix); 136 } 137 138 { 139 char *method; 140 struct GNUNET_TIME_Timestamp start_date; 141 struct GNUNET_TIME_Timestamp end_date; 142 struct TALER_MasterSignatureP master_sig; 143 struct TALER_WireFeeSet fees; 144 145 method = TALER_payto_get_method (payto_uri.full_payto); 146 qs = TMH_db->lookup_wire_fee ( 147 TMH_db->cls, 148 &master_pub, 149 method, 150 expected_time, 151 &fees, 152 &start_date, 153 &end_date, 154 &master_sig); 155 GNUNET_free (method); 156 if (0 > qs) 157 { 158 /* Simple select queries should not cause serialization issues */ 159 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 160 /* Always report on hard error as well to enable diagnostics */ 161 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 162 GNUNET_free (exchange_url); 163 GNUNET_free (payto_uri.full_payto); 164 return TALER_MHD_reply_with_error (connection, 165 MHD_HTTP_INTERNAL_SERVER_ERROR, 166 TALER_EC_GENERIC_DB_FETCH_FAILED, 167 "lookup_wire_fee"); 168 } 169 no_fee = (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs); 170 if (! no_fee) 171 wire_fee = fees.wire; 172 } 173 174 } 175 176 { 177 enum GNUNET_DB_QueryStatus qs; 178 json_t *rd; 179 MHD_RESULT mret; 180 181 rd = json_array (); 182 GNUNET_assert (NULL != rd); 183 qs = TMH_db->lookup_reconciliation_details (TMH_db->cls, 184 hc->instance->settings.id, 185 serial_id, 186 &reconciliation_cb, 187 rd); 188 if (0 > qs) 189 { 190 /* Simple select queries should not cause serialization issues */ 191 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 192 /* Always report on hard error as well to enable diagnostics */ 193 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 194 GNUNET_free (exchange_url); 195 GNUNET_free (payto_uri.full_payto); 196 return TALER_MHD_reply_with_error (connection, 197 MHD_HTTP_INTERNAL_SERVER_ERROR, 198 TALER_EC_GENERIC_DB_FETCH_FAILED, 199 "lookup_reconciliation_details"); 200 } 201 202 mret = TALER_MHD_REPLY_JSON_PACK ( 203 connection, 204 MHD_HTTP_OK, 205 GNUNET_JSON_pack_allow_null ( 206 TALER_JSON_pack_amount ( 207 "expected_credit_amount", 208 TALER_amount_is_valid (&expected_credit_amount) 209 ? &expected_credit_amount 210 : NULL)), 211 GNUNET_JSON_pack_data_auto ("wtid", 212 &wtid), 213 TALER_JSON_pack_full_payto ("payto_uri", 214 payto_uri), 215 GNUNET_JSON_pack_string ("exchange_url", 216 exchange_url), 217 GNUNET_JSON_pack_bool ("confirmed", 218 confirmed), 219 GNUNET_JSON_pack_allow_null ( 220 GNUNET_JSON_pack_timestamp ("execution_time", 221 execution_time)), 222 GNUNET_JSON_pack_timestamp ("expected_time", 223 expected_time), 224 GNUNET_JSON_pack_allow_null ( 225 TALER_JSON_pack_amount ("wire_fee", 226 no_fee ? NULL : &wire_fee)), 227 GNUNET_JSON_pack_array_steal ("reconciliation_details", 228 rd)); 229 GNUNET_free (exchange_url); 230 GNUNET_free (payto_uri.full_payto); 231 return mret; 232 } 233 } 234 235 236 /* end of taler-merchant-httpd_get-private-incoming-ID.c */