merchant

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

testing_api_cmd_pay_order.c (50635B)


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