/* This file is part of TALER Copyright (C) 2020 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file lib/testing_api_cmd_post_orders_paid.c * @brief command to test POST /orders/$ID/paid. * @author Jonathan Buchanan */ #include "platform.h" #include #include #include "taler_merchant_service.h" #include "taler_merchant_testing_lib.h" /** * State of a "POST /orders/$ID/paid" CMD. */ struct PostOrdersPaidState { /** * Handle for a "POST /paid" request. */ struct TALER_MERCHANT_OrderPaidHandle *oph; /** * The interpreter state. */ struct TALER_TESTING_Interpreter *is; /** * Base URL of the merchant serving the request. */ const char *merchant_url; /** * Reference to the "pay" command to verify. */ const char *pay_reference; /** * The session to use for the requet. */ const char *session_id; /** * Expected HTTP response code. */ unsigned int http_status; }; /** * Response from the merchant after POST /paid. * * @param cls pointer to `struct PostOrdersPaidState`. * @param hr the http response. */ static void paid_cb (void *cls, const struct TALER_MERCHANT_HttpResponse *hr) { struct PostOrdersPaidState *ops = cls; ops->oph = NULL; if (ops->http_status != hr->http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u (%d) to command %s\n", hr->http_status, (int) hr->ec, TALER_TESTING_interpreter_get_current_label (ops->is)); TALER_TESTING_FAIL (ops->is); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successful order-paid (HTTP status: %u)\n", ops->http_status); TALER_TESTING_interpreter_next (ops->is); } /** * Run a "paid" CMD. * * @param cls closure * @param cmd command being run. * @param is interpreter state */ static void paid_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) { struct PostOrdersPaidState *ops = cls; const struct TALER_TESTING_Command *pay_cmd; const char *proposal_reference; const struct TALER_TESTING_Command *proposal_cmd; const char *order_id; const struct GNUNET_HashCode *h_contract_terms; struct TALER_MerchantSignatureP *merchant_sig; ops->is = is; pay_cmd = TALER_TESTING_interpreter_lookup_command (is, ops->pay_reference); if (NULL == pay_cmd) TALER_TESTING_FAIL (is); if (GNUNET_OK != TALER_TESTING_get_trait_merchant_sig (pay_cmd, 0, &merchant_sig)) TALER_TESTING_FAIL (is); if (GNUNET_OK != TALER_TESTING_get_trait_proposal_reference (pay_cmd, 0, &proposal_reference)) TALER_TESTING_FAIL (is); proposal_cmd = TALER_TESTING_interpreter_lookup_command (is, proposal_reference); if (NULL == proposal_cmd) TALER_TESTING_FAIL (is); { const json_t *contract_terms; const char *error_name; unsigned int error_line; if (GNUNET_OK != TALER_TESTING_get_trait_contract_terms (proposal_cmd, 0, &contract_terms)) TALER_TESTING_FAIL (is); { /* Get information that needs to be put verbatim in the * deposit permission */ struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("order_id", &order_id), GNUNET_JSON_spec_end () }; if (GNUNET_OK != GNUNET_JSON_parse (contract_terms, spec, &error_name, &error_line)) { char *js; js = json_dumps (contract_terms, JSON_INDENT (1)); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Parser failed on %s:%u for input `%s'\n", error_name, error_line, js); free (js); TALER_TESTING_FAIL (is); } } } if (GNUNET_OK != TALER_TESTING_get_trait_h_contract_terms (proposal_cmd, 0, &h_contract_terms)) TALER_TESTING_FAIL (is); ops->oph = TALER_MERCHANT_order_paid (is->ctx, ops->merchant_url, order_id, ops->session_id, h_contract_terms, merchant_sig, &paid_cb, ops); if (NULL == ops->oph) TALER_TESTING_FAIL (is); } /** * Free a "paid" CMD, and cancel it if need be. * * @param cls closure. * @param cmd command currently being freed. */ static void paid_cleanup (void *cls, const struct TALER_TESTING_Command *cmd) { struct PostOrdersPaidState *ops = cls; if (NULL != ops->oph) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Command `%s' did not complete.\n", TALER_TESTING_interpreter_get_current_label ( ops->is)); TALER_MERCHANT_order_paid_cancel (ops->oph); } GNUNET_free (ops); } /** * Make an "order paid" test command. * * @param label command label * @param merchant_url merchant base URL * @param pay_reference reference to the payment to verify * @param session_id the session to use for the verification. * @param http_status expected HTTP response code * @return the command */ struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_post_orders_paid (const char *label, const char *merchant_url, const char *pay_reference, const char *session_id, unsigned int http_status) { struct PostOrdersPaidState *ops; ops = GNUNET_new (struct PostOrdersPaidState); ops->http_status = http_status; ops->pay_reference = pay_reference; ops->merchant_url = merchant_url; ops->session_id = session_id; { struct TALER_TESTING_Command cmd = { .cls = ops, .label = label, .run = &paid_run, .cleanup = &paid_cleanup }; return cmd; } }