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