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