taler-merchant-httpd_post-orders-ID-paid.c (6738B)
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 taler-merchant-httpd_post-orders-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-ID-paid.h" 32 33 34 /** 35 * Use database to notify other clients about the 36 * session being captured. 37 * 38 * @param hc http context 39 * @param session_id the captured session 40 * @param fulfillment_url the URL that is now paid for by @a session_id 41 */ 42 static void 43 trigger_session_notification (struct TMH_HandlerContext *hc, 44 const char *session_id, 45 const char *fulfillment_url) 46 { 47 struct TMH_SessionEventP session_eh = { 48 .header.size = htons (sizeof (session_eh)), 49 .header.type = htons (TALER_DBEVENT_MERCHANT_SESSION_CAPTURED), 50 .merchant_pub = hc->instance->merchant_pub 51 }; 52 53 GNUNET_CRYPTO_hash (session_id, 54 strlen (session_id), 55 &session_eh.h_session_id); 56 GNUNET_CRYPTO_hash (fulfillment_url, 57 strlen (fulfillment_url), 58 &session_eh.h_fulfillment_url); 59 TMH_db->event_notify (TMH_db->cls, 60 &session_eh.header, 61 NULL, 62 0); 63 } 64 65 66 MHD_RESULT 67 TMH_post_orders_ID_paid (const struct TMH_RequestHandler *rh, 68 struct MHD_Connection *connection, 69 struct TMH_HandlerContext *hc) 70 { 71 const char *order_id = hc->infix; 72 struct TALER_MerchantSignatureP merchant_sig; 73 const char *session_id; 74 struct TALER_PrivateContractHashP hct; 75 char *fulfillment_url; 76 enum GNUNET_DB_QueryStatus qs; 77 bool refunded; 78 79 { 80 struct GNUNET_JSON_Specification spec[] = { 81 GNUNET_JSON_spec_fixed_auto ("sig", 82 &merchant_sig), 83 GNUNET_JSON_spec_fixed_auto ("h_contract", 84 &hct), 85 GNUNET_JSON_spec_string ("session_id", 86 &session_id), 87 GNUNET_JSON_spec_end () 88 }; 89 enum GNUNET_GenericReturnValue res; 90 91 res = TALER_MHD_parse_json_data (connection, 92 hc->request_body, 93 spec); 94 if (GNUNET_YES != res) 95 { 96 GNUNET_break_op (0); 97 return (GNUNET_NO == res) 98 ? MHD_YES 99 : MHD_NO; 100 } 101 } 102 103 if (GNUNET_OK != 104 TALER_merchant_pay_verify (&hct, 105 &hc->instance->merchant_pub, 106 &merchant_sig)) 107 { 108 GNUNET_break_op (0); 109 return TALER_MHD_reply_with_error (connection, 110 MHD_HTTP_FORBIDDEN, 111 TALER_EC_MERCHANT_POST_ORDERS_ID_PAID_COIN_SIGNATURE_INVALID, 112 NULL); 113 } 114 115 TMH_db->preflight (TMH_db->cls); 116 117 qs = TMH_db->update_contract_session (TMH_db->cls, 118 hc->instance->settings.id, 119 &hct, 120 session_id, 121 &fulfillment_url, 122 &refunded); 123 switch (qs) 124 { 125 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 126 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 127 "Unknown order id given: `%s'\n", 128 order_id); 129 return TALER_MHD_reply_with_error (connection, 130 MHD_HTTP_NOT_FOUND, 131 TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN, 132 NULL); 133 case GNUNET_DB_STATUS_HARD_ERROR: 134 GNUNET_break (0); 135 return TALER_MHD_reply_with_error (connection, 136 MHD_HTTP_INTERNAL_SERVER_ERROR, 137 TALER_EC_GENERIC_DB_STORE_FAILED, 138 "update_contract_session"); 139 case GNUNET_DB_STATUS_SOFT_ERROR: 140 GNUNET_break (0); 141 return TALER_MHD_reply_with_error (connection, 142 MHD_HTTP_INTERNAL_SERVER_ERROR, 143 TALER_EC_GENERIC_DB_STORE_FAILED, 144 "update_contract_session"); 145 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 146 /* continued below */ 147 break; 148 } 149 150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 151 "Marking contract %s with %s/%s as paid\n", 152 order_id, 153 session_id, 154 fulfillment_url); 155 156 /* Wake everybody up who waits for this fulfillment_url and session_id */ 157 if ( (NULL != fulfillment_url) && 158 (NULL != session_id) ) 159 trigger_session_notification (hc, 160 session_id, 161 fulfillment_url); 162 /*Trigger webhook */ 163 /*Commented out until its purpose is defined 164 { 165 enum GNUNET_DB_QueryStatus qs; 166 json_t *jhook; 167 168 jhook = GNUNET_JSON_PACK ( 169 GNUNET_JSON_pack_object_incref ("contract_terms", 170 contract_terms), 171 GNUNET_JSON_pack_string ("order_id", 172 order_id) 173 ); 174 GNUNET_assert (NULL != jhook); 175 qs = TMH_trigger_webhook (hc->instance->settings.id, 176 "paid", 177 jhook); 178 json_decref (jhook); 179 if (qs < 0) 180 { 181 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 182 "Failed to init the webhook for contract %s with %s/%s as paid\n", 183 order_id, 184 session_id, 185 fulfillment_url); 186 } 187 }*/ 188 GNUNET_free (fulfillment_url); 189 190 return TALER_MHD_REPLY_JSON_PACK ( 191 connection, 192 MHD_HTTP_OK, 193 GNUNET_JSON_pack_bool ("refunded", 194 refunded)); 195 } 196 197 198 /* end of taler-merchant-httpd_post-orders-ID-paid.c */