merchant

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

pg_lookup_transfers.c (7507B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2022-2024 Taler Systems SA
      4 
      5    TALER is free software; you can redistribute it and/or modify it under the
      6    terms of the GNU 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 backenddb/pg_lookup_transfers.c
     18  * @brief Implementation of the lookup_transfers function for Postgres
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"
     22 #include <taler/taler_error_codes.h>
     23 #include <taler/taler_dbevents.h>
     24 #include <taler/taler_pq_lib.h>
     25 #include "pg_lookup_transfers.h"
     26 #include "pg_helper.h"
     27 
     28 
     29 /**
     30  * Closure for #lookup_transfers_cb().
     31  */
     32 struct LookupTransfersContext
     33 {
     34   /**
     35    * Function to call on results.
     36    */
     37   TALER_MERCHANTDB_TransferCallback cb;
     38 
     39   /**
     40    * Closure for @e cb.
     41    */
     42   void *cb_cls;
     43 
     44   /**
     45    * Postgres context.
     46    */
     47   struct PostgresClosure *pg;
     48 
     49   /**
     50    * Transaction status (set).
     51    */
     52   enum GNUNET_DB_QueryStatus qs;
     53 
     54 };
     55 
     56 
     57 /**
     58  * Function to be called with the results of a SELECT statement
     59  * that has returned @a num_results results.
     60  *
     61  * @param cls of type `struct LookupTransfersContext *`
     62  * @param result the postgres result
     63  * @param num_results the number of results in @a result
     64  */
     65 static void
     66 lookup_transfers_cb (void *cls,
     67                      PGresult *result,
     68                      unsigned int num_results)
     69 {
     70   struct LookupTransfersContext *ltc = cls;
     71 
     72   for (unsigned int i = 0; i<num_results; i++)
     73   {
     74     struct TALER_Amount credit_amount;
     75     struct TALER_WireTransferIdentifierRawP wtid;
     76     struct TALER_FullPayto payto_uri;
     77     char *exchange_url;
     78     uint64_t transfer_serial_id;
     79     struct GNUNET_TIME_Absolute execution_time;
     80     bool expected;
     81     struct GNUNET_PQ_ResultSpec rs[] = {
     82       TALER_PQ_result_spec_amount_with_currency ("credit_amount",
     83                                                  &credit_amount),
     84       GNUNET_PQ_result_spec_auto_from_type ("wtid",
     85                                             &wtid),
     86       GNUNET_PQ_result_spec_string ("payto_uri",
     87                                     &payto_uri.full_payto),
     88       GNUNET_PQ_result_spec_string ("exchange_url",
     89                                     &exchange_url),
     90       GNUNET_PQ_result_spec_uint64 ("credit_serial",
     91                                     &transfer_serial_id),
     92       GNUNET_PQ_result_spec_absolute_time ("execution_time",
     93                                            &execution_time),
     94       GNUNET_PQ_result_spec_bool ("expected",
     95                                   &expected),
     96       GNUNET_PQ_result_spec_end
     97     };
     98 
     99     if (GNUNET_OK !=
    100         GNUNET_PQ_extract_result (result,
    101                                   rs,
    102                                   i))
    103     {
    104       GNUNET_break (0);
    105       ltc->qs = GNUNET_DB_STATUS_HARD_ERROR;
    106       return;
    107     }
    108     ltc->cb (ltc->cb_cls,
    109              &credit_amount,
    110              &wtid,
    111              payto_uri,
    112              exchange_url,
    113              transfer_serial_id,
    114              execution_time,
    115              expected);
    116     GNUNET_PQ_cleanup_result (rs);
    117   }
    118   ltc->qs = num_results;
    119 }
    120 
    121 
    122 enum GNUNET_DB_QueryStatus
    123 TMH_PG_lookup_transfers (void *cls,
    124                          const char *instance_id,
    125                          struct TALER_FullPayto payto_uri,
    126                          struct GNUNET_TIME_Timestamp before,
    127                          struct GNUNET_TIME_Timestamp after,
    128                          int64_t limit,
    129                          uint64_t offset,
    130                          enum TALER_EXCHANGE_YesNoAll expected,
    131                          TALER_MERCHANTDB_TransferCallback cb,
    132                          void *cb_cls)
    133 {
    134   struct PostgresClosure *pg = cls;
    135   uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
    136   bool by_time = ( (! GNUNET_TIME_absolute_is_never (before.abs_time)) ||
    137                    (! GNUNET_TIME_absolute_is_zero (after.abs_time)) );
    138   struct LookupTransfersContext ltc = {
    139     .cb = cb,
    140     .cb_cls = cb_cls,
    141     .pg = pg
    142   };
    143   struct GNUNET_PQ_QueryParam params[] = {
    144     GNUNET_PQ_query_param_string (instance_id),
    145     GNUNET_PQ_query_param_timestamp (&before),
    146     GNUNET_PQ_query_param_timestamp (&after),
    147     GNUNET_PQ_query_param_uint64 (&offset),
    148     GNUNET_PQ_query_param_uint64 (&plimit),
    149     NULL == payto_uri.full_payto
    150     ? GNUNET_PQ_query_param_null () /* NULL: do not filter by payto URI */
    151     : GNUNET_PQ_query_param_string (payto_uri.full_payto),
    152     GNUNET_PQ_query_param_bool (! by_time),     /* $7: filter by time? */
    153     GNUNET_PQ_query_param_bool (TALER_EXCHANGE_YNA_ALL == expected), /* filter by expected? */
    154     GNUNET_PQ_query_param_bool (TALER_EXCHANGE_YNA_YES == expected),
    155 
    156     GNUNET_PQ_query_param_end
    157   };
    158   enum GNUNET_DB_QueryStatus qs;
    159 
    160   check_connection (pg);
    161   PREPARE (pg,
    162            "lookup_transfers_asc",
    163            "SELECT"
    164            " mt.credit_amount"
    165            ",mt.wtid"
    166            ",mac.payto_uri"
    167            ",mt.exchange_url"
    168            ",mt.credit_serial"
    169            ",mt.execution_time"
    170            ",mt.expected"
    171            " FROM merchant_transfers mt"
    172            "  JOIN merchant_accounts mac"
    173            "    USING (account_serial)"
    174            " WHERE ( $7 OR "
    175            "         (mt.execution_time < $2 AND"
    176            "          mt.execution_time >= $3) )"
    177            "   AND ( (CAST($6 AS TEXT) IS NULL) OR "
    178            "         (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
    179            "         =REGEXP_REPLACE($6,'\\?.*','')) )"
    180            "   AND ( $8 OR "
    181            "         (mt.expected = $9) )"
    182            "   AND merchant_serial ="
    183            "     (SELECT merchant_serial"
    184            "        FROM merchant_instances"
    185            "       WHERE merchant_id=$1)"
    186            "   AND (mt.credit_serial > $4)"
    187            " ORDER BY mt.credit_serial ASC"
    188            " LIMIT $5");
    189   PREPARE (pg,
    190            "lookup_transfers_desc",
    191            "SELECT"
    192            " mt.credit_amount"
    193            ",mt.wtid"
    194            ",mac.payto_uri"
    195            ",mt.exchange_url"
    196            ",mt.credit_serial"
    197            ",mt.execution_time"
    198            ",mt.expected"
    199            " FROM merchant_transfers mt"
    200            "  JOIN merchant_accounts mac"
    201            "    USING (account_serial)"
    202            " WHERE ( $7 OR "
    203            "         (mt.execution_time < $2 AND"
    204            "          mt.execution_time >= $3) )"
    205            "   AND ( (CAST($6 AS TEXT) IS NULL) OR "
    206            "         (REGEXP_REPLACE(mac.payto_uri,'\\?.*','')"
    207            "         =REGEXP_REPLACE($6,'\\?.*','')) )"
    208            "   AND ( $8 OR "
    209            "         (mt.expected = $9) )"
    210            "   AND merchant_serial ="
    211            "     (SELECT merchant_serial"
    212            "        FROM merchant_instances"
    213            "       WHERE merchant_id=$1)"
    214            "   AND (mt.credit_serial < $4)"
    215            " ORDER BY mt.credit_serial DESC"
    216            " LIMIT $5");
    217   qs = GNUNET_PQ_eval_prepared_multi_select (
    218     pg->conn,
    219     (limit > 0)
    220     ? "lookup_transfers_asc"
    221     : "lookup_transfers_desc",
    222     params,
    223     &lookup_transfers_cb,
    224     &ltc);
    225   if (0 >= qs)
    226     return qs;
    227   return ltc.qs;
    228 }