merchant

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

testing_api_cmd_pay_order.c (50882B)


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