merchant

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

testing_api_cmd_pay_order.c (51581B)


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