LCOV - code coverage report
Current view: top level - lib - merchant_api_post-private-orders-ORDER_ID-refund-external.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.2 % 82 60
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2026 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify it under the
       6              :   terms of the GNU Lesser General Public License as published by the Free Software
       7              :   Foundation; either version 2.1, or (at your option) any later version.
       8              : 
       9              :   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      10              :   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11              :   A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
      12              : 
      13              :   You should have received a copy of the GNU Lesser General Public License along with
      14              :   TALER; see the file COPYING.LGPL.  If not, see
      15              :   <http://www.gnu.org/licenses/>
      16              : */
      17              : /**
      18              :  * @file src/lib/merchant_api_post-private-orders-ORDER_ID-refund-external.c
      19              :  * @brief Implementation of the POST /private/orders/$ORDER_ID/refund-external request
      20              :  * @author Bohdan Potuzhnyi
      21              :  * @author Volodymyr Potuzhnyi
      22              :  */
      23              : #include "platform.h"
      24              : #include <curl/curl.h>
      25              : #include <jansson.h>
      26              : #include <microhttpd.h> /* just for HTTP status codes */
      27              : #include <gnunet/gnunet_util_lib.h>
      28              : #include <gnunet/gnunet_curl_lib.h>
      29              : #include <taler/merchant/post-private-orders-ORDER_ID-refund-external.h>
      30              : #include "merchant_api_curl_defaults.h"
      31              : #include "merchant_api_common.h"
      32              : #include <taler/taler_json_lib.h>
      33              : #include <taler/taler_curl_lib.h>
      34              : 
      35              : 
      36              : /**
      37              :  * Handle for a POST /private/orders/$ORDER_ID/refund-external operation.
      38              :  */
      39              : struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle
      40              : {
      41              :   /**
      42              :    * Base URL of the merchant backend.
      43              :    */
      44              :   char *base_url;
      45              : 
      46              :   /**
      47              :    * The full URL for this request.
      48              :    */
      49              :   char *url;
      50              : 
      51              :   /**
      52              :    * Handle for the request.
      53              :    */
      54              :   struct GNUNET_CURL_Job *job;
      55              : 
      56              :   /**
      57              :    * Function to call with the result.
      58              :    */
      59              :   TALER_MERCHANT_PostPrivateOrdersRefundExternalCallback cb;
      60              : 
      61              :   /**
      62              :    * Closure for @a cb.
      63              :    */
      64              :   TALER_MERCHANT_POST_PRIVATE_ORDERS_REFUND_EXTERNAL_RESULT_CLOSURE *cb_cls;
      65              : 
      66              :   /**
      67              :    * Reference to the execution context.
      68              :    */
      69              :   struct GNUNET_CURL_Context *ctx;
      70              : 
      71              :   /**
      72              :    * Minor context that holds body and headers.
      73              :    */
      74              :   struct TALER_CURL_PostContext post_ctx;
      75              : 
      76              :   /**
      77              :    * Identifier of the order to record the refund for.
      78              :    */
      79              :   char *order_id;
      80              : 
      81              :   /**
      82              :    * External refund entry to record.
      83              :    */
      84              :   json_t *body;
      85              : };
      86              : 
      87              : 
      88              : /**
      89              :  * Function called when we're done processing the
      90              :  * HTTP POST /private/orders/$ORDER_ID/refund-external request.
      91              :  *
      92              :  * @param cls the `struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle`
      93              :  * @param response_code HTTP response code, 0 on error
      94              :  * @param response response body, NULL if not in JSON
      95              :  */
      96              : static void
      97           24 : handle_refund_external_finished (void *cls,
      98              :                                  long response_code,
      99              :                                  const void *response)
     100              : {
     101           24 :   struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle *poreh = cls;
     102           24 :   const json_t *json = response;
     103           24 :   struct TALER_MERCHANT_PostPrivateOrdersRefundExternalResponse rer = {
     104           24 :     .hr.http_status = (unsigned int) response_code,
     105              :     .hr.reply = json
     106              :   };
     107              : 
     108           24 :   poreh->job = NULL;
     109           24 :   switch (response_code)
     110              :   {
     111            0 :   case 0:
     112            0 :     rer.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     113            0 :     break;
     114           10 :   case MHD_HTTP_OK:
     115              :     {
     116              :       struct GNUNET_JSON_Specification spec[] = {
     117           10 :         GNUNET_JSON_spec_string ("refund_id",
     118              :                                  &rer.details.ok.refund_id),
     119           10 :         GNUNET_JSON_spec_end ()
     120              :       };
     121              : 
     122           10 :       if (GNUNET_OK !=
     123           10 :           GNUNET_JSON_parse (json,
     124              :                              spec,
     125              :                              NULL,
     126              :                              NULL))
     127              :       {
     128            0 :         GNUNET_break_op (0);
     129            0 :         rer.hr.http_status = 0;
     130            0 :         rer.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     131              :       }
     132           10 :       break;
     133              :     }
     134            2 :   case MHD_HTTP_BAD_REQUEST:
     135            2 :     rer.hr.ec = TALER_JSON_get_error_code (json);
     136            2 :     rer.hr.hint = TALER_JSON_get_error_hint (json);
     137            2 :     break;
     138            0 :   case MHD_HTTP_UNAUTHORIZED:
     139            0 :     rer.hr.ec = TALER_JSON_get_error_code (json);
     140            0 :     rer.hr.hint = TALER_JSON_get_error_hint (json);
     141            0 :     break;
     142            2 :   case MHD_HTTP_NOT_FOUND:
     143            2 :     rer.hr.ec = TALER_JSON_get_error_code (json);
     144            2 :     rer.hr.hint = TALER_JSON_get_error_hint (json);
     145            2 :     break;
     146           10 :   case MHD_HTTP_CONFLICT:
     147           10 :     rer.hr.ec = TALER_JSON_get_error_code (json);
     148           10 :     rer.hr.hint = TALER_JSON_get_error_hint (json);
     149           10 :     break;
     150            0 :   default:
     151            0 :     GNUNET_break_op (0);
     152            0 :     TALER_MERCHANT_parse_error_details_ (json,
     153              :                                          response_code,
     154              :                                          &rer.hr);
     155            0 :     break;
     156              :   }
     157           24 :   poreh->cb (poreh->cb_cls,
     158              :              &rer);
     159           24 :   TALER_MERCHANT_post_private_orders_refund_external_cancel (poreh);
     160           24 : }
     161              : 
     162              : 
     163              : struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle *
     164           24 : TALER_MERCHANT_post_private_orders_refund_external_create (
     165              :   struct GNUNET_CURL_Context *ctx,
     166              :   const char *url,
     167              :   const char *order_id,
     168              :   const json_t *body)
     169              : {
     170              :   struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle *poreh;
     171              : 
     172           24 :   poreh = GNUNET_new (
     173              :     struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle);
     174           24 :   poreh->ctx = ctx;
     175           24 :   poreh->base_url = GNUNET_strdup (url);
     176           24 :   poreh->order_id = GNUNET_strdup (order_id);
     177           24 :   poreh->body = json_deep_copy (body);
     178           24 :   GNUNET_assert (NULL != poreh->body);
     179           24 :   return poreh;
     180              : }
     181              : 
     182              : 
     183              : enum TALER_ErrorCode
     184           24 : TALER_MERCHANT_post_private_orders_refund_external_start (
     185              :   struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle *poreh,
     186              :   TALER_MERCHANT_PostPrivateOrdersRefundExternalCallback cb,
     187              :   TALER_MERCHANT_POST_PRIVATE_ORDERS_REFUND_EXTERNAL_RESULT_CLOSURE *cb_cls)
     188              : {
     189              :   CURL *eh;
     190              : 
     191           24 :   poreh->cb = cb;
     192           24 :   poreh->cb_cls = cb_cls;
     193              :   {
     194              :     char *path;
     195              : 
     196           24 :     GNUNET_asprintf (&path,
     197              :                      "private/orders/%s/refund-external",
     198              :                      poreh->order_id);
     199           24 :     poreh->url = TALER_url_join (poreh->base_url,
     200              :                                  path,
     201              :                                  NULL);
     202           24 :     GNUNET_free (path);
     203              :   }
     204           24 :   if (NULL == poreh->url)
     205            0 :     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
     206           24 :   eh = TALER_MERCHANT_curl_easy_get_ (poreh->url);
     207           48 :   if ( (NULL == eh) ||
     208              :        (GNUNET_OK !=
     209           24 :         TALER_curl_easy_post (&poreh->post_ctx,
     210              :                               eh,
     211           24 :                               poreh->body)) )
     212              :   {
     213            0 :     GNUNET_break (0);
     214            0 :     if (NULL != eh)
     215            0 :       curl_easy_cleanup (eh);
     216            0 :     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     217              :   }
     218           48 :   poreh->job = GNUNET_CURL_job_add2 (poreh->ctx,
     219              :                                      eh,
     220           24 :                                      poreh->post_ctx.headers,
     221              :                                      &handle_refund_external_finished,
     222              :                                      poreh);
     223           24 :   if (NULL == poreh->job)
     224            0 :     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     225           24 :   return TALER_EC_NONE;
     226              : }
     227              : 
     228              : 
     229              : void
     230           24 : TALER_MERCHANT_post_private_orders_refund_external_cancel (
     231              :   struct TALER_MERCHANT_PostPrivateOrdersRefundExternalHandle *poreh)
     232              : {
     233           24 :   if (NULL != poreh->job)
     234              :   {
     235            0 :     GNUNET_CURL_job_cancel (poreh->job);
     236            0 :     poreh->job = NULL;
     237              :   }
     238           24 :   TALER_curl_easy_post_finished (&poreh->post_ctx);
     239           24 :   json_decref (poreh->body);
     240           24 :   GNUNET_free (poreh->order_id);
     241           24 :   GNUNET_free (poreh->url);
     242           24 :   GNUNET_free (poreh->base_url);
     243           24 :   GNUNET_free (poreh);
     244           24 : }
     245              : 
     246              : 
     247              : /* end of merchant_api_post-private-orders-ORDER_ID-refund-external.c */
        

Generated by: LCOV version 2.0-1