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