taler-merchant-httpd_post-orders-ORDER_ID-paid.c (6997B)
1 /* 2 This file is part of TALER 3 (C) 2014-2023 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Affero General Public License as 7 published by the Free Software Foundation; either version 3, 8 or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, 17 see <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file src/backend/taler-merchant-httpd_post-orders-ORDER_ID-paid.c 22 * @brief handling of POST /orders/$ID/paid requests 23 * @author Christian Grothoff 24 */ 25 #include "platform.h" 26 #include <taler/taler_dbevents.h> 27 #include <taler/taler_signatures.h> 28 #include <taler/taler_json_lib.h> 29 #include <taler/taler_exchange_service.h> 30 #include "taler-merchant-httpd_helper.h" 31 #include "taler-merchant-httpd_post-orders-ORDER_ID-paid.h" 32 #include "merchant-database/update_contract_session.h" 33 #include "merchant-database/event_notify.h" 34 #include "merchant-database/preflight.h" 35 36 37 /** 38 * Use database to notify other clients about the 39 * session being captured. 40 * 41 * @param hc http context 42 * @param session_id the captured session 43 * @param fulfillment_url the URL that is now paid for by @a session_id 44 */ 45 static void 46 trigger_session_notification (struct TMH_HandlerContext *hc, 47 const char *session_id, 48 const char *fulfillment_url) 49 { 50 struct TMH_SessionEventP session_eh = { 51 .header.size = htons (sizeof (session_eh)), 52 .header.type = htons (TALER_DBEVENT_MERCHANT_SESSION_CAPTURED), 53 .merchant_pub = hc->instance->merchant_pub 54 }; 55 56 GNUNET_CRYPTO_hash (session_id, 57 strlen (session_id), 58 &session_eh.h_session_id); 59 GNUNET_CRYPTO_hash (fulfillment_url, 60 strlen (fulfillment_url), 61 &session_eh.h_fulfillment_url); 62 TALER_MERCHANTDB_event_notify (TMH_db, 63 &session_eh.header, 64 NULL, 65 0); 66 } 67 68 69 enum MHD_Result 70 TMH_post_orders_ID_paid (const struct TMH_RequestHandler *rh, 71 struct MHD_Connection *connection, 72 struct TMH_HandlerContext *hc) 73 { 74 const char *order_id = hc->infix; 75 struct TALER_MerchantSignatureP merchant_sig; 76 const char *session_id; 77 struct TALER_PrivateContractHashP hct; 78 char *fulfillment_url; 79 enum GNUNET_DB_QueryStatus qs; 80 bool refunded; 81 82 { 83 struct GNUNET_JSON_Specification spec[] = { 84 GNUNET_JSON_spec_fixed_auto ("sig", 85 &merchant_sig), 86 GNUNET_JSON_spec_fixed_auto ("h_contract", 87 &hct), 88 GNUNET_JSON_spec_string ("session_id", 89 &session_id), 90 GNUNET_JSON_spec_end () 91 }; 92 enum GNUNET_GenericReturnValue res; 93 94 res = TALER_MHD_parse_json_data (connection, 95 hc->request_body, 96 spec); 97 if (GNUNET_YES != res) 98 { 99 GNUNET_break_op (0); 100 return (GNUNET_NO == res) 101 ? MHD_YES 102 : MHD_NO; 103 } 104 } 105 106 if (GNUNET_OK != 107 TALER_merchant_pay_verify (&hct, 108 &hc->instance->merchant_pub, 109 &merchant_sig)) 110 { 111 GNUNET_break_op (0); 112 return TALER_MHD_reply_with_error (connection, 113 MHD_HTTP_FORBIDDEN, 114 TALER_EC_MERCHANT_POST_ORDERS_ID_PAID_COIN_SIGNATURE_INVALID, 115 NULL); 116 } 117 118 TALER_MERCHANTDB_preflight (TMH_db); 119 120 qs = TALER_MERCHANTDB_update_contract_session (TMH_db, 121 hc->instance->settings.id, 122 &hct, 123 session_id, 124 &fulfillment_url, 125 &refunded); 126 switch (qs) 127 { 128 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 129 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 130 "Unknown order id given: `%s'\n", 131 order_id); 132 return TALER_MHD_reply_with_error (connection, 133 MHD_HTTP_NOT_FOUND, 134 TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN, 135 NULL); 136 case GNUNET_DB_STATUS_HARD_ERROR: 137 GNUNET_break (0); 138 return TALER_MHD_reply_with_error (connection, 139 MHD_HTTP_INTERNAL_SERVER_ERROR, 140 TALER_EC_GENERIC_DB_STORE_FAILED, 141 "update_contract_session"); 142 case GNUNET_DB_STATUS_SOFT_ERROR: 143 GNUNET_break (0); 144 return TALER_MHD_reply_with_error (connection, 145 MHD_HTTP_INTERNAL_SERVER_ERROR, 146 TALER_EC_GENERIC_DB_STORE_FAILED, 147 "update_contract_session"); 148 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 149 /* continued below */ 150 break; 151 } 152 153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 154 "Marking contract %s with %s/%s as paid\n", 155 order_id, 156 session_id, 157 fulfillment_url); 158 159 /* Wake everybody up who waits for this fulfillment_url and session_id */ 160 if ( (NULL != fulfillment_url) && 161 (NULL != session_id) ) 162 trigger_session_notification (hc, 163 session_id, 164 fulfillment_url); 165 /*Trigger webhook */ 166 /*Commented out until its purpose is defined 167 { 168 enum GNUNET_DB_QueryStatus qs; 169 json_t *jhook; 170 171 jhook = GNUNET_JSON_PACK ( 172 GNUNET_JSON_pack_object_incref ("contract_terms", 173 contract_terms), 174 GNUNET_JSON_pack_string ("order_id", 175 order_id) 176 ); 177 GNUNET_assert (NULL != jhook); 178 qs = TMH_trigger_webhook (hc->instance->settings.id, 179 "paid", 180 jhook); 181 json_decref (jhook); 182 if (qs < 0) 183 { 184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 185 "Failed to init the webhook for contract %s with %s/%s as paid\n", 186 order_id, 187 session_id, 188 fulfillment_url); 189 } 190 }*/ 191 GNUNET_free (fulfillment_url); 192 193 return TALER_MHD_REPLY_JSON_PACK ( 194 connection, 195 MHD_HTTP_OK, 196 GNUNET_JSON_pack_bool ("refunded", 197 refunded)); 198 } 199 200 201 /* end of taler-merchant-httpd_post-orders-ORDER_ID-paid.c */