merchant

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

testing_api_cmd_claim_order.c (8072B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2023 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_api_cmd_claim_order.c
     22  * @brief command to claim an order
     23  * @author Marcello Stanisci
     24  */
     25 #include "taler/platform.h"
     26 #include <taler/taler_exchange_service.h>
     27 #include <taler/taler_testing_lib.h>
     28 #include "taler/taler_merchant_service.h"
     29 #include "taler/taler_merchant_testing_lib.h"
     30 #include <taler/taler-merchant/post-orders-ORDER_ID-claim.h>
     31 
     32 /**
     33  * State for a "order claim" CMD.  Not used by
     34  * the initial claim operation.
     35  */
     36 struct OrderClaimState
     37 {
     38   /**
     39    * The interpreter state.
     40    */
     41   struct TALER_TESTING_Interpreter *is;
     42 
     43   /**
     44    * URL of the merchant backend.
     45    */
     46   const char *merchant_url;
     47 
     48   /**
     49    * Contract terms we downloaded. Only set if we got #MHD_HTTP_OK.
     50    */
     51   json_t *contract_terms;
     52 
     53   /**
     54    * Hash over the contract terms. Only set if we got #MHD_HTTP_OK.
     55    */
     56   struct TALER_PrivateContractHashP contract_terms_hash;
     57 
     58   /**
     59    * Signature of the merchant. Only set if we got #MHD_HTTP_OK.
     60    */
     61   struct TALER_MerchantSignatureP merchant_sig;
     62 
     63   /**
     64    * Public key of the merchant. Only set if we got #MHD_HTTP_OK.
     65    */
     66   struct TALER_MerchantPublicKeyP merchant_pub;
     67 
     68   /**
     69    * Expected status code.
     70    */
     71   unsigned int http_status;
     72 
     73   /**
     74    * /order/claim operation handle.
     75    */
     76   struct TALER_MERCHANT_PostOrdersClaimHandle *och;
     77 
     78   /**
     79    * Reference to a order operation.  Will offer the
     80    * nonce for the operation.
     81    */
     82   const char *order_reference;
     83 
     84   /**
     85    * Order id to claim upon.  If null, the @a order_reference
     86    * will offer this value.
     87    */
     88   const char *order_id;
     89 };
     90 
     91 
     92 /**
     93  * Free the state of a "order claim" CMD, and possibly
     94  * cancel it if it did not complete.
     95  *
     96  * @param cls closure.
     97  * @param cmd command being freed.
     98  */
     99 static void
    100 order_claim_cleanup (void *cls,
    101                      const struct TALER_TESTING_Command *cmd)
    102 {
    103   struct OrderClaimState *pls = cls;
    104 
    105   if (NULL != pls->och)
    106   {
    107     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    108                 "Command '%s' did not complete\n",
    109                 cmd->label);
    110     TALER_MERCHANT_post_orders_claim_cancel (pls->och);
    111     pls->och = NULL;
    112   }
    113   if (NULL != pls->contract_terms)
    114   {
    115     json_decref (pls->contract_terms);
    116     pls->contract_terms = NULL;
    117   }
    118   GNUNET_free (pls);
    119 }
    120 
    121 
    122 /**
    123  * Callback for "order claim" operation, to check the
    124  * response code is as expected.
    125  *
    126  * @param cls closure
    127  * @param ocr response we got
    128  */
    129 static void
    130 order_claim_cb (void *cls,
    131                 const struct TALER_MERCHANT_PostOrdersClaimResponse *ocr)
    132 {
    133   struct OrderClaimState *pls = cls;
    134 
    135   pls->och = NULL;
    136   if (pls->http_status != ocr->hr.http_status)
    137     TALER_TESTING_FAIL (pls->is);
    138   if (MHD_HTTP_OK == ocr->hr.http_status)
    139   {
    140     pls->contract_terms
    141       = json_incref ((json_t *) ocr->details.ok.contract_terms);
    142     pls->contract_terms_hash = ocr->details.ok.h_contract_terms;
    143     pls->merchant_sig = ocr->details.ok.merchant_sig;
    144     {
    145       const char *error_name;
    146       unsigned int error_line;
    147       struct GNUNET_JSON_Specification spec[] = {
    148         GNUNET_JSON_spec_fixed_auto ("merchant_pub",
    149                                      &pls->merchant_pub),
    150         GNUNET_JSON_spec_end ()
    151       };
    152 
    153       if (GNUNET_OK !=
    154           GNUNET_JSON_parse (pls->contract_terms,
    155                              spec,
    156                              &error_name,
    157                              &error_line))
    158         TALER_TESTING_FAIL (pls->is);
    159     }
    160   }
    161   TALER_TESTING_interpreter_next (pls->is);
    162 }
    163 
    164 
    165 /**
    166  * Run the "order claim" CMD.
    167  *
    168  * @param cls closure.
    169  * @param cmd command currently being run.
    170  * @param is interpreter state.
    171  */
    172 static void
    173 order_claim_run (void *cls,
    174                  const struct TALER_TESTING_Command *cmd,
    175                  struct TALER_TESTING_Interpreter *is)
    176 {
    177   struct OrderClaimState *pls = cls;
    178   const char *order_id;
    179   const struct GNUNET_CRYPTO_EddsaPublicKey *nonce;
    180   /* Only used if we do NOT use the nonce/token from traits.  */
    181   struct GNUNET_CRYPTO_EddsaPublicKey dummy_nonce;
    182   const struct TALER_ClaimTokenP *claim_token;
    183 
    184   pls->is = is;
    185   if (NULL != pls->order_id)
    186   {
    187     order_id = pls->order_id;
    188     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    189                                 &dummy_nonce,
    190                                 sizeof (dummy_nonce));
    191     nonce = &dummy_nonce;
    192     claim_token = NULL;
    193   }
    194   else
    195   {
    196     const struct TALER_TESTING_Command *order_cmd;
    197 
    198     order_cmd
    199       = TALER_TESTING_interpreter_lookup_command (is,
    200                                                   pls->order_reference);
    201     if (NULL == order_cmd)
    202       TALER_TESTING_FAIL (is);
    203     if (GNUNET_OK !=
    204         TALER_TESTING_get_trait_claim_nonce (order_cmd,
    205                                              &nonce))
    206     {
    207       GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
    208                                   &dummy_nonce,
    209                                   sizeof (dummy_nonce));
    210       nonce = &dummy_nonce;
    211     }
    212     if (GNUNET_OK !=
    213         TALER_TESTING_get_trait_claim_token (order_cmd,
    214                                              &claim_token))
    215       claim_token = NULL;
    216     if (GNUNET_OK !=
    217         TALER_TESTING_get_trait_order_id (order_cmd,
    218                                           &order_id))
    219       TALER_TESTING_FAIL (is);
    220   }
    221   pls->och = TALER_MERCHANT_post_orders_claim_create (
    222     TALER_TESTING_interpreter_get_context (is),
    223     pls->merchant_url,
    224     order_id,
    225     nonce);
    226   if (NULL != claim_token)
    227     TALER_MERCHANT_post_orders_claim_set_options (
    228       pls->och,
    229       TALER_MERCHANT_post_orders_claim_option_token (claim_token));
    230   {
    231     enum TALER_ErrorCode ec;
    232 
    233     ec = TALER_MERCHANT_post_orders_claim_start (
    234       pls->och,
    235       &order_claim_cb,
    236       pls);
    237     GNUNET_assert (TALER_EC_NONE == ec);
    238   }
    239 }
    240 
    241 
    242 /**
    243  * Offer internal data to other commands.
    244  *
    245  * @param cls closure
    246  * @param[out] ret result (could be anything)
    247  * @param trait name of the trait
    248  * @param index index number of the object to extract.
    249  * @return #GNUNET_OK on success
    250  */
    251 static enum GNUNET_GenericReturnValue
    252 order_claim_traits (void *cls,
    253                     const void **ret,
    254                     const char *trait,
    255                     unsigned int index)
    256 {
    257   struct OrderClaimState *pls = cls;
    258 
    259   struct TALER_TESTING_Trait traits[] = {
    260     TALER_TESTING_make_trait_contract_terms (pls->contract_terms),
    261     TALER_TESTING_make_trait_h_contract_terms (&pls->contract_terms_hash),
    262     TALER_TESTING_make_trait_merchant_sig (&pls->merchant_sig),
    263     TALER_TESTING_make_trait_merchant_pub (&pls->merchant_pub),
    264     TALER_TESTING_trait_end ()
    265   };
    266 
    267   return TALER_TESTING_get_trait (traits,
    268                                   ret,
    269                                   trait,
    270                                   index);
    271 }
    272 
    273 
    274 struct TALER_TESTING_Command
    275 TALER_TESTING_cmd_merchant_claim_order (
    276   const char *label,
    277   const char *merchant_url,
    278   unsigned int http_status,
    279   const char *order_reference,
    280   const char *order_id)
    281 {
    282   struct OrderClaimState *pls;
    283 
    284   pls = GNUNET_new (struct OrderClaimState);
    285   pls->http_status = http_status;
    286   pls->order_reference = order_reference;
    287   pls->merchant_url = merchant_url;
    288   pls->order_id = order_id;
    289   {
    290     struct TALER_TESTING_Command cmd = {
    291       .cls = pls,
    292       .label = label,
    293       .run = &order_claim_run,
    294       .cleanup = &order_claim_cleanup,
    295       .traits = &order_claim_traits
    296     };
    297 
    298     return cmd;
    299   }
    300 }