taler-merchant-httpd_private-post-transfers.c (5649B)
1 /* 2 This file is part of TALER 3 (C) 2014-2023, 2025 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_private-post-transfers.c 18 * @brief implement API for registering wire transfers 19 * @author Marcello Stanisci 20 * @author Christian Grothoff 21 */ 22 #include "platform.h" 23 #include <jansson.h> 24 #include <taler/taler_signatures.h> 25 #include <taler/taler_json_lib.h> 26 #include <taler/taler_dbevents.h> 27 #include "taler-merchant-httpd_exchanges.h" 28 #include "taler-merchant-httpd_helper.h" 29 #include "taler-merchant-httpd_private-post-transfers.h" 30 31 32 /** 33 * How often do we retry the simple INSERT database transaction? 34 */ 35 #define MAX_RETRIES 5 36 37 38 MHD_RESULT 39 TMH_private_post_transfers (const struct TMH_RequestHandler *rh, 40 struct MHD_Connection *connection, 41 struct TMH_HandlerContext *hc) 42 { 43 struct TALER_FullPayto payto_uri; 44 const char *exchange_url; 45 struct TALER_WireTransferIdentifierRawP wtid; 46 struct TALER_Amount amount; 47 struct GNUNET_JSON_Specification spec[] = { 48 TALER_JSON_spec_amount_any ("credit_amount", 49 &amount), 50 GNUNET_JSON_spec_fixed_auto ("wtid", 51 &wtid), 52 TALER_JSON_spec_full_payto_uri ("payto_uri", 53 &payto_uri), 54 TALER_JSON_spec_web_url ("exchange_url", 55 &exchange_url), 56 GNUNET_JSON_spec_end () 57 }; 58 enum GNUNET_GenericReturnValue res; 59 enum GNUNET_DB_QueryStatus qs; 60 61 res = TALER_MHD_parse_json_data (connection, 62 hc->request_body, 63 spec); 64 if (GNUNET_OK != res) 65 return (GNUNET_NO == res) 66 ? MHD_YES 67 : MHD_NO; 68 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 69 "New inbound wire transfer over %s to %s from %s\n", 70 TALER_amount2s (&amount), 71 payto_uri.full_payto, 72 exchange_url); 73 74 /* Check if transfer data is in database, if not, add it. */ 75 for (unsigned int retry = 0; retry<MAX_RETRIES; retry++) 76 { 77 TMH_db->preflight (TMH_db->cls); 78 if (GNUNET_OK != 79 TMH_db->start (TMH_db->cls, 80 "post-transfers")) 81 { 82 GNUNET_break (0); 83 return TALER_MHD_reply_with_error (connection, 84 MHD_HTTP_INTERNAL_SERVER_ERROR, 85 TALER_EC_GENERIC_DB_START_FAILED, 86 "transfer"); 87 } 88 qs = TMH_db->insert_transfer (TMH_db->cls, 89 hc->instance->settings.id, 90 exchange_url, 91 &wtid, 92 &amount, 93 payto_uri, 94 0 /* no bank serial known! */); 95 switch (qs) 96 { 97 case GNUNET_DB_STATUS_HARD_ERROR: 98 GNUNET_break (0); 99 TMH_db->rollback (TMH_db->cls); 100 return TALER_MHD_reply_with_error (connection, 101 MHD_HTTP_INTERNAL_SERVER_ERROR, 102 TALER_EC_GENERIC_DB_STORE_FAILED, 103 "insert_transfer"); 104 case GNUNET_DB_STATUS_SOFT_ERROR: 105 TMH_db->rollback (TMH_db->cls); 106 continue; 107 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 108 /* Must mean the bank account is unknown! */ 109 TMH_db->rollback (TMH_db->cls); 110 return TALER_MHD_reply_with_error ( 111 connection, 112 MHD_HTTP_CONFLICT, 113 TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION, 114 payto_uri.full_payto); 115 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 116 break; 117 } 118 { 119 struct GNUNET_DB_EventHeaderP es = { 120 .size = htons (sizeof (es)), 121 .type = htons (TALER_DBEVENT_MERCHANT_WIRE_TRANSFER_CONFIRMED) 122 }; 123 124 TMH_db->event_notify (TMH_db->cls, 125 &es, 126 NULL, 127 0); 128 } 129 qs = TMH_db->commit (TMH_db->cls); 130 switch (qs) 131 { 132 case GNUNET_DB_STATUS_HARD_ERROR: 133 GNUNET_break (0); 134 TMH_db->rollback (TMH_db->cls); 135 return TALER_MHD_reply_with_error (connection, 136 MHD_HTTP_INTERNAL_SERVER_ERROR, 137 TALER_EC_GENERIC_DB_COMMIT_FAILED, 138 NULL); 139 case GNUNET_DB_STATUS_SOFT_ERROR: 140 TMH_db->rollback (TMH_db->cls); 141 continue; 142 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 143 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 144 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 145 "post-transfer committed successfully\n"); 146 break; 147 } 148 break; 149 } 150 return TALER_MHD_reply_static (connection, 151 MHD_HTTP_NO_CONTENT, 152 NULL, 153 NULL, 154 0); 155 } 156 157 158 /* end of taler-merchant-httpd_private-post-transfers.c */