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