taler-merchant-httpd_get-private-incoming-ID.c (8578B)
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 src/backend/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 "platform.h" 22 #include <jansson.h> 23 #include <taler/taler_json_lib.h> 24 #include "taler-merchant-httpd_get-private-incoming-ID.h" 25 #include "merchant-database/lookup_expected_transfer.h" 26 #include "merchant-database/lookup_reconciliation_details.h" 27 #include "merchant-database/lookup_wire_fee.h" 28 #include "merchant-database/preflight.h" 29 30 31 /** 32 * Function called with information about orders aggregated into 33 * a wire transfer. 34 * Generate a response (array entry) based on the given arguments. 35 * 36 * @param cls closure with a `json_t *` array to build up the response 37 * @param order_id ID of the order that was paid and aggregated 38 * @param remaining_deposit deposited amount minus any refunds 39 * @param deposit_fee deposit fees paid to the exchange for the order 40 */ 41 static void 42 reconciliation_cb (void *cls, 43 const char *order_id, 44 const struct TALER_Amount *remaining_deposit, 45 const struct TALER_Amount *deposit_fee) 46 { 47 json_t *rd = cls; 48 json_t *r; 49 50 r = GNUNET_JSON_PACK ( 51 GNUNET_JSON_pack_string ("order_id", 52 order_id), 53 TALER_JSON_pack_amount ("remaining_deposit", 54 remaining_deposit), 55 TALER_JSON_pack_amount ("deposit_fee", 56 deposit_fee)); 57 GNUNET_assert (0 == 58 json_array_append_new (rd, 59 r)); 60 } 61 62 63 enum MHD_Result 64 TMH_private_get_incoming_ID (const struct TMH_RequestHandler *rh, 65 struct MHD_Connection *connection, 66 struct TMH_HandlerContext *hc) 67 { 68 unsigned long long serial_id; 69 struct TALER_Amount wire_fee; 70 bool no_fee; 71 struct GNUNET_TIME_Timestamp expected_time; 72 struct TALER_Amount expected_credit_amount; 73 struct TALER_WireTransferIdentifierRawP wtid; 74 struct TALER_FullPayto payto_uri; 75 char *exchange_url = NULL; 76 struct GNUNET_TIME_Timestamp execution_time; 77 bool confirmed; 78 79 { 80 char dummy; 81 82 if (1 != 83 sscanf (hc->infix, 84 "%llu%c", 85 &serial_id, 86 &dummy)) 87 { 88 GNUNET_break_op (0); 89 return TALER_MHD_reply_with_error ( 90 connection, 91 MHD_HTTP_BAD_REQUEST, 92 TALER_EC_GENERIC_PARAMETER_MALFORMED, 93 "transfer ID must be a number"); 94 } 95 } 96 97 TALER_MERCHANTDB_preflight (TMH_db); 98 { 99 struct TALER_MasterPublicKeyP master_pub; 100 enum GNUNET_DB_QueryStatus qs; 101 102 qs = TALER_MERCHANTDB_lookup_expected_transfer (TMH_db, 103 hc->instance->settings.id, 104 serial_id, 105 &expected_time, 106 &expected_credit_amount, 107 &wtid, 108 &payto_uri, 109 &exchange_url, 110 &execution_time, 111 &confirmed, 112 &master_pub); 113 if (0 > qs) 114 { 115 /* Simple select queries should not cause serialization issues */ 116 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 117 /* Always report on hard error as well to enable diagnostics */ 118 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 119 return TALER_MHD_reply_with_error (connection, 120 MHD_HTTP_INTERNAL_SERVER_ERROR, 121 TALER_EC_GENERIC_DB_FETCH_FAILED, 122 "lookup_expected_transfer"); 123 } 124 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 125 { 126 GNUNET_break_op (0); 127 return TALER_MHD_reply_with_error ( 128 connection, 129 MHD_HTTP_NOT_FOUND, 130 TALER_EC_MERCHANT_GENERIC_EXPECTED_TRANSFER_UNKNOWN, 131 hc->infix); 132 } 133 134 { 135 char *method; 136 struct GNUNET_TIME_Timestamp start_date; 137 struct GNUNET_TIME_Timestamp end_date; 138 struct TALER_MasterSignatureP master_sig; 139 struct TALER_WireFeeSet fees; 140 141 method = TALER_payto_get_method (payto_uri.full_payto); 142 qs = TALER_MERCHANTDB_lookup_wire_fee ( 143 TMH_db, 144 &master_pub, 145 method, 146 expected_time, 147 &fees, 148 &start_date, 149 &end_date, 150 &master_sig); 151 GNUNET_free (method); 152 if (0 > qs) 153 { 154 /* Simple select queries should not cause serialization issues */ 155 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 156 /* Always report on hard error as well to enable diagnostics */ 157 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 158 GNUNET_free (exchange_url); 159 GNUNET_free (payto_uri.full_payto); 160 return TALER_MHD_reply_with_error (connection, 161 MHD_HTTP_INTERNAL_SERVER_ERROR, 162 TALER_EC_GENERIC_DB_FETCH_FAILED, 163 "lookup_wire_fee"); 164 } 165 no_fee = (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs); 166 if (! no_fee) 167 wire_fee = fees.wire; 168 } 169 170 } 171 172 { 173 enum GNUNET_DB_QueryStatus qs; 174 json_t *rd; 175 enum MHD_Result mret; 176 177 rd = json_array (); 178 GNUNET_assert (NULL != rd); 179 qs = TALER_MERCHANTDB_lookup_reconciliation_details (TMH_db, 180 hc->instance->settings.id, 181 serial_id, 182 &reconciliation_cb, 183 rd); 184 if (0 > qs) 185 { 186 /* Simple select queries should not cause serialization issues */ 187 GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); 188 /* Always report on hard error as well to enable diagnostics */ 189 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); 190 GNUNET_free (exchange_url); 191 GNUNET_free (payto_uri.full_payto); 192 return TALER_MHD_reply_with_error (connection, 193 MHD_HTTP_INTERNAL_SERVER_ERROR, 194 TALER_EC_GENERIC_DB_FETCH_FAILED, 195 "lookup_reconciliation_details"); 196 } 197 198 mret = TALER_MHD_REPLY_JSON_PACK ( 199 connection, 200 MHD_HTTP_OK, 201 GNUNET_JSON_pack_allow_null ( 202 TALER_JSON_pack_amount ( 203 "expected_credit_amount", 204 TALER_amount_is_valid (&expected_credit_amount) 205 ? &expected_credit_amount 206 : NULL)), 207 GNUNET_JSON_pack_data_auto ("wtid", 208 &wtid), 209 TALER_JSON_pack_full_payto ("payto_uri", 210 payto_uri), 211 GNUNET_JSON_pack_string ("exchange_url", 212 exchange_url), 213 GNUNET_JSON_pack_bool ("confirmed", 214 confirmed), 215 GNUNET_JSON_pack_allow_null ( 216 GNUNET_JSON_pack_timestamp ("execution_time", 217 execution_time)), 218 GNUNET_JSON_pack_timestamp ("expected_time", 219 expected_time), 220 GNUNET_JSON_pack_allow_null ( 221 TALER_JSON_pack_amount ("wire_fee", 222 no_fee ? NULL : &wire_fee)), 223 GNUNET_JSON_pack_array_steal ("reconciliation_details", 224 rd)); 225 GNUNET_free (exchange_url); 226 GNUNET_free (payto_uri.full_payto); 227 return mret; 228 } 229 } 230 231 232 /* end of taler-merchant-httpd_get-private-incoming-ID.c */