Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020 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 : * @file testing_api_cmd_wallet_get_order.c
21 : * @brief command to test GET /order/$ORDER_ID
22 : * @author Jonathan Buchanan
23 : */
24 : #include "platform.h"
25 : #include <taler/taler_exchange_service.h>
26 : #include <taler/taler_testing_lib.h>
27 : #include "taler_merchant_service.h"
28 : #include "taler_merchant_testing_lib.h"
29 :
30 :
31 : /**
32 : * State for a GET /orders/$ORDER_ID CMD.
33 : */
34 : struct WalletGetOrderState
35 : {
36 : /**
37 : * The merchant base URL.
38 : */
39 : const char *merchant_url;
40 :
41 : /**
42 : * Expected HTTP response code for this CMD.
43 : */
44 : unsigned int http_status;
45 :
46 : /**
47 : * The handle to the current GET /orders/$ORDER_ID request.
48 : */
49 : struct TALER_MERCHANT_OrderWalletGetHandle *ogh;
50 :
51 : /**
52 : * The interpreter state.
53 : */
54 : struct TALER_TESTING_Interpreter *is;
55 :
56 : /**
57 : * Reference to a command that created an order.
58 : */
59 : const char *order_reference;
60 :
61 : /**
62 : * Whether the order was paid or not.
63 : */
64 : bool paid;
65 :
66 : /**
67 : * Whether the order was refunded or not.
68 : */
69 : bool refunded;
70 :
71 : /**
72 : * Whether the order has refunds pending.
73 : */
74 : bool refund_pending;
75 : };
76 :
77 :
78 : /**
79 : * Callback to process a GET /orders/$ID request
80 : *
81 : * @param cls closure
82 : * @param hr HTTP response details
83 : * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not
84 : * settled, #GNUNET_SYSERR on error
85 : * (note that refunded payments are returned as paid!)
86 : * @param refunded #GNUNET_YES if there is at least on refund on this payment,
87 : * #GNUNET_NO if refunded, #GNUNET_SYSERR or error
88 : * @param refund_pending #GNUNET_YES if there are refunds waiting to be
89 : * obtained, #GNUNET_NO if all refunds have been obtained, #GNUNET_SYSERR
90 : * on error.
91 : * @param refund_amount amount that was refunded, NULL if there
92 : * was no refund
93 : * @param taler_pay_uri the URI that instructs the wallets to process
94 : * the payment
95 : * @param already_paid_order_id equivalent order that this customer
96 : * paid already, or NULL for none
97 : */
98 : static void
99 0 : wallet_get_order_cb (
100 : void *cls,
101 : const struct TALER_MERCHANT_HttpResponse *hr,
102 : enum GNUNET_GenericReturnValue paid,
103 : enum GNUNET_GenericReturnValue refunded,
104 : enum GNUNET_GenericReturnValue refund_pending,
105 : struct TALER_Amount *refund_amount,
106 : const char *taler_pay_uri,
107 : const char *already_paid_order_id)
108 : {
109 0 : struct WalletGetOrderState *gos = cls;
110 0 : bool paid_b = (paid == GNUNET_YES);
111 0 : bool refunded_b = (refunded == GNUNET_YES);
112 0 : bool refund_pending_b = (refund_pending == GNUNET_YES);
113 :
114 0 : gos->ogh = NULL;
115 0 : if (gos->http_status != hr->http_status)
116 : {
117 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 : "Unexpected response code %u (%d) to command %s\n",
119 : hr->http_status,
120 : (int) hr->ec,
121 : TALER_TESTING_interpreter_get_current_label (gos->is));
122 0 : TALER_TESTING_interpreter_fail (gos->is);
123 0 : return;
124 : }
125 0 : switch (hr->http_status)
126 : {
127 0 : case MHD_HTTP_OK:
128 : // FIXME: use gos->order_reference here to
129 : // check if the data returned matches that from the POST / PATCH
130 0 : if (gos->paid != paid_b)
131 : {
132 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
133 : "Order paid does not match\n");
134 0 : TALER_TESTING_interpreter_fail (gos->is);
135 0 : return;
136 : }
137 0 : if (gos->refunded != refunded_b)
138 : {
139 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
140 : "Order refunded does not match\n");
141 0 : TALER_TESTING_interpreter_fail (gos->is);
142 0 : return;
143 : }
144 0 : if (gos->refund_pending != refund_pending_b)
145 : {
146 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
147 : "Order refund pending does not match\n");
148 0 : TALER_TESTING_interpreter_fail (gos->is);
149 0 : return;
150 : }
151 0 : if (! paid_b)
152 : {
153 : /* FIXME: Check all of the members of `pud` */
154 : struct TALER_MERCHANT_PayUriData pud;
155 : const struct TALER_TESTING_Command *order_cmd;
156 : const char **order_id;
157 : const struct TALER_ClaimTokenP *claim_token;
158 :
159 0 : if (GNUNET_OK !=
160 0 : TALER_MERCHANT_parse_pay_uri (taler_pay_uri,
161 : &pud))
162 : {
163 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
164 : "Taler pay uri `%s' is malformed\n",
165 : taler_pay_uri);
166 0 : TALER_TESTING_interpreter_fail (gos->is);
167 0 : return;
168 : }
169 :
170 0 : order_cmd = TALER_TESTING_interpreter_lookup_command (
171 : gos->is,
172 : gos->order_reference);
173 :
174 0 : if (GNUNET_OK !=
175 0 : TALER_TESTING_get_trait_order_id (order_cmd,
176 : &order_id))
177 : {
178 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
179 0 : TALER_TESTING_FAIL (gos->is);
180 : }
181 :
182 0 : if (GNUNET_OK !=
183 0 : TALER_TESTING_get_trait_claim_token (order_cmd,
184 : &claim_token))
185 : {
186 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
187 0 : TALER_TESTING_FAIL (gos->is);
188 : }
189 :
190 : {
191 : char *port;
192 : char *host;
193 :
194 0 : if (GNUNET_OK !=
195 0 : GNUNET_CONFIGURATION_get_value_string (gos->is->cfg,
196 : "merchant",
197 : "PORT",
198 : &port))
199 : {
200 : /* How did we get here without a configured port? */
201 0 : GNUNET_break (0);
202 0 : TALER_TESTING_interpreter_fail (gos->is);
203 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
204 0 : return;
205 : }
206 0 : GNUNET_asprintf (&host,
207 : "localhost:%s",
208 : port);
209 0 : GNUNET_free (port);
210 0 : if ((0 != strcmp (host,
211 0 : pud.merchant_host)) ||
212 0 : (NULL != pud.merchant_prefix_path) ||
213 0 : (0 != strcmp (*order_id,
214 0 : pud.order_id)) ||
215 0 : (NULL != pud.ssid))
216 : {
217 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
218 : "Order pay uri `%s' does not match `%s'\n",
219 : taler_pay_uri,
220 : pud.order_id);
221 0 : TALER_TESTING_interpreter_fail (gos->is);
222 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
223 0 : GNUNET_free (host);
224 0 : return;
225 : }
226 0 : GNUNET_free (host);
227 : }
228 : /* The claim token is not given in the pay uri if the order
229 : has been claimed already. */
230 0 : if ((NULL != pud.claim_token) &&
231 0 : ((NULL == claim_token) ||
232 0 : (0 != GNUNET_memcmp (claim_token,
233 : pud.claim_token))))
234 : {
235 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
236 : "Order pay uri claim token does not match (%d/%d)\n",
237 : NULL == pud.claim_token,
238 : NULL == claim_token);
239 0 : TALER_TESTING_interpreter_fail (gos->is);
240 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
241 0 : return;
242 : }
243 0 : TALER_MERCHANT_parse_pay_uri_free (&pud);
244 : }
245 0 : break;
246 0 : default:
247 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
248 : "Unhandled HTTP status.\n");
249 : }
250 0 : TALER_TESTING_interpreter_next (gos->is);
251 : }
252 :
253 :
254 : /**
255 : * Run the "GET order" CMD.
256 : *
257 : * @param cls closure.
258 : * @param cmd command being run now.
259 : * @param is interpreter state.
260 : */
261 : static void
262 0 : wallet_get_order_run (void *cls,
263 : const struct TALER_TESTING_Command *cmd,
264 : struct TALER_TESTING_Interpreter *is)
265 : {
266 0 : struct WalletGetOrderState *gos = cls;
267 : const struct TALER_TESTING_Command *order_cmd;
268 : const char **order_id;
269 : const struct TALER_PrivateContractHashP *h_contract;
270 :
271 0 : order_cmd = TALER_TESTING_interpreter_lookup_command (
272 : is,
273 : gos->order_reference);
274 :
275 0 : if (GNUNET_OK !=
276 0 : TALER_TESTING_get_trait_order_id (order_cmd,
277 : &order_id))
278 0 : TALER_TESTING_FAIL (is);
279 :
280 0 : if (GNUNET_OK !=
281 0 : TALER_TESTING_get_trait_h_contract_terms (order_cmd,
282 : &h_contract))
283 0 : TALER_TESTING_FAIL (is);
284 :
285 0 : gos->is = is;
286 0 : gos->ogh = TALER_MERCHANT_wallet_order_get (is->ctx,
287 : gos->merchant_url,
288 : *order_id,
289 : h_contract,
290 0 : GNUNET_TIME_UNIT_ZERO,
291 : NULL,
292 : NULL,
293 : false,
294 : &wallet_get_order_cb,
295 : gos);
296 : }
297 :
298 :
299 : /**
300 : * Free the state of a "GET order" CMD, and possibly
301 : * cancel a pending operation thereof.
302 : *
303 : * @param cls closure.
304 : * @param cmd command being run.
305 : */
306 : static void
307 0 : wallet_get_order_cleanup (void *cls,
308 : const struct TALER_TESTING_Command *cmd)
309 : {
310 0 : struct WalletGetOrderState *gos = cls;
311 :
312 0 : if (NULL != gos->ogh)
313 : {
314 0 : TALER_LOG_WARNING ("Get tip operation did not complete\n");
315 0 : TALER_MERCHANT_wallet_order_get_cancel (gos->ogh);
316 : }
317 0 : GNUNET_free (gos);
318 0 : }
319 :
320 :
321 : struct TALER_TESTING_Command
322 0 : TALER_TESTING_cmd_wallet_get_order (const char *label,
323 : const char *merchant_url,
324 : const char *order_reference,
325 : bool paid,
326 : bool refunded,
327 : bool refund_pending,
328 : unsigned int http_status)
329 : {
330 : struct WalletGetOrderState *gos;
331 :
332 0 : gos = GNUNET_new (struct WalletGetOrderState);
333 0 : gos->merchant_url = merchant_url;
334 0 : gos->order_reference = order_reference;
335 0 : gos->http_status = http_status;
336 0 : gos->paid = paid;
337 0 : gos->refunded = refunded;
338 0 : gos->refund_pending = refund_pending;
339 : {
340 0 : struct TALER_TESTING_Command cmd = {
341 : .cls = gos,
342 : .label = label,
343 : .run = &wallet_get_order_run,
344 : .cleanup = &wallet_get_order_cleanup
345 : };
346 :
347 0 : return cmd;
348 : }
349 : }
350 :
351 :
352 : struct WalletPollOrderConcludeState
353 : {
354 : /**
355 : * The interpreter state.
356 : */
357 : struct TALER_TESTING_Interpreter *is;
358 :
359 : /**
360 : * Reference to a command that can provide a poll order start command.
361 : */
362 : const char *start_reference;
363 :
364 : /**
365 : * Already paid order ID expected, or NULL for none.
366 : */
367 : const char *already_paid_order_id;
368 :
369 : /**
370 : * Task to wait for the deadline.
371 : */
372 : struct GNUNET_SCHEDULER_Task *task;
373 :
374 : /**
375 : * Amount of a refund expected.
376 : */
377 : struct TALER_Amount expected_refund_amount;
378 :
379 : /**
380 : * Expected HTTP response status code.
381 : */
382 : unsigned int expected_http_status;
383 :
384 : /**
385 : * Are we expecting a refund?
386 : */
387 : bool expected_refund;
388 : };
389 :
390 :
391 : struct WalletPollOrderStartState
392 : {
393 : /**
394 : * The merchant base URL.
395 : */
396 : const char *merchant_url;
397 :
398 : /**
399 : * The handle to the current GET /orders/$ORDER_ID request.
400 : */
401 : struct TALER_MERCHANT_OrderWalletGetHandle *ogh;
402 :
403 : /**
404 : * The interpreter state.
405 : */
406 : struct TALER_TESTING_Interpreter *is;
407 :
408 : /**
409 : * Reference to a command that created an order.
410 : */
411 : const char *order_ref;
412 :
413 : /**
414 : * Which session ID to poll for.
415 : */
416 : const char *session_id;
417 :
418 : /**
419 : * How long to wait for server to return a response.
420 : */
421 : struct GNUNET_TIME_Relative timeout;
422 :
423 : /**
424 : * Conclude state waiting for completion (if any).
425 : */
426 : struct WalletPollOrderConcludeState *cs;
427 :
428 : /**
429 : * The HTTP status code returned by the backend.
430 : */
431 : unsigned int http_status;
432 :
433 : /**
434 : * When the request should be completed by.
435 : */
436 : struct GNUNET_TIME_Absolute deadline;
437 :
438 : /**
439 : * Minimum refund to wait for.
440 : */
441 : struct TALER_Amount refund_threshold;
442 :
443 : /**
444 : * Available refund as returned by the merchant.
445 : */
446 : struct TALER_Amount refund_available;
447 :
448 : /**
449 : * Already paid order ID returned, or NULL for none.
450 : */
451 : char *already_paid_order_id;
452 :
453 : /**
454 : * Should we poll for a refund?
455 : */
456 : bool wait_for_refund;
457 :
458 : /**
459 : * Did we receive a refund according to response from the merchant?
460 : */
461 : bool refunded;
462 :
463 : /**
464 : * Was the order paid according to response from the merchant?
465 : */
466 : bool paid;
467 :
468 : /**
469 : * Has the order a pending refund according to response from the merchant?
470 : */
471 : bool refund_pending;
472 : };
473 :
474 :
475 : /**
476 : * Task called when either the timeout for the GET /private/order/$ID command
477 : * expired or we got a response. Checks if the result is what we expected.
478 : *
479 : * @param cls a `struct WalletPollOrderConcludeState`
480 : */
481 : static void
482 0 : conclude_task (void *cls)
483 : {
484 0 : struct WalletPollOrderConcludeState *ppc = cls;
485 : const struct TALER_TESTING_Command *poll_cmd;
486 : struct WalletPollOrderStartState *cps;
487 : struct GNUNET_TIME_Absolute now;
488 :
489 0 : ppc->task = NULL;
490 : poll_cmd =
491 0 : TALER_TESTING_interpreter_lookup_command (ppc->is,
492 : ppc->start_reference);
493 0 : if (NULL == poll_cmd)
494 0 : TALER_TESTING_FAIL (ppc->is);
495 0 : cps = poll_cmd->cls;
496 0 : if (NULL != cps->ogh)
497 : {
498 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
499 : "Expected poll GET /orders/$ORDER_ID to have completed, but it did not!\n");
500 0 : TALER_TESTING_FAIL (ppc->is);
501 : }
502 0 : if (cps->http_status != ppc->expected_http_status)
503 : {
504 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
505 : "Expected HTTP status %u, got %u\n",
506 : ppc->expected_http_status,
507 : cps->http_status);
508 0 : TALER_TESTING_FAIL (ppc->is);
509 : }
510 0 : if (ppc->expected_refund != cps->refunded)
511 : {
512 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
513 : "Order was %srefunded, contrary to our expectations\n",
514 : cps->refunded ? "" : "NOT ");
515 0 : TALER_TESTING_FAIL (ppc->is);
516 : }
517 0 : if ( (NULL == ppc->already_paid_order_id)
518 0 : ^ (NULL == cps->already_paid_order_id) )
519 : {
520 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
521 : "Mismatch in already paid order IDs: %s vs %s\n",
522 : ppc->already_paid_order_id,
523 : cps->already_paid_order_id);
524 0 : TALER_TESTING_FAIL (ppc->is);
525 : }
526 0 : if ( (NULL != ppc->already_paid_order_id) &&
527 0 : (0 != strcmp (ppc->already_paid_order_id,
528 0 : cps->already_paid_order_id) ) )
529 : {
530 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
531 : "Mismatch in already paid order IDs: %s vs %s\n",
532 : ppc->already_paid_order_id,
533 : cps->already_paid_order_id);
534 0 : TALER_TESTING_FAIL (ppc->is);
535 : }
536 :
537 0 : if (cps->refunded)
538 : {
539 0 : if (0 != TALER_amount_cmp (&ppc->expected_refund_amount,
540 0 : &cps->refund_available))
541 : {
542 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
543 : "Refund amount %s does not match our expectation!\n",
544 : TALER_amount2s (&cps->refund_available));
545 0 : TALER_TESTING_FAIL (ppc->is);
546 : }
547 : }
548 : // FIXME: add checks for cps->paid/refund_available status flags?
549 0 : now = GNUNET_TIME_absolute_get ();
550 0 : if ((GNUNET_TIME_absolute_add (cps->deadline,
551 0 : GNUNET_TIME_UNIT_SECONDS).abs_value_us <
552 0 : now.abs_value_us) )
553 : {
554 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
555 : "Expected answer to be delayed until %llu, but got response at %llu\n",
556 : (unsigned long long) cps->deadline.abs_value_us,
557 : (unsigned long long) now.abs_value_us);
558 0 : TALER_TESTING_FAIL (ppc->is);
559 : }
560 0 : TALER_TESTING_interpreter_next (ppc->is);
561 : }
562 :
563 :
564 : /**
565 : * Process response from a GET /orders/$ID request
566 : *
567 : * @param cls a `struct WalletPollOrderStartState *`
568 : * @param hr HTTP response details
569 : * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not
570 : * settled, #GNUNET_SYSERR on error
571 : * (note that refunded payments are returned as paid!)
572 : * @param refunded #GNUNET_YES if there is at least on refund on this payment,
573 : * #GNUNET_NO if refunded, #GNUNET_SYSERR or error
574 : * @param refund_pending #GNUNET_YES if there are refunds waiting to be
575 : * obtained, #GNUNET_NO if all refunds have been obtained, #GNUNET_SYSERR
576 : * on error.
577 : * @param refund_amount amount that was refunded, NULL if there
578 : * was no refund
579 : * @param taler_pay_uri the URI that instructs the wallets to process
580 : * the payment
581 : * @param already_paid_order_id equivalent order that this customer
582 : * paid already, or NULL for none
583 : */
584 : static void
585 0 : wallet_poll_order_cb (
586 : void *cls,
587 : const struct TALER_MERCHANT_HttpResponse *hr,
588 : enum GNUNET_GenericReturnValue paid,
589 : enum GNUNET_GenericReturnValue refunded,
590 : enum GNUNET_GenericReturnValue refund_pending,
591 : struct TALER_Amount *refund_amount,
592 : const char *taler_pay_uri,
593 : const char *already_paid_order_id)
594 : {
595 0 : struct WalletPollOrderStartState *pos = cls;
596 :
597 0 : pos->ogh = NULL;
598 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
599 : "GET /orders/$ID finished with status %u.\n",
600 : hr->http_status);
601 0 : pos->http_status = hr->http_status;
602 0 : switch (hr->http_status)
603 : {
604 0 : case MHD_HTTP_OK:
605 0 : pos->paid = (GNUNET_YES == paid);
606 0 : pos->refunded = (GNUNET_YES == refunded);
607 0 : pos->refund_pending = (GNUNET_YES == refund_pending);
608 0 : if (NULL != refund_amount)
609 0 : pos->refund_available = *refund_amount;
610 0 : if (NULL != already_paid_order_id)
611 0 : pos->already_paid_order_id = GNUNET_strdup (already_paid_order_id);
612 0 : break;
613 0 : default:
614 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
615 : "Unhandled HTTP status.\n");
616 0 : break;
617 : }
618 0 : if ( (NULL != pos->cs) &&
619 0 : (NULL != pos->cs->task) )
620 : {
621 0 : GNUNET_SCHEDULER_cancel (pos->cs->task);
622 0 : pos->cs->task = GNUNET_SCHEDULER_add_now (&conclude_task,
623 0 : pos->cs);
624 : }
625 0 : }
626 :
627 :
628 : /**
629 : * Run the "GET order" CMD.
630 : *
631 : * @param cls closure.
632 : * @param cmd command being run now.
633 : * @param is interpreter state.
634 : */
635 : static void
636 0 : wallet_poll_order_start_run (void *cls,
637 : const struct TALER_TESTING_Command *cmd,
638 : struct TALER_TESTING_Interpreter *is)
639 : {
640 0 : struct WalletPollOrderStartState *pos = cls;
641 : const struct TALER_TESTING_Command *order_cmd;
642 : const char **order_id;
643 : const struct TALER_PrivateContractHashP *h_contract;
644 :
645 0 : order_cmd = TALER_TESTING_interpreter_lookup_command (
646 : is,
647 : pos->order_ref);
648 :
649 0 : if (GNUNET_OK !=
650 0 : TALER_TESTING_get_trait_order_id (order_cmd,
651 : &order_id))
652 0 : TALER_TESTING_FAIL (is);
653 :
654 0 : if (GNUNET_OK !=
655 0 : TALER_TESTING_get_trait_h_contract_terms (order_cmd,
656 : &h_contract))
657 0 : TALER_TESTING_FAIL (is);
658 :
659 : /* add 1s grace time to timeout */
660 : pos->deadline
661 0 : = GNUNET_TIME_absolute_add (GNUNET_TIME_relative_to_absolute (pos->timeout),
662 : GNUNET_TIME_UNIT_SECONDS);
663 0 : pos->is = is;
664 0 : pos->ogh = TALER_MERCHANT_wallet_order_get (is->ctx,
665 : pos->merchant_url,
666 : *order_id,
667 : h_contract,
668 : pos->timeout,
669 : pos->session_id,
670 0 : pos->wait_for_refund
671 : ? &pos->refund_threshold
672 : : NULL,
673 : false, /* await_refund_obtained */
674 : &wallet_poll_order_cb,
675 : pos);
676 0 : GNUNET_assert (NULL != pos->ogh);
677 : /* We CONTINUE to run the interpreter while the long-polled command
678 : completes asynchronously! */
679 0 : TALER_TESTING_interpreter_next (pos->is);
680 : }
681 :
682 :
683 : /**
684 : * Free the state of a "GET order" CMD, and possibly
685 : * cancel a pending operation thereof.
686 : *
687 : * @param cls closure.
688 : * @param cmd command being run.
689 : */
690 : static void
691 0 : wallet_poll_order_start_cleanup (void *cls,
692 : const struct TALER_TESTING_Command *cmd)
693 : {
694 0 : struct WalletPollOrderStartState *pos = cls;
695 :
696 0 : if (NULL != pos->ogh)
697 : {
698 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
699 : "Command `%s' was not terminated\n",
700 : TALER_TESTING_interpreter_get_current_label (
701 : pos->is));
702 0 : TALER_MERCHANT_wallet_order_get_cancel (pos->ogh);
703 : }
704 0 : GNUNET_free (pos->already_paid_order_id);
705 0 : GNUNET_free (pos);
706 0 : }
707 :
708 :
709 : struct TALER_TESTING_Command
710 0 : TALER_TESTING_cmd_wallet_poll_order_start (
711 : const char *label,
712 : const char *merchant_url,
713 : const char *order_ref,
714 : struct GNUNET_TIME_Relative timeout,
715 : const char *await_refund)
716 : {
717 : struct WalletPollOrderStartState *pos;
718 :
719 0 : pos = GNUNET_new (struct WalletPollOrderStartState);
720 0 : pos->order_ref = order_ref;
721 0 : pos->merchant_url = merchant_url;
722 0 : pos->timeout = timeout;
723 0 : if (NULL != await_refund)
724 : {
725 0 : pos->wait_for_refund = true;
726 0 : GNUNET_assert (GNUNET_OK ==
727 : TALER_string_to_amount (await_refund,
728 : &pos->refund_threshold));
729 : }
730 : {
731 0 : struct TALER_TESTING_Command cmd = {
732 : .cls = pos,
733 : .label = label,
734 : .run = &wallet_poll_order_start_run,
735 : .cleanup = &wallet_poll_order_start_cleanup
736 : };
737 :
738 0 : return cmd;
739 : }
740 : }
741 :
742 :
743 : struct TALER_TESTING_Command
744 0 : TALER_TESTING_cmd_wallet_poll_order_start2 (
745 : const char *label,
746 : const char *merchant_url,
747 : const char *order_ref,
748 : struct GNUNET_TIME_Relative timeout,
749 : const char *await_refund,
750 : const char *session_id)
751 : {
752 : struct WalletPollOrderStartState *pos;
753 : struct TALER_TESTING_Command cmd;
754 :
755 0 : cmd = TALER_TESTING_cmd_wallet_poll_order_start (label,
756 : merchant_url,
757 : order_ref,
758 : timeout,
759 : await_refund);
760 0 : pos = cmd.cls;
761 0 : pos->session_id = session_id;
762 0 : return cmd;
763 : }
764 :
765 :
766 : /**
767 : * Run the "GET order conclude" CMD.
768 : *
769 : * @param cls closure.
770 : * @param cmd command being run now.
771 : * @param is interpreter state.
772 : */
773 : static void
774 0 : wallet_poll_order_conclude_run (void *cls,
775 : const struct TALER_TESTING_Command *cmd,
776 : struct TALER_TESTING_Interpreter *is)
777 : {
778 0 : struct WalletPollOrderConcludeState *poc = cls;
779 : const struct TALER_TESTING_Command *poll_cmd;
780 : struct WalletPollOrderStartState *pos;
781 :
782 0 : poc->is = is;
783 : poll_cmd =
784 0 : TALER_TESTING_interpreter_lookup_command (is,
785 : poc->start_reference);
786 0 : if (NULL == poll_cmd)
787 0 : TALER_TESTING_FAIL (poc->is);
788 0 : GNUNET_assert (poll_cmd->run == &wallet_poll_order_start_run);
789 0 : pos = poll_cmd->cls;
790 0 : pos->cs = poc;
791 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
792 : "Waiting on GET /orders/$ID of %s (%s)\n",
793 : poc->start_reference,
794 : (NULL == pos->ogh)
795 : ? "finished"
796 : : "active");
797 0 : if (NULL == pos->ogh)
798 0 : poc->task = GNUNET_SCHEDULER_add_now (&conclude_task,
799 : poc);
800 : else
801 0 : poc->task = GNUNET_SCHEDULER_add_at (pos->deadline,
802 : &conclude_task,
803 : poc);
804 : }
805 :
806 :
807 : /**
808 : * Free the state of a "GET order" CMD, and possibly
809 : * cancel a pending operation thereof.
810 : *
811 : * @param cls closure.
812 : * @param cmd command being run.
813 : */
814 : static void
815 0 : wallet_poll_order_conclude_cleanup (void *cls,
816 : const struct TALER_TESTING_Command *cmd)
817 : {
818 0 : struct WalletPollOrderConcludeState *poc = cls;
819 :
820 0 : if (NULL != poc->task)
821 : {
822 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
823 : "Command `%s' was not terminated\n",
824 : TALER_TESTING_interpreter_get_current_label (
825 : poc->is));
826 0 : GNUNET_SCHEDULER_cancel (poc->task);
827 0 : poc->task = NULL;
828 : }
829 0 : GNUNET_free (poc);
830 0 : }
831 :
832 :
833 : struct TALER_TESTING_Command
834 0 : TALER_TESTING_cmd_wallet_poll_order_conclude (
835 : const char *label,
836 : unsigned int expected_http_status,
837 : const char *expected_refund_amount,
838 : const char *poll_start_reference)
839 : {
840 : struct WalletPollOrderConcludeState *cps;
841 :
842 0 : cps = GNUNET_new (struct WalletPollOrderConcludeState);
843 0 : cps->start_reference = poll_start_reference;
844 0 : cps->expected_http_status = expected_http_status;
845 0 : if (NULL != expected_refund_amount)
846 : {
847 0 : cps->expected_refund = true;
848 0 : GNUNET_assert (GNUNET_OK ==
849 : TALER_string_to_amount (expected_refund_amount,
850 : &cps->expected_refund_amount));
851 : }
852 : {
853 0 : struct TALER_TESTING_Command cmd = {
854 : .cls = cps,
855 : .label = label,
856 : .run = &wallet_poll_order_conclude_run,
857 : .cleanup = &wallet_poll_order_conclude_cleanup
858 : };
859 :
860 0 : return cmd;
861 : }
862 : }
863 :
864 :
865 : struct TALER_TESTING_Command
866 0 : TALER_TESTING_cmd_wallet_poll_order_conclude2 (
867 : const char *label,
868 : unsigned int expected_http_status,
869 : const char *expected_refund_amount,
870 : const char *poll_start_reference,
871 : const char *already_paid_order_id)
872 : {
873 : struct WalletPollOrderConcludeState *cps;
874 : struct TALER_TESTING_Command cmd;
875 :
876 0 : cmd = TALER_TESTING_cmd_wallet_poll_order_conclude (
877 : label,
878 : expected_http_status,
879 : expected_refund_amount,
880 : poll_start_reference);
881 0 : cps = cmd.cls;
882 0 : cps->already_paid_order_id = already_paid_order_id;
883 0 : return cmd;
884 : }
885 :
886 :
887 : /* end of testing_api_cmd_wallet_get_order.c */
|