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 }