merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_get-private-incoming-ID.c (8452B)


      1 /*
      2   This file is part of TALER
      3   (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 Affero General Public License as published by the Free Software
      7   Foundation; either version 3, 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 General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file taler-merchant-httpd_get-private-incoming-ID.c
     18  * @brief implement API for obtaining details about an expected incoming wire transfer
     19  * @author Christian Grothoff
     20  */
     21 #include "taler/platform.h"
     22 #include <jansson.h>
     23 #include <taler/taler_json_lib.h>
     24 #include "taler-merchant-httpd_get-private-incoming-ID.h"
     25 
     26 
     27 /**
     28  * Function called with information about orders aggregated into
     29  * a wire transfer.
     30  * Generate a response (array entry) based on the given arguments.
     31  *
     32  * @param cls closure with a `json_t *` array to build up the response
     33  * @param order_id ID of the order that was paid and aggregated
     34  * @param remaining_deposit deposited amount minus any refunds
     35  * @param deposit_fee deposit fees paid to the exchange for the order
     36  */
     37 static void
     38 reconciliation_cb (void *cls,
     39                    const char *order_id,
     40                    const struct TALER_Amount *remaining_deposit,
     41                    const struct TALER_Amount *deposit_fee)
     42 {
     43   json_t *rd = cls;
     44   json_t *r;
     45 
     46   r = GNUNET_JSON_PACK (
     47     GNUNET_JSON_pack_string ("order_id",
     48                              order_id),
     49     TALER_JSON_pack_amount ("remaining_deposit",
     50                             remaining_deposit),
     51     TALER_JSON_pack_amount ("deposit_fee",
     52                             deposit_fee));
     53   GNUNET_assert (0 ==
     54                  json_array_append_new (rd,
     55                                         r));
     56 }
     57 
     58 
     59 /**
     60  * Manages a GET /private/incoming call.
     61  *
     62  * @param rh context of the handler
     63  * @param connection the MHD connection to handle
     64  * @param[in,out] hc context with further information about the request
     65  * @return MHD result code
     66  */
     67 MHD_RESULT
     68 TMH_private_get_incoming_ID (const struct TMH_RequestHandler *rh,
     69                              struct MHD_Connection *connection,
     70                              struct TMH_HandlerContext *hc)
     71 {
     72   unsigned long long serial_id;
     73   struct TALER_Amount wire_fee;
     74   bool no_fee;
     75   struct GNUNET_TIME_Timestamp expected_time;
     76   struct TALER_Amount expected_credit_amount;
     77   struct TALER_WireTransferIdentifierRawP wtid;
     78   struct TALER_FullPayto payto_uri;
     79   char *exchange_url = NULL;
     80   struct GNUNET_TIME_Timestamp execution_time;
     81   bool confirmed;
     82 
     83   {
     84     char dummy;
     85 
     86     if (1 !=
     87         sscanf (hc->infix,
     88                 "%llu%c",
     89                 &serial_id,
     90                 &dummy))
     91     {
     92       GNUNET_break_op (0);
     93       return TALER_MHD_reply_with_error (
     94         connection,
     95         MHD_HTTP_BAD_REQUEST,
     96         TALER_EC_GENERIC_PARAMETER_MALFORMED,
     97         "transfer ID must be a number");
     98     }
     99   }
    100 
    101   TMH_db->preflight (TMH_db->cls);
    102   {
    103     struct TALER_MasterPublicKeyP master_pub;
    104     enum GNUNET_DB_QueryStatus qs;
    105 
    106     qs = TMH_db->lookup_expected_transfer (TMH_db->cls,
    107                                            hc->instance->settings.id,
    108                                            serial_id,
    109                                            &expected_time,
    110                                            &expected_credit_amount,
    111                                            &wtid,
    112                                            &payto_uri,
    113                                            &exchange_url,
    114                                            &execution_time,
    115                                            &confirmed,
    116                                            &master_pub);
    117     if (0 > qs)
    118     {
    119       /* Simple select queries should not cause serialization issues */
    120       GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
    121       /* Always report on hard error as well to enable diagnostics */
    122       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
    123       return TALER_MHD_reply_with_error (connection,
    124                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
    125                                          TALER_EC_GENERIC_DB_FETCH_FAILED,
    126                                          "lookup_expected_transfer");
    127     }
    128     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
    129     {
    130       GNUNET_break_op (0);
    131       return TALER_MHD_reply_with_error (
    132         connection,
    133         MHD_HTTP_NOT_FOUND,
    134         TALER_EC_MERCHANT_GENERIC_EXPECTED_TRANSFER_UNKNOWN,
    135         hc->infix);
    136     }
    137 
    138     {
    139       char *method;
    140       struct GNUNET_TIME_Timestamp start_date;
    141       struct GNUNET_TIME_Timestamp end_date;
    142       struct TALER_MasterSignatureP master_sig;
    143       struct TALER_WireFeeSet fees;
    144 
    145       method = TALER_payto_get_method (payto_uri.full_payto);
    146       qs = TMH_db->lookup_wire_fee (
    147         TMH_db->cls,
    148         &master_pub,
    149         method,
    150         expected_time,
    151         &fees,
    152         &start_date,
    153         &end_date,
    154         &master_sig);
    155       GNUNET_free (method);
    156       if (0 > qs)
    157       {
    158         /* Simple select queries should not cause serialization issues */
    159         GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
    160         /* Always report on hard error as well to enable diagnostics */
    161         GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
    162         GNUNET_free (exchange_url);
    163         GNUNET_free (payto_uri.full_payto);
    164         return TALER_MHD_reply_with_error (connection,
    165                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
    166                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
    167                                            "lookup_wire_fee");
    168       }
    169       no_fee = (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
    170       if (! no_fee)
    171         wire_fee = fees.wire;
    172     }
    173 
    174   }
    175 
    176   {
    177     enum GNUNET_DB_QueryStatus qs;
    178     json_t *rd;
    179     MHD_RESULT mret;
    180 
    181     rd = json_array ();
    182     GNUNET_assert (NULL != rd);
    183     qs = TMH_db->lookup_reconciliation_details (TMH_db->cls,
    184                                                 hc->instance->settings.id,
    185                                                 serial_id,
    186                                                 &reconciliation_cb,
    187                                                 rd);
    188     if (0 > qs)
    189     {
    190       /* Simple select queries should not cause serialization issues */
    191       GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
    192       /* Always report on hard error as well to enable diagnostics */
    193       GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
    194       GNUNET_free (exchange_url);
    195       GNUNET_free (payto_uri.full_payto);
    196       return TALER_MHD_reply_with_error (connection,
    197                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
    198                                          TALER_EC_GENERIC_DB_FETCH_FAILED,
    199                                          "lookup_reconciliation_details");
    200     }
    201 
    202     mret = TALER_MHD_REPLY_JSON_PACK (
    203       connection,
    204       MHD_HTTP_OK,
    205       GNUNET_JSON_pack_allow_null (
    206         TALER_JSON_pack_amount (
    207           "expected_credit_amount",
    208           TALER_amount_is_valid (&expected_credit_amount)
    209           ? &expected_credit_amount
    210           : NULL)),
    211       GNUNET_JSON_pack_data_auto ("wtid",
    212                                   &wtid),
    213       TALER_JSON_pack_full_payto ("payto_uri",
    214                                   payto_uri),
    215       GNUNET_JSON_pack_string ("exchange_url",
    216                                exchange_url),
    217       GNUNET_JSON_pack_bool ("confirmed",
    218                              confirmed),
    219       GNUNET_JSON_pack_allow_null (
    220         GNUNET_JSON_pack_timestamp ("execution_time",
    221                                     execution_time)),
    222       GNUNET_JSON_pack_timestamp ("expected_time",
    223                                   expected_time),
    224       GNUNET_JSON_pack_allow_null (
    225         TALER_JSON_pack_amount ("wire_fee",
    226                                 no_fee ? NULL : &wire_fee)),
    227       GNUNET_JSON_pack_array_steal ("reconciliation_details",
    228                                     rd));
    229     GNUNET_free (exchange_url);
    230     GNUNET_free (payto_uri.full_payto);
    231     return mret;
    232   }
    233 }
    234 
    235 
    236 /* end of taler-merchant-httpd_get-private-incoming-ID.c */