Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2022-2023 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 src/testing/testing_api_cmd_post_using_templates.c
21 : * @brief command to test POST /using-templates
22 : * @author Priscilla HUANG
23 : */
24 : #include "platform.h"
25 : struct PostUsingTemplatesState;
26 : #define TALER_MERCHANT_POST_TEMPLATES_RESULT_CLOSURE struct PostUsingTemplatesState
27 : #define TALER_MERCHANT_POST_ORDERS_CLAIM_RESULT_CLOSURE struct PostUsingTemplatesState
28 : #include <taler/taler_exchange_service.h>
29 : #include <taler/taler_testing_lib.h>
30 : #include "taler/taler_merchant_service.h"
31 : #include "taler/taler_merchant_testing_lib.h"
32 : #include <taler/merchant/post-templates-TEMPLATE_ID.h>
33 : #include <taler/merchant/post-orders-ORDER_ID-claim.h>
34 :
35 :
36 : /**
37 : * State of a "POST /templates" CMD.
38 : */
39 : struct PostUsingTemplatesState
40 : {
41 :
42 : /**
43 : * Handle for a "POST /templates/$TEMPLATE_ID" request.
44 : */
45 : struct TALER_MERCHANT_PostTemplatesHandle *iph;
46 :
47 : /**
48 : * The interpreter state.
49 : */
50 : struct TALER_TESTING_Interpreter *is;
51 :
52 : /**
53 : * The (initial) POST /orders/$ID/claim operation handle.
54 : * The logic is such that after an order creation,
55 : * we immediately claim the order.
56 : */
57 : struct TALER_MERCHANT_PostOrdersClaimHandle *och;
58 :
59 : /**
60 : * Base URL of the merchant serving the request.
61 : */
62 : const char *merchant_url;
63 :
64 : /**
65 : * ID of the using template to run.
66 : */
67 : const char *using_template_id;
68 :
69 : /**
70 : * Summary given by the customer.
71 : */
72 : const char *summary;
73 :
74 : /**
75 : * Amount given by the customer.
76 : */
77 : struct TALER_Amount amount;
78 :
79 : /**
80 : * Raw request body for inventory templates (if set).
81 : */
82 : json_t *details;
83 :
84 : /**
85 : * Label of a command that created the template we should use.
86 : */
87 : const char *template_ref;
88 :
89 : /**
90 : * Order id.
91 : */
92 : char *order_id;
93 :
94 : /**
95 : * The order id we expect the merchant to assign (if not NULL).
96 : */
97 : const char *expected_order_id;
98 :
99 : /**
100 : * Contract terms obtained from the backend.
101 : */
102 : json_t *contract_terms;
103 :
104 : /**
105 : * Order submitted to the backend.
106 : */
107 : json_t *order_terms;
108 :
109 : /**
110 : * Contract terms hash code.
111 : */
112 : struct TALER_PrivateContractHashP h_contract_terms;
113 :
114 : /**
115 : * Merchant signature over the orders.
116 : */
117 : struct TALER_MerchantSignatureP merchant_sig;
118 :
119 : /**
120 : * Merchant public key.
121 : */
122 : struct TALER_MerchantPublicKeyP merchant_pub;
123 :
124 : /**
125 : * The nonce.
126 : */
127 : struct GNUNET_CRYPTO_EddsaPublicKey nonce;
128 :
129 : /**
130 : * The claim token
131 : */
132 : struct TALER_ClaimTokenP claim_token;
133 :
134 : /**
135 : * Pay deadline returned when the template was instantiated.
136 : */
137 : struct GNUNET_TIME_Timestamp pay_deadline;
138 :
139 : /**
140 : * Time when the template instantiation request was started.
141 : */
142 : struct GNUNET_TIME_Absolute request_start;
143 :
144 : /**
145 : * Pay duration configured in the template.
146 : */
147 : struct GNUNET_TIME_Relative pay_duration;
148 :
149 : /**
150 : * Whether @e pay_duration is finite and non-zero and should be checked.
151 : */
152 : bool check_pay_duration;
153 :
154 : /**
155 : * Whether @e pay_duration was explicitly supplied as the expected duration.
156 : */
157 : bool have_expected_pay_duration;
158 :
159 : /**
160 : * Should the command also CLAIM the order?
161 : */
162 : bool with_claim;
163 :
164 : /**
165 : * If not NULL, the command should duplicate the request and verify the
166 : * response is the same as in this command.
167 : */
168 : const char *duplicate_of;
169 :
170 : /**
171 : * Label of command creating/updating OTP device, or NULL.
172 : */
173 : const char *otp_ref;
174 :
175 : /**
176 : * Encoded key for the payment verification.
177 : */
178 : const char *otp_key;
179 :
180 : /**
181 : * Option that add amount of the order
182 : */
183 : const enum TALER_MerchantConfirmationAlgorithm *otp_alg;
184 :
185 : /**
186 : * Expected HTTP response code.
187 : */
188 : unsigned int http_status;
189 :
190 : };
191 :
192 : /**
193 : * Used to fill the "using_template" CMD state with backend-provided
194 : * values. Also double-checks that the using_template was correctly
195 : * created.
196 : *
197 : * @param cls closure
198 : * @param ocr response we got
199 : */
200 : static void
201 16 : using_claim_cb (struct PostUsingTemplatesState *tis,
202 : const struct TALER_MERCHANT_PostOrdersClaimResponse *ocr)
203 : {
204 : const char *error_name;
205 : unsigned int error_line;
206 : struct GNUNET_TIME_Timestamp pay_deadline;
207 : struct GNUNET_JSON_Specification spec[] = {
208 16 : GNUNET_JSON_spec_fixed_auto ("merchant_pub",
209 : &tis->merchant_pub),
210 16 : GNUNET_JSON_spec_timestamp ("pay_deadline",
211 : &pay_deadline),
212 16 : GNUNET_JSON_spec_end ()
213 : };
214 :
215 16 : tis->och = NULL;
216 16 : if (tis->http_status != ocr->hr.http_status)
217 : {
218 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
219 : "Expected status %u, got %u\n",
220 : tis->http_status,
221 : ocr->hr.http_status);
222 0 : TALER_TESTING_FAIL (tis->is);
223 : }
224 16 : if (MHD_HTTP_OK != ocr->hr.http_status)
225 : {
226 0 : TALER_TESTING_interpreter_next (tis->is);
227 0 : return;
228 : }
229 32 : tis->contract_terms = json_deep_copy (
230 16 : (json_t *) ocr->details.ok.contract_terms);
231 16 : if (GNUNET_OK !=
232 16 : TALER_JSON_contract_hash (tis->contract_terms,
233 : &tis->h_contract_terms))
234 : {
235 0 : GNUNET_break (0);
236 0 : TALER_TESTING_FAIL (tis->is);
237 : }
238 16 : tis->merchant_sig = ocr->details.ok.merchant_sig;
239 16 : if (GNUNET_OK !=
240 16 : GNUNET_JSON_parse (tis->contract_terms,
241 : spec,
242 : &error_name,
243 : &error_line))
244 : {
245 : char *log;
246 :
247 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
248 : "Parser failed on %s:%u\n",
249 : error_name,
250 : error_line);
251 0 : log = json_dumps (tis->contract_terms,
252 : JSON_INDENT (1));
253 0 : fprintf (stderr,
254 : "%s\n",
255 : log);
256 0 : free (log);
257 0 : TALER_TESTING_FAIL (tis->is);
258 : }
259 16 : if (GNUNET_TIME_timestamp_cmp (pay_deadline,
260 : !=,
261 : tis->pay_deadline))
262 : {
263 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
264 : "Pay deadline in claimed contract does not match template instantiation response\n");
265 0 : TALER_TESTING_FAIL (tis->is);
266 : }
267 16 : TALER_TESTING_interpreter_next (tis->is);
268 : }
269 :
270 :
271 : /**
272 : * Callback for a POST /using-templates operation.
273 : *
274 : * @param cls closure for this function
275 : * @param por response being processed
276 : */
277 : static void
278 38 : post_using_templates_cb (struct PostUsingTemplatesState *tis,
279 : const struct TALER_MERCHANT_PostTemplatesResponse *por)
280 : {
281 :
282 38 : tis->iph = NULL;
283 38 : if (tis->http_status != por->hr.http_status)
284 : {
285 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
286 : "Unexpected response code %u (%d) to command %s\n",
287 : por->hr.http_status,
288 : (int) por->hr.ec,
289 : TALER_TESTING_interpreter_get_current_label (tis->is));
290 0 : TALER_TESTING_interpreter_fail (tis->is);
291 22 : return;
292 : }
293 38 : if (0 == tis->http_status)
294 : {
295 0 : TALER_LOG_DEBUG ("/using_templates, expected 0 status code\n");
296 0 : TALER_TESTING_interpreter_next (tis->is);
297 0 : return;
298 : }
299 : // check for order
300 38 : switch (por->hr.http_status)
301 : {
302 16 : case MHD_HTTP_OK:
303 16 : tis->pay_deadline = por->details.ok.pay_deadline;
304 16 : if (tis->check_pay_duration)
305 : {
306 : struct GNUNET_TIME_Absolute earliest;
307 : struct GNUNET_TIME_Absolute latest;
308 :
309 16 : earliest = GNUNET_TIME_absolute_subtract (
310 : GNUNET_TIME_absolute_add (tis->request_start,
311 : tis->pay_duration),
312 : GNUNET_TIME_UNIT_SECONDS);
313 16 : latest = GNUNET_TIME_absolute_add (
314 : GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
315 : tis->pay_duration),
316 : GNUNET_TIME_UNIT_SECONDS);
317 16 : if ( (GNUNET_TIME_absolute_cmp (tis->pay_deadline.abs_time,
318 : <,
319 16 : earliest)) ||
320 16 : (GNUNET_TIME_absolute_cmp (tis->pay_deadline.abs_time,
321 : >,
322 : latest)) )
323 : {
324 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
325 : "Template pay deadline does not match configured pay duration\n");
326 0 : TALER_TESTING_interpreter_fail (tis->is);
327 0 : return;
328 : }
329 : }
330 16 : if (NULL != por->details.ok.token)
331 16 : tis->claim_token = *por->details.ok.token;
332 16 : tis->order_id = GNUNET_strdup (por->details.ok.order_id);
333 16 : if ((NULL != tis->expected_order_id) &&
334 0 : (0 != strcmp (por->details.ok.order_id,
335 : tis->expected_order_id)))
336 : {
337 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
338 : "Order id assigned does not match\n");
339 0 : TALER_TESTING_interpreter_fail (tis->is);
340 0 : return;
341 : }
342 16 : if (NULL != tis->duplicate_of)
343 : {
344 : const struct TALER_TESTING_Command *order_cmd;
345 : const struct TALER_ClaimTokenP *prev_token;
346 0 : struct TALER_ClaimTokenP zero_token = {0};
347 : const struct TALER_ClaimTokenP *resp_token;
348 :
349 0 : order_cmd = TALER_TESTING_interpreter_lookup_command (
350 : tis->is,
351 : tis->duplicate_of);
352 0 : if (GNUNET_OK !=
353 0 : TALER_TESTING_get_trait_claim_token (order_cmd,
354 : &prev_token))
355 : {
356 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
357 : "Could not fetch previous order claim token\n");
358 0 : TALER_TESTING_interpreter_fail (tis->is);
359 0 : return;
360 : }
361 :
362 0 : resp_token = (NULL != por->details.ok.token)
363 : ? por->details.ok.token
364 0 : : &zero_token;
365 0 : if (0 != GNUNET_memcmp (prev_token,
366 : resp_token))
367 : {
368 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
369 : "Claim tokens for identical requests do not match\n");
370 0 : TALER_TESTING_interpreter_fail (tis->is);
371 0 : return;
372 : }
373 : }
374 16 : break;
375 4 : case MHD_HTTP_NOT_FOUND:
376 4 : TALER_TESTING_interpreter_next (tis->is);
377 4 : return;
378 0 : case MHD_HTTP_GONE:
379 0 : TALER_TESTING_interpreter_next (tis->is);
380 0 : return;
381 18 : case MHD_HTTP_CONFLICT:
382 18 : TALER_TESTING_interpreter_next (tis->is);
383 18 : return;
384 0 : default:
385 : {
386 0 : char *s = json_dumps (por->hr.reply,
387 : JSON_COMPACT);
388 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
389 : "Unexpected status code from /orders: %u (%d) at %s; JSON: %s\n",
390 : por->hr.http_status,
391 : (int) por->hr.ec,
392 : TALER_TESTING_interpreter_get_current_label (tis->is),
393 : s);
394 0 : GNUNET_free (s);
395 : /**
396 : * Not failing, as test cases are _supposed_
397 : * to create non 200 OK situations.
398 : */
399 0 : TALER_TESTING_interpreter_next (tis->is);
400 : }
401 0 : return;
402 : }
403 :
404 16 : if (! tis->with_claim)
405 : {
406 0 : TALER_TESTING_interpreter_next (tis->is);
407 0 : return;
408 : }
409 16 : tis->och = TALER_MERCHANT_post_orders_claim_create (
410 : TALER_TESTING_interpreter_get_context (tis->is),
411 : tis->merchant_url,
412 16 : tis->order_id,
413 16 : &tis->nonce);
414 16 : if (NULL == tis->och)
415 0 : TALER_TESTING_FAIL (tis->is);
416 16 : TALER_MERCHANT_post_orders_claim_set_options (
417 : tis->och,
418 : TALER_MERCHANT_post_orders_claim_option_token (
419 : &tis->claim_token));
420 : {
421 : enum TALER_ErrorCode ec;
422 :
423 16 : ec = TALER_MERCHANT_post_orders_claim_start (tis->och,
424 : &using_claim_cb,
425 : tis);
426 16 : GNUNET_assert (TALER_EC_NONE == ec);
427 : }
428 : }
429 :
430 :
431 : /**
432 : * Run the "POST /using-templates" CMD.
433 : *
434 : *
435 : * @param cls closure.
436 : * @param cmd command being run now.
437 : * @param is interpreter state.
438 : */
439 : static void
440 38 : post_using_templates_run (void *cls,
441 : const struct TALER_TESTING_Command *cmd,
442 : struct TALER_TESTING_Interpreter *is)
443 : {
444 38 : struct PostUsingTemplatesState *tis = cls;
445 : const struct TALER_TESTING_Command *ref;
446 : const char *template_id;
447 : const json_t *template_contract;
448 :
449 38 : tis->is = is;
450 38 : ref = TALER_TESTING_interpreter_lookup_command (is,
451 : tis->template_ref);
452 38 : if (GNUNET_OK !=
453 38 : TALER_TESTING_get_trait_template_id (ref,
454 : &template_id))
455 0 : TALER_TESTING_FAIL (is);
456 38 : if (GNUNET_OK !=
457 38 : TALER_TESTING_get_trait_template_contract (ref,
458 : &template_contract))
459 0 : TALER_TESTING_FAIL (is);
460 38 : if (tis->have_expected_pay_duration)
461 : {
462 : tis->check_pay_duration
463 8 : = (! GNUNET_TIME_relative_is_zero (tis->pay_duration)) &&
464 8 : (! GNUNET_TIME_relative_is_forever (tis->pay_duration));
465 : }
466 34 : else if (NULL !=
467 34 : json_object_get (template_contract,
468 : "pay_duration"))
469 : {
470 : struct GNUNET_JSON_Specification spec[] = {
471 34 : GNUNET_JSON_spec_relative_time ("pay_duration",
472 : &tis->pay_duration),
473 34 : GNUNET_JSON_spec_end ()
474 : };
475 :
476 34 : GNUNET_assert (GNUNET_OK ==
477 : GNUNET_JSON_parse ((json_t *) template_contract,
478 : spec,
479 : NULL,
480 : NULL));
481 : tis->check_pay_duration
482 68 : = (! GNUNET_TIME_relative_is_zero (tis->pay_duration)) &&
483 68 : (! GNUNET_TIME_relative_is_forever (tis->pay_duration));
484 : }
485 38 : if (NULL != tis->otp_ref)
486 : {
487 2 : ref = TALER_TESTING_interpreter_lookup_command (is,
488 : tis->otp_ref);
489 2 : if (GNUNET_OK !=
490 2 : TALER_TESTING_get_trait_otp_key (ref,
491 : &tis->otp_key))
492 0 : TALER_TESTING_FAIL (is);
493 2 : if (GNUNET_OK !=
494 2 : TALER_TESTING_get_trait_otp_alg (ref,
495 : &tis->otp_alg))
496 0 : TALER_TESTING_FAIL (is);
497 : }
498 38 : GNUNET_CRYPTO_random_block (&tis->nonce,
499 : sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
500 38 : tis->iph = TALER_MERCHANT_post_templates_create (
501 : TALER_TESTING_interpreter_get_context (is),
502 : tis->merchant_url,
503 : template_id);
504 38 : GNUNET_assert (NULL != tis->iph);
505 38 : if (NULL != tis->details)
506 : {
507 20 : TALER_MERCHANT_post_templates_set_options (
508 : tis->iph,
509 : TALER_MERCHANT_post_templates_option_details (
510 : tis->details));
511 : }
512 : else
513 : {
514 18 : if (NULL != tis->summary)
515 12 : TALER_MERCHANT_post_templates_set_options (
516 : tis->iph,
517 : TALER_MERCHANT_post_templates_option_summary (
518 : tis->summary));
519 18 : if (TALER_amount_is_valid (&tis->amount))
520 12 : TALER_MERCHANT_post_templates_set_options (
521 : tis->iph,
522 : TALER_MERCHANT_post_templates_option_amount (
523 : &tis->amount));
524 : }
525 : {
526 : enum TALER_ErrorCode ec;
527 :
528 38 : tis->request_start = GNUNET_TIME_absolute_get ();
529 38 : ec = TALER_MERCHANT_post_templates_start (tis->iph,
530 : &post_using_templates_cb,
531 : tis);
532 38 : GNUNET_assert (TALER_EC_NONE == ec);
533 : }
534 : }
535 :
536 :
537 : /**
538 : * Offers information from the POST /using-templates CMD state to other
539 : * commands.
540 : *
541 : * @param cls closure
542 : * @param[out] ret result (could be anything)
543 : * @param trait name of the trait
544 : * @param index index number of the object to extract.
545 : * @return #GNUNET_OK on success
546 : */
547 : static enum GNUNET_GenericReturnValue
548 30 : post_using_templates_traits (void *cls,
549 : const void **ret,
550 : const char *trait,
551 : unsigned int index)
552 : {
553 30 : struct PostUsingTemplatesState *pts = cls;
554 : struct TALER_TESTING_Trait traits[] = {
555 30 : TALER_TESTING_make_trait_order_id (pts->order_id),
556 30 : TALER_TESTING_make_trait_contract_terms (pts->contract_terms),
557 30 : TALER_TESTING_make_trait_order_terms (pts->order_terms),
558 30 : TALER_TESTING_make_trait_h_contract_terms (&pts->h_contract_terms),
559 30 : TALER_TESTING_make_trait_merchant_sig (&pts->merchant_sig),
560 30 : TALER_TESTING_make_trait_merchant_pub (&pts->merchant_pub),
561 30 : TALER_TESTING_make_trait_claim_nonce (&pts->nonce),
562 30 : TALER_TESTING_make_trait_claim_token (&pts->claim_token),
563 30 : TALER_TESTING_make_trait_otp_key (pts->otp_key),
564 30 : TALER_TESTING_make_trait_otp_alg (pts->otp_alg),
565 30 : TALER_TESTING_trait_end (),
566 : };
567 :
568 : (void) pts;
569 30 : return TALER_TESTING_get_trait (traits,
570 : ret,
571 : trait,
572 : index);
573 : }
574 :
575 :
576 : /**
577 : * Free the state of a "POST using-template" CMD, and possibly
578 : * cancel a pending operation thereof.
579 : *
580 : * @param cls closure.
581 : * @param cmd command being run.
582 : */
583 : static void
584 38 : post_using_templates_cleanup (void *cls,
585 : const struct TALER_TESTING_Command *cmd)
586 : {
587 38 : struct PostUsingTemplatesState *tis = cls;
588 :
589 38 : if (NULL != tis->iph)
590 : {
591 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
592 : "POST /using-templates operation did not complete\n");
593 0 : TALER_MERCHANT_post_templates_cancel (tis->iph);
594 : }
595 38 : json_decref (tis->order_terms);
596 38 : json_decref (tis->contract_terms);
597 38 : json_decref (tis->details);
598 38 : GNUNET_free (tis->order_id);
599 38 : GNUNET_free (tis);
600 38 : }
601 :
602 :
603 : /**
604 : * Mark part of the contract terms as possible to forget.
605 : *
606 : * @param cls pointer to the result of the forget operation.
607 : * @param object_id name of the object to forget.
608 : * @param parent parent of the object at @e object_id.
609 : */
610 : static void
611 72 : mark_forgettable (void *cls,
612 : const char *object_id,
613 : json_t *parent)
614 : {
615 72 : GNUNET_assert (GNUNET_OK ==
616 : TALER_JSON_contract_mark_forgettable (parent,
617 : object_id));
618 72 : }
619 :
620 :
621 : /**
622 : * Constructs the json for a POST using template request.
623 : *
624 : * @param using_template_id the name of the using_template to add, can be NULL.
625 : * @param refund_deadline the deadline for refunds on this using template.
626 : * @param pay_deadline the deadline for payment on this using template.
627 : * @param amount the amount this using template is for.
628 : * @param[out] using_template where to write the json string.
629 : */
630 : static void
631 18 : make_order_json (const char *using_template_id,
632 : struct GNUNET_TIME_Timestamp refund_deadline,
633 : struct GNUNET_TIME_Timestamp pay_deadline,
634 : const char *amount,
635 : json_t **using_template)
636 : {
637 18 : struct GNUNET_TIME_Timestamp refund = refund_deadline;
638 18 : struct GNUNET_TIME_Timestamp pay = pay_deadline;
639 : json_t *contract_terms;
640 : struct TALER_Amount tamount;
641 : json_t *arr;
642 :
643 18 : if (NULL != amount)
644 12 : GNUNET_assert (GNUNET_OK ==
645 : TALER_string_to_amount (amount,
646 : &tamount));
647 : /* Include required fields and some dummy objects to test forgetting. */
648 18 : arr = json_array ();
649 18 : GNUNET_assert (NULL != arr);
650 18 : GNUNET_assert (0 ==
651 : json_array_append_new (
652 : arr,
653 : GNUNET_JSON_PACK (
654 : GNUNET_JSON_pack_string (
655 : "item", "speakers"))));
656 18 : GNUNET_assert (0 ==
657 : json_array_append_new (
658 : arr,
659 : GNUNET_JSON_PACK (
660 : GNUNET_JSON_pack_string (
661 : "item", "headphones"))));
662 18 : GNUNET_assert (0 ==
663 : json_array_append_new (
664 : arr,
665 : GNUNET_JSON_PACK (
666 : GNUNET_JSON_pack_string (
667 : "item", "earbuds"))));
668 18 : contract_terms = GNUNET_JSON_PACK (
669 : GNUNET_JSON_pack_string ("summary",
670 : "merchant-lib testcase"),
671 : GNUNET_JSON_pack_allow_null (
672 : GNUNET_JSON_pack_string (
673 : "using_template_id", using_template_id)),
674 : GNUNET_JSON_pack_conditional (
675 : NULL != amount,
676 : TALER_JSON_pack_amount ("amount",
677 : &tamount)),
678 : GNUNET_JSON_pack_string ("fulfillment_url",
679 : "https://example.com"),
680 : GNUNET_JSON_pack_allow_null (
681 : GNUNET_JSON_pack_timestamp ("refund_deadline",
682 : refund)),
683 : GNUNET_JSON_pack_allow_null (
684 : GNUNET_JSON_pack_timestamp ("pay_deadline",
685 : pay)),
686 : GNUNET_JSON_pack_string ("dummy_obj",
687 : "EUR:1.0"),
688 : GNUNET_JSON_pack_array_steal ("dummy_array",
689 : arr));
690 18 : GNUNET_assert (GNUNET_OK ==
691 : TALER_JSON_expand_path (contract_terms,
692 : "$.dummy_obj",
693 : &mark_forgettable,
694 : NULL));
695 18 : GNUNET_assert (GNUNET_OK ==
696 : TALER_JSON_expand_path (contract_terms,
697 : "$.dummy_array[*].item",
698 : &mark_forgettable,
699 : NULL));
700 18 : *using_template = contract_terms;
701 18 : }
702 :
703 :
704 : struct TALER_TESTING_Command
705 18 : TALER_TESTING_cmd_merchant_post_using_templates (
706 : const char *label,
707 : const char *template_ref,
708 : const char *otp_ref,
709 : const char *merchant_url,
710 : const char *using_template_id,
711 : const char *summary,
712 : const char *amount,
713 : struct GNUNET_TIME_Timestamp refund_deadline,
714 : struct GNUNET_TIME_Timestamp pay_deadline,
715 : unsigned int http_status)
716 : {
717 : struct PostUsingTemplatesState *tis;
718 :
719 18 : tis = GNUNET_new (struct PostUsingTemplatesState);
720 18 : tis->template_ref = template_ref;
721 18 : tis->otp_ref = otp_ref;
722 18 : tis->merchant_url = merchant_url;
723 18 : tis->using_template_id = using_template_id;
724 18 : tis->http_status = http_status;
725 18 : tis->summary = summary;
726 18 : tis->with_claim = true;
727 18 : make_order_json (using_template_id,
728 : refund_deadline,
729 : pay_deadline,
730 : amount,
731 : &tis->order_terms);
732 18 : if (NULL != amount)
733 12 : GNUNET_assert (GNUNET_OK ==
734 : TALER_string_to_amount (amount,
735 : &tis->amount));
736 : {
737 18 : struct TALER_TESTING_Command cmd = {
738 : .cls = tis,
739 : .label = label,
740 : .run = &post_using_templates_run,
741 : .cleanup = &post_using_templates_cleanup,
742 : .traits = &post_using_templates_traits
743 : };
744 :
745 18 : return cmd;
746 : }
747 : }
748 :
749 :
750 : struct TALER_TESTING_Command
751 4 : TALER_TESTING_cmd_merchant_post_using_templates_with_expected_pay_duration (
752 : const char *label,
753 : const char *template_ref,
754 : const char *otp_ref,
755 : const char *merchant_url,
756 : const char *using_template_id,
757 : const char *summary,
758 : const char *amount,
759 : struct GNUNET_TIME_Timestamp refund_deadline,
760 : struct GNUNET_TIME_Timestamp pay_deadline,
761 : struct GNUNET_TIME_Relative expected_pay_duration,
762 : unsigned int http_status)
763 : {
764 : struct TALER_TESTING_Command cmd;
765 : struct PostUsingTemplatesState *tis;
766 :
767 4 : cmd = TALER_TESTING_cmd_merchant_post_using_templates (
768 : label,
769 : template_ref,
770 : otp_ref,
771 : merchant_url,
772 : using_template_id,
773 : summary,
774 : amount,
775 : refund_deadline,
776 : pay_deadline,
777 : http_status);
778 4 : tis = cmd.cls;
779 4 : tis->pay_duration = expected_pay_duration;
780 4 : tis->have_expected_pay_duration = true;
781 4 : return cmd;
782 : }
783 :
784 :
785 : struct TALER_TESTING_Command
786 20 : TALER_TESTING_cmd_merchant_post_using_templates2 (
787 : const char *label,
788 : const char *template_ref,
789 : const char *otp_ref,
790 : const char *merchant_url,
791 : const char *using_template_id,
792 : const json_t *details,
793 : unsigned int http_status)
794 : {
795 : struct PostUsingTemplatesState *tis;
796 :
797 20 : tis = GNUNET_new (struct PostUsingTemplatesState);
798 20 : tis->template_ref = template_ref;
799 20 : tis->otp_ref = otp_ref;
800 20 : tis->merchant_url = merchant_url;
801 20 : tis->using_template_id = using_template_id;
802 20 : tis->http_status = http_status;
803 20 : tis->with_claim = true;
804 20 : if (NULL != details)
805 20 : tis->details = json_incref ((json_t *) details);
806 : {
807 20 : struct TALER_TESTING_Command cmd = {
808 : .cls = tis,
809 : .label = label,
810 : .run = &post_using_templates_run,
811 : .cleanup = &post_using_templates_cleanup,
812 : .traits = &post_using_templates_traits
813 : };
814 :
815 20 : return cmd;
816 : }
817 : }
818 :
819 :
820 : /* end of testing_api_cmd_post_using_templates.c */
|