exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_deposits_get.c (10843B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2021, 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 /**
     21  * @file testing/testing_api_cmd_deposits_get.c
     22  * @brief Implement the testing CMDs for the /deposits/ GET operations.
     23  * @author Marcello Stanisci
     24  */
     25 #include "taler/taler_json_lib.h"
     26 #include <gnunet/gnunet_curl_lib.h>
     27 #include "taler/taler_testing_lib.h"
     28 
     29 /**
     30  * State for a "track transaction" CMD.
     31  */
     32 struct TrackTransactionState
     33 {
     34 
     35   /**
     36    * If non NULL, will provide a WTID to be compared against
     37    * the one returned by the "track transaction" operation.
     38    */
     39   const char *bank_transfer_reference;
     40 
     41   /**
     42    * Our command.
     43    */
     44   const struct TALER_TESTING_Command *cmd;
     45 
     46   /**
     47    * The WTID associated by the transaction being tracked.
     48    */
     49   struct TALER_WireTransferIdentifierRawP wtid;
     50 
     51   /**
     52    * Expected HTTP response code.
     53    */
     54   unsigned int expected_response_code;
     55 
     56   /**
     57    * Set to the KYC requirement payto hash *if* the exchange replied with a
     58    * request for KYC (#MHD_HTTP_ACCEPTED).
     59    * Note: set based on our @e merchant_payto_uri, as
     60    * the exchange does not respond with the payto hash.
     61    */
     62   struct TALER_NormalizedPaytoHashP h_payto;
     63 
     64   /**
     65    * Set to the KYC requirement row *if* the exchange replied with
     66    * a request for KYC (#MHD_HTTP_ACCEPTED).
     67    */
     68   uint64_t requirement_row;
     69 
     70   /**
     71    * Reference to any operation that can provide a transaction.
     72    * Will be the transaction to track.
     73    */
     74   const char *transaction_reference;
     75 
     76   /**
     77    * Payto URI of the merchant receiving the deposit.
     78    */
     79   struct TALER_FullPayto merchant_payto_uri;
     80 
     81   /**
     82    * Index of the coin involved in the transaction.  Recall:
     83    * at the exchange, the tracking is done _per coin_.
     84    */
     85   unsigned int coin_index;
     86 
     87   /**
     88    * Handle to the "track transaction" pending operation.
     89    */
     90   struct TALER_EXCHANGE_GetDepositsHandle *tth;
     91 
     92   /**
     93    * Interpreter state.
     94    */
     95   struct TALER_TESTING_Interpreter *is;
     96 };
     97 
     98 
     99 /**
    100  * Checks what is returned by the "track transaction" operation.
    101  * Checks that the HTTP response code is acceptable, and - if the
    102  * right reference is non NULL - that the wire transfer subject
    103  * line matches our expectations.
    104  *
    105  * @param cls closure.
    106  * @param dr GET deposit response details
    107  */
    108 static void
    109 deposit_wtid_cb (
    110   void *cls,
    111   const struct TALER_EXCHANGE_GetDepositsResponse *dr)
    112 {
    113   struct TrackTransactionState *tts = cls;
    114   struct TALER_TESTING_Interpreter *is = tts->is;
    115 
    116   tts->tth = NULL;
    117   if (tts->expected_response_code != dr->hr.http_status)
    118   {
    119     TALER_TESTING_unexpected_status (is,
    120                                      dr->hr.http_status,
    121                                      tts->expected_response_code);
    122     return;
    123   }
    124   switch (dr->hr.http_status)
    125   {
    126   case MHD_HTTP_OK:
    127     tts->wtid = dr->details.ok.wtid;
    128     if (NULL != tts->bank_transfer_reference)
    129     {
    130       const struct TALER_TESTING_Command *bank_transfer_cmd;
    131       const struct TALER_WireTransferIdentifierRawP *wtid_want;
    132 
    133       /* _this_ wire transfer subject line.  */
    134       bank_transfer_cmd
    135         = TALER_TESTING_interpreter_lookup_command (is,
    136                                                     tts->bank_transfer_reference
    137                                                     );
    138       if (NULL == bank_transfer_cmd)
    139       {
    140         GNUNET_break (0);
    141         TALER_TESTING_interpreter_fail (is);
    142         return;
    143       }
    144 
    145       if (GNUNET_OK !=
    146           TALER_TESTING_get_trait_wtid (bank_transfer_cmd,
    147                                         &wtid_want))
    148       {
    149         GNUNET_break (0);
    150         TALER_TESTING_interpreter_fail (is);
    151         return;
    152       }
    153 
    154       /* Compare that expected and gotten subjects match.  */
    155       if (0 != GNUNET_memcmp (&dr->details.ok.wtid,
    156                               wtid_want))
    157       {
    158         GNUNET_break (0);
    159         TALER_TESTING_interpreter_fail (tts->is);
    160         return;
    161       }
    162     }
    163     break;
    164   case MHD_HTTP_ACCEPTED:
    165     /* allowed, nothing to check here */
    166     TALER_full_payto_normalize_and_hash (tts->merchant_payto_uri,
    167                                          &tts->h_payto);
    168     tts->requirement_row
    169       = dr->details.accepted.requirement_row;
    170     break;
    171   case MHD_HTTP_NOT_FOUND:
    172     /* allowed, nothing to check here */
    173     break;
    174   default:
    175     GNUNET_break (0);
    176     break;
    177   }
    178   TALER_TESTING_interpreter_next (tts->is);
    179 }
    180 
    181 
    182 /**
    183  * Run the command.
    184  *
    185  * @param cls closure.
    186  * @param cmd the command to execute.
    187  * @param is the interpreter state.
    188  */
    189 static void
    190 deposits_get_run (
    191   void *cls,
    192   const struct TALER_TESTING_Command *cmd,
    193   struct TALER_TESTING_Interpreter *is)
    194 {
    195   struct TrackTransactionState *tts = cls;
    196   const struct TALER_TESTING_Command *transaction_cmd;
    197   const struct TALER_CoinSpendPrivateKeyP *coin_priv;
    198   struct TALER_CoinSpendPublicKeyP coin_pub;
    199   const json_t *contract_terms;
    200   const json_t *wire_details;
    201   struct TALER_MerchantWireHashP h_wire_details;
    202   struct TALER_PrivateContractHashP h_contract_terms;
    203   const struct TALER_MerchantPrivateKeyP *merchant_priv;
    204 
    205   tts->cmd = cmd;
    206   tts->is = is;
    207   transaction_cmd
    208     = TALER_TESTING_interpreter_lookup_command (tts->is,
    209                                                 tts->transaction_reference);
    210   if (NULL == transaction_cmd)
    211   {
    212     GNUNET_break (0);
    213     TALER_TESTING_interpreter_fail (tts->is);
    214     return;
    215   }
    216 
    217   if (GNUNET_OK !=
    218       TALER_TESTING_get_trait_coin_priv (transaction_cmd,
    219                                          tts->coin_index,
    220                                          &coin_priv))
    221   {
    222     GNUNET_break (0);
    223     TALER_TESTING_interpreter_fail (tts->is);
    224     return;
    225   }
    226 
    227   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
    228                                       &coin_pub.eddsa_pub);
    229 
    230   /* Get the strings.. */
    231   if (GNUNET_OK !=
    232       TALER_TESTING_get_trait_wire_details (transaction_cmd,
    233                                             &wire_details))
    234   {
    235     GNUNET_break (0);
    236     TALER_TESTING_interpreter_fail (tts->is);
    237     return;
    238   }
    239   tts->merchant_payto_uri.full_payto
    240     = GNUNET_strdup (json_string_value (json_object_get (wire_details,
    241                                                          "payto_uri")));
    242   if (GNUNET_OK !=
    243       TALER_TESTING_get_trait_contract_terms (transaction_cmd,
    244                                               &contract_terms))
    245   {
    246     GNUNET_break (0);
    247     TALER_TESTING_interpreter_fail (tts->is);
    248     return;
    249   }
    250 
    251   if ( (NULL == wire_details) ||
    252        (NULL == contract_terms) )
    253   {
    254     GNUNET_break (0);
    255     TALER_TESTING_interpreter_fail (tts->is);
    256     return;
    257   }
    258 
    259   /* Should not fail here, json has been parsed already */
    260   GNUNET_assert
    261     ( (GNUNET_OK ==
    262        TALER_JSON_merchant_wire_signature_hash (wire_details,
    263                                                 &h_wire_details)) &&
    264     (GNUNET_OK ==
    265      TALER_JSON_contract_hash (contract_terms,
    266                                &h_contract_terms)) );
    267 
    268   if (GNUNET_OK !=
    269       TALER_TESTING_get_trait_merchant_priv (transaction_cmd,
    270                                              &merchant_priv))
    271   {
    272     GNUNET_break (0);
    273     TALER_TESTING_interpreter_fail (tts->is);
    274     return;
    275   }
    276 
    277   tts->tth = TALER_EXCHANGE_get_deposits_create (
    278     TALER_TESTING_interpreter_get_context (is),
    279     TALER_TESTING_get_exchange_url (is),
    280     TALER_TESTING_get_keys (is),
    281     merchant_priv,
    282     &h_wire_details,
    283     &h_contract_terms,
    284     &coin_pub);
    285   if (NULL == tts->tth)
    286   {
    287     GNUNET_break (0);
    288     TALER_TESTING_interpreter_fail (is);
    289     return;
    290   }
    291   if (TALER_EC_NONE !=
    292       TALER_EXCHANGE_get_deposits_start (tts->tth,
    293                                          &deposit_wtid_cb,
    294                                          tts))
    295   {
    296     GNUNET_break (0);
    297     TALER_EXCHANGE_get_deposits_cancel (tts->tth);
    298     tts->tth = NULL;
    299     TALER_TESTING_interpreter_fail (is);
    300     return;
    301   }
    302 }
    303 
    304 
    305 /**
    306  * Cleanup the state from a "track transaction" CMD, and possibly
    307  * cancel a operation thereof.
    308  *
    309  * @param cls closure.
    310  * @param cmd the command which is being cleaned up.
    311  */
    312 static void
    313 deposits_get_cleanup (
    314   void *cls,
    315   const struct TALER_TESTING_Command *cmd)
    316 {
    317   struct TrackTransactionState *tts = cls;
    318 
    319   if (NULL != tts->tth)
    320   {
    321     TALER_TESTING_command_incomplete (tts->is,
    322                                       cmd->label);
    323     TALER_EXCHANGE_get_deposits_cancel (tts->tth);
    324     tts->tth = NULL;
    325   }
    326   GNUNET_free (tts->merchant_payto_uri.full_payto);
    327   GNUNET_free (tts);
    328 }
    329 
    330 
    331 /**
    332  * Offer internal data from a "track transaction" CMD.
    333  *
    334  * @param cls closure.
    335  * @param[out] ret result (could be anything).
    336  * @param trait name of the trait.
    337  * @param index index number of the object to offer.
    338  * @return #GNUNET_OK on success.
    339  */
    340 static enum GNUNET_GenericReturnValue
    341 deposits_get_traits (void *cls,
    342                      const void **ret,
    343                      const char *trait,
    344                      unsigned int index)
    345 {
    346   struct TrackTransactionState *tts = cls;
    347   struct TALER_TESTING_Trait traits[] = {
    348     TALER_TESTING_make_trait_wtid (&tts->wtid),
    349     TALER_TESTING_make_trait_legi_requirement_row (
    350       &tts->requirement_row),
    351     TALER_TESTING_make_trait_h_normalized_payto (&tts->h_payto),
    352     TALER_TESTING_make_trait_full_payto_uri (&tts->merchant_payto_uri),
    353     TALER_TESTING_trait_end ()
    354   };
    355 
    356   return TALER_TESTING_get_trait (traits,
    357                                   ret,
    358                                   trait,
    359                                   index);
    360 }
    361 
    362 
    363 struct TALER_TESTING_Command
    364 TALER_TESTING_cmd_deposits_get (
    365   const char *label,
    366   const char *transaction_reference,
    367   unsigned int coin_index,
    368   unsigned int expected_response_code,
    369   const char *bank_transfer_reference)
    370 {
    371   struct TrackTransactionState *tts;
    372 
    373   tts = GNUNET_new (struct TrackTransactionState);
    374   tts->transaction_reference = transaction_reference;
    375   tts->expected_response_code = expected_response_code;
    376   tts->bank_transfer_reference = bank_transfer_reference;
    377   tts->coin_index = coin_index;
    378   {
    379     struct TALER_TESTING_Command cmd = {
    380       .cls = tts,
    381       .label = label,
    382       .run = &deposits_get_run,
    383       .cleanup = &deposits_get_cleanup,
    384       .traits = &deposits_get_traits
    385     };
    386 
    387     return cmd;
    388   }
    389 }
    390 
    391 
    392 /* end of testing_api_cmd_deposits_get.c */