Line data Source code
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 4 : trigger_session_notification (struct TMH_HandlerContext *hc,
44 : const char *session_id,
45 : const char *fulfillment_url)
46 : {
47 4 : struct TMH_SessionEventP session_eh = {
48 4 : .header.size = htons (sizeof (session_eh)),
49 4 : .header.type = htons (TALER_DBEVENT_MERCHANT_SESSION_CAPTURED),
50 4 : .merchant_pub = hc->instance->merchant_pub
51 : };
52 :
53 4 : GNUNET_CRYPTO_hash (session_id,
54 : strlen (session_id),
55 : &session_eh.h_session_id);
56 4 : GNUNET_CRYPTO_hash (fulfillment_url,
57 : strlen (fulfillment_url),
58 : &session_eh.h_fulfillment_url);
59 4 : TMH_db->event_notify (TMH_db->cls,
60 : &session_eh.header,
61 : NULL,
62 : 0);
63 4 : }
64 :
65 :
66 : MHD_RESULT
67 4 : TMH_post_orders_ID_paid (const struct TMH_RequestHandler *rh,
68 : struct MHD_Connection *connection,
69 : struct TMH_HandlerContext *hc)
70 : {
71 4 : 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 4 : GNUNET_JSON_spec_fixed_auto ("sig",
82 : &merchant_sig),
83 4 : GNUNET_JSON_spec_fixed_auto ("h_contract",
84 : &hct),
85 4 : GNUNET_JSON_spec_string ("session_id",
86 : &session_id),
87 4 : GNUNET_JSON_spec_end ()
88 : };
89 : enum GNUNET_GenericReturnValue res;
90 :
91 4 : res = TALER_MHD_parse_json_data (connection,
92 4 : hc->request_body,
93 : spec);
94 4 : if (GNUNET_YES != res)
95 : {
96 0 : GNUNET_break_op (0);
97 : return (GNUNET_NO == res)
98 : ? MHD_YES
99 0 : : MHD_NO;
100 : }
101 : }
102 :
103 4 : if (GNUNET_OK !=
104 4 : TALER_merchant_pay_verify (&hct,
105 4 : &hc->instance->merchant_pub,
106 : &merchant_sig))
107 : {
108 0 : GNUNET_break_op (0);
109 0 : 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 4 : TMH_db->preflight (TMH_db->cls);
116 :
117 4 : qs = TMH_db->update_contract_session (TMH_db->cls,
118 4 : hc->instance->settings.id,
119 : &hct,
120 : session_id,
121 : &fulfillment_url,
122 : &refunded);
123 4 : switch (qs)
124 : {
125 0 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
126 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
127 : "Unknown order id given: `%s'\n",
128 : order_id);
129 0 : return TALER_MHD_reply_with_error (connection,
130 : MHD_HTTP_NOT_FOUND,
131 : TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN,
132 : NULL);
133 0 : case GNUNET_DB_STATUS_HARD_ERROR:
134 0 : GNUNET_break (0);
135 0 : 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 0 : case GNUNET_DB_STATUS_SOFT_ERROR:
140 0 : GNUNET_break (0);
141 0 : 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 4 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
146 : /* continued below */
147 4 : break;
148 : }
149 :
150 4 : 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 4 : if ( (NULL != fulfillment_url) &&
158 4 : (NULL != session_id) )
159 4 : 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 4 : GNUNET_free (fulfillment_url);
189 :
190 4 : 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 */
|