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