merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_pay_order.c (53499B)


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