testing_api_cmd_pay_order.c (51581B)
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_pay_service.h" 37 #include "taler/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 /** 351 * All the details about a token that are generated during issuance and 352 * that may be needed for future operations on the coin. 353 */ 354 struct TALER_MERCHANT_PrivateTokenDetails 355 { 356 357 /** 358 * Master secret used to derive the private key from. 359 */ 360 struct TALER_TokenUseMasterSecretP master; 361 362 /** 363 * Private key of the token. 364 */ 365 struct TALER_TokenUsePrivateKeyP token_priv; 366 367 /** 368 * Public key of the token. 369 */ 370 struct TALER_TokenUsePublicKeyP token_pub; 371 372 /** 373 * Public key of the token. 374 */ 375 struct TALER_TokenUsePublicKeyHashP h_token_pub; 376 377 /** 378 * Blinded public key of the token. 379 */ 380 struct TALER_TokenEnvelope envelope; 381 382 /** 383 * Value used to blind the key for the signature. 384 */ 385 union GNUNET_CRYPTO_BlindingSecretP blinding_secret; 386 387 /** 388 * Inputs needed from the merchant for blind signing. 389 */ 390 struct TALER_TokenUseMerchantValues blinding_inputs; 391 392 /** 393 * Token issue public key. 394 */ 395 struct TALER_TokenIssuePublicKey issue_pub; 396 397 /** 398 * Unblinded token issue signature made by the merchant. 399 */ 400 struct TALER_TokenIssueSignature issue_sig; 401 402 /** 403 * Blinded token issue signature made by the merchant. 404 */ 405 struct TALER_BlindedTokenIssueSignature blinded_sig; 406 407 }; 408 409 410 /** 411 * State for a /pay CMD. 412 */ 413 struct PayState 414 { 415 /** 416 * Contract terms hash code. 417 */ 418 struct TALER_PrivateContractHashP h_contract_terms; 419 420 /** 421 * The interpreter state. 422 */ 423 struct TALER_TESTING_Interpreter *is; 424 425 /** 426 * Expected HTTP response status code. 427 */ 428 unsigned int http_status; 429 430 /** 431 * Reference to a command that can provide a order id, 432 * typically a /proposal test command. 433 */ 434 const char *proposal_reference; 435 436 /** 437 * Reference to a command that can provide a coin, so 438 * we can pay here. 439 */ 440 const char *coin_reference; 441 442 /** 443 * Reference to a command that can provide one or 444 * multiple tokens used as inputs for the payment. 445 * In the form "LABEL0[/INDEX];LABEL1[/INDEX];..." 446 */ 447 const char *token_reference; 448 449 /** 450 * The merchant base URL. 451 */ 452 const char *merchant_url; 453 454 /** 455 * Total amount to be paid. 456 */ 457 struct TALER_Amount total_amount; 458 459 /** 460 * Amount to be paid, plus the deposit fee. 461 */ 462 const char *amount_with_fee; 463 464 /** 465 * Amount to be paid, including NO fees. 466 */ 467 const char *amount_without_fee; 468 469 /** 470 * Handle to the pay operation. 471 */ 472 struct TALER_MERCHANT_OrderPayHandle *oph; 473 474 /** 475 * Signature from the merchant, set on success. 476 */ 477 struct TALER_MerchantSignatureP merchant_sig; 478 479 /** 480 * Array of issued tokens, set on success. 481 */ 482 struct TALER_MERCHANT_PrivateTokenDetails *issued_tokens; 483 484 /** 485 * Number of tokens in @e issued_tokens. 486 */ 487 unsigned int num_issued_tokens; 488 489 /** 490 * Number of donau_tokens in @e issued_tokens. 491 */ 492 unsigned int num_donau_tokens; 493 494 /** 495 * The session for which the payment is made. 496 */ 497 const char *session_id; 498 499 /** 500 * base64-encoded key 501 */ 502 const char *pos_key; 503 504 /** 505 * Option that add amount of the order 506 */ 507 enum TALER_MerchantConfirmationAlgorithm pos_alg; 508 509 /** 510 * Index of the choice to be used in the payment. -1 for orders without choices. 511 */ 512 int choice_index; 513 514 #ifdef HAVE_DONAU_DONAU_SERVICE_H 515 /** 516 * Donau data, if required. 517 */ 518 struct MerchantDonauPayData donau_data; 519 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 520 }; 521 522 523 /** 524 * Find the token issue public key for a given token family @a slug and 525 * @a valid_after timestamp. 526 * 527 * @param token_families json object of token families where the key is the slug 528 * @param slug the slug of the token family 529 * @param key_index index of the key within the token family 530 * @param[out] pub the token issue public key of the token family 531 * @return #GNUNET_OK on success and #GNUNET_SYSERR if not found 532 */ 533 static enum GNUNET_GenericReturnValue 534 find_token_public_key (const json_t *token_families, 535 const char *slug, 536 unsigned int key_index, 537 struct TALER_TokenIssuePublicKey *pub) 538 539 { 540 const json_t *tf = json_object_get (token_families, slug); 541 const json_t *keys; 542 struct GNUNET_JSON_Specification spec[] = { 543 GNUNET_JSON_spec_array_const ("keys", 544 &keys), 545 GNUNET_JSON_spec_end () 546 }; 547 const json_t *key; 548 const char *error_name; 549 unsigned int error_line; 550 struct GNUNET_JSON_Specification ispec[] = { 551 TALER_JSON_spec_token_pub (NULL, 552 pub), 553 GNUNET_JSON_spec_end () 554 }; 555 556 if (NULL == tf) 557 { 558 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 559 "Token family `%s' not found\n", 560 slug); 561 return GNUNET_SYSERR; 562 } 563 if (GNUNET_OK != 564 GNUNET_JSON_parse (tf, 565 spec, 566 NULL, 567 NULL)) 568 { 569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 570 "Failed to parse token family `%s'\n", 571 slug); 572 return GNUNET_SYSERR; 573 } 574 575 key = json_array_get (keys, 576 key_index); 577 if (NULL == key) 578 { 579 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 580 "Key with index %u for token family '%s' not found\n", 581 key_index, 582 slug); 583 return GNUNET_SYSERR; 584 } 585 if (GNUNET_OK != 586 GNUNET_JSON_parse (key, 587 ispec, 588 &error_name, 589 &error_line)) 590 { 591 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 592 "Failed to parse %s at %u: %s\n", 593 ispec[error_line].field, 594 error_line, 595 error_name); 596 return GNUNET_SYSERR; 597 } 598 return GNUNET_OK; 599 } 600 601 602 /** 603 * Parse the @a coins specification and grow the @a pc 604 * array with the coins found, updating @a npc. 605 * 606 * @param[in,out] pc pointer to array of coins found 607 * @param[in,out] npc length of array at @a pc 608 * @param[in] coins string specifying coins to add to @a pc, 609 * clobbered in the process 610 * @param is interpreter state 611 * @param amount_with_fee total amount to be paid for a contract. 612 * @param amount_without_fee to be removed, there is no 613 * per-contract fee, only per-coin exists. 614 * @return #GNUNET_OK on success 615 */ 616 static enum GNUNET_GenericReturnValue 617 build_coins (struct TALER_MERCHANT_PayCoin **pc, 618 unsigned int *npc, 619 char *coins, 620 struct TALER_TESTING_Interpreter *is, 621 const char *amount_with_fee, 622 const char *amount_without_fee) 623 { 624 char *token; 625 struct TALER_EXCHANGE_Keys *keys; 626 627 keys = TALER_TESTING_get_keys (is); 628 if (NULL == keys) 629 { 630 GNUNET_break (0); 631 return GNUNET_SYSERR; 632 } 633 634 for (token = strtok (coins, ";"); 635 NULL != token; 636 token = strtok (NULL, ";")) 637 { 638 const struct TALER_TESTING_Command *coin_cmd; 639 char *ctok; 640 unsigned int ci; 641 struct TALER_MERCHANT_PayCoin *icoin; 642 const struct TALER_EXCHANGE_DenomPublicKey *dpk; 643 const char *exchange_url; 644 645 /* Token syntax is "LABEL[/NUMBER]" */ 646 ctok = strchr (token, '/'); 647 /* FIXME: Check why ci variable is parsed but not used? */ 648 ci = 0; 649 if (NULL != ctok) 650 { 651 *ctok = '\0'; 652 ctok++; 653 if (1 != sscanf (ctok, 654 "%u", 655 &ci)) 656 { 657 GNUNET_break (0); 658 return GNUNET_SYSERR; 659 } 660 } 661 662 coin_cmd = TALER_TESTING_interpreter_lookup_command 663 (is, token); 664 665 if (NULL == coin_cmd) 666 { 667 GNUNET_break (0); 668 return GNUNET_SYSERR; 669 } 670 671 GNUNET_array_grow (*pc, 672 *npc, 673 (*npc) + 1); 674 675 icoin = &((*pc)[(*npc) - 1]); 676 677 { 678 const struct TALER_CoinSpendPrivateKeyP *coin_priv; 679 const struct TALER_DenominationSignature *denom_sig; 680 const struct TALER_Amount *denom_value; 681 const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; 682 const struct TALER_AgeCommitmentHashP *h_age_commitment; 683 684 GNUNET_assert (GNUNET_OK == 685 TALER_TESTING_get_trait_coin_priv (coin_cmd, 686 0, 687 &coin_priv)); 688 GNUNET_assert (GNUNET_OK == 689 TALER_TESTING_get_trait_denom_pub (coin_cmd, 690 0, 691 &denom_pub)); 692 GNUNET_assert (GNUNET_OK == 693 TALER_TESTING_get_trait_denom_sig (coin_cmd, 694 0, 695 &denom_sig)); 696 GNUNET_assert (GNUNET_OK == 697 TALER_TESTING_get_trait_amount (coin_cmd, 698 &denom_value)); 699 GNUNET_assert (GNUNET_OK == 700 TALER_TESTING_get_trait_h_age_commitment (coin_cmd, 701 0, 702 &h_age_commitment 703 )); 704 icoin->coin_priv = *coin_priv; 705 icoin->denom_pub = denom_pub->key; 706 icoin->denom_sig = *denom_sig; 707 icoin->denom_value = *denom_value; 708 icoin->amount_with_fee = *denom_value; 709 icoin->h_age_commitment = h_age_commitment; 710 } 711 GNUNET_assert (NULL != (dpk = 712 TALER_TESTING_find_pk (keys, 713 &icoin->denom_value, 714 false))); 715 716 GNUNET_assert (0 <= 717 TALER_amount_subtract (&icoin->amount_without_fee, 718 &icoin->denom_value, 719 &dpk->fees.deposit)); 720 GNUNET_assert (GNUNET_OK == 721 TALER_TESTING_get_trait_exchange_url (coin_cmd, 722 &exchange_url)); 723 icoin->exchange_url = exchange_url; 724 } 725 726 return GNUNET_OK; 727 } 728 729 730 /** 731 * Parse the @a pay_references specification and grow the @a tokens 732 * array with the tokens found, updating @a tokens_num. 733 * 734 * @param[in,out] tokens array of tokens found 735 * @param[in,out] tokens_num length of @a tokens array 736 * @param[in] pay_references string of ; separated references to pay commands 737 that issued the tokens. 738 * @param is interpreter state 739 * @return #GNUNET_OK on success 740 */ 741 static enum GNUNET_GenericReturnValue 742 build_tokens (struct TALER_MERCHANT_UseToken **tokens, 743 unsigned int *tokens_num, 744 char *pay_references, 745 struct TALER_TESTING_Interpreter *is) 746 { 747 char *ref; 748 749 for (ref = strtok (pay_references, ";"); 750 NULL != ref; 751 ref = strtok (NULL, ";")) 752 { 753 const struct TALER_TESTING_Command *pay_cmd; 754 char *slash; 755 unsigned int index; 756 struct TALER_MERCHANT_UseToken *token; 757 758 /* Reference syntax is "LABEL[/NUMBER]" */ 759 slash = strchr (ref, '/'); 760 index = 0; 761 if (NULL != slash) 762 { 763 *slash = '\0'; 764 slash++; 765 if (1 != sscanf (slash, 766 "%u", 767 &index)) 768 { 769 GNUNET_break (0); 770 return GNUNET_SYSERR; 771 } 772 } 773 774 pay_cmd = TALER_TESTING_interpreter_lookup_command (is, ref); 775 776 if (NULL == pay_cmd) 777 { 778 GNUNET_break (0); 779 return GNUNET_SYSERR; 780 } 781 782 GNUNET_array_grow (*tokens, 783 *tokens_num, 784 (*tokens_num) + 1); 785 786 token = &((*tokens)[(*tokens_num) - 1]); 787 788 { 789 const struct TALER_TokenUsePrivateKeyP *token_priv; 790 const struct TALER_TokenIssueSignature *issue_sig; 791 const struct TALER_TokenIssuePublicKey *issue_pub; 792 793 GNUNET_assert (GNUNET_OK == 794 TALER_TESTING_get_trait_token_priv (pay_cmd, 795 index, 796 &token_priv)); 797 798 GNUNET_assert (GNUNET_OK == 799 TALER_TESTING_get_trait_token_issue_sig (pay_cmd, 800 index, 801 &issue_sig)); 802 803 GNUNET_assert (GNUNET_OK == 804 TALER_TESTING_get_trait_token_issue_pub (pay_cmd, 805 index, 806 &issue_pub)); 807 808 token->token_priv = *token_priv; 809 token->ub_sig = *issue_sig; 810 token->issue_pub = *issue_pub; 811 } 812 } 813 814 return GNUNET_OK; 815 } 816 817 818 /** 819 * Function called with the result of a /pay operation. 820 * Checks whether the merchant signature is valid and the 821 * HTTP response code matches our expectation. 822 * 823 * @param cls closure with the interpreter state 824 * @param pr HTTP response 825 */ 826 static void 827 pay_cb (void *cls, 828 const struct TALER_MERCHANT_PayResponse *pr) 829 { 830 struct PayState *ps = cls; 831 832 ps->oph = NULL; 833 if (ps->http_status != pr->hr.http_status) 834 { 835 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 836 "Unexpected response code %u (%d) to command (%s) %s\n", 837 pr->hr.http_status, 838 (int) pr->hr.ec, 839 pr->hr.hint, 840 TALER_TESTING_interpreter_get_current_label (ps->is)); 841 TALER_TESTING_FAIL (ps->is); 842 } 843 if (MHD_HTTP_OK == pr->hr.http_status) 844 { 845 ps->merchant_sig = pr->details.ok.merchant_sig; 846 if (ps->num_issued_tokens + ps->num_donau_tokens != 847 pr->details.ok.num_tokens) 848 { 849 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 850 "Unexpected number of tokens issued. " 851 "Sent %d envelopes but got %d tokens issued.\n", 852 ps->num_issued_tokens, 853 pr->details.ok.num_tokens); 854 GNUNET_break (0); 855 TALER_TESTING_interpreter_fail (ps->is); 856 return; 857 } 858 for (unsigned int i = 0; i < ps->num_issued_tokens; i++) 859 { 860 struct TALER_MERCHANT_PrivateTokenDetails *details = 861 &ps->issued_tokens[i]; 862 863 /* The issued tokens should be in the 864 same order as the provided envelopes. */ 865 ps->issued_tokens[i].blinded_sig = pr->details.ok.tokens[i].blinded_sig; 866 867 if (GNUNET_OK != 868 TALER_token_issue_sig_unblind (&details->issue_sig, 869 &details->blinded_sig, 870 &details->blinding_secret, 871 &details->h_token_pub, 872 &details->blinding_inputs, 873 &details->issue_pub)) 874 { 875 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 876 "Failed to unblind token signature\n"); 877 GNUNET_break (0); 878 TALER_TESTING_interpreter_fail (ps->is); 879 return; 880 } 881 } 882 if (NULL != ps->pos_key) 883 { 884 char *pc; 885 bool found = false; 886 887 if (NULL == pr->details.ok.pos_confirmation) 888 { 889 GNUNET_break (0); 890 TALER_TESTING_interpreter_fail (ps->is); 891 return; 892 } 893 pc = TALER_build_pos_confirmation (ps->pos_key, 894 ps->pos_alg, 895 &ps->total_amount, 896 GNUNET_TIME_timestamp_get ()); 897 /* Check if *any* of our TOTP codes overlaps 898 with any of the returned TOTP codes. */ 899 for (const char *tok = strtok (pc, "\n"); 900 NULL != tok; 901 tok = strtok (NULL, "\n")) 902 { 903 if (NULL != strstr (pr->details.ok.pos_confirmation, 904 tok)) 905 { 906 found = true; 907 break; 908 } 909 } 910 GNUNET_free (pc); 911 if (! found) 912 { 913 GNUNET_break (0); 914 TALER_TESTING_interpreter_fail (ps->is); 915 return; 916 } 917 } 918 } 919 TALER_TESTING_interpreter_next (ps->is); 920 } 921 922 923 /** 924 * Run a "pay" CMD. 925 * 926 * @param cls closure. 927 * @param cmd current CMD being run. 928 * @param is interpreter state. 929 */ 930 static void 931 pay_run (void *cls, 932 const struct TALER_TESTING_Command *cmd, 933 struct TALER_TESTING_Interpreter *is) 934 { 935 struct PayState *ps = cls; 936 const struct TALER_TESTING_Command *proposal_cmd; 937 const json_t *contract_terms; 938 const char *order_id; 939 struct GNUNET_TIME_Timestamp refund_deadline; 940 struct GNUNET_TIME_Timestamp pay_deadline; 941 struct GNUNET_TIME_Timestamp timestamp; 942 struct TALER_MerchantPublicKeyP merchant_pub; 943 struct TALER_MerchantWireHashP h_wire; 944 const struct TALER_PrivateContractHashP *h_proposal; 945 struct TALER_Amount max_fee; 946 const char *error_name = NULL; 947 unsigned int error_line = 0; 948 struct TALER_MERCHANT_PayCoin *pay_coins; 949 unsigned int npay_coins; 950 struct TALER_MERCHANT_UseToken *use_tokens = NULL; 951 unsigned int len_use_tokens = 0; 952 struct TALER_MERCHANT_OutputToken *output_tokens = NULL; 953 unsigned int len_output_tokens = 0; 954 const struct TALER_MerchantSignatureP *merchant_sig; 955 const enum TALER_MerchantConfirmationAlgorithm *alg_ptr; 956 957 ps->is = is; 958 proposal_cmd = TALER_TESTING_interpreter_lookup_command ( 959 is, 960 ps->proposal_reference); 961 962 if (NULL == proposal_cmd) 963 TALER_TESTING_FAIL (is); 964 965 if (GNUNET_OK != 966 TALER_TESTING_get_trait_contract_terms (proposal_cmd, 967 &contract_terms)) 968 TALER_TESTING_FAIL (is); 969 if (NULL == contract_terms) 970 TALER_TESTING_FAIL (is); 971 if (GNUNET_OK != 972 TALER_TESTING_get_trait_otp_key (proposal_cmd, 973 &ps->pos_key)) 974 ps->pos_key = NULL; 975 if ( (GNUNET_OK == 976 TALER_TESTING_get_trait_otp_alg (proposal_cmd, 977 &alg_ptr)) && 978 (NULL != alg_ptr) ) 979 ps->pos_alg = *alg_ptr; 980 { 981 /* Get information that needs to be put verbatim in the 982 * deposit permission */ 983 uint64_t version = 0; 984 struct GNUNET_JSON_Specification spec[] = { 985 GNUNET_JSON_spec_mark_optional ( 986 GNUNET_JSON_spec_uint64 ("version", 987 &version), 988 NULL), 989 GNUNET_JSON_spec_string ("order_id", 990 &order_id), 991 GNUNET_JSON_spec_timestamp ("refund_deadline", 992 &refund_deadline), 993 GNUNET_JSON_spec_timestamp ("pay_deadline", 994 &pay_deadline), 995 GNUNET_JSON_spec_timestamp ("timestamp", 996 ×tamp), 997 GNUNET_JSON_spec_fixed_auto ("merchant_pub", 998 &merchant_pub), 999 GNUNET_JSON_spec_fixed_auto ("h_wire", 1000 &h_wire), 1001 /* FIXME oec: parse minimum age, use data later? */ 1002 GNUNET_JSON_spec_end () 1003 }; 1004 1005 if (GNUNET_OK != 1006 GNUNET_JSON_parse (contract_terms, 1007 spec, 1008 &error_name, 1009 &error_line)) 1010 { 1011 char *js; 1012 1013 js = json_dumps (contract_terms, 1014 JSON_INDENT (1)); 1015 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1016 "Parser failed on %s:%u for input `%s'\n", 1017 error_name, 1018 error_line, 1019 js); 1020 free (js); 1021 TALER_TESTING_FAIL (is); 1022 } 1023 switch (version) 1024 { 1025 case 0: 1026 { 1027 struct GNUNET_JSON_Specification v0spec[] = { 1028 TALER_JSON_spec_amount_any ("amount", 1029 &ps->total_amount), 1030 TALER_JSON_spec_amount_any ("max_fee", 1031 &max_fee), 1032 GNUNET_JSON_spec_end () 1033 }; 1034 1035 if (GNUNET_OK != 1036 GNUNET_JSON_parse (contract_terms, 1037 v0spec, 1038 &error_name, 1039 &error_line)) 1040 { 1041 char *js; 1042 1043 js = json_dumps (contract_terms, 1044 JSON_INDENT (1)); 1045 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1046 "Parser failed on %s:%u for input `%s'\n", 1047 error_name, 1048 error_line, 1049 js); 1050 free (js); 1051 TALER_TESTING_FAIL (is); 1052 } 1053 } 1054 if (0 < ps->choice_index) 1055 TALER_TESTING_FAIL (is); 1056 break; 1057 case 1: 1058 { 1059 const json_t *choices; 1060 const json_t *token_families; 1061 struct GNUNET_JSON_Specification v1spec[] = { 1062 GNUNET_JSON_spec_object_const ("token_families", 1063 &token_families), 1064 GNUNET_JSON_spec_array_const ("choices", 1065 &choices), 1066 GNUNET_JSON_spec_end () 1067 }; 1068 const json_t *outputs; 1069 json_t *output; 1070 unsigned int output_index; 1071 const json_t *choice; 1072 1073 if (GNUNET_OK != 1074 GNUNET_JSON_parse (contract_terms, 1075 v1spec, 1076 &error_name, 1077 &error_line)) 1078 { 1079 char *js; 1080 1081 js = json_dumps (contract_terms, 1082 JSON_INDENT (1)); 1083 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1084 "Parser failed on %s:%u for input `%s'\n", 1085 error_name, 1086 error_line, 1087 js); 1088 free (js); 1089 TALER_TESTING_FAIL (is); 1090 } 1091 1092 choice = json_array_get (choices, 1093 ps->choice_index); 1094 if (NULL == choice) 1095 { 1096 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1097 "No choice found at index %d\n", 1098 ps->choice_index); 1099 TALER_TESTING_FAIL (is); 1100 } 1101 1102 { 1103 const char *ierror_name = NULL; 1104 unsigned int ierror_line = 0; 1105 1106 struct GNUNET_JSON_Specification ispec[] = { 1107 TALER_JSON_spec_amount_any ("amount", 1108 &ps->total_amount), 1109 TALER_JSON_spec_amount_any ("max_fee", 1110 &max_fee), 1111 GNUNET_JSON_spec_array_const ("outputs", 1112 &outputs), 1113 GNUNET_JSON_spec_end () 1114 }; 1115 1116 if (GNUNET_OK != 1117 GNUNET_JSON_parse (choice, 1118 ispec, 1119 &ierror_name, 1120 &ierror_line)) 1121 { 1122 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1123 "Parser failed on %s:%u for input `%s'\n", 1124 ierror_name, 1125 ierror_line, 1126 json_dumps (choice, 1127 JSON_INDENT (2))); 1128 TALER_TESTING_FAIL (is); 1129 } 1130 } 1131 1132 json_array_foreach (outputs, output_index, output) 1133 { 1134 const char *slug; 1135 const char *kind; 1136 uint32_t key_index; 1137 uint32_t count = 1; 1138 const char *ierror_name = NULL; 1139 unsigned int ierror_line = 0; 1140 1141 struct GNUNET_JSON_Specification typespec[] = { 1142 GNUNET_JSON_spec_string ("type", 1143 &kind), 1144 GNUNET_JSON_spec_end () 1145 }; 1146 1147 if (GNUNET_OK != 1148 GNUNET_JSON_parse (output, 1149 typespec, 1150 &ierror_name, 1151 &ierror_line)) 1152 { 1153 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1154 "Parser failed on %s:%u for input `%s'\n", 1155 ierror_name, 1156 ierror_line, 1157 json_dumps (output, 1158 JSON_INDENT (2))); 1159 TALER_TESTING_FAIL (is); 1160 } 1161 1162 if (0 == strcmp ("tax-receipt", 1163 kind)) 1164 { 1165 const json_t *donau_urls; 1166 1167 // For test, we care only about the presence of it 1168 struct GNUNET_JSON_Specification donauspec[] = { 1169 GNUNET_JSON_spec_array_const ("donau_urls", 1170 &donau_urls), 1171 GNUNET_JSON_spec_end () 1172 }; 1173 1174 if (GNUNET_OK != 1175 GNUNET_JSON_parse (output, 1176 donauspec, 1177 &ierror_name, 1178 &ierror_line)) 1179 { 1180 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1181 "Parser failed on %s:%u for input `%s'\n", 1182 ierror_name, 1183 ierror_line, 1184 json_dumps (output, 1185 JSON_INDENT (2))); 1186 TALER_TESTING_FAIL (is); 1187 } 1188 1189 #ifdef HAVE_DONAU_DONAU_SERVICE_H 1190 { 1191 const char *donau_url_str; 1192 1193 if ( (NULL == donau_urls) || 1194 (0 == json_array_size (donau_urls)) ) 1195 { 1196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1197 "No donau_urls found in output\n"); 1198 TALER_TESTING_FAIL (is); 1199 } 1200 1201 donau_url_str = json_string_value (json_array_get (donau_urls, 1202 0)); 1203 if (NULL == donau_url_str) 1204 { 1205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1206 "First entry in donau_urls is not a string\n"); 1207 TALER_TESTING_FAIL (is); 1208 } 1209 1210 ps->donau_data.donau_url = GNUNET_strdup (donau_url_str); 1211 1212 if (NULL != ps->donau_data.charity_reference) 1213 { 1214 switch (prepare_donau_data (is, 1215 &ps->donau_data)) 1216 { 1217 case GNUNET_OK: 1218 break; 1219 case GNUNET_NO: 1220 TALER_TESTING_interpreter_next (ps->is); 1221 return; 1222 case GNUNET_SYSERR: 1223 TALER_TESTING_FAIL (is); 1224 return; 1225 } 1226 ps->num_donau_tokens = ps->donau_data.num_bkps; 1227 } 1228 } 1229 #else /* HAVE_DONAU_DONAU_SERVICE_H */ 1230 /* SIMPLY NOTHING */ 1231 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 1232 } 1233 1234 if (0 == strcmp ("token", 1235 kind)) 1236 { 1237 struct GNUNET_JSON_Specification ispec[] = { 1238 GNUNET_JSON_spec_string ("token_family_slug", 1239 &slug), 1240 GNUNET_JSON_spec_uint32 ("key_index", 1241 &key_index), 1242 GNUNET_JSON_spec_mark_optional ( 1243 GNUNET_JSON_spec_uint32 ("count", 1244 &count), 1245 NULL), 1246 GNUNET_JSON_spec_end () 1247 }; 1248 1249 if (GNUNET_OK != 1250 GNUNET_JSON_parse (output, 1251 ispec, 1252 &ierror_name, 1253 &ierror_line)) 1254 { 1255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1256 "Parser failed on %s:%u for input `%s'\n", 1257 ierror_name, 1258 ierror_line, 1259 json_dumps (output, 1260 JSON_INDENT (2))); 1261 TALER_TESTING_FAIL (is); 1262 } 1263 1264 if (0 != strcmp ("token", 1265 kind)) 1266 { 1267 continue; 1268 } 1269 1270 GNUNET_array_grow ( 1271 ps->issued_tokens, 1272 ps->num_issued_tokens, 1273 ps->num_issued_tokens + count + ps->num_donau_tokens); 1274 1275 for (unsigned int k = 0; k < count; k++) 1276 { 1277 struct TALER_MERCHANT_PrivateTokenDetails *details = 1278 &ps->issued_tokens[ps->num_issued_tokens - count + k 1279 + ps->num_donau_tokens]; 1280 1281 if (GNUNET_OK != 1282 find_token_public_key (token_families, 1283 slug, 1284 key_index, 1285 &details->issue_pub)) 1286 { 1287 TALER_TESTING_FAIL (is); 1288 } 1289 1290 /* Only RSA is supported for now. */ 1291 GNUNET_assert (GNUNET_CRYPTO_BSA_RSA == 1292 details->issue_pub.public_key->cipher); 1293 1294 TALER_token_blind_input_copy (&details->blinding_inputs, 1295 TALER_token_blind_input_rsa_singleton () 1296 ); 1297 /* FIXME: Where to get details->blinding_inputs from? */ 1298 TALER_token_use_setup_random (&details->master); 1299 TALER_token_use_setup_priv (&details->master, 1300 &details->blinding_inputs, 1301 &details->token_priv); 1302 TALER_token_use_blinding_secret_create (&details->master, 1303 &details->blinding_inputs, 1304 &details->blinding_secret) 1305 ; 1306 GNUNET_CRYPTO_eddsa_key_get_public ( 1307 &details->token_priv.private_key, 1308 &details->token_pub.public_key); 1309 GNUNET_CRYPTO_hash (&details->token_pub.public_key, 1310 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), 1311 &details->h_token_pub.hash); 1312 details->envelope.blinded_pub = 1313 GNUNET_CRYPTO_message_blind_to_sign 1314 ( 1315 details->issue_pub.public_key, 1316 &details->blinding_secret, 1317 NULL, /* FIXME: Add session nonce to support CS tokens */ 1318 &details->h_token_pub.hash, 1319 sizeof (details->h_token_pub.hash), 1320 details->blinding_inputs.blinding_inputs); 1321 1322 if (NULL == details->envelope.blinded_pub) 1323 { 1324 GNUNET_break (0); 1325 TALER_TESTING_FAIL (is); 1326 } 1327 } 1328 } 1329 } 1330 } 1331 1332 break; 1333 default: 1334 TALER_TESTING_FAIL (is); 1335 } 1336 } 1337 1338 { 1339 char *cr; 1340 1341 cr = GNUNET_strdup (ps->coin_reference); 1342 pay_coins = NULL; 1343 npay_coins = 0; 1344 if (GNUNET_OK != 1345 build_coins (&pay_coins, 1346 &npay_coins, 1347 cr, 1348 is, 1349 ps->amount_with_fee, 1350 ps->amount_without_fee)) 1351 { 1352 GNUNET_array_grow (pay_coins, 1353 npay_coins, 1354 0); 1355 GNUNET_free (cr); 1356 TALER_TESTING_FAIL (is); 1357 } 1358 GNUNET_free (cr); 1359 } 1360 if (NULL != ps->token_reference) 1361 { 1362 char *tr; 1363 1364 tr = GNUNET_strdup (ps->token_reference); 1365 if (GNUNET_OK != 1366 build_tokens (&use_tokens, 1367 &len_use_tokens, 1368 tr, 1369 is)) 1370 { 1371 GNUNET_array_grow (use_tokens, 1372 len_use_tokens, 1373 0); 1374 GNUNET_free (tr); 1375 TALER_TESTING_FAIL (is); 1376 } 1377 GNUNET_free (tr); 1378 } 1379 1380 GNUNET_array_grow (output_tokens, 1381 len_output_tokens, 1382 ps->num_issued_tokens); 1383 for (unsigned int i = 0; i<len_output_tokens; i++) 1384 { 1385 output_tokens[i].envelope.blinded_pub 1386 = ps->issued_tokens[i].envelope.blinded_pub; 1387 } 1388 1389 if (GNUNET_OK != 1390 TALER_TESTING_get_trait_merchant_sig (proposal_cmd, 1391 &merchant_sig)) 1392 TALER_TESTING_FAIL (is); 1393 1394 if (GNUNET_OK != 1395 TALER_TESTING_get_trait_h_contract_terms (proposal_cmd, 1396 &h_proposal)) 1397 TALER_TESTING_FAIL (is); 1398 ps->h_contract_terms = *h_proposal; 1399 1400 /* New logic of setting pay params */ 1401 { 1402 struct GNUNET_CURL_Context *ctx = 1403 TALER_TESTING_interpreter_get_context (is); 1404 struct TALER_MERCHANT_OrderPayOption opts[32]; 1405 size_t oi = 0; 1406 1407 ps->oph = TALER_MERCHANT_order_pay_create (ctx, 1408 &pay_cb, 1409 ps); 1410 1411 if (NULL == ps->oph) 1412 TALER_TESTING_FAIL (is); 1413 1414 #define ADD(_opt) opts[oi++] = (_opt) 1415 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_URL (ps->merchant_url)); 1416 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_ORDER_ID (order_id)); 1417 if (NULL != ps->session_id) 1418 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_SESSION_ID (ps->session_id)); 1419 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_CONTRACT (h_proposal)); 1420 if (ps->choice_index >= 0) 1421 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_CHOICE_INDEX (ps->choice_index)); 1422 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_AMOUNT (&ps->total_amount)); 1423 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MAX_FEE (&max_fee)); 1424 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_PUB (&merchant_pub)); 1425 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TIMESTAMP (timestamp)); 1426 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_REFUND_DEADLINE (refund_deadline)); 1427 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_PAY_DEADLINE (pay_deadline)); 1428 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_WIRE (&h_wire)); 1429 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_COINS (npay_coins, 1430 pay_coins)); 1431 if (len_use_tokens > 0) 1432 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_INPUT_TOKENS (len_use_tokens, 1433 use_tokens)); 1434 if (len_output_tokens > 0) 1435 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_OUTPUT_TOKENS (len_output_tokens, 1436 output_tokens)); 1437 1438 #ifdef HAVE_DONAU_DONAU_SERVICE_H 1439 if (ps->donau_data.charity_reference) 1440 { 1441 ADD ( 1442 TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_URL (ps->donau_data.donau_url)); 1443 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_YEAR (ps->donau_data.year)); 1444 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_BUDIS ( 1445 ps->donau_data.budis_json)); 1446 } 1447 #endif 1448 ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ()); 1449 #undef ADD 1450 1451 if (TALER_MERCHANT_OPOEC_OK != 1452 TALER_MERCHANT_order_pay_set_options (ps->oph, 1453 opts, 1454 oi)) 1455 TALER_TESTING_FAIL (is); 1456 1457 if (TALER_MERCHANT_OPOEC_OK != 1458 TALER_MERCHANT_order_pay_start (ps->oph)) 1459 TALER_TESTING_FAIL (is); 1460 } 1461 1462 GNUNET_array_grow (pay_coins, 1463 npay_coins, 1464 0); 1465 1466 GNUNET_array_grow (use_tokens, 1467 len_use_tokens, 1468 0); 1469 1470 GNUNET_array_grow (output_tokens, 1471 len_output_tokens, 1472 0); 1473 } 1474 1475 1476 /** 1477 * Free a "pay" CMD, and cancel it if need be. 1478 * 1479 * @param cls closure. 1480 * @param cmd command currently being freed. 1481 */ 1482 static void 1483 pay_cleanup (void *cls, 1484 const struct TALER_TESTING_Command *cmd) 1485 { 1486 struct PayState *ps = cls; 1487 1488 if (NULL != ps->oph) 1489 { 1490 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1491 "Command `%s' did not complete.\n", 1492 TALER_TESTING_interpreter_get_current_label ( 1493 ps->is)); 1494 TALER_MERCHANT_order_pay_cancel1 (ps->oph); 1495 } 1496 1497 GNUNET_free (ps); 1498 } 1499 1500 1501 /** 1502 * Offer internal data useful to other commands. 1503 * 1504 * @param cls closure 1505 * @param[out] ret result 1506 * @param trait name of the trait 1507 * @param index index number of the object to extract. 1508 * @return #GNUNET_OK on success 1509 */ 1510 static enum GNUNET_GenericReturnValue 1511 pay_traits (void *cls, 1512 const void **ret, 1513 const char *trait, 1514 unsigned int index) 1515 { 1516 1517 struct PayState *ps = cls; 1518 const char *order_id; 1519 const struct TALER_TESTING_Command *proposal_cmd; 1520 const struct TALER_MerchantPublicKeyP *merchant_pub; 1521 1522 if (NULL != ps->token_reference && 1523 index >= ps->num_issued_tokens) 1524 { 1525 GNUNET_break (0); 1526 return GNUNET_NO; 1527 } 1528 1529 if (NULL == 1530 (proposal_cmd = 1531 TALER_TESTING_interpreter_lookup_command (ps->is, 1532 ps->proposal_reference))) 1533 { 1534 GNUNET_break (0); 1535 return GNUNET_SYSERR; 1536 } 1537 1538 if (GNUNET_OK != 1539 TALER_TESTING_get_trait_order_id (proposal_cmd, 1540 &order_id)) 1541 { 1542 GNUNET_break (0); 1543 return GNUNET_SYSERR; 1544 } 1545 1546 if (GNUNET_OK != 1547 TALER_TESTING_get_trait_merchant_pub (proposal_cmd, 1548 &merchant_pub)) 1549 { 1550 GNUNET_break (0); 1551 return GNUNET_SYSERR; 1552 } 1553 { 1554 struct TALER_Amount amount_with_fee; 1555 1556 GNUNET_assert (GNUNET_OK == 1557 TALER_string_to_amount (ps->amount_with_fee, 1558 &amount_with_fee)); 1559 { 1560 struct TALER_TESTING_Trait traits[] = { 1561 TALER_TESTING_make_trait_proposal_reference (ps->proposal_reference), 1562 TALER_TESTING_make_trait_coin_reference (0, 1563 ps->coin_reference), 1564 TALER_TESTING_make_trait_order_id (order_id), 1565 TALER_TESTING_make_trait_merchant_pub (merchant_pub), 1566 TALER_TESTING_make_trait_merchant_sig (&ps->merchant_sig), 1567 TALER_TESTING_make_trait_amount (&amount_with_fee), 1568 TALER_TESTING_make_trait_otp_key (ps->pos_key), 1569 TALER_TESTING_make_trait_otp_alg (&ps->pos_alg), 1570 TALER_TESTING_make_trait_token_priv (index, 1571 &ps->issued_tokens[index]. 1572 token_priv), 1573 TALER_TESTING_make_trait_token_issue_pub (index, 1574 &ps->issued_tokens[index]. 1575 issue_pub), 1576 TALER_TESTING_make_trait_token_issue_sig (index, 1577 &ps->issued_tokens[index]. 1578 issue_sig), 1579 TALER_TESTING_trait_end () 1580 }; 1581 1582 return TALER_TESTING_get_trait (traits, 1583 ret, 1584 trait, 1585 index); 1586 } 1587 } 1588 } 1589 1590 1591 struct TALER_TESTING_Command 1592 TALER_TESTING_cmd_merchant_pay_order_choices ( 1593 const char *label, 1594 const char *merchant_url, 1595 unsigned int http_status, 1596 const char *proposal_reference, 1597 const char *coin_reference, 1598 const char *amount_with_fee, 1599 const char *amount_without_fee, 1600 const char *session_id, 1601 int choice_index, 1602 const char *token_reference) 1603 { 1604 struct PayState *ps; 1605 1606 ps = GNUNET_new (struct PayState); 1607 ps->http_status = http_status; 1608 ps->proposal_reference = proposal_reference; 1609 ps->coin_reference = coin_reference; 1610 ps->merchant_url = merchant_url; 1611 ps->amount_with_fee = amount_with_fee; 1612 ps->amount_without_fee = amount_without_fee; 1613 ps->session_id = session_id; 1614 ps->token_reference = token_reference; 1615 ps->choice_index = choice_index; 1616 { 1617 struct TALER_TESTING_Command cmd = { 1618 .cls = ps, 1619 .label = label, 1620 .run = &pay_run, 1621 .cleanup = &pay_cleanup, 1622 .traits = &pay_traits 1623 }; 1624 1625 return cmd; 1626 } 1627 } 1628 1629 1630 #ifdef HAVE_DONAU_DONAU_SERVICE_H 1631 1632 struct TALER_TESTING_Command 1633 TALER_TESTING_cmd_merchant_pay_order_donau ( 1634 const char *label, 1635 const char *merchant_url, 1636 unsigned int http_status, 1637 const char *proposal_reference, 1638 const char *coin_reference, 1639 const char *amount_with_fee, 1640 const char *amount_without_fee, 1641 const char *amount_donation, 1642 const char *session_id, 1643 int choice_index, 1644 const char *charity_reference, 1645 uint64_t year, 1646 const char *donor_tax_id, 1647 const char *salt) 1648 { 1649 struct PayState *ps; 1650 1651 ps = GNUNET_new (struct PayState); 1652 ps->http_status = http_status; 1653 ps->proposal_reference = proposal_reference; 1654 ps->coin_reference = coin_reference; 1655 ps->merchant_url = merchant_url; 1656 ps->amount_with_fee = amount_with_fee; 1657 ps->amount_without_fee = amount_without_fee; 1658 ps->session_id = session_id; 1659 ps->token_reference = NULL; 1660 ps->choice_index = choice_index; 1661 ps->donau_data.year = year; 1662 ps->donau_data.num_bkps = 5; 1663 ps->donau_data.charity_reference = charity_reference; 1664 if (GNUNET_OK != 1665 TALER_string_to_amount (amount_donation, 1666 &ps->donau_data.donation_amount)) 1667 { 1668 GNUNET_assert (0); 1669 } 1670 1671 /* Compute h_donor_tax_id directly into ps->donau_data: */ 1672 if (! DONAU_compute_salted_tax_id_hash (donor_tax_id, 1673 salt, 1674 ps->donau_data.h_donor_tax_id.hash)) 1675 { 1676 GNUNET_assert (0); 1677 } 1678 1679 { 1680 struct TALER_TESTING_Command cmd = { 1681 .cls = ps, 1682 .label = label, 1683 .run = &pay_run, 1684 .cleanup = &pay_cleanup, 1685 .traits = &pay_traits 1686 }; 1687 1688 return cmd; 1689 } 1690 } 1691 1692 1693 #endif /* HAVE_DONAU_DONAU_SERVICE_H */ 1694 1695 1696 struct TALER_TESTING_Command 1697 TALER_TESTING_cmd_merchant_pay_order ( 1698 const char *label, 1699 const char *merchant_url, 1700 unsigned int http_status, 1701 const char *proposal_reference, 1702 const char *coin_reference, 1703 const char *amount_with_fee, 1704 const char *amount_without_fee, 1705 const char *session_id) 1706 { 1707 return TALER_TESTING_cmd_merchant_pay_order_choices ( 1708 label, 1709 merchant_url, 1710 http_status, 1711 proposal_reference, 1712 coin_reference, 1713 amount_with_fee, 1714 amount_without_fee, 1715 session_id, 1716 -1, 1717 NULL); 1718 } 1719 1720 1721 /* end of testing_api_cmd_pay_order.c */