merchant

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

testing_api_cmd_pay_order.c (50317B)


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