merchant

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

testing_api_cmd_pay_order.c (50567B)


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