LCOV - code coverage report
Current view: top level - lib - merchant_api_refund.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 53 72 73.6 %
Date: 2018-05-16 06:16:58 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014, 2015, 2016, 2017 GNUnet e.V. and INRIA
       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 lib/merchant_api_proposal.c
      19             :  * @brief Implementation of the /refund POST and GET
      20             :  * @author Christian Grothoff
      21             :  * @author Marcello Stanisci
      22             :  */
      23             : 
      24             : #include "platform.h"
      25             : #include <curl/curl.h>
      26             : #include <jansson.h>
      27             : #include <microhttpd.h> /* just for HTTP status codes */
      28             : #include <gnunet/gnunet_util_lib.h>
      29             : #include <gnunet/gnunet_curl_lib.h>
      30             : #include "taler_merchant_service.h"
      31             : #include <taler/taler_json_lib.h>
      32             : #include <taler/taler_signatures.h>
      33             : 
      34             : 
      35             : struct TALER_MERCHANT_RefundLookupOperation
      36             : {
      37             :   /**
      38             :    * URL of the request, includes parameters
      39             :    */
      40             :   char *url;
      41             : 
      42             :   /**
      43             :    * Handle of the request
      44             :    */
      45             :   struct GNUNET_CURL_Job *job;
      46             : 
      47             :   /**
      48             :    * Function to call with the response
      49             :    */
      50             :   TALER_MERCHANT_RefundLookupCallback cb;
      51             : 
      52             :   /**
      53             :    * Closure for cb
      54             :    */
      55             :   void *cb_cls;
      56             : 
      57             :   /**
      58             :    * Reference to the execution context
      59             :    */
      60             :   struct GNUNET_CURL_Context *ctx;
      61             : 
      62             : };
      63             : 
      64             : struct TALER_MERCHANT_RefundIncreaseOperation
      65             : {
      66             :   /**
      67             :    * Complete URL where the backend offers /refund
      68             :    */
      69             :   char *url;
      70             : 
      71             :   /**
      72             :    * The request body
      73             :    */
      74             :   char *json_enc;
      75             : 
      76             :   /**
      77             :    * The CURL context to connect to the backend
      78             :    */
      79             :   struct GNUNET_CURL_Context *ctx;
      80             : 
      81             :   /**
      82             :    * The callback to pass the backend response to
      83             :    */
      84             :   TALER_MERCHANT_RefundIncreaseCallback cb;
      85             : 
      86             :   /**
      87             :    * Clasure to pass to the callback
      88             :    */
      89             :   void *cb_cls;
      90             : 
      91             :   /**
      92             :    * Handle for the request
      93             :    */
      94             :   struct GNUNET_CURL_Job *job;
      95             : 
      96             : };
      97             : 
      98             : 
      99             : /**
     100             :  * Callback to process POST /refund response
     101             :  *
     102             :  * @param cls the `struct TALER_MERCHANT_RefundIncreaseOperation`
     103             :  * @param response_code HTTP response code, 0 on error
     104             :  * @param json response body, NULL if not JSON
     105             :  */
     106             : static void
     107           3 : handle_refund_increase_finished (void *cls,
     108             :                                  long response_code,
     109             :                                  const json_t *json)
     110             : {
     111           3 :   struct TALER_MERCHANT_RefundIncreaseOperation *rio = cls;
     112             :   char *error;
     113             :   char *hint;
     114             :   enum TALER_ErrorCode code;
     115             : 
     116           3 :   rio->job = NULL;
     117           3 :   switch (response_code)
     118             :   {
     119             :   case 0:
     120             :     /* Hard error */
     121           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     122             :                 "Backend didn't even return from POST /refund\n");
     123           0 :     return;
     124             :   case MHD_HTTP_OK:
     125           3 :     rio->cb (rio->cb_cls,
     126             :              MHD_HTTP_OK,
     127             :              TALER_EC_NONE,
     128             :              json);
     129           3 :     break;
     130             :   default:
     131             :     /**
     132             :      * The backend gave response, but it's error, log it.
     133             :      * NOTE that json must be a Taler-specific error object (FIXME,
     134             :      * need a link to error objects at docs)
     135             :      */
     136           0 :     json_unpack ((json_t *) json,
     137             :                  "{s:s, s:I, s:s}",
     138             :                  "error", &error,
     139             :                  "code", &code,
     140             :                  "hint", &hint);
     141           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     142             :                 "Failed POST /refund, error: %s, code: %d, hint: %s\n",
     143             :                 error,
     144             :                 code,
     145             :                 hint);
     146             :   }
     147           3 :   TALER_MERCHANT_refund_increase_cancel (rio);
     148             : }
     149             : 
     150             : /**
     151             :  * Cancel a POST /refund request.
     152             :  *
     153             :  * @param rio the refund increasing operation to cancel
     154             :  */
     155             : void
     156           3 : TALER_MERCHANT_refund_increase_cancel (struct TALER_MERCHANT_RefundIncreaseOperation *rio)
     157             : {
     158           3 :   if (NULL != rio->job)
     159             :   {
     160           0 :     GNUNET_CURL_job_cancel (rio->job);
     161           0 :     rio->job = NULL;
     162             :   }
     163           3 :   GNUNET_free (rio->url);
     164           3 :   GNUNET_free (rio->json_enc);
     165           3 :   GNUNET_free (rio);
     166           3 : }
     167             : 
     168             : /**
     169             :  * Increase the refund associated to a order
     170             :  *
     171             :  * @param ctx the CURL context used to connect to the backend
     172             :  * @param backend_url backend's base URL, including final "/"
     173             :  * @param order_id id of the order whose refund is to be increased
     174             :  * @param refund amount to which increase the refund
     175             :  * @param reason human-readable reason justifying the refund
     176             :  * @param instance id of the merchant instance issuing the request
     177             :  * @param cb callback processing the response from /refund
     178             :  * @param cb_cls closure for cb
     179             :  */
     180             : struct TALER_MERCHANT_RefundIncreaseOperation *
     181           3 : TALER_MERCHANT_refund_increase (struct GNUNET_CURL_Context *ctx,
     182             :                                 const char *backend_url,
     183             :                                 const char *order_id,
     184             :                                 const struct TALER_Amount *refund,
     185             :                                 const char *reason,
     186             :                                 const char *instance,
     187             :                                 TALER_MERCHANT_RefundIncreaseCallback cb,
     188             :                                 void *cb_cls)
     189             : {
     190             :   struct TALER_MERCHANT_RefundIncreaseOperation *rio;
     191             :   json_t *req;
     192             :   CURL *eh;
     193             : 
     194           3 :   rio = GNUNET_new (struct TALER_MERCHANT_RefundIncreaseOperation);
     195           3 :   rio->ctx = ctx;
     196           3 :   rio->cb = cb;
     197           3 :   rio->cb_cls = cb_cls;
     198           3 :   rio->url = TALER_url_join (backend_url, "/refund", NULL);
     199           3 :   req = json_pack ("{s:o, s:s, s:s, s:s}",
     200             :                    "refund", TALER_JSON_from_amount (refund),
     201             :                    "order_id", order_id,
     202             :                    "reason", reason,
     203             :                    "instance", instance);
     204           3 :   eh = curl_easy_init ();
     205           3 :   rio->json_enc = json_dumps (req,
     206             :                               JSON_COMPACT);
     207           3 :   json_decref (req);
     208           3 :   if (NULL == rio->json_enc)
     209             :   {
     210           0 :     GNUNET_break (0);
     211           0 :     GNUNET_free (rio);
     212           0 :     return NULL;
     213             :   }
     214           3 :   GNUNET_assert (CURLE_OK ==
     215             :                  curl_easy_setopt (eh,
     216             :                                    CURLOPT_URL,
     217             :                                    rio->url));
     218           3 :   GNUNET_assert (CURLE_OK ==
     219             :                  curl_easy_setopt (eh,
     220             :                                    CURLOPT_POSTFIELDS,
     221             :                                    rio->json_enc));
     222           3 :   GNUNET_assert (CURLE_OK ==
     223             :                  curl_easy_setopt (eh,
     224             :                                    CURLOPT_POSTFIELDSIZE,
     225             :                                    strlen (rio->json_enc)));
     226           3 :   rio->job = GNUNET_CURL_job_add (ctx,
     227             :                                   eh,
     228             :                                   GNUNET_YES,
     229             :                                   &handle_refund_increase_finished,
     230             :                                   rio);
     231           3 :   return rio;
     232             : }
     233             : 
     234             : 
     235             : /**
     236             :  * Cancel a /refund lookup operation
     237             :  *
     238             :  * @param 
     239             :  */
     240             : void
     241           3 : TALER_MERCHANT_refund_lookup_cancel (struct TALER_MERCHANT_RefundLookupOperation *rlo)
     242             : {
     243           3 :   if (NULL != rlo->job)
     244             :   {
     245           0 :     GNUNET_CURL_job_cancel (rlo->job);
     246           0 :     rlo->job = NULL;
     247             :   }
     248             :   
     249           3 :   GNUNET_free (rlo->url);
     250           3 :   GNUNET_free (rlo);
     251           3 : }
     252             : 
     253             : 
     254             : /**
     255             :  * Process GET /refund response
     256             :  */
     257             : void
     258           3 : handle_refund_lookup_finished (void *cls,
     259             :                                long response_code,
     260             :                                const json_t *json)
     261             : {
     262           3 :   struct TALER_MERCHANT_RefundLookupOperation *rlo = cls;
     263             :   char *error;
     264             :   enum TALER_ErrorCode code;
     265             : 
     266           3 :   rlo->job = NULL;
     267           3 :   switch (response_code)
     268             :   {
     269             :   case 0:
     270             :     /* Hard error */
     271           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     272             :                 "Backend didn't even return from GET /refund\n");
     273           0 :     return;
     274             :   case MHD_HTTP_OK:
     275           3 :     rlo->cb (rlo->cb_cls,
     276             :              MHD_HTTP_OK,
     277             :              TALER_EC_NONE,
     278             :              json);
     279           3 :     TALER_MERCHANT_refund_lookup_cancel (rlo);
     280           3 :     break;
     281             :   default:
     282             :     /**
     283             :      * The backend gave response, but it's error, log it.
     284             :      * NOTE that json must be a Taler-specific error object (FIXME,
     285             :      * need a link to error objects at docs)
     286             :      */
     287           0 :     json_unpack ((json_t *) json,
     288             :                  "{s:s, s:I, s:s}",
     289             :                  "error", &error,
     290             :                  "code", &code);
     291           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     292             :                 "Failed GET /refund, error: %s, code: %d\n",
     293             :                 error,
     294             :                 code);
     295             :   }
     296             : }
     297             : 
     298             : 
     299             : /**
     300             :  * Does a GET /refund.
     301             :  *
     302             :  * @param ctx execution context
     303             :  * @param backend_url base URL of the merchant backend
     304             :  * @param order_id order id used to perform the lookup
     305             :  * @param cb callback which will work the response gotten from the backend
     306             :  * @param cb_cls closure to pass to the callback
     307             :  * @return handle for this operation, NULL upon errors
     308             :  */
     309             : struct TALER_MERCHANT_RefundLookupOperation *
     310           3 : TALER_MERCHANT_refund_lookup (struct GNUNET_CURL_Context *ctx,
     311             :                               const char *backend_url,
     312             :                               const char *order_id,
     313             :                               const char *instance,
     314             :                               TALER_MERCHANT_RefundLookupCallback cb,
     315             :                               void *cb_cls)
     316             : {
     317             :   struct TALER_MERCHANT_RefundLookupOperation *rlo;
     318             :   CURL *eh;
     319             :   char *base;
     320             : 
     321           3 :   rlo = GNUNET_new (struct TALER_MERCHANT_RefundLookupOperation);
     322           3 :   rlo->ctx = ctx;
     323           3 :   rlo->cb = cb;
     324           3 :   rlo->cb_cls = cb_cls;
     325             :   
     326           3 :   base = TALER_url_join (backend_url, "/public/refund", NULL);
     327           3 :   GNUNET_asprintf (&rlo->url,
     328             :                    "%s?instance=%s&order_id=%s",
     329             :                    base,
     330             :                    instance,
     331             :                    order_id);
     332           3 :   GNUNET_free (base);
     333           3 :   eh = curl_easy_init ();
     334           3 :   if (CURLE_OK != curl_easy_setopt (eh,
     335             :                                     CURLOPT_URL,
     336             :                                     rlo->url))
     337             :   {
     338           0 :     GNUNET_break (0);
     339           0 :     return NULL;
     340             :   }
     341             : 
     342           3 :   if (NULL == (rlo->job = GNUNET_CURL_job_add (ctx,
     343             :                                                eh,
     344             :                                                GNUNET_NO,
     345             :                                                handle_refund_lookup_finished,
     346             :                                                rlo)))
     347             :   {
     348           0 :     GNUNET_break (0);
     349           0 :     return NULL;
     350             :   
     351             :   }
     352             : 
     353           3 :   return rlo;
     354             : }

Generated by: LCOV version 1.13