LCOV - code coverage report
Current view: top level - lib - merchant_api_get-private-orders-ORDER_ID.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 59.5 % 252 150
Test Date: 2026-09-11 17:45:24 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2018-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_get-private-orders-ORDER_ID.c
      19              :  * @brief Implementation of the GET /private/orders/$ORDER_ID request
      20              :  * @author Christian Grothoff
      21              :  */
      22              : #include "platform.h"
      23              : #include <curl/curl.h>
      24              : #include <jansson.h>
      25              : #include <microhttpd.h> /* just for HTTP status codes */
      26              : #include <gnunet/gnunet_util_lib.h>
      27              : #include <gnunet/gnunet_curl_lib.h>
      28              : #include <taler/merchant/get-private-orders-ORDER_ID.h>
      29              : #include "merchant_api_curl_defaults.h"
      30              : #include <taler/taler_json_lib.h>
      31              : 
      32              : 
      33              : /**
      34              :  * Maximum number of refund details we return.
      35              :  */
      36              : #define MAX_REFUND_DETAILS 1024
      37              : 
      38              : /**
      39              :  * Maximum number of wire details we return.
      40              :  */
      41              : #define MAX_WIRE_DETAILS 1024
      42              : 
      43              : 
      44              : /**
      45              :  * Handle for a GET /private/orders/$ORDER_ID operation.
      46              :  */
      47              : struct TALER_MERCHANT_GetPrivateOrderHandle
      48              : {
      49              :   /**
      50              :    * Base URL of the merchant backend.
      51              :    */
      52              :   char *base_url;
      53              : 
      54              :   /**
      55              :    * The full URL for this request.
      56              :    */
      57              :   char *url;
      58              : 
      59              :   /**
      60              :    * Handle for the request.
      61              :    */
      62              :   struct GNUNET_CURL_Job *job;
      63              : 
      64              :   /**
      65              :    * Function to call with the result.
      66              :    */
      67              :   TALER_MERCHANT_GetPrivateOrderCallback cb;
      68              : 
      69              :   /**
      70              :    * Closure for @a cb.
      71              :    */
      72              :   TALER_MERCHANT_GET_PRIVATE_ORDER_RESULT_CLOSURE *cb_cls;
      73              : 
      74              :   /**
      75              :    * Reference to the execution context.
      76              :    */
      77              :   struct GNUNET_CURL_Context *ctx;
      78              : 
      79              :   /**
      80              :    * Order ID.
      81              :    */
      82              :   char *order_id;
      83              : 
      84              :   /**
      85              :    * Session ID for repurchase detection, or NULL.
      86              :    */
      87              :   char *session_id;
      88              : 
      89              :   /**
      90              :    * Long polling timeout.
      91              :    */
      92              :   struct GNUNET_TIME_Relative timeout;
      93              : 
      94              :   /**
      95              :    * Long-poll ETag to suppress unchanged responses.
      96              :    */
      97              :   struct GNUNET_ShortHashCode lp_not_etag;
      98              : 
      99              :   /**
     100              :    * True if @e lp_not_etag was set.
     101              :    */
     102              :   bool have_lp_not_etag;
     103              : 
     104              :   /**
     105              :    * If true, try to obtain wire transfer status from the exchange.
     106              :    */
     107              :   bool transfer;
     108              : 
     109              :   /**
     110              :    * If true, allow refunded orders under already_paid_order_id.
     111              :    */
     112              :   bool allow_refunded_for_repurchase;
     113              : };
     114              : 
     115              : 
     116              : /**
     117              :  * Handle HTTP OK response for an unpaid order.
     118              :  *
     119              :  * @param oph handle for the request
     120              :  * @param[in,out] osr HTTP response we got
     121              :  */
     122              : static void
     123            6 : handle_unpaid (struct TALER_MERCHANT_GetPrivateOrderHandle *oph,
     124              :                struct TALER_MERCHANT_GetPrivateOrderResponse *osr)
     125              : {
     126              :   struct GNUNET_JSON_Specification spec[] = {
     127            6 :     GNUNET_JSON_spec_mark_optional (
     128              :       TALER_JSON_spec_slug (
     129              :         "already_paid_order_id",
     130              :         &osr->details.ok.details.unpaid.already_paid_order_id),
     131              :       NULL),
     132            6 :     GNUNET_JSON_spec_mark_optional (
     133              :       TALER_JSON_spec_web_url (
     134              :         "already_paid_fulfillment_url",
     135              :         &osr->details.ok.details.unpaid.already_paid_fulfillment_url),
     136              :       NULL),
     137            6 :     GNUNET_JSON_spec_string (
     138              :       "taler_pay_uri",
     139              :       &osr->details.ok.details.unpaid.taler_pay_uri),
     140            6 :     GNUNET_JSON_spec_string (
     141              :       "summary",
     142              :       &osr->details.ok.details.unpaid.summary),
     143            6 :     GNUNET_JSON_spec_mark_optional (
     144              :       GNUNET_JSON_spec_object_const (
     145              :         "proto_contract_terms",
     146              :         &osr->details.ok.details.unpaid.proto_contract_terms),
     147              :       NULL),
     148            6 :     TALER_JSON_spec_web_url (
     149              :       "order_status_url",
     150              :       &osr->details.ok.details.unpaid.order_status_url),
     151            6 :     GNUNET_JSON_spec_timestamp (
     152              :       "creation_time",
     153              :       &osr->details.ok.details.unpaid.creation_time),
     154            6 :     GNUNET_JSON_spec_mark_optional (
     155              :       GNUNET_JSON_spec_timestamp (
     156              :         "pay_deadline",
     157              :         &osr->details.ok.details.unpaid.pay_deadline),
     158              :       NULL),
     159            6 :     GNUNET_JSON_spec_end ()
     160              :   };
     161              : 
     162            6 :   if (GNUNET_OK !=
     163            6 :       GNUNET_JSON_parse (osr->hr.reply,
     164              :                          spec,
     165              :                          NULL, NULL))
     166              :   {
     167            0 :     GNUNET_break_op (0);
     168            0 :     osr->hr.http_status = 0;
     169            0 :     osr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     170            0 :     oph->cb (oph->cb_cls,
     171              :              osr);
     172            0 :     return;
     173              :   }
     174            6 :   osr->details.ok.status = TALER_MERCHANT_OSC_UNPAID;
     175            6 :   oph->cb (oph->cb_cls,
     176              :            osr);
     177              : }
     178              : 
     179              : 
     180              : /**
     181              :  * Handle HTTP OK response for a claimed order.
     182              :  *
     183              :  * @param oph handle for the request
     184              :  * @param[in,out] osr HTTP response we got
     185              :  */
     186              : static void
     187            9 : handle_claimed (struct TALER_MERCHANT_GetPrivateOrderHandle *oph,
     188              :                 struct TALER_MERCHANT_GetPrivateOrderResponse *osr)
     189              : {
     190              :   struct GNUNET_JSON_Specification spec[] = {
     191            9 :     GNUNET_JSON_spec_object_const (
     192              :       "contract_terms",
     193              :       &osr->details.ok.details.claimed.contract_terms),
     194            9 :     GNUNET_JSON_spec_mark_optional (
     195              :       TALER_JSON_spec_web_url (
     196              :         "order_status_url",
     197              :         &osr->details.ok.details.claimed.order_status_url),
     198              :       NULL),
     199            9 :     GNUNET_JSON_spec_end ()
     200              :   };
     201              : 
     202            9 :   if (GNUNET_OK !=
     203            9 :       GNUNET_JSON_parse (osr->hr.reply,
     204              :                          spec,
     205              :                          NULL, NULL))
     206              :   {
     207            0 :     GNUNET_break_op (0);
     208            0 :     osr->hr.http_status = 0;
     209            0 :     osr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     210            0 :     oph->cb (oph->cb_cls,
     211              :              osr);
     212            0 :     return;
     213              :   }
     214            9 :   osr->details.ok.status = TALER_MERCHANT_OSC_CLAIMED;
     215            9 :   oph->cb (oph->cb_cls,
     216              :            osr);
     217              : }
     218              : 
     219              : 
     220              : /**
     221              :  * Handle HTTP OK response for a paid order.
     222              :  *
     223              :  * @param oph handle for the request
     224              :  * @param[in,out] osr HTTP response we got
     225              :  */
     226              : static void
     227           28 : handle_paid (struct TALER_MERCHANT_GetPrivateOrderHandle *oph,
     228              :              struct TALER_MERCHANT_GetPrivateOrderResponse *osr)
     229              : {
     230              :   uint32_t hc32;
     231              :   uint32_t ci32;
     232              :   bool ci_missing;
     233              :   const json_t *wire_details;
     234              :   const json_t *refund_details;
     235              :   struct GNUNET_JSON_Specification spec[] = {
     236           28 :     GNUNET_JSON_spec_bool ("refunded",
     237              :                            &osr->details.ok.details.paid.refunded),
     238           28 :     GNUNET_JSON_spec_bool ("refund_pending",
     239              :                            &osr->details.ok.details.paid.refund_pending),
     240           28 :     GNUNET_JSON_spec_bool ("wired",
     241              :                            &osr->details.ok.details.paid.wired),
     242           28 :     TALER_JSON_spec_amount_any ("deposit_total",
     243              :                                 &osr->details.ok.details.paid.deposit_total),
     244           28 :     TALER_JSON_spec_ec ("exchange_code",
     245              :                         &osr->details.ok.details.paid.exchange_ec),
     246           28 :     GNUNET_JSON_spec_uint32 ("exchange_http_status",
     247              :                              &hc32),
     248           28 :     TALER_JSON_spec_amount_any ("refund_amount",
     249              :                                 &osr->details.ok.details.paid.refund_amount),
     250           28 :     GNUNET_JSON_spec_object_const (
     251              :       "contract_terms",
     252              :       &osr->details.ok.details.paid.contract_terms),
     253           28 :     GNUNET_JSON_spec_mark_optional (
     254              :       GNUNET_JSON_spec_uint32 ("choice_index",
     255              :                                &ci32),
     256              :       &ci_missing),
     257           28 :     GNUNET_JSON_spec_array_const ("wire_details",
     258              :                                   &wire_details),
     259           28 :     GNUNET_JSON_spec_array_const ("refund_details",
     260              :                                   &refund_details),
     261           28 :     GNUNET_JSON_spec_mark_optional (
     262              :       GNUNET_JSON_spec_array_const (
     263              :         "refunds_external",
     264              :         &osr->details.ok.details.paid.refunds_external),
     265              :       NULL),
     266           28 :     GNUNET_JSON_spec_mark_optional (
     267              :       GNUNET_JSON_spec_timestamp ("last_payment",
     268              :                                   &osr->details.ok.details.paid.last_payment),
     269              :       NULL),
     270           28 :     TALER_JSON_spec_web_url (
     271              :       "order_status_url",
     272              :       &osr->details.ok.details.paid.order_status_url),
     273           28 :     GNUNET_JSON_spec_end ()
     274              :   };
     275              : 
     276           28 :   if (GNUNET_OK !=
     277           28 :       GNUNET_JSON_parse (osr->hr.reply,
     278              :                          spec,
     279              :                          NULL, NULL))
     280              :   {
     281            0 :     GNUNET_break_op (0);
     282            0 :     osr->hr.http_status = 0;
     283            0 :     osr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     284            0 :     oph->cb (oph->cb_cls,
     285              :              osr);
     286            0 :     return;
     287              :   }
     288           28 :   osr->details.ok.status = TALER_MERCHANT_OSC_PAID;
     289           28 :   osr->details.ok.details.paid.exchange_hc = (unsigned int) hc32;
     290           28 :   osr->details.ok.details.paid.choice_index = ci_missing
     291              :                                                ? -1
     292           28 :                                                : (int) ci32;
     293              :   {
     294           28 :     unsigned int wts_len = (unsigned int) json_array_size (wire_details);
     295           28 :     unsigned int ref_len = (unsigned int) json_array_size (refund_details);
     296              : 
     297           28 :     if ( (json_array_size (wire_details) != (size_t) wts_len) ||
     298              :          (wts_len > MAX_WIRE_DETAILS) )
     299              :     {
     300            0 :       GNUNET_break (0);
     301            0 :       osr->hr.http_status = 0;
     302            0 :       osr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     303            0 :       oph->cb (oph->cb_cls,
     304              :                osr);
     305            0 :       return;
     306              :     }
     307           28 :     if ( (json_array_size (refund_details) != (size_t) ref_len) ||
     308              :          (ref_len > MAX_REFUND_DETAILS) )
     309              :     {
     310            0 :       GNUNET_break (0);
     311            0 :       osr->hr.http_status = 0;
     312            0 :       osr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     313            0 :       oph->cb (oph->cb_cls,
     314              :                osr);
     315            0 :       return;
     316              :     }
     317           28 :     {
     318           28 :       struct TALER_MERCHANT_WireTransfer wts[GNUNET_NZL (wts_len)];
     319           28 :       struct TALER_MERCHANT_GetPrivateOrderRefundDetail ref[
     320           28 :         GNUNET_NZL (ref_len)];
     321              : 
     322           28 :       memset (wts,
     323              :               0,
     324              :               sizeof (wts));
     325           37 :       for (unsigned int i = 0; i<wts_len; i++)
     326              :       {
     327            9 :         struct TALER_MERCHANT_WireTransfer *wt = &wts[i];
     328            9 :         const json_t *w = json_array_get (wire_details,
     329              :                                           i);
     330              :         struct GNUNET_JSON_Specification ispec[] = {
     331            9 :           TALER_JSON_spec_web_url ("exchange_url",
     332              :                                    &wt->exchange_url),
     333            9 :           GNUNET_JSON_spec_fixed_auto ("wtid",
     334              :                                        &wt->wtid),
     335            9 :           GNUNET_JSON_spec_timestamp ("execution_time",
     336              :                                       &wt->execution_time),
     337            9 :           TALER_JSON_spec_amount_any ("amount",
     338              :                                       &wt->total_amount),
     339            9 :           GNUNET_JSON_spec_mark_optional (
     340              :             TALER_JSON_spec_amount_any ("deposit_fee",
     341              :                                         &wt->deposit_fee),
     342              :             NULL),
     343            9 :           GNUNET_JSON_spec_bool ("confirmed",
     344              :                                  &wt->confirmed),
     345            9 :           GNUNET_JSON_spec_mark_optional (
     346              :             GNUNET_JSON_spec_uint64 ("expected_transfer_serial_id",
     347              :                                      &wt->expected_transfer_serial_id),
     348              :             NULL),
     349            9 :           GNUNET_JSON_spec_end ()
     350              :         };
     351              : 
     352            9 :         if (GNUNET_OK !=
     353            9 :             GNUNET_JSON_parse (w,
     354              :                                ispec,
     355              :                                NULL, NULL))
     356              :         {
     357            0 :           GNUNET_break_op (0);
     358            0 :           osr->hr.http_status = 0;
     359            0 :           osr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     360            0 :           oph->cb (oph->cb_cls,
     361              :                    osr);
     362            0 :           return;
     363              :         }
     364              :       }
     365              : 
     366           36 :       for (unsigned int i = 0; i<ref_len; i++)
     367              :       {
     368            8 :         struct TALER_MERCHANT_GetPrivateOrderRefundDetail *ro = &ref[i];
     369            8 :         const json_t *w = json_array_get (refund_details,
     370              :                                           i);
     371              :         struct GNUNET_JSON_Specification ispec[] = {
     372            8 :           TALER_JSON_spec_amount_any ("amount",
     373              :                                       &ro->refund_amount),
     374            8 :           GNUNET_JSON_spec_string ("reason",
     375              :                                    &ro->reason),
     376            8 :           GNUNET_JSON_spec_bool ("pending",
     377              :                                  &ro->pending),
     378            8 :           GNUNET_JSON_spec_timestamp ("timestamp",
     379              :                                       &ro->refund_time),
     380            8 :           GNUNET_JSON_spec_end ()
     381              :         };
     382              : 
     383            8 :         if (GNUNET_OK !=
     384            8 :             GNUNET_JSON_parse (w,
     385              :                                ispec,
     386              :                                NULL, NULL))
     387              :         {
     388            0 :           GNUNET_break_op (0);
     389            0 :           osr->hr.http_status = 0;
     390            0 :           osr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     391            0 :           oph->cb (oph->cb_cls,
     392              :                    osr);
     393            0 :           return;
     394              :         }
     395              :       }
     396              : 
     397           28 :       osr->details.ok.details.paid.wts = wts;
     398           28 :       osr->details.ok.details.paid.wts_len = wts_len;
     399           28 :       osr->details.ok.details.paid.refunds = ref;
     400           28 :       osr->details.ok.details.paid.refunds_len = ref_len;
     401           28 :       oph->cb (oph->cb_cls,
     402              :                osr);
     403              :     }
     404              :   }
     405              : }
     406              : 
     407              : 
     408              : /**
     409              :  * Function called when we're done processing the
     410              :  * HTTP GET /private/orders/$ORDER_ID request.
     411              :  *
     412              :  * @param cls the `struct TALER_MERCHANT_GetPrivateOrderHandle`
     413              :  * @param response_code HTTP response code, 0 on error
     414              :  * @param response response body, NULL if not in JSON
     415              :  */
     416              : static void
     417           43 : handle_get_private_order_finished (void *cls,
     418              :                                    long response_code,
     419              :                                    const void *response)
     420              : {
     421           43 :   struct TALER_MERCHANT_GetPrivateOrderHandle *oph = cls;
     422           43 :   const json_t *json = response;
     423              :   const char *order_status;
     424           43 :   struct TALER_MERCHANT_GetPrivateOrderResponse osr = {
     425           43 :     .hr.http_status = (unsigned int) response_code,
     426              :     .hr.reply = json
     427              :   };
     428              : 
     429           43 :   oph->job = NULL;
     430           43 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     431              :               "Got /private/orders/$ORDER_ID response with status code %u\n",
     432              :               (unsigned int) response_code);
     433           43 :   switch (response_code)
     434              :   {
     435           43 :   case MHD_HTTP_OK:
     436              :     /* see below */
     437           43 :     break;
     438            0 :   case MHD_HTTP_NOT_MODIFIED:
     439            0 :     oph->cb (oph->cb_cls,
     440              :              &osr);
     441            0 :     TALER_MERCHANT_get_private_order_cancel (oph);
     442            0 :     return;
     443            0 :   case MHD_HTTP_ACCEPTED:
     444            0 :     oph->cb (oph->cb_cls,
     445              :              &osr);
     446            0 :     TALER_MERCHANT_get_private_order_cancel (oph);
     447            0 :     return;
     448            0 :   case MHD_HTTP_UNAUTHORIZED:
     449            0 :     osr.hr.ec = TALER_JSON_get_error_code (json);
     450            0 :     osr.hr.hint = TALER_JSON_get_error_hint (json);
     451            0 :     oph->cb (oph->cb_cls,
     452              :              &osr);
     453            0 :     TALER_MERCHANT_get_private_order_cancel (oph);
     454            0 :     return;
     455            0 :   case MHD_HTTP_NOT_FOUND:
     456            0 :     osr.hr.ec = TALER_JSON_get_error_code (json);
     457            0 :     osr.hr.hint = TALER_JSON_get_error_hint (json);
     458            0 :     oph->cb (oph->cb_cls,
     459              :              &osr);
     460            0 :     TALER_MERCHANT_get_private_order_cancel (oph);
     461            0 :     return;
     462            0 :   case MHD_HTTP_GATEWAY_TIMEOUT:
     463            0 :     osr.hr.ec = TALER_JSON_get_error_code (json);
     464            0 :     osr.hr.hint = TALER_JSON_get_error_hint (json);
     465            0 :     oph->cb (oph->cb_cls,
     466              :              &osr);
     467            0 :     TALER_MERCHANT_get_private_order_cancel (oph);
     468            0 :     return;
     469            0 :   default:
     470            0 :     osr.hr.ec = TALER_JSON_get_error_code (json);
     471            0 :     osr.hr.hint = TALER_JSON_get_error_hint (json);
     472            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     473              :                 "Polling order status failed with HTTP status code %u/%d\n",
     474              :                 (unsigned int) response_code,
     475              :                 (int) osr.hr.ec);
     476            0 :     GNUNET_break_op (0);
     477            0 :     oph->cb (oph->cb_cls,
     478              :              &osr);
     479            0 :     TALER_MERCHANT_get_private_order_cancel (oph);
     480            0 :     return;
     481              :   }
     482              : 
     483           43 :   order_status = json_string_value (json_object_get (json,
     484              :                                                      "order_status"));
     485           43 :   if (NULL == order_status)
     486              :   {
     487            0 :     GNUNET_break_op (0);
     488            0 :     osr.hr.http_status = 0;
     489            0 :     osr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     490            0 :     oph->cb (oph->cb_cls,
     491              :              &osr);
     492            0 :     TALER_MERCHANT_get_private_order_cancel (oph);
     493            0 :     return;
     494              :   }
     495              : 
     496           43 :   if (0 == strcmp ("paid",
     497              :                    order_status))
     498              :   {
     499           28 :     handle_paid (oph,
     500              :                  &osr);
     501              :   }
     502           15 :   else if (0 == strcmp ("claimed",
     503              :                         order_status))
     504              :   {
     505            9 :     handle_claimed (oph,
     506              :                     &osr);
     507              :   }
     508            6 :   else if (0 == strcmp ("unpaid",
     509              :                         order_status))
     510              :   {
     511            6 :     handle_unpaid (oph,
     512              :                    &osr);
     513              :   }
     514              :   else
     515              :   {
     516            0 :     GNUNET_break_op (0);
     517            0 :     osr.hr.http_status = 0;
     518            0 :     osr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     519            0 :     oph->cb (oph->cb_cls,
     520              :              &osr);
     521              :   }
     522           43 :   TALER_MERCHANT_get_private_order_cancel (oph);
     523              : }
     524              : 
     525              : 
     526              : struct TALER_MERCHANT_GetPrivateOrderHandle *
     527           43 : TALER_MERCHANT_get_private_order_create (
     528              :   struct GNUNET_CURL_Context *ctx,
     529              :   const char *url,
     530              :   const char *order_id)
     531              : {
     532              :   struct TALER_MERCHANT_GetPrivateOrderHandle *oph;
     533              : 
     534           43 :   oph = GNUNET_new (struct TALER_MERCHANT_GetPrivateOrderHandle);
     535           43 :   oph->ctx = ctx;
     536           43 :   oph->base_url = GNUNET_strdup (url);
     537           43 :   oph->order_id = GNUNET_strdup (order_id);
     538           43 :   return oph;
     539              : }
     540              : 
     541              : 
     542              : enum GNUNET_GenericReturnValue
     543           14 : TALER_MERCHANT_get_private_order_set_options_ (
     544              :   struct TALER_MERCHANT_GetPrivateOrderHandle *oph,
     545              :   unsigned int num_options,
     546              :   const struct TALER_MERCHANT_GetPrivateOrderOptionValue *options)
     547              : {
     548           28 :   for (unsigned int i = 0; i < num_options; i++)
     549              :   {
     550           28 :     const struct TALER_MERCHANT_GetPrivateOrderOptionValue *opt =
     551           28 :       &options[i];
     552              : 
     553           28 :     switch (opt->option)
     554              :     {
     555           14 :     case TALER_MERCHANT_GET_PRIVATE_ORDER_OPTION_END:
     556           14 :       return GNUNET_OK;
     557           10 :     case TALER_MERCHANT_GET_PRIVATE_ORDER_OPTION_SESSION_ID:
     558           10 :       GNUNET_free (oph->session_id);
     559           10 :       if (NULL != opt->details.session_id)
     560           10 :         oph->session_id = GNUNET_strdup (opt->details.session_id);
     561           10 :       break;
     562            4 :     case TALER_MERCHANT_GET_PRIVATE_ORDER_OPTION_TIMEOUT:
     563            4 :       oph->timeout = opt->details.timeout;
     564            4 :       break;
     565            0 :     case TALER_MERCHANT_GET_PRIVATE_ORDER_OPTION_TRANSFER:
     566            0 :       oph->transfer = opt->details.transfer;
     567            0 :       break;
     568            0 :     case TALER_MERCHANT_GET_PRIVATE_ORDER_OPTION_LP_NOT_ETAG:
     569            0 :       if (NULL != opt->details.lp_not_etag)
     570              :       {
     571            0 :         oph->lp_not_etag = *opt->details.lp_not_etag;
     572            0 :         oph->have_lp_not_etag = true;
     573              :       }
     574            0 :       break;
     575            0 :     case TALER_MERCHANT_GET_PRIVATE_ORDER_OPTION_ALLOW_REFUNDED_FOR_REPURCHASE:
     576              :       oph->allow_refunded_for_repurchase
     577            0 :         = opt->details.allow_refunded_for_repurchase;
     578            0 :       break;
     579            0 :     default:
     580            0 :       GNUNET_break (0);
     581            0 :       return GNUNET_NO;
     582              :     }
     583              :   }
     584            0 :   return GNUNET_OK;
     585              : }
     586              : 
     587              : 
     588              : enum TALER_ErrorCode
     589           43 : TALER_MERCHANT_get_private_order_start (
     590              :   struct TALER_MERCHANT_GetPrivateOrderHandle *oph,
     591              :   TALER_MERCHANT_GetPrivateOrderCallback cb,
     592              :   TALER_MERCHANT_GET_PRIVATE_ORDER_RESULT_CLOSURE *cb_cls)
     593              : {
     594              :   CURL *eh;
     595              :   unsigned int tms;
     596              : 
     597           43 :   oph->cb = cb;
     598           43 :   oph->cb_cls = cb_cls;
     599           86 :   tms = (unsigned int) (oph->timeout.rel_value_us
     600           43 :                         / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
     601              :   {
     602              :     char *path;
     603              :     char timeout_ms[32];
     604              :     char etag_str[sizeof (struct GNUNET_ShortHashCode) * 2 + 1];
     605              : 
     606           43 :     GNUNET_snprintf (timeout_ms,
     607              :                      sizeof (timeout_ms),
     608              :                      "%u",
     609              :                      tms);
     610           43 :     if (oph->have_lp_not_etag)
     611              :     {
     612              :       char *end;
     613              : 
     614            0 :       end = GNUNET_STRINGS_data_to_string (
     615            0 :         &oph->lp_not_etag,
     616              :         sizeof (oph->lp_not_etag),
     617              :         etag_str,
     618              :         sizeof (etag_str) - 1);
     619            0 :       *end = '\0';
     620              :     }
     621           43 :     GNUNET_asprintf (&path,
     622              :                      "private/orders/%s",
     623              :                      oph->order_id);
     624          129 :     oph->url = TALER_url_join (oph->base_url,
     625              :                                path,
     626              :                                "session_id",
     627              :                                oph->session_id,
     628              :                                "timeout_ms",
     629              :                                (0 != tms)
     630              :                                ? timeout_ms
     631              :                                : NULL,
     632              :                                "transfer",
     633           43 :                                oph->transfer
     634              :                                ? "YES"
     635              :                                : NULL,
     636              :                                "lp_not_etag",
     637           43 :                                oph->have_lp_not_etag
     638              :                                ? etag_str
     639              :                                : NULL,
     640              :                                "allow_refunded_for_repurchase",
     641           43 :                                oph->allow_refunded_for_repurchase
     642              :                                ? "YES"
     643              :                                : NULL,
     644              :                                NULL);
     645           43 :     GNUNET_free (path);
     646              :   }
     647           43 :   if (NULL == oph->url)
     648            0 :     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
     649           43 :   eh = TALER_MERCHANT_curl_easy_get_ (oph->url);
     650           43 :   if (NULL == eh)
     651            0 :     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
     652           43 :   if (0 != tms)
     653              :   {
     654            4 :     GNUNET_break (CURLE_OK ==
     655              :                   curl_easy_setopt (eh,
     656              :                                     CURLOPT_TIMEOUT_MS,
     657              :                                     (long) (tms + 100L)));
     658              :   }
     659           43 :   oph->job = GNUNET_CURL_job_add (oph->ctx,
     660              :                                   eh,
     661              :                                   &handle_get_private_order_finished,
     662              :                                   oph);
     663           43 :   if (NULL == oph->job)
     664            0 :     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     665           43 :   return TALER_EC_NONE;
     666              : }
     667              : 
     668              : 
     669              : void
     670           43 : TALER_MERCHANT_get_private_order_cancel (
     671              :   struct TALER_MERCHANT_GetPrivateOrderHandle *oph)
     672              : {
     673           43 :   if (NULL != oph->job)
     674              :   {
     675            0 :     GNUNET_CURL_job_cancel (oph->job);
     676            0 :     oph->job = NULL;
     677              :   }
     678           43 :   GNUNET_free (oph->url);
     679           43 :   GNUNET_free (oph->order_id);
     680           43 :   GNUNET_free (oph->session_id);
     681           43 :   GNUNET_free (oph->base_url);
     682           43 :   GNUNET_free (oph);
     683           43 : }
     684              : 
     685              : 
     686              : /* end of merchant_api_get-private-orders-ORDER_ID-new.c */
        

Generated by: LCOV version 2.0-1