testing_api_cmd_pay_order.c (50317B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-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 * @file testing_api_cmd_pay_order.c 21 * @brief command to test the /orders/ID/pay feature. 22 * @author Marcello Stanisci 23 * @author Christian Grothoff 24 */ 25 #include "platform.h" 26 #include <gnunet/gnunet_common.h> 27 #include <gnunet/gnunet_json_lib.h> 28 #include <gnunet/gnunet_time_lib.h> 29 #include <jansson.h> 30 #include <stddef.h> 31 #include <stdint.h> 32 #include <taler/taler_exchange_service.h> 33 #include <taler/taler_testing_lib.h> 34 #include <taler/taler_signatures.h> 35 #include "taler_merchant_service.h" 36 #include "taler_merchant_pay_service.h" 37 #include "taler_merchant_testing_lib.h" 38 39 #ifdef HAVE_DONAU_DONAU_SERVICE_H 40 #include <donau/donau_service.h> 41 #include <donau/donau_testing_lib.h> 42 #include <donau/donau_json_lib.h> 43 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 44 45 #ifdef HAVE_DONAU_DONAU_SERVICE_H 46 /** 47 * Struct for handling the CS approach in signing of the bkps 48 */ 49 struct CSR_Data 50 { 51 /** 52 * Handle to the "batch issue receipt status" operation. 53 */ 54 struct DONAU_CsRBatchIssueHandle *csr_handle; 55 56 /** 57 * CS-Nonce 58 */ 59 union GNUNET_CRYPTO_BlindSessionNonce nonce; 60 61 /** 62 * batch issue receipt status state 63 */ 64 struct StatusState *ss; 65 66 /** 67 * array position in batch issue receipt request (first position is zero) 68 */ 69 size_t position; 70 }; 71 72 /** 73 * Handling all data needed for the /pay DONAU CMD. 74 */ 75 struct MerchantDonauPayData 76 { 77 /** 78 * Donau URL. 79 */ 80 const char *donau_url; 81 82 /** 83 * Donau keys 84 */ 85 struct DONAU_Keys *keys; 86 87 /** 88 * Charity reference 89 */ 90 const char *charity_reference; 91 92 /** 93 * Charity id 94 */ 95 uint64_t charity_id; 96 97 /** 98 * Amount of the donation 99 */ 100 struct TALER_Amount donation_amount; 101 102 /** 103 * Number of BUDIs to create or fetch. Example only. 104 */ 105 uint32_t num_bkps; 106 107 /** 108 * Year of the donation 109 */ 110 uint64_t year; 111 112 /** 113 * Selected donation unit pub keys for this pay order request 114 */ 115 struct DONAU_DonationUnitPublicKey *selected_pks; 116 117 /** 118 * BUDI key pairs used in the payment (blinded_udi + pubkey). 119 */ 120 struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps; 121 122 /** 123 * Blinding secrets, if needed for each BUDI (CS vs. RSA). 124 */ 125 union GNUNET_CRYPTO_BlindingSecretP *blinding_secrets; 126 127 /** 128 * Blinding values. Cs-nonces, cipher. 129 */ 130 const struct DONAU_BatchIssueValues **alg_values; 131 132 /** 133 * Hash of the salted donor tax id, if relevant. 134 */ 135 struct DONAU_HashDonorTaxId h_donor_tax_id; 136 137 /** 138 * Array of donation receipts; 139 */ 140 struct DONAU_DonationReceipt *receipts; 141 142 /** 143 * Array of hashed udis. 144 */ 145 struct DONAU_UniqueDonorIdentifierHashP *h_udis; 146 147 /** 148 * If using the CS approach, we might track how many 149 * asynchronous calls are still pending, etc. 150 */ 151 unsigned int cs_pending; 152 153 /** 154 * Budis Key Pairs json 155 */ 156 json_t *budis_json; 157 }; 158 159 160 /** 161 * Prepares the donau data for the /pay CMD. 162 * 163 * @param is interpreter state 164 * @param ss donau data to prepare 165 */ 166 static enum GNUNET_GenericReturnValue 167 prepare_donau_data (struct TALER_TESTING_Interpreter *is, 168 struct MerchantDonauPayData *ss) 169 { 170 /* Get charity id and the charity private key from trait */ 171 { 172 const struct TALER_TESTING_Command *charity_post_cmd; 173 const uint64_t *charity_id; 174 175 charity_post_cmd = TALER_TESTING_interpreter_lookup_command ( 176 is, 177 ss->charity_reference); 178 179 if (GNUNET_OK != 180 TALER_TESTING_get_trait_charity_id (charity_post_cmd, 181 &charity_id)) 182 { 183 GNUNET_break (0); 184 return GNUNET_SYSERR; 185 } 186 ss->charity_id = (uint64_t) *(charity_id); 187 } 188 189 /* Get donau keys from trait */ 190 { 191 const struct TALER_TESTING_Command *keys_cmd; 192 struct DONAU_Keys *keys; 193 194 keys_cmd = TALER_TESTING_interpreter_get_command (is, 195 "donau"); 196 197 if (GNUNET_OK != 198 TALER_TESTING_get_trait_donau_keys (keys_cmd, 199 &keys)) 200 { 201 GNUNET_break (0); 202 return GNUNET_SYSERR; 203 } 204 ss->keys = keys; 205 } 206 207 /* Get selected_pks + num_bkps*/ 208 { 209 enum GNUNET_GenericReturnValue sret; 210 211 sret = DONAU_select_donation_unit_keys_for_amount ( 212 ss->keys, 213 &ss->donation_amount, 214 ss->year, 215 &ss->selected_pks, 216 &ss->num_bkps); 217 218 if (GNUNET_SYSERR == sret) 219 { 220 GNUNET_break (0); 221 TALER_TESTING_interpreter_fail (is); 222 return GNUNET_SYSERR; 223 } 224 if ((GNUNET_NO == sret) || (0 == ss->num_bkps)) 225 { 226 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 227 "Could not compose exact amount from donation units\n"); 228 TALER_TESTING_interpreter_fail (is); 229 return GNUNET_NO; 230 } 231 } 232 233 /* Get BUDIsKP */ 234 { 235 ss->bkps 236 = GNUNET_new_array (ss->num_bkps, 237 struct DONAU_BlindedUniqueDonorIdentifierKeyPair); 238 ss->blinding_secrets 239 = GNUNET_new_array (ss->num_bkps, 240 union GNUNET_CRYPTO_BlindingSecretP); 241 ss->receipts 242 = GNUNET_new_array (ss->num_bkps, 243 struct DONAU_DonationReceipt); 244 ss->alg_values 245 = GNUNET_new_array (ss->num_bkps, 246 const struct DONAU_BatchIssueValues *); 247 ss->h_udis 248 = GNUNET_new_array (ss->num_bkps, 249 struct DONAU_UniqueDonorIdentifierHashP); 250 251 for (size_t cnt = 0; cnt < ss->num_bkps; cnt++) 252 { 253 struct DONAU_UniqueDonorIdentifierNonce *udi_nonce; 254 struct DONAU_BudiMasterSecretP ps; 255 const struct DONAU_BatchIssueValues *alg_values; 256 struct DONAU_BlindedUniqueDonorIdentifier *blinded_udi; 257 struct DONAU_UniqueDonorIdentifierHashP *udi_hash; 258 259 DONAU_donation_unit_pub_hash (&ss->selected_pks[cnt], 260 &ss->bkps[cnt].h_donation_unit_pub); 261 262 ss->receipts[cnt].h_donation_unit_pub 263 = ss->bkps[cnt].h_donation_unit_pub; 264 udi_nonce 265 = &ss->receipts[cnt].nonce; 266 blinded_udi 267 = &ss->bkps[cnt].blinded_udi; 268 udi_hash = &ss->h_udis[cnt]; 269 270 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, 271 &ps, 272 sizeof (ps)); 273 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, 274 udi_nonce, 275 sizeof (*udi_nonce)); 276 switch (ss->selected_pks[cnt].bsign_pub_key->cipher) 277 { 278 case GNUNET_CRYPTO_BSA_RSA: 279 alg_values = DONAU_donation_unit_ewv_rsa_singleton (); 280 DONAU_budi_secret_create (&ps, 281 alg_values, 282 &ss->blinding_secrets[cnt]); 283 GNUNET_assert (GNUNET_OK == 284 DONAU_donation_unit_blind ( 285 &ss->selected_pks[cnt], 286 &ss->blinding_secrets[cnt], 287 NULL, /* no cs-nonce needed for rsa */ 288 udi_nonce, 289 &ss->h_donor_tax_id, 290 alg_values, 291 udi_hash, 292 blinded_udi)); 293 ss->alg_values[cnt] = alg_values; 294 break; 295 case GNUNET_CRYPTO_BSA_CS: 296 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 297 "CS donation-unit key not yet supported – skip"); 298 return GNUNET_NO; 299 /* FIXME: BUG-#### Cs support missing/broken for donau 300 struct CSR_Data *csr_data = GNUNET_new (struct CSR_Data); 301 TALER_cs_withdraw_nonce_derive ( // FIXME: write new method 302 (struct TALER_PlanchetMasterSecretP *) &ps, 303 &csr_data->nonce.cs_nonce); 304 csr_data->ss = is; 305 csr_data->position = cnt; 306 307 csr_data->csr_handle = DONAU_csr_issue ( 308 TALER_TESTING_interpreter_get_context (is), 309 TALER_TESTING_get_donau_url (is), 310 &ss->selected_pks[cnt], 311 &csr_data->nonce.cs_nonce, 312 &cs_stage_two_callback, 313 csr_data); 314 if (NULL == csr_data->csr_handle) 315 { 316 GNUNET_break (0); 317 } 318 ss->cs_pending++; */ 319 break; 320 default: 321 GNUNET_break (0); 322 } 323 } 324 325 { 326 json_t *budikeypairs = json_array (); 327 328 GNUNET_assert (NULL != budikeypairs); 329 for (size_t i = 0; i < ss->num_bkps; i++) 330 { 331 json_t *budikeypair = GNUNET_JSON_PACK ( 332 GNUNET_JSON_pack_data_auto ("h_donation_unit_pub", 333 &ss->bkps[i].h_donation_unit_pub), 334 DONAU_JSON_pack_blinded_donation_identifier ("blinded_udi", 335 &ss->bkps[i].blinded_udi) 336 ); 337 338 /* steal the reference into the array */ 339 GNUNET_assert (0 == json_array_append_new (budikeypairs, 340 budikeypair)); 341 } 342 ss->budis_json = budikeypairs; 343 } 344 } 345 return GNUNET_OK; 346 }; 347 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 348 349 /** 350 * State for a /pay CMD. 351 */ 352 struct PayState 353 { 354 /** 355 * Contract terms hash code. 356 */ 357 struct TALER_PrivateContractHashP h_contract_terms; 358 359 /** 360 * The interpreter state. 361 */ 362 struct TALER_TESTING_Interpreter *is; 363 364 /** 365 * Expected HTTP response status code. 366 */ 367 unsigned int http_status; 368 369 /** 370 * Reference to a command that can provide a order id, 371 * typically a /proposal test command. 372 */ 373 const char *proposal_reference; 374 375 /** 376 * Reference to a command that can provide a coin, so 377 * we can pay here. 378 */ 379 const char *coin_reference; 380 381 /** 382 * Reference to a command that can provide one or 383 * multiple tokens used as inputs for the payment. 384 * In the form "LABEL0[/INDEX];LABEL1[/INDEX];..." 385 */ 386 const char *token_reference; 387 388 /** 389 * The merchant base URL. 390 */ 391 const char *merchant_url; 392 393 /** 394 * Total amount to be paid. 395 */ 396 struct TALER_Amount total_amount; 397 398 /** 399 * Amount to be paid, plus the deposit fee. 400 */ 401 const char *amount_with_fee; 402 403 /** 404 * Amount to be paid, including NO fees. 405 */ 406 const char *amount_without_fee; 407 408 /** 409 * Handle to the pay operation. 410 */ 411 struct TALER_MERCHANT_OrderPayHandle *oph; 412 413 /** 414 * Signature from the merchant, set on success. 415 */ 416 struct TALER_MerchantSignatureP merchant_sig; 417 418 /** 419 * Array of issued tokens, set on success. 420 */ 421 struct TALER_MERCHANT_PrivateTokenDetails *issued_tokens; 422 423 /** 424 * Number of tokens in @e issued_tokens. 425 */ 426 unsigned int num_issued_tokens; 427 428 /** 429 * Number of donau_tokens in @e issued_tokens. 430 */ 431 unsigned int num_donau_tokens; 432 433 /** 434 * The session for which the payment is made. 435 */ 436 const char *session_id; 437 438 /** 439 * base64-encoded key 440 */ 441 const char *pos_key; 442 443 /** 444 * Option that add amount of the order 445 */ 446 enum TALER_MerchantConfirmationAlgorithm pos_alg; 447 448 /** 449 * Index of the choice to be used in the payment. -1 for orders without choices. 450 */ 451 int choice_index; 452 453 #ifdef HAVE_DONAU_DONAU_SERVICE_H 454 /** 455 * Donau data, if required. 456 */ 457 struct MerchantDonauPayData donau_data; 458 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 459 }; 460 461 462 /** 463 * Find the token issue public key for a given token family @a slug and 464 * @a valid_after timestamp. 465 * 466 * @param token_families json object of token families where the key is the slug 467 * @param slug the slug of the token family 468 * @param key_index index of the key within the token family 469 * @param[out] pub the token issue public key of the token family 470 * @return #GNUNET_OK on success and #GNUNET_SYSERR if not found 471 */ 472 static enum GNUNET_GenericReturnValue 473 find_token_public_key (const json_t *token_families, 474 const char *slug, 475 unsigned int key_index, 476 struct TALER_TokenIssuePublicKey *pub) 477 478 { 479 const json_t *tf = json_object_get (token_families, slug); 480 const json_t *keys; 481 struct GNUNET_JSON_Specification spec[] = { 482 GNUNET_JSON_spec_array_const ("keys", 483 &keys), 484 GNUNET_JSON_spec_end () 485 }; 486 const json_t *key; 487 const char *error_name; 488 unsigned int error_line; 489 struct GNUNET_JSON_Specification ispec[] = { 490 TALER_JSON_spec_token_pub (NULL, 491 pub), 492 GNUNET_JSON_spec_end () 493 }; 494 495 if (NULL == tf) 496 { 497 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 498 "Token family `%s' not found\n", 499 slug); 500 return GNUNET_SYSERR; 501 } 502 if (GNUNET_OK != 503 GNUNET_JSON_parse (tf, 504 spec, 505 NULL, 506 NULL)) 507 { 508 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 509 "Failed to parse token family `%s'\n", 510 slug); 511 return GNUNET_SYSERR; 512 } 513 514 key = json_array_get (keys, 515 key_index); 516 if (NULL == key) 517 { 518 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 519 "Key with index %u for token family '%s' not found\n", 520 key_index, 521 slug); 522 return GNUNET_SYSERR; 523 } 524 if (GNUNET_OK != 525 GNUNET_JSON_parse (key, 526 ispec, 527 &error_name, 528 &error_line)) 529 { 530 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 531 "Failed to parse %s at %u: %s\n", 532 ispec[error_line].field, 533 error_line, 534 error_name); 535 return GNUNET_SYSERR; 536 } 537 return GNUNET_OK; 538 } 539 540 541 /** 542 * Parse the @a coins specification and grow the @a pc 543 * array with the coins found, updating @a npc. 544 * 545 * @param[in,out] pc pointer to array of coins found 546 * @param[in,out] npc length of array at @a pc 547 * @param[in] coins string specifying coins to add to @a pc, 548 * clobbered in the process 549 * @param is interpreter state 550 * @param amount_with_fee total amount to be paid for a contract. 551 * @param amount_without_fee to be removed, there is no 552 * per-contract fee, only per-coin exists. 553 * @return #GNUNET_OK on success 554 */ 555 static enum GNUNET_GenericReturnValue 556 build_coins (struct TALER_MERCHANT_PayCoin **pc, 557 unsigned int *npc, 558 char *coins, 559 struct TALER_TESTING_Interpreter *is, 560 const char *amount_with_fee, 561 const char *amount_without_fee) 562 { 563 char *token; 564 struct TALER_EXCHANGE_Keys *keys; 565 566 keys = TALER_TESTING_get_keys (is); 567 if (NULL == keys) 568 { 569 GNUNET_break (0); 570 return GNUNET_SYSERR; 571 } 572 573 for (token = strtok (coins, ";"); 574 NULL != token; 575 token = strtok (NULL, ";")) 576 { 577 const struct TALER_TESTING_Command *coin_cmd; 578 char *ctok; 579 unsigned int ci; 580 struct TALER_MERCHANT_PayCoin *icoin; 581 const struct TALER_EXCHANGE_DenomPublicKey *dpk; 582 const char *exchange_url; 583 584 /* Token syntax is "LABEL[/NUMBER]" */ 585 ctok = strchr (token, '/'); 586 /* FIXME: Check why ci variable is parsed but not used? */ 587 ci = 0; 588 if (NULL != ctok) 589 { 590 *ctok = '\0'; 591 ctok++; 592 if (1 != sscanf (ctok, 593 "%u", 594 &ci)) 595 { 596 GNUNET_break (0); 597 return GNUNET_SYSERR; 598 } 599 } 600 601 coin_cmd = TALER_TESTING_interpreter_lookup_command 602 (is, token); 603 604 if (NULL == coin_cmd) 605 { 606 GNUNET_break (0); 607 return GNUNET_SYSERR; 608 } 609 610 GNUNET_array_grow (*pc, 611 *npc, 612 (*npc) + 1); 613 614 icoin = &((*pc)[(*npc) - 1]); 615 616 { 617 const struct TALER_CoinSpendPrivateKeyP *coin_priv; 618 const struct TALER_DenominationSignature *denom_sig; 619 const struct TALER_Amount *denom_value; 620 const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; 621 const struct TALER_AgeCommitmentHashP *h_age_commitment; 622 623 GNUNET_assert (GNUNET_OK == 624 TALER_TESTING_get_trait_coin_priv (coin_cmd, 625 0, 626 &coin_priv)); 627 GNUNET_assert (GNUNET_OK == 628 TALER_TESTING_get_trait_denom_pub (coin_cmd, 629 0, 630 &denom_pub)); 631 GNUNET_assert (GNUNET_OK == 632 TALER_TESTING_get_trait_denom_sig (coin_cmd, 633 0, 634 &denom_sig)); 635 GNUNET_assert (GNUNET_OK == 636 TALER_TESTING_get_trait_amount (coin_cmd, 637 &denom_value)); 638 GNUNET_assert (GNUNET_OK == 639 TALER_TESTING_get_trait_h_age_commitment (coin_cmd, 640 0, 641 &h_age_commitment 642 )); 643 icoin->coin_priv = *coin_priv; 644 icoin->denom_pub = denom_pub->key; 645 icoin->denom_sig = *denom_sig; 646 icoin->denom_value = *denom_value; 647 icoin->amount_with_fee = *denom_value; 648 icoin->h_age_commitment = h_age_commitment; 649 } 650 GNUNET_assert (NULL != (dpk = 651 TALER_TESTING_find_pk (keys, 652 &icoin->denom_value, 653 false))); 654 655 GNUNET_assert (0 <= 656 TALER_amount_subtract (&icoin->amount_without_fee, 657 &icoin->denom_value, 658 &dpk->fees.deposit)); 659 GNUNET_assert (GNUNET_OK == 660 TALER_TESTING_get_trait_exchange_url (coin_cmd, 661 &exchange_url)); 662 icoin->exchange_url = exchange_url; 663 } 664 665 return GNUNET_OK; 666 } 667 668 669 /** 670 * Parse the @a pay_references specification and grow the @a tokens 671 * array with the tokens found, updating @a tokens_num. 672 * 673 * @param[in,out] tokens array of tokens found 674 * @param[in,out] tokens_num length of @a tokens array 675 * @param[in] pay_references string of ; separated references to pay commands 676 that issued the tokens. 677 * @param is interpreter state 678 * @return #GNUNET_OK on success 679 */ 680 static enum GNUNET_GenericReturnValue 681 build_tokens (struct TALER_MERCHANT_UseToken **tokens, 682 unsigned int *tokens_num, 683 char *pay_references, 684 struct TALER_TESTING_Interpreter *is) 685 { 686 char *ref; 687 688 for (ref = strtok (pay_references, ";"); 689 NULL != ref; 690 ref = strtok (NULL, ";")) 691 { 692 const struct TALER_TESTING_Command *pay_cmd; 693 char *slash; 694 unsigned int index; 695 struct TALER_MERCHANT_UseToken *token; 696 697 /* Reference syntax is "LABEL[/NUMBER]" */ 698 slash = strchr (ref, '/'); 699 index = 0; 700 if (NULL != slash) 701 { 702 *slash = '\0'; 703 slash++; 704 if (1 != sscanf (slash, 705 "%u", 706 &index)) 707 { 708 GNUNET_break (0); 709 return GNUNET_SYSERR; 710 } 711 } 712 713 pay_cmd = TALER_TESTING_interpreter_lookup_command (is, ref); 714 715 if (NULL == pay_cmd) 716 { 717 GNUNET_break (0); 718 return GNUNET_SYSERR; 719 } 720 721 GNUNET_array_grow (*tokens, 722 *tokens_num, 723 (*tokens_num) + 1); 724 725 token = &((*tokens)[(*tokens_num) - 1]); 726 727 { 728 const struct TALER_TokenUsePrivateKeyP *token_priv; 729 const struct TALER_TokenIssueSignature *issue_sig; 730 const struct TALER_TokenIssuePublicKey *issue_pub; 731 732 GNUNET_assert (GNUNET_OK == 733 TALER_TESTING_get_trait_token_priv (pay_cmd, 734 index, 735 &token_priv)); 736 737 GNUNET_assert (GNUNET_OK == 738 TALER_TESTING_get_trait_token_issue_sig (pay_cmd, 739 index, 740 &issue_sig)); 741 742 GNUNET_assert (GNUNET_OK == 743 TALER_TESTING_get_trait_token_issue_pub (pay_cmd, 744 index, 745 &issue_pub)); 746 747 token->token_priv = *token_priv; 748 token->ub_sig = *issue_sig; 749 token->issue_pub = *issue_pub; 750 } 751 } 752 753 return GNUNET_OK; 754 } 755 756 757 /** 758 * Function called with the result of a /pay operation. 759 * Checks whether the merchant signature is valid and the 760 * HTTP response code matches our expectation. 761 * 762 * @param cls closure with the interpreter state 763 * @param pr HTTP response 764 */ 765 static void 766 pay_cb (void *cls, 767 const struct TALER_MERCHANT_PayResponse *pr) 768 { 769 struct PayState *ps = cls; 770 771 ps->oph = NULL; 772 if (ps->http_status != pr->hr.http_status) 773 { 774 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 775 "Unexpected response code %u (%d) to command (%s) %s\n", 776 pr->hr.http_status, 777 (int) pr->hr.ec, 778 pr->hr.hint, 779 TALER_TESTING_interpreter_get_current_label (ps->is)); 780 TALER_TESTING_FAIL (ps->is); 781 } 782 if (MHD_HTTP_OK == pr->hr.http_status) 783 { 784 ps->merchant_sig = pr->details.ok.merchant_sig; 785 if (ps->num_issued_tokens + ps->num_donau_tokens != 786 pr->details.ok.num_tokens) 787 { 788 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 789 "Unexpected number of tokens issued. " 790 "Sent %d envelopes but got %d tokens issued.\n", 791 ps->num_issued_tokens, 792 pr->details.ok.num_tokens); 793 GNUNET_break (0); 794 TALER_TESTING_interpreter_fail (ps->is); 795 return; 796 } 797 for (unsigned int i = 0; i < ps->num_issued_tokens; i++) 798 { 799 struct TALER_MERCHANT_PrivateTokenDetails *details = 800 &ps->issued_tokens[i]; 801 802 /* The issued tokens should be in the 803 same order as the provided envelopes. */ 804 ps->issued_tokens[i].blinded_sig = pr->details.ok.tokens[i].blinded_sig; 805 806 if (GNUNET_OK != 807 TALER_token_issue_sig_unblind (&details->issue_sig, 808 &details->blinded_sig, 809 &details->blinding_secret, 810 &details->h_token_pub, 811 &details->blinding_inputs, 812 &details->issue_pub)) 813 { 814 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 815 "Failed to unblind token signature\n"); 816 GNUNET_break (0); 817 TALER_TESTING_interpreter_fail (ps->is); 818 return; 819 } 820 } 821 if (NULL != ps->pos_key) 822 { 823 char *pc; 824 bool found = false; 825 826 if (NULL == pr->details.ok.pos_confirmation) 827 { 828 GNUNET_break (0); 829 TALER_TESTING_interpreter_fail (ps->is); 830 return; 831 } 832 pc = TALER_build_pos_confirmation (ps->pos_key, 833 ps->pos_alg, 834 &ps->total_amount, 835 GNUNET_TIME_timestamp_get ()); 836 /* Check if *any* of our TOTP codes overlaps 837 with any of the returned TOTP codes. */ 838 for (const char *tok = strtok (pc, "\n"); 839 NULL != tok; 840 tok = strtok (NULL, "\n")) 841 { 842 if (NULL != strstr (pr->details.ok.pos_confirmation, 843 tok)) 844 { 845 found = true; 846 break; 847 } 848 } 849 GNUNET_free (pc); 850 if (! found) 851 { 852 GNUNET_break (0); 853 TALER_TESTING_interpreter_fail (ps->is); 854 return; 855 } 856 } 857 } 858 TALER_TESTING_interpreter_next (ps->is); 859 } 860 861 862 /** 863 * Run a "pay" CMD. 864 * 865 * @param cls closure. 866 * @param cmd current CMD being run. 867 * @param is interpreter state. 868 */ 869 static void 870 pay_run (void *cls, 871 const struct TALER_TESTING_Command *cmd, 872 struct TALER_TESTING_Interpreter *is) 873 { 874 struct PayState *ps = cls; 875 const struct TALER_TESTING_Command *proposal_cmd; 876 const json_t *contract_terms; 877 const char *order_id; 878 struct GNUNET_TIME_Timestamp refund_deadline; 879 struct GNUNET_TIME_Timestamp pay_deadline; 880 struct GNUNET_TIME_Timestamp timestamp; 881 struct TALER_MerchantPublicKeyP merchant_pub; 882 struct TALER_MerchantWireHashP h_wire; 883 const struct TALER_PrivateContractHashP *h_proposal; 884 struct TALER_Amount max_fee; 885 const char *error_name = NULL; 886 unsigned int error_line = 0; 887 struct TALER_MERCHANT_PayCoin *pay_coins; 888 unsigned int npay_coins; 889 struct TALER_MERCHANT_UseToken *use_tokens = NULL; 890 unsigned int len_use_tokens = 0; 891 struct TALER_MERCHANT_OutputToken *output_tokens = NULL; 892 unsigned int len_output_tokens = 0; 893 const struct TALER_MerchantSignatureP *merchant_sig; 894 const enum TALER_MerchantConfirmationAlgorithm *alg_ptr; 895 896 ps->is = is; 897 proposal_cmd = TALER_TESTING_interpreter_lookup_command ( 898 is, 899 ps->proposal_reference); 900 901 if (NULL == proposal_cmd) 902 TALER_TESTING_FAIL (is); 903 904 if (GNUNET_OK != 905 TALER_TESTING_get_trait_contract_terms (proposal_cmd, 906 &contract_terms)) 907 TALER_TESTING_FAIL (is); 908 if (NULL == contract_terms) 909 TALER_TESTING_FAIL (is); 910 if (GNUNET_OK != 911 TALER_TESTING_get_trait_otp_key (proposal_cmd, 912 &ps->pos_key)) 913 ps->pos_key = NULL; 914 if ( (GNUNET_OK == 915 TALER_TESTING_get_trait_otp_alg (proposal_cmd, 916 &alg_ptr)) && 917 (NULL != alg_ptr) ) 918 ps->pos_alg = *alg_ptr; 919 { 920 /* Get information that needs to be put verbatim in the 921 * deposit permission */ 922 uint64_t version = 0; 923 struct GNUNET_JSON_Specification spec[] = { 924 GNUNET_JSON_spec_mark_optional ( 925 GNUNET_JSON_spec_uint64 ("version", 926 &version), 927 NULL), 928 GNUNET_JSON_spec_string ("order_id", 929 &order_id), 930 GNUNET_JSON_spec_timestamp ("refund_deadline", 931 &refund_deadline), 932 GNUNET_JSON_spec_timestamp ("pay_deadline", 933 &pay_deadline), 934 GNUNET_JSON_spec_timestamp ("timestamp", 935 ×tamp), 936 GNUNET_JSON_spec_fixed_auto ("merchant_pub", 937 &merchant_pub), 938 GNUNET_JSON_spec_fixed_auto ("h_wire", 939 &h_wire), 940 /* FIXME oec: parse minimum age, use data later? */ 941 GNUNET_JSON_spec_end () 942 }; 943 944 if (GNUNET_OK != 945 GNUNET_JSON_parse (contract_terms, 946 spec, 947 &error_name, 948 &error_line)) 949 { 950 char *js; 951 952 js = json_dumps (contract_terms, 953 JSON_INDENT (1)); 954 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 955 "Parser failed on %s:%u for input `%s'\n", 956 error_name, 957 error_line, 958 js); 959 free (js); 960 TALER_TESTING_FAIL (is); 961 } 962 switch (version) 963 { 964 case 0: 965 { 966 struct GNUNET_JSON_Specification v0spec[] = { 967 TALER_JSON_spec_amount_any ("amount", 968 &ps->total_amount), 969 TALER_JSON_spec_amount_any ("max_fee", 970 &max_fee), 971 GNUNET_JSON_spec_end () 972 }; 973 974 if (GNUNET_OK != 975 GNUNET_JSON_parse (contract_terms, 976 v0spec, 977 &error_name, 978 &error_line)) 979 { 980 char *js; 981 982 js = json_dumps (contract_terms, 983 JSON_INDENT (1)); 984 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 985 "Parser failed on %s:%u for input `%s'\n", 986 error_name, 987 error_line, 988 js); 989 free (js); 990 TALER_TESTING_FAIL (is); 991 } 992 } 993 if (0 < ps->choice_index) 994 TALER_TESTING_FAIL (is); 995 break; 996 case 1: 997 { 998 const json_t *choices; 999 const json_t *token_families; 1000 struct GNUNET_JSON_Specification v1spec[] = { 1001 GNUNET_JSON_spec_object_const ("token_families", 1002 &token_families), 1003 GNUNET_JSON_spec_array_const ("choices", 1004 &choices), 1005 GNUNET_JSON_spec_end () 1006 }; 1007 const json_t *outputs; 1008 json_t *output; 1009 unsigned int output_index; 1010 const json_t *choice; 1011 1012 if (GNUNET_OK != 1013 GNUNET_JSON_parse (contract_terms, 1014 v1spec, 1015 &error_name, 1016 &error_line)) 1017 { 1018 char *js; 1019 1020 js = json_dumps (contract_terms, 1021 JSON_INDENT (1)); 1022 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1023 "Parser failed on %s:%u for input `%s'\n", 1024 error_name, 1025 error_line, 1026 js); 1027 free (js); 1028 TALER_TESTING_FAIL (is); 1029 } 1030 1031 choice = json_array_get (choices, 1032 ps->choice_index); 1033 if (NULL == choice) 1034 { 1035 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1036 "No choice found at index %d\n", 1037 ps->choice_index); 1038 TALER_TESTING_FAIL (is); 1039 } 1040 1041 { 1042 const char *ierror_name = NULL; 1043 unsigned int ierror_line = 0; 1044 1045 struct GNUNET_JSON_Specification ispec[] = { 1046 TALER_JSON_spec_amount_any ("amount", 1047 &ps->total_amount), 1048 TALER_JSON_spec_amount_any ("max_fee", 1049 &max_fee), 1050 GNUNET_JSON_spec_array_const ("outputs", 1051 &outputs), 1052 GNUNET_JSON_spec_end () 1053 }; 1054 1055 if (GNUNET_OK != 1056 GNUNET_JSON_parse (choice, 1057 ispec, 1058 &ierror_name, 1059 &ierror_line)) 1060 { 1061 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1062 "Parser failed on %s:%u for input `%s'\n", 1063 ierror_name, 1064 ierror_line, 1065 json_dumps (choice, 1066 JSON_INDENT (2))); 1067 TALER_TESTING_FAIL (is); 1068 } 1069 } 1070 1071 json_array_foreach (outputs, output_index, output) 1072 { 1073 const char *slug; 1074 const char *kind; 1075 uint32_t key_index; 1076 uint32_t count = 1; 1077 const char *ierror_name = NULL; 1078 unsigned int ierror_line = 0; 1079 1080 struct GNUNET_JSON_Specification typespec[] = { 1081 GNUNET_JSON_spec_string ("type", 1082 &kind), 1083 GNUNET_JSON_spec_end () 1084 }; 1085 1086 if (GNUNET_OK != 1087 GNUNET_JSON_parse (output, 1088 typespec, 1089 &ierror_name, 1090 &ierror_line)) 1091 { 1092 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1093 "Parser failed on %s:%u for input `%s'\n", 1094 ierror_name, 1095 ierror_line, 1096 json_dumps (output, 1097 JSON_INDENT (2))); 1098 TALER_TESTING_FAIL (is); 1099 } 1100 1101 if (0 == strcmp ("tax-receipt", 1102 kind)) 1103 { 1104 const json_t *donau_urls; 1105 1106 // For test, we care only about the presence of it 1107 struct GNUNET_JSON_Specification donauspec[] = { 1108 GNUNET_JSON_spec_array_const ("donau_urls", 1109 &donau_urls), 1110 GNUNET_JSON_spec_end () 1111 }; 1112 1113 if (GNUNET_OK != 1114 GNUNET_JSON_parse (output, 1115 donauspec, 1116 &ierror_name, 1117 &ierror_line)) 1118 { 1119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1120 "Parser failed on %s:%u for input `%s'\n", 1121 ierror_name, 1122 ierror_line, 1123 json_dumps (output, 1124 JSON_INDENT (2))); 1125 TALER_TESTING_FAIL (is); 1126 } 1127 1128 #ifdef HAVE_DONAU_DONAU_SERVICE_H 1129 { 1130 const char *donau_url_str; 1131 1132 if ( (NULL == donau_urls) || 1133 (0 == json_array_size (donau_urls)) ) 1134 { 1135 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1136 "No donau_urls found in output\n"); 1137 TALER_TESTING_FAIL (is); 1138 } 1139 1140 donau_url_str = json_string_value (json_array_get (donau_urls, 1141 0)); 1142 if (NULL == donau_url_str) 1143 { 1144 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1145 "First entry in donau_urls is not a string\n"); 1146 TALER_TESTING_FAIL (is); 1147 } 1148 1149 ps->donau_data.donau_url = GNUNET_strdup (donau_url_str); 1150 1151 if (NULL != ps->donau_data.charity_reference) 1152 { 1153 switch (prepare_donau_data (is, 1154 &ps->donau_data)) 1155 { 1156 case GNUNET_OK: 1157 break; 1158 case GNUNET_NO: 1159 TALER_TESTING_interpreter_next (ps->is); 1160 return; 1161 case GNUNET_SYSERR: 1162 TALER_TESTING_FAIL (is); 1163 return; 1164 } 1165 ps->num_donau_tokens = ps->donau_data.num_bkps; 1166 } 1167 } 1168 #else /* HAVE_DONAU_DONAU_SERVICE_H */ 1169 /* SIMPLY NOTHING */ 1170 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 1171 } 1172 1173 if (0 == strcmp ("token", 1174 kind)) 1175 { 1176 struct GNUNET_JSON_Specification ispec[] = { 1177 GNUNET_JSON_spec_string ("token_family_slug", 1178 &slug), 1179 GNUNET_JSON_spec_uint32 ("key_index", 1180 &key_index), 1181 GNUNET_JSON_spec_mark_optional ( 1182 GNUNET_JSON_spec_uint32 ("count", 1183 &count), 1184 NULL), 1185 GNUNET_JSON_spec_end () 1186 }; 1187 1188 if (GNUNET_OK != 1189 GNUNET_JSON_parse (output, 1190 ispec, 1191 &ierror_name, 1192 &ierror_line)) 1193 { 1194 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1195 "Parser failed on %s:%u for input `%s'\n", 1196 ierror_name, 1197 ierror_line, 1198 json_dumps (output, 1199 JSON_INDENT (2))); 1200 TALER_TESTING_FAIL (is); 1201 } 1202 1203 if (0 != strcmp ("token", 1204 kind)) 1205 { 1206 continue; 1207 } 1208 1209 GNUNET_array_grow ( 1210 ps->issued_tokens, 1211 ps->num_issued_tokens, 1212 ps->num_issued_tokens + count + ps->num_donau_tokens); 1213 1214 for (unsigned int k = 0; k < count; k++) 1215 { 1216 struct TALER_MERCHANT_PrivateTokenDetails *details = 1217 &ps->issued_tokens[ps->num_issued_tokens - count + k 1218 + ps->num_donau_tokens]; 1219 1220 if (GNUNET_OK != 1221 find_token_public_key (token_families, 1222 slug, 1223 key_index, 1224 &details->issue_pub)) 1225 { 1226 TALER_TESTING_FAIL (is); 1227 } 1228 1229 /* Only RSA is supported for now. */ 1230 GNUNET_assert (GNUNET_CRYPTO_BSA_RSA == 1231 details->issue_pub.public_key->cipher); 1232 1233 TALER_token_blind_input_copy (&details->blinding_inputs, 1234 TALER_token_blind_input_rsa_singleton () 1235 ); 1236 /* FIXME: Where to get details->blinding_inputs from? */ 1237 TALER_token_use_setup_random (&details->master); 1238 TALER_token_use_setup_priv (&details->master, 1239 &details->blinding_inputs, 1240 &details->token_priv); 1241 TALER_token_use_blinding_secret_create (&details->master, 1242 &details->blinding_inputs, 1243 &details->blinding_secret) 1244 ; 1245 GNUNET_CRYPTO_eddsa_key_get_public ( 1246 &details->token_priv.private_key, 1247 &details->token_pub.public_key); 1248 GNUNET_CRYPTO_hash (&details->token_pub.public_key, 1249 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), 1250 &details->h_token_pub.hash); 1251 details->envelope.blinded_pub = 1252 GNUNET_CRYPTO_message_blind_to_sign 1253 ( 1254 details->issue_pub.public_key, 1255 &details->blinding_secret, 1256 NULL, /* FIXME: Add session nonce to support CS tokens */ 1257 &details->h_token_pub.hash, 1258 sizeof (details->h_token_pub.hash), 1259 details->blinding_inputs.blinding_inputs); 1260 1261 if (NULL == details->envelope.blinded_pub) 1262 { 1263 GNUNET_break (0); 1264 TALER_TESTING_FAIL (is); 1265 } 1266 } 1267 } 1268 } 1269 } 1270 1271 break; 1272 default: 1273 TALER_TESTING_FAIL (is); 1274 } 1275 } 1276 1277 { 1278 char *cr; 1279 1280 cr = GNUNET_strdup (ps->coin_reference); 1281 pay_coins = NULL; 1282 npay_coins = 0; 1283 if (GNUNET_OK != 1284 build_coins (&pay_coins, 1285 &npay_coins, 1286 cr, 1287 is, 1288 ps->amount_with_fee, 1289 ps->amount_without_fee)) 1290 { 1291 GNUNET_array_grow (pay_coins, 1292 npay_coins, 1293 0); 1294 GNUNET_free (cr); 1295 TALER_TESTING_FAIL (is); 1296 } 1297 GNUNET_free (cr); 1298 } 1299 if (NULL != ps->token_reference) 1300 { 1301 char *tr; 1302 1303 tr = GNUNET_strdup (ps->token_reference); 1304 if (GNUNET_OK != 1305 build_tokens (&use_tokens, 1306 &len_use_tokens, 1307 tr, 1308 is)) 1309 { 1310 GNUNET_array_grow (use_tokens, 1311 len_use_tokens, 1312 0); 1313 GNUNET_free (tr); 1314 TALER_TESTING_FAIL (is); 1315 } 1316 GNUNET_free (tr); 1317 } 1318 1319 GNUNET_array_grow (output_tokens, 1320 len_output_tokens, 1321 ps->num_issued_tokens); 1322 for (unsigned int i = 0; i<len_output_tokens; i++) 1323 { 1324 output_tokens[i].envelope.blinded_pub 1325 = ps->issued_tokens[i].envelope.blinded_pub; 1326 } 1327 1328 if (GNUNET_OK != 1329 TALER_TESTING_get_trait_merchant_sig (proposal_cmd, 1330 &merchant_sig)) 1331 TALER_TESTING_FAIL (is); 1332 1333 if (GNUNET_OK != 1334 TALER_TESTING_get_trait_h_contract_terms (proposal_cmd, 1335 &h_proposal)) 1336 TALER_TESTING_FAIL (is); 1337 ps->h_contract_terms = *h_proposal; 1338 1339 /* New logic of setting pay params */ 1340 { 1341 struct GNUNET_CURL_Context *ctx = 1342 TALER_TESTING_interpreter_get_context (is); 1343 struct TALER_MERCHANT_OrderPayOption opts[32]; 1344 size_t oi = 0; 1345 1346 ps->oph = TALER_MERCHANT_order_pay_create (ctx, 1347 &pay_cb, 1348 ps); 1349 1350 if (NULL == ps->oph) 1351 TALER_TESTING_FAIL (is); 1352 1353 #define ADD(_opt) opts[oi++] = (_opt) 1354 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_URL (ps->merchant_url)); 1355 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_ORDER_ID (order_id)); 1356 if (NULL != ps->session_id) 1357 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_SESSION_ID (ps->session_id)); 1358 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_CONTRACT (h_proposal)); 1359 if (ps->choice_index >= 0) 1360 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_CHOICE_INDEX (ps->choice_index)); 1361 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_AMOUNT (&ps->total_amount)); 1362 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MAX_FEE (&max_fee)); 1363 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_PUB (&merchant_pub)); 1364 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TIMESTAMP (timestamp)); 1365 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_REFUND_DEADLINE (refund_deadline)); 1366 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_PAY_DEADLINE (pay_deadline)); 1367 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_WIRE (&h_wire)); 1368 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_COINS (npay_coins, 1369 pay_coins)); 1370 if (len_use_tokens > 0) 1371 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_INPUT_TOKENS (len_use_tokens, 1372 use_tokens)); 1373 if (len_output_tokens > 0) 1374 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_OUTPUT_TOKENS (len_output_tokens, 1375 output_tokens)); 1376 1377 #ifdef HAVE_DONAU_DONAU_SERVICE_H 1378 if (ps->donau_data.charity_reference) 1379 { 1380 ADD ( 1381 TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_URL (ps->donau_data.donau_url)); 1382 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_YEAR (ps->donau_data.year)); 1383 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_BUDIS ( 1384 ps->donau_data.budis_json)); 1385 } 1386 #endif 1387 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ()); 1388 #undef ADD 1389 1390 if (TALER_MERCHANT_OPOEC_OK != 1391 TALER_MERCHANT_order_pay_set_options (ps->oph, 1392 opts, 1393 oi)) 1394 TALER_TESTING_FAIL (is); 1395 1396 if (TALER_MERCHANT_OPOEC_OK != 1397 TALER_MERCHANT_order_pay_start (ps->oph)) 1398 TALER_TESTING_FAIL (is); 1399 } 1400 1401 GNUNET_array_grow (pay_coins, 1402 npay_coins, 1403 0); 1404 1405 GNUNET_array_grow (use_tokens, 1406 len_use_tokens, 1407 0); 1408 1409 GNUNET_array_grow (output_tokens, 1410 len_output_tokens, 1411 0); 1412 } 1413 1414 1415 /** 1416 * Free a "pay" CMD, and cancel it if need be. 1417 * 1418 * @param cls closure. 1419 * @param cmd command currently being freed. 1420 */ 1421 static void 1422 pay_cleanup (void *cls, 1423 const struct TALER_TESTING_Command *cmd) 1424 { 1425 struct PayState *ps = cls; 1426 1427 if (NULL != ps->oph) 1428 { 1429 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1430 "Command `%s' did not complete.\n", 1431 TALER_TESTING_interpreter_get_current_label ( 1432 ps->is)); 1433 TALER_MERCHANT_order_pay_cancel1 (ps->oph); 1434 } 1435 1436 GNUNET_free (ps); 1437 } 1438 1439 1440 /** 1441 * Offer internal data useful to other commands. 1442 * 1443 * @param cls closure 1444 * @param[out] ret result 1445 * @param trait name of the trait 1446 * @param index index number of the object to extract. 1447 * @return #GNUNET_OK on success 1448 */ 1449 static enum GNUNET_GenericReturnValue 1450 pay_traits (void *cls, 1451 const void **ret, 1452 const char *trait, 1453 unsigned int index) 1454 { 1455 1456 struct PayState *ps = cls; 1457 const char *order_id; 1458 const struct TALER_TESTING_Command *proposal_cmd; 1459 const struct TALER_MerchantPublicKeyP *merchant_pub; 1460 1461 if (NULL != ps->token_reference && 1462 index >= ps->num_issued_tokens) 1463 { 1464 GNUNET_break (0); 1465 return GNUNET_NO; 1466 } 1467 1468 if (NULL == 1469 (proposal_cmd = 1470 TALER_TESTING_interpreter_lookup_command (ps->is, 1471 ps->proposal_reference))) 1472 { 1473 GNUNET_break (0); 1474 return GNUNET_SYSERR; 1475 } 1476 1477 if (GNUNET_OK != 1478 TALER_TESTING_get_trait_order_id (proposal_cmd, 1479 &order_id)) 1480 { 1481 GNUNET_break (0); 1482 return GNUNET_SYSERR; 1483 } 1484 1485 if (GNUNET_OK != 1486 TALER_TESTING_get_trait_merchant_pub (proposal_cmd, 1487 &merchant_pub)) 1488 { 1489 GNUNET_break (0); 1490 return GNUNET_SYSERR; 1491 } 1492 { 1493 struct TALER_Amount amount_with_fee; 1494 1495 GNUNET_assert (GNUNET_OK == 1496 TALER_string_to_amount (ps->amount_with_fee, 1497 &amount_with_fee)); 1498 { 1499 struct TALER_TESTING_Trait traits[] = { 1500 TALER_TESTING_make_trait_proposal_reference (ps->proposal_reference), 1501 TALER_TESTING_make_trait_coin_reference (0, 1502 ps->coin_reference), 1503 TALER_TESTING_make_trait_order_id (order_id), 1504 TALER_TESTING_make_trait_merchant_pub (merchant_pub), 1505 TALER_TESTING_make_trait_merchant_sig (&ps->merchant_sig), 1506 TALER_TESTING_make_trait_amount (&amount_with_fee), 1507 TALER_TESTING_make_trait_otp_key (ps->pos_key), 1508 TALER_TESTING_make_trait_otp_alg (&ps->pos_alg), 1509 TALER_TESTING_make_trait_token_priv (index, 1510 &ps->issued_tokens[index]. 1511 token_priv), 1512 TALER_TESTING_make_trait_token_issue_pub (index, 1513 &ps->issued_tokens[index]. 1514 issue_pub), 1515 TALER_TESTING_make_trait_token_issue_sig (index, 1516 &ps->issued_tokens[index]. 1517 issue_sig), 1518 TALER_TESTING_trait_end () 1519 }; 1520 1521 return TALER_TESTING_get_trait (traits, 1522 ret, 1523 trait, 1524 index); 1525 } 1526 } 1527 } 1528 1529 1530 struct TALER_TESTING_Command 1531 TALER_TESTING_cmd_merchant_pay_order_choices ( 1532 const char *label, 1533 const char *merchant_url, 1534 unsigned int http_status, 1535 const char *proposal_reference, 1536 const char *coin_reference, 1537 const char *amount_with_fee, 1538 const char *amount_without_fee, 1539 const char *session_id, 1540 int choice_index, 1541 const char *token_reference) 1542 { 1543 struct PayState *ps; 1544 1545 ps = GNUNET_new (struct PayState); 1546 ps->http_status = http_status; 1547 ps->proposal_reference = proposal_reference; 1548 ps->coin_reference = coin_reference; 1549 ps->merchant_url = merchant_url; 1550 ps->amount_with_fee = amount_with_fee; 1551 ps->amount_without_fee = amount_without_fee; 1552 ps->session_id = session_id; 1553 ps->token_reference = token_reference; 1554 ps->choice_index = choice_index; 1555 { 1556 struct TALER_TESTING_Command cmd = { 1557 .cls = ps, 1558 .label = label, 1559 .run = &pay_run, 1560 .cleanup = &pay_cleanup, 1561 .traits = &pay_traits 1562 }; 1563 1564 return cmd; 1565 } 1566 } 1567 1568 1569 #ifdef HAVE_DONAU_DONAU_SERVICE_H 1570 1571 struct TALER_TESTING_Command 1572 TALER_TESTING_cmd_merchant_pay_order_donau ( 1573 const char *label, 1574 const char *merchant_url, 1575 unsigned int http_status, 1576 const char *proposal_reference, 1577 const char *coin_reference, 1578 const char *amount_with_fee, 1579 const char *amount_without_fee, 1580 const char *amount_donation, 1581 const char *session_id, 1582 int choice_index, 1583 const char *charity_reference, 1584 uint64_t year, 1585 const char *donor_tax_id, 1586 const char *salt) 1587 { 1588 struct PayState *ps; 1589 1590 ps = GNUNET_new (struct PayState); 1591 ps->http_status = http_status; 1592 ps->proposal_reference = proposal_reference; 1593 ps->coin_reference = coin_reference; 1594 ps->merchant_url = merchant_url; 1595 ps->amount_with_fee = amount_with_fee; 1596 ps->amount_without_fee = amount_without_fee; 1597 ps->session_id = session_id; 1598 ps->token_reference = NULL; 1599 ps->choice_index = choice_index; 1600 ps->donau_data.year = year; 1601 ps->donau_data.num_bkps = 5; 1602 ps->donau_data.charity_reference = charity_reference; 1603 if (GNUNET_OK != 1604 TALER_string_to_amount (amount_donation, 1605 &ps->donau_data.donation_amount)) 1606 { 1607 GNUNET_assert (0); 1608 } 1609 1610 /* Compute h_donor_tax_id directly into ps->donau_data: */ 1611 if (! DONAU_compute_salted_tax_id_hash (donor_tax_id, 1612 salt, 1613 ps->donau_data.h_donor_tax_id.hash)) 1614 { 1615 GNUNET_assert (0); 1616 } 1617 1618 { 1619 struct TALER_TESTING_Command cmd = { 1620 .cls = ps, 1621 .label = label, 1622 .run = &pay_run, 1623 .cleanup = &pay_cleanup, 1624 .traits = &pay_traits 1625 }; 1626 1627 return cmd; 1628 } 1629 } 1630 1631 1632 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 1633 1634 1635 struct TALER_TESTING_Command 1636 TALER_TESTING_cmd_merchant_pay_order ( 1637 const char *label, 1638 const char *merchant_url, 1639 unsigned int http_status, 1640 const char *proposal_reference, 1641 const char *coin_reference, 1642 const char *amount_with_fee, 1643 const char *amount_without_fee, 1644 const char *session_id) 1645 { 1646 return TALER_TESTING_cmd_merchant_pay_order_choices ( 1647 label, 1648 merchant_url, 1649 http_status, 1650 proposal_reference, 1651 coin_reference, 1652 amount_with_fee, 1653 amount_without_fee, 1654 session_id, 1655 -1, 1656 NULL); 1657 } 1658 1659 1660 /* end of testing_api_cmd_pay_order.c */