Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2021, 2024 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as
7 : published by the Free Software Foundation; either version 3, or
8 : (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, see
17 : <http://www.gnu.org/licenses/>
18 : */
19 :
20 : /**
21 : * @file testing/testing_api_cmd_deposits_get.c
22 : * @brief Implement the testing CMDs for the /deposits/ GET operations.
23 : * @author Marcello Stanisci
24 : */
25 : #include "platform.h"
26 : #include "taler_json_lib.h"
27 : #include <gnunet/gnunet_curl_lib.h>
28 : #include "taler_testing_lib.h"
29 :
30 : /**
31 : * State for a "track transaction" CMD.
32 : */
33 : struct TrackTransactionState
34 : {
35 :
36 : /**
37 : * If non NULL, will provide a WTID to be compared against
38 : * the one returned by the "track transaction" operation.
39 : */
40 : const char *bank_transfer_reference;
41 :
42 : /**
43 : * Our command.
44 : */
45 : const struct TALER_TESTING_Command *cmd;
46 :
47 : /**
48 : * The WTID associated by the transaction being tracked.
49 : */
50 : struct TALER_WireTransferIdentifierRawP wtid;
51 :
52 : /**
53 : * Expected HTTP response code.
54 : */
55 : unsigned int expected_response_code;
56 :
57 : /**
58 : * Set to the KYC requirement payto hash *if* the exchange replied with a
59 : * request for KYC (#MHD_HTTP_ACCEPTED).
60 : * Note: set based on our @e merchant_payto_uri, as
61 : * the exchange does not respond with the payto hash.
62 : */
63 : struct TALER_NormalizedPaytoHashP h_payto;
64 :
65 : /**
66 : * Set to the KYC requirement row *if* the exchange replied with
67 : * a request for KYC (#MHD_HTTP_ACCEPTED).
68 : */
69 : uint64_t requirement_row;
70 :
71 : /**
72 : * Reference to any operation that can provide a transaction.
73 : * Will be the transaction to track.
74 : */
75 : const char *transaction_reference;
76 :
77 : /**
78 : * Payto URI of the merchant receiving the deposit.
79 : */
80 : struct TALER_FullPayto merchant_payto_uri;
81 :
82 : /**
83 : * Index of the coin involved in the transaction. Recall:
84 : * at the exchange, the tracking is done _per coin_.
85 : */
86 : unsigned int coin_index;
87 :
88 : /**
89 : * Handle to the "track transaction" pending operation.
90 : */
91 : struct TALER_EXCHANGE_DepositGetHandle *tth;
92 :
93 : /**
94 : * Interpreter state.
95 : */
96 : struct TALER_TESTING_Interpreter *is;
97 : };
98 :
99 :
100 : /**
101 : * Checks what is returned by the "track transaction" operation.
102 : * Checks that the HTTP response code is acceptable, and - if the
103 : * right reference is non NULL - that the wire transfer subject
104 : * line matches our expectations.
105 : *
106 : * @param cls closure.
107 : * @param dr GET deposit response details
108 : */
109 : static void
110 8 : deposit_wtid_cb (
111 : void *cls,
112 : const struct TALER_EXCHANGE_GetDepositResponse *dr)
113 : {
114 8 : struct TrackTransactionState *tts = cls;
115 8 : struct TALER_TESTING_Interpreter *is = tts->is;
116 :
117 8 : tts->tth = NULL;
118 8 : if (tts->expected_response_code != dr->hr.http_status)
119 : {
120 0 : TALER_TESTING_unexpected_status (is,
121 : dr->hr.http_status,
122 : tts->expected_response_code);
123 0 : return;
124 : }
125 8 : switch (dr->hr.http_status)
126 : {
127 2 : case MHD_HTTP_OK:
128 2 : tts->wtid = dr->details.ok.wtid;
129 2 : if (NULL != tts->bank_transfer_reference)
130 : {
131 : const struct TALER_TESTING_Command *bank_transfer_cmd;
132 : const struct TALER_WireTransferIdentifierRawP *wtid_want;
133 :
134 : /* _this_ wire transfer subject line. */
135 : bank_transfer_cmd
136 2 : = TALER_TESTING_interpreter_lookup_command (is,
137 : tts->bank_transfer_reference
138 : );
139 2 : if (NULL == bank_transfer_cmd)
140 : {
141 0 : GNUNET_break (0);
142 0 : TALER_TESTING_interpreter_fail (is);
143 0 : return;
144 : }
145 :
146 2 : if (GNUNET_OK !=
147 2 : TALER_TESTING_get_trait_wtid (bank_transfer_cmd,
148 : &wtid_want))
149 : {
150 0 : GNUNET_break (0);
151 0 : TALER_TESTING_interpreter_fail (is);
152 0 : return;
153 : }
154 :
155 : /* Compare that expected and gotten subjects match. */
156 2 : if (0 != GNUNET_memcmp (&dr->details.ok.wtid,
157 : wtid_want))
158 : {
159 0 : GNUNET_break (0);
160 0 : TALER_TESTING_interpreter_fail (tts->is);
161 0 : return;
162 : }
163 : }
164 2 : break;
165 4 : case MHD_HTTP_ACCEPTED:
166 : /* allowed, nothing to check here */
167 4 : TALER_full_payto_normalize_and_hash (tts->merchant_payto_uri,
168 : &tts->h_payto);
169 : tts->requirement_row
170 4 : = dr->details.accepted.requirement_row;
171 4 : break;
172 2 : case MHD_HTTP_NOT_FOUND:
173 : /* allowed, nothing to check here */
174 2 : break;
175 0 : default:
176 0 : GNUNET_break (0);
177 0 : break;
178 : }
179 8 : TALER_TESTING_interpreter_next (tts->is);
180 : }
181 :
182 :
183 : /**
184 : * Run the command.
185 : *
186 : * @param cls closure.
187 : * @param cmd the command to execute.
188 : * @param is the interpreter state.
189 : */
190 : static void
191 8 : deposits_get_run (
192 : void *cls,
193 : const struct TALER_TESTING_Command *cmd,
194 : struct TALER_TESTING_Interpreter *is)
195 : {
196 8 : struct TrackTransactionState *tts = cls;
197 : const struct TALER_TESTING_Command *transaction_cmd;
198 : const struct TALER_CoinSpendPrivateKeyP *coin_priv;
199 : struct TALER_CoinSpendPublicKeyP coin_pub;
200 : const json_t *contract_terms;
201 : const json_t *wire_details;
202 : struct TALER_MerchantWireHashP h_wire_details;
203 : struct TALER_PrivateContractHashP h_contract_terms;
204 : const struct TALER_MerchantPrivateKeyP *merchant_priv;
205 :
206 8 : tts->cmd = cmd;
207 8 : tts->is = is;
208 : transaction_cmd
209 8 : = TALER_TESTING_interpreter_lookup_command (tts->is,
210 : tts->transaction_reference);
211 8 : if (NULL == transaction_cmd)
212 : {
213 0 : GNUNET_break (0);
214 0 : TALER_TESTING_interpreter_fail (tts->is);
215 0 : return;
216 : }
217 :
218 8 : if (GNUNET_OK !=
219 8 : TALER_TESTING_get_trait_coin_priv (transaction_cmd,
220 : tts->coin_index,
221 : &coin_priv))
222 : {
223 0 : GNUNET_break (0);
224 0 : TALER_TESTING_interpreter_fail (tts->is);
225 0 : return;
226 : }
227 :
228 8 : GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
229 : &coin_pub.eddsa_pub);
230 :
231 : /* Get the strings.. */
232 8 : if (GNUNET_OK !=
233 8 : TALER_TESTING_get_trait_wire_details (transaction_cmd,
234 : &wire_details))
235 : {
236 0 : GNUNET_break (0);
237 0 : TALER_TESTING_interpreter_fail (tts->is);
238 0 : return;
239 : }
240 : tts->merchant_payto_uri.full_payto
241 8 : = GNUNET_strdup (json_string_value (json_object_get (wire_details,
242 : "payto_uri")));
243 8 : if (GNUNET_OK !=
244 8 : TALER_TESTING_get_trait_contract_terms (transaction_cmd,
245 : &contract_terms))
246 : {
247 0 : GNUNET_break (0);
248 0 : TALER_TESTING_interpreter_fail (tts->is);
249 0 : return;
250 : }
251 :
252 8 : if ( (NULL == wire_details) ||
253 8 : (NULL == contract_terms) )
254 : {
255 0 : GNUNET_break (0);
256 0 : TALER_TESTING_interpreter_fail (tts->is);
257 0 : return;
258 : }
259 :
260 : /* Should not fail here, json has been parsed already */
261 8 : GNUNET_assert
262 : ( (GNUNET_OK ==
263 : TALER_JSON_merchant_wire_signature_hash (wire_details,
264 : &h_wire_details)) &&
265 : (GNUNET_OK ==
266 : TALER_JSON_contract_hash (contract_terms,
267 : &h_contract_terms)) );
268 :
269 8 : if (GNUNET_OK !=
270 8 : TALER_TESTING_get_trait_merchant_priv (transaction_cmd,
271 : &merchant_priv))
272 : {
273 0 : GNUNET_break (0);
274 0 : TALER_TESTING_interpreter_fail (tts->is);
275 0 : return;
276 : }
277 :
278 8 : tts->tth = TALER_EXCHANGE_deposits_get (
279 : TALER_TESTING_interpreter_get_context (is),
280 : TALER_TESTING_get_exchange_url (is),
281 : TALER_TESTING_get_keys (is),
282 : merchant_priv,
283 : &h_wire_details,
284 : &h_contract_terms,
285 : &coin_pub,
286 8 : GNUNET_TIME_UNIT_ZERO,
287 : &deposit_wtid_cb,
288 : tts);
289 8 : GNUNET_assert (NULL != tts->tth);
290 : }
291 :
292 :
293 : /**
294 : * Cleanup the state from a "track transaction" CMD, and possibly
295 : * cancel a operation thereof.
296 : *
297 : * @param cls closure.
298 : * @param cmd the command which is being cleaned up.
299 : */
300 : static void
301 8 : deposits_get_cleanup (
302 : void *cls,
303 : const struct TALER_TESTING_Command *cmd)
304 : {
305 8 : struct TrackTransactionState *tts = cls;
306 :
307 8 : if (NULL != tts->tth)
308 : {
309 0 : TALER_TESTING_command_incomplete (tts->is,
310 : cmd->label);
311 0 : TALER_EXCHANGE_deposits_get_cancel (tts->tth);
312 0 : tts->tth = NULL;
313 : }
314 8 : GNUNET_free (tts->merchant_payto_uri.full_payto);
315 8 : GNUNET_free (tts);
316 8 : }
317 :
318 :
319 : /**
320 : * Offer internal data from a "track transaction" CMD.
321 : *
322 : * @param cls closure.
323 : * @param[out] ret result (could be anything).
324 : * @param trait name of the trait.
325 : * @param index index number of the object to offer.
326 : * @return #GNUNET_OK on success.
327 : */
328 : static enum GNUNET_GenericReturnValue
329 25 : deposits_get_traits (void *cls,
330 : const void **ret,
331 : const char *trait,
332 : unsigned int index)
333 : {
334 25 : struct TrackTransactionState *tts = cls;
335 : struct TALER_TESTING_Trait traits[] = {
336 25 : TALER_TESTING_make_trait_wtid (&tts->wtid),
337 25 : TALER_TESTING_make_trait_legi_requirement_row (
338 25 : &tts->requirement_row),
339 25 : TALER_TESTING_make_trait_h_normalized_payto (&tts->h_payto),
340 25 : TALER_TESTING_make_trait_full_payto_uri (&tts->merchant_payto_uri),
341 25 : TALER_TESTING_trait_end ()
342 : };
343 :
344 25 : return TALER_TESTING_get_trait (traits,
345 : ret,
346 : trait,
347 : index);
348 : }
349 :
350 :
351 : struct TALER_TESTING_Command
352 8 : TALER_TESTING_cmd_deposits_get (
353 : const char *label,
354 : const char *transaction_reference,
355 : unsigned int coin_index,
356 : unsigned int expected_response_code,
357 : const char *bank_transfer_reference)
358 : {
359 : struct TrackTransactionState *tts;
360 :
361 8 : tts = GNUNET_new (struct TrackTransactionState);
362 8 : tts->transaction_reference = transaction_reference;
363 8 : tts->expected_response_code = expected_response_code;
364 8 : tts->bank_transfer_reference = bank_transfer_reference;
365 8 : tts->coin_index = coin_index;
366 : {
367 8 : struct TALER_TESTING_Command cmd = {
368 : .cls = tts,
369 : .label = label,
370 : .run = &deposits_get_run,
371 : .cleanup = &deposits_get_cleanup,
372 : .traits = &deposits_get_traits
373 : };
374 :
375 8 : return cmd;
376 : }
377 : }
378 :
379 :
380 : /* end of testing_api_cmd_deposits_get.c */
|