summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2023-05-15 13:02:54 -0600
committerIván Ávalos <avalos@disroot.org>2023-05-15 13:02:54 -0600
commitb712481beaeb1dcc2e2a7195d0607a3c0f073665 (patch)
treed7f5135530d2e9f01671d1898685f9ff2edb3e9c
parent51ee9c489a0f2c5749d84af39bb3e27fc99cf682 (diff)
downloadmerchant-b712481beaeb1dcc2e2a7195d0607a3c0f073665.tar.gz
merchant-b712481beaeb1dcc2e2a7195d0607a3c0f073665.tar.bz2
merchant-b712481beaeb1dcc2e2a7195d0607a3c0f073665.zip
Factor out 9 new functions (shit job)
-rw-r--r--src/backenddb/Makefile.am9
-rw-r--r--src/backenddb/pg_insert_deposit.c114
-rw-r--r--src/backenddb/pg_insert_deposit.h61
-rw-r--r--src/backenddb/pg_insert_exchange_signkey.c66
-rw-r--r--src/backenddb/pg_insert_exchange_signkey.h48
-rw-r--r--src/backenddb/pg_lookup_deposits.c173
-rw-r--r--src/backenddb/pg_lookup_deposits.h46
-rw-r--r--src/backenddb/pg_lookup_order_status.c73
-rw-r--r--src/backenddb/pg_lookup_order_status.h45
-rw-r--r--src/backenddb/pg_lookup_order_status_by_serial.c77
-rw-r--r--src/backenddb/pg_lookup_order_status_by_serial.h48
-rw-r--r--src/backenddb/pg_lookup_payment_status.c98
-rw-r--r--src/backenddb/pg_lookup_payment_status.h45
-rw-r--r--src/backenddb/pg_lookup_refunds.c150
-rw-r--r--src/backenddb/pg_lookup_refunds.h45
-rw-r--r--src/backenddb/pg_mark_contract_paid.c112
-rw-r--r--src/backenddb/pg_mark_contract_paid.h45
-rw-r--r--src/backenddb/pg_refund_coin.c77
-rw-r--r--src/backenddb/pg_refund_coin.h51
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c863
20 files changed, 1410 insertions, 836 deletions
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index 1b400bce..745e33eb 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -94,6 +94,15 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \
pg_insert_contract_terms.h pg_insert_contract_terms.c \
pg_update_contract_terms.h pg_update_contract_terms.c \
pg_delete_contract_terms.h pg_delete_contract_terms.c \
+ pg_lookup_deposits.h pg_lookup_deposits.c \
+ pg_insert_exchange_signkey.h pg_insert_exchange_signkey.c \
+ pg_insert_deposit.h pg_insert_deposit.c \
+ pg_lookup_refunds.h pg_lookup_refunds.c \
+ pg_mark_contract_paid.h pg_mark_contract_paid.c \
+ pg_refund_coin.h pg_refund_coin.c \
+ pg_lookup_order_status.h pg_lookup_order_status.c \
+ pg_lookup_order_status_by_serial.h pg_lookup_order_status_by_serial.c \
+ pg_lookup_payment_status.h pg_lookup_payment_status.c \
plugin_merchantdb_postgres.c pg_helper.h
libtaler_plugin_merchantdb_postgres_la_LIBADD = \
$(LTLIBINTL)
diff --git a/src/backenddb/pg_insert_deposit.c b/src/backenddb/pg_insert_deposit.c
new file mode 100644
index 00000000..f7f20d47
--- /dev/null
+++ b/src/backenddb/pg_insert_deposit.c
@@ -0,0 +1,114 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_insert_deposit.c
+ * @brief Implementation of the insert_deposit function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_insert_deposit.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_deposit (
+ void *cls,
+ const char *instance_id,
+ struct GNUNET_TIME_Timestamp deposit_timestamp,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const char *exchange_url,
+ const struct TALER_Amount *amount_with_fee,
+ const struct TALER_Amount *deposit_fee,
+ const struct TALER_Amount *refund_fee,
+ const struct TALER_Amount *wire_fee,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const struct TALER_ExchangeSignatureP *exchange_sig,
+ const struct TALER_ExchangePublicKeyP *exchange_pub)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_timestamp (&deposit_timestamp), /* $3 */
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_string (exchange_url),
+ TALER_PQ_query_param_amount (amount_with_fee), /* $6/$7 */
+ TALER_PQ_query_param_amount (deposit_fee), /* $8, $9 */
+ TALER_PQ_query_param_amount (refund_fee), /* $10, $11 */
+ TALER_PQ_query_param_amount (wire_fee), /* $12, $13 */
+ GNUNET_PQ_query_param_auto_from_type (h_wire), /* $14 */
+ GNUNET_PQ_query_param_auto_from_type (exchange_sig), /* $15 */
+ GNUNET_PQ_query_param_auto_from_type (exchange_pub), /* $16 */
+ GNUNET_PQ_query_param_end
+ };
+
+ /* no preflight check here, run in transaction by caller! */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Storing deposit for instance `%s' h_contract_terms `%s', coin_pub: `%s', amount_with_fee: %s\n",
+ instance_id,
+ GNUNET_h2s (&h_contract_terms->hash),
+ TALER_B2S (coin_pub),
+ TALER_amount2s (amount_with_fee));
+ check_connection (pg);
+ PREPARE (pg,
+ "insert_deposit",
+ "WITH md AS"
+ " (SELECT account_serial, merchant_serial"
+ " FROM merchant_accounts"
+ " WHERE h_wire=$14"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))"
+ ", ed AS"
+ " (SELECT signkey_serial"
+ " FROM merchant_exchange_signing_keys"
+ " WHERE exchange_pub=$16"
+ " ORDER BY start_date DESC"
+ " LIMIT 1)"
+ "INSERT INTO merchant_deposits"
+ "(order_serial"
+ ",deposit_timestamp"
+ ",coin_pub"
+ ",exchange_url"
+ ",amount_with_fee_val"
+ ",amount_with_fee_frac"
+ ",deposit_fee_val"
+ ",deposit_fee_frac"
+ ",refund_fee_val"
+ ",refund_fee_frac"
+ ",wire_fee_val"
+ ",wire_fee_frac"
+ ",exchange_sig"
+ ",signkey_serial"
+ ",account_serial)"
+ " SELECT "
+ " order_serial"
+ " ,$3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $15"
+ " ,ed.signkey_serial"
+ " ,md.account_serial"
+ " FROM merchant_contract_terms"
+ " JOIN md USING (merchant_serial)"
+ " FULL OUTER JOIN ed ON TRUE"
+ " WHERE h_contract_terms=$2");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_deposit",
+ params);
+
+}
diff --git a/src/backenddb/pg_insert_deposit.h b/src/backenddb/pg_insert_deposit.h
new file mode 100644
index 00000000..49d783aa
--- /dev/null
+++ b/src/backenddb/pg_insert_deposit.h
@@ -0,0 +1,61 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_insert_deposit.h
+ * @brief implementation of the insert_deposit function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_INSERT_DEPOSIT_H
+#define PG_INSERT_DEPOSIT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Insert payment confirmation from the exchange into the database.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup deposits for
+ * @param deposit_timestamp time when the exchange generated the deposit confirmation
+ * @param h_contract_terms proposal data's hashcode
+ * @param coin_pub public key of the coin
+ * @param exchange_url URL of the exchange that issued @a coin_pub
+ * @param amount_with_fee amount the exchange will deposit for this coin
+ * @param deposit_fee fee the exchange will charge for this coin
+ * @param wire_fee wire fee the exchange charges
+ * @param refund_fee fee the exchange charges to refund this coin
+ * @param h_wire hash of the wire details of the target account of the merchant
+ * @param exchange_sig signature from exchange that coin was accepted
+ * @param exchange_pub signgin key that was used for @a exchange_sig
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_deposit (void *cls,
+ const char *instance_id,
+ struct GNUNET_TIME_Timestamp deposit_timestamp,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const char *exchange_url,
+ const struct TALER_Amount *amount_with_fee,
+ const struct TALER_Amount *deposit_fee,
+ const struct TALER_Amount *refund_fee,
+ const struct TALER_Amount *wire_fee,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const struct TALER_ExchangeSignatureP *exchange_sig,
+ const struct TALER_ExchangePublicKeyP *exchange_pub);
+
+#endif
diff --git a/src/backenddb/pg_insert_exchange_signkey.c b/src/backenddb/pg_insert_exchange_signkey.c
new file mode 100644
index 00000000..81d27d60
--- /dev/null
+++ b/src/backenddb/pg_insert_exchange_signkey.c
@@ -0,0 +1,66 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_insert_exchange_signkey.c
+ * @brief Implementation of the insert_exchange_signkey function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_insert_exchange_signkey.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_exchange_signkey (
+ void *cls,
+ const struct TALER_MasterPublicKeyP *master_pub,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ struct GNUNET_TIME_Timestamp start_date,
+ struct GNUNET_TIME_Timestamp expire_date,
+ struct GNUNET_TIME_Timestamp end_date,
+ const struct TALER_MasterSignatureP *master_sig)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (master_pub),
+ GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+ GNUNET_PQ_query_param_timestamp (&start_date),
+ GNUNET_PQ_query_param_timestamp (&expire_date),
+ GNUNET_PQ_query_param_timestamp (&end_date),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ postgres_preflight (pg);
+ PREPARE (pg,
+ "insert_exchange_signkey",
+ "INSERT INTO merchant_exchange_signing_keys"
+ "(master_pub"
+ ",exchange_pub"
+ ",start_date"
+ ",expire_date"
+ ",end_date"
+ ",master_sig)"
+ "VALUES"
+ "($1, $2, $3, $4, $5, $6)");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_exchange_signkey",
+ params);
+
+}
diff --git a/src/backenddb/pg_insert_exchange_signkey.h b/src/backenddb/pg_insert_exchange_signkey.h
new file mode 100644
index 00000000..78f84846
--- /dev/null
+++ b/src/backenddb/pg_insert_exchange_signkey.h
@@ -0,0 +1,48 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_insert_exchange_signkey.h
+ * @brief implementation of the insert_exchange_signkey function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_INSERT_EXCHANGE_SIGNKEY_H
+#define PG_INSERT_EXCHANGE_SIGNKEY_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Insert an exchange signing key into our database.
+ *
+ * @param cls closure
+ * @param master_pub exchange master public key used for @a master_sig
+ * @param exchange_pub exchange signing key to insert
+ * @param start_date when does the signing key become valid
+ * @param expire_date when does the signing key stop being used
+ * @param end_date when does the signing key become void as proof
+ * @param master_sig signature of @a master_pub over the @a exchange_pub and the dates
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_exchange_signkey (void *cls,
+ const struct TALER_MasterPublicKeyP *master_pub,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ struct GNUNET_TIME_Timestamp start_date,
+ struct GNUNET_TIME_Timestamp expire_date,
+ struct GNUNET_TIME_Timestamp end_date,
+ const struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/backenddb/pg_lookup_deposits.c b/src/backenddb/pg_lookup_deposits.c
new file mode 100644
index 00000000..27647dda
--- /dev/null
+++ b/src/backenddb/pg_lookup_deposits.c
@@ -0,0 +1,173 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_deposits.c
+ * @brief Implementation of the lookup_deposits function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_deposits.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #lookup_deposits_cb().
+ */
+struct LookupDepositsContext
+{
+ /**
+ * Function to call with results.
+ */
+ TALER_MERCHANTDB_DepositsCallback cb;
+
+ /**
+ * Closure for @e cls.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct PostgresClosure *pg;
+
+ /**
+ * Transaction status (set).
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param[in,out] cls of type `struct LookupDepositsContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_deposits_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupDepositsContext *ldc = cls;
+ struct PostgresClosure *pg = ldc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount deposit_fee;
+ struct TALER_Amount refund_fee;
+ struct TALER_Amount wire_fee;
+ char *exchange_url;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("exchange_url",
+ &exchange_url),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &coin_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("deposit_fee",
+ &deposit_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("refund_fee",
+ &refund_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+ &wire_fee),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ldc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ ldc->cb (ldc->cb_cls,
+ exchange_url,
+ &coin_pub,
+ &amount_with_fee,
+ &deposit_fee,
+ &refund_fee,
+ &wire_fee);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+ ldc->qs = num_results;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_deposits (
+ void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ TALER_MERCHANTDB_DepositsCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_end
+ };
+ struct LookupDepositsContext ldc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* no preflight check here, run in its own transaction by the caller! */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Finding deposits for h_contract_terms '%s'\n",
+ GNUNET_h2s (&h_contract_terms->hash));
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_deposits",
+ "SELECT"
+ " exchange_url"
+ ",coin_pub"
+ ",amount_with_fee_val"
+ ",amount_with_fee_frac"
+ ",deposit_fee_val"
+ ",deposit_fee_frac"
+ ",refund_fee_val"
+ ",refund_fee_frac"
+ ",wire_fee_val"
+ ",wire_fee_frac"
+ " FROM merchant_deposits"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_deposits",
+ params,
+ &lookup_deposits_cb,
+ &ldc);
+ if (qs <= 0)
+ return qs;
+ return ldc.qs;
+}
diff --git a/src/backenddb/pg_lookup_deposits.h b/src/backenddb/pg_lookup_deposits.h
new file mode 100644
index 00000000..891a1093
--- /dev/null
+++ b/src/backenddb/pg_lookup_deposits.h
@@ -0,0 +1,46 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_deposits.h
+ * @brief implementation of the lookup_deposits function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_DEPOSITS_H
+#define PG_LOOKUP_DEPOSITS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Lookup information about coins that were successfully deposited for a
+ * given contract.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup deposits for
+ * @param h_contract_terms proposal data's hashcode
+ * @param cb function to call with payment data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_deposits (void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ TALER_MERCHANTDB_DepositsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/backenddb/pg_lookup_order_status.c b/src/backenddb/pg_lookup_order_status.c
new file mode 100644
index 00000000..be6f0a15
--- /dev/null
+++ b/src/backenddb/pg_lookup_order_status.c
@@ -0,0 +1,73 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_order_status.c
+ * @brief Implementation of the lookup_order_status function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_order_status.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_order_status (
+ void *cls,
+ const char *instance_id,
+ const char *order_id,
+ struct TALER_PrivateContractHashP *h_contract_terms,
+ bool *paid)
+{
+ struct PostgresClosure *pg = cls;
+ uint8_t paid8;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_string (order_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("paid",
+ &paid8),
+ GNUNET_PQ_result_spec_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_order_status",
+ "SELECT"
+ " h_contract_terms"
+ ",paid"
+ " FROM merchant_contract_terms"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND order_id=$2");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_order_status",
+ params,
+ rs);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ *paid = (0 != paid8);
+ else
+ *paid = false; /* just to be safe(r) */
+ return qs;
+}
diff --git a/src/backenddb/pg_lookup_order_status.h b/src/backenddb/pg_lookup_order_status.h
new file mode 100644
index 00000000..acf8fe31
--- /dev/null
+++ b/src/backenddb/pg_lookup_order_status.h
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_order_status.h
+ * @brief implementation of the lookup_order_status function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_ORDER_STATUS_H
+#define PG_LOOKUP_ORDER_STATUS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Retrieve contract terms given its @a order_id
+ *
+ * @param cls closure
+ * @param instance_id instance's identifier
+ * @param order_id order to lookup contract for
+ * @param[out] h_contract_terms set to the hash of the contract.
+ * @param[out] paid set to the payment status of the contract
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_order_status (void *cls,
+ const char *instance_id,
+ const char *order_id,
+ struct TALER_PrivateContractHashP *h_contract_terms,
+ bool *paid);
+
+#endif
diff --git a/src/backenddb/pg_lookup_order_status_by_serial.c b/src/backenddb/pg_lookup_order_status_by_serial.c
new file mode 100644
index 00000000..b6a4ebb0
--- /dev/null
+++ b/src/backenddb/pg_lookup_order_status_by_serial.c
@@ -0,0 +1,77 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_order_status_by_serial.c
+ * @brief Implementation of the lookup_order_status_by_serial function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_order_status_by_serial.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_order_status_by_serial (void *cls,
+ const char *instance_id,
+ uint64_t order_serial,
+ char **order_id,
+ struct TALER_PrivateContractHashP *
+ h_contract_terms,
+ bool *paid)
+{
+ struct PostgresClosure *pg = cls;
+ uint8_t paid8;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_uint64 (&order_serial),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("paid",
+ &paid8),
+ GNUNET_PQ_result_spec_string ("order_id",
+ order_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_order_status_by_serial",
+ "SELECT"
+ " h_contract_terms"
+ ",order_id"
+ ",paid"
+ " FROM merchant_contract_terms"
+ " WHERE merchant_serial="
+ " (SELECT merchant_serial "
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND order_serial=$2");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_order_status_by_serial",
+ params,
+ rs);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ *paid = (0 != paid8);
+ else
+ *paid = false; /* just to be safe(r) */
+ return qs;
+}
diff --git a/src/backenddb/pg_lookup_order_status_by_serial.h b/src/backenddb/pg_lookup_order_status_by_serial.h
new file mode 100644
index 00000000..eb60e97f
--- /dev/null
+++ b/src/backenddb/pg_lookup_order_status_by_serial.h
@@ -0,0 +1,48 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_order_status_by_serial.h
+ * @brief implementation of the lookup_order_status_by_serial function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_ORDER_STATUS_BY_SERIAL_H
+#define PG_LOOKUP_ORDER_STATUS_BY_SERIAL_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Retrieve contract terms given its @a order_serial
+ *
+ * @param cls closure
+ * @param instance_id instance's identifier
+ * @param order_serial serial ID of the order to look up
+ * @param[out] order_id set to ID of the order
+ * @param[out] h_contract_terms set to the hash of the contract.
+ * @param[out] paid set to the payment status of the contract
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_order_status_by_serial (void *cls,
+ const char *instance_id,
+ uint64_t order_serial,
+ char **order_id,
+ struct TALER_PrivateContractHashP *
+ h_contract_terms,
+ bool *paid);
+
+#endif
diff --git a/src/backenddb/pg_lookup_payment_status.c b/src/backenddb/pg_lookup_payment_status.c
new file mode 100644
index 00000000..fc4e5d94
--- /dev/null
+++ b/src/backenddb/pg_lookup_payment_status.c
@@ -0,0 +1,98 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_payment_status.c
+ * @brief Implementation of the lookup_payment_status function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_payment_status.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_payment_status (void *cls,
+ uint64_t order_serial,
+ const char *session_id,
+ bool *paid,
+ bool *wired)
+{
+ struct PostgresClosure *pg = cls;
+ uint8_t paid8;
+ uint8_t wired8;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("paid",
+ &paid8),
+ GNUNET_PQ_result_spec_auto_from_type ("wired",
+ &wired8),
+ GNUNET_PQ_result_spec_end
+ };
+ check_connection (pg);
+ if (NULL == session_id)
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&order_serial),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "lookup_payment_status",
+ "SELECT"
+ " wired"
+ ",paid"
+ " FROM merchant_contract_terms"
+ " WHERE order_serial=$1");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_payment_status",
+ params,
+ rs);
+ }
+ else
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&order_serial),
+ GNUNET_PQ_query_param_string (session_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "lookup_payment_status_session_id",
+ "SELECT"
+ " wired"
+ ",paid"
+ " FROM merchant_contract_terms"
+ " WHERE order_serial=$1"
+ " AND session_id=$2");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_payment_status_session_id",
+ params,
+ rs);
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ *paid = (0 != paid8);
+ *wired = (0 != wired8);
+ }
+ else
+ {
+ *paid = false; /* just to be safe(r) */
+ *wired = false; /* just to be safe(r) */
+ }
+ return qs;
+}
diff --git a/src/backenddb/pg_lookup_payment_status.h b/src/backenddb/pg_lookup_payment_status.h
new file mode 100644
index 00000000..a46ee31e
--- /dev/null
+++ b/src/backenddb/pg_lookup_payment_status.h
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_payment_status.h
+ * @brief implementation of the lookup_payment_status function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_PAYMENT_STATUS_H
+#define PG_LOOKUP_PAYMENT_STATUS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Retrieve payment and wire status for a given @a order_serial and session ID.
+ *
+ * @param cls closure
+ * @param order_serial identifies the order
+ * @param session_id session for which to check the payment status, NULL for any
+ * @param[out] paid set to the payment status of the contract
+ * @param[out] wired set to the wire transfer status of the exchange payment
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_payment_status (void *cls,
+ uint64_t order_serial,
+ const char *session_id,
+ bool *paid,
+ bool *wired);
+
+#endif
diff --git a/src/backenddb/pg_lookup_refunds.c b/src/backenddb/pg_lookup_refunds.c
new file mode 100644
index 00000000..bc943162
--- /dev/null
+++ b/src/backenddb/pg_lookup_refunds.c
@@ -0,0 +1,150 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_refunds.c
+ * @brief Implementation of the lookup_refunds function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_lookup_refunds.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #lookup_refunds_cb().
+ */
+struct LookupRefundsContext
+{
+ /**
+ * Function to call for each refund.
+ */
+ TALER_MERCHANTDB_RefundCallback rc;
+
+ /**
+ * Closure for @e rc.
+ */
+ void *rc_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct PostgresClosure *pg;
+
+ /**
+ * Transaction result.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls of type `struct LookupRefundsContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lookup_refunds_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRefundsContext *lrc = cls;
+ struct PostgresClosure *pg = lrc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_Amount refund_amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &coin_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("refund_amount",
+ &refund_amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ lrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ lrc->rc (lrc->rc_cls,
+ &coin_pub,
+ &refund_amount);
+ GNUNET_PQ_cleanup_result (rs); /* technically useless here */
+ }
+ lrc->qs = num_results;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_refunds (
+ void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ TALER_MERCHANTDB_RefundCallback rc,
+ void *rc_cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_end
+ };
+ struct LookupRefundsContext lrc = {
+ .rc = rc,
+ .rc_cls = rc_cls,
+ .pg = pg
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* no preflight check here, run in transaction by caller! */
+ TALER_LOG_DEBUG ("Looking for refund of h_contract_terms %s at `%s'\n",
+ GNUNET_h2s (&h_contract_terms->hash),
+ instance_id);
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_refunds",
+ "SELECT"
+ " coin_pub"
+ ",refund_amount_val"
+ ",refund_amount_frac"
+ " FROM merchant_refunds"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_refunds",
+ params,
+ &lookup_refunds_cb,
+ &lrc);
+ if (0 >= qs)
+ return qs;
+ return lrc.qs;
+}
diff --git a/src/backenddb/pg_lookup_refunds.h b/src/backenddb/pg_lookup_refunds.h
new file mode 100644
index 00000000..dcd0d203
--- /dev/null
+++ b/src/backenddb/pg_lookup_refunds.h
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_lookup_refunds.h
+ * @brief implementation of the lookup_refunds function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_LOOKUP_REFUNDS_H
+#define PG_LOOKUP_REFUNDS_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Obtain refunds associated with a contract.
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id instance to lookup refunds for
+ * @param h_contract_terms hash code of the contract
+ * @param rc function to call for each coin on which there is a refund
+ * @param rc_cls closure for @a rc
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_lookup_refunds (void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ TALER_MERCHANTDB_RefundCallback rc,
+ void *rc_cls);
+
+#endif
diff --git a/src/backenddb/pg_mark_contract_paid.c b/src/backenddb/pg_mark_contract_paid.c
new file mode 100644
index 00000000..1119dd76
--- /dev/null
+++ b/src/backenddb/pg_mark_contract_paid.c
@@ -0,0 +1,112 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_mark_contract_paid.c
+ * @brief Implementation of the mark_contract_paid function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_mark_contract_paid.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_mark_contract_paid (
+ void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const char *session_id)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_string (session_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam uparams[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Session ID must always be given by the caller. */
+ GNUNET_assert (NULL != session_id);
+
+ /* no preflight check here, run in transaction by caller! */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Marking h_contract_terms '%s' of %s as paid for session `%s'\n",
+ GNUNET_h2s (&h_contract_terms->hash),
+ instance_id,
+ session_id);
+ PREPARE (pg,
+ "mark_contract_paid",
+ "UPDATE merchant_contract_terms SET"
+ " paid=TRUE"
+ ",session_id=$3"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "mark_contract_paid",
+ params);
+ if (qs <= 0)
+ return qs;
+ PREPARE (pg,
+ "mark_inventory_sold",
+ "UPDATE merchant_inventory SET"
+ " total_sold=total_sold + order_locks.total_locked"
+ " FROM (SELECT total_locked,product_serial"
+ " FROM merchant_order_locks"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))"
+ " ) AS order_locks"
+ " WHERE merchant_inventory.product_serial"
+ " =order_locks.product_serial");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "mark_inventory_sold",
+ uparams);
+ if (qs < 0)
+ return qs; /* 0: no inventory management, that's OK! */
+ /* ON DELETE CASCADE deletes from merchant_order_locks */
+ PREPARE (pg,
+ "delete_completed_order",
+ "WITH md AS"
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1) "
+ "DELETE"
+ " FROM merchant_orders"
+ " WHERE order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " JOIN md USING (merchant_serial)"
+ " WHERE h_contract_terms=$2)");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "delete_completed_order",
+ uparams);
+}
diff --git a/src/backenddb/pg_mark_contract_paid.h b/src/backenddb/pg_mark_contract_paid.h
new file mode 100644
index 00000000..20c87bd2
--- /dev/null
+++ b/src/backenddb/pg_mark_contract_paid.h
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_mark_contract_paid.h
+ * @brief implementation of the mark_contract_paid function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_MARK_CONTRACT_PAID_H
+#define PG_MARK_CONTRACT_PAID_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Mark contract as paid and store the current @a session_id
+ * for which the contract was paid. Deletes the underlying order
+ * and marks the locked stocks of the order as sold.
+ *
+ * @param cls closure
+ * @param instance_id instance to mark contract as paid for
+ * @param h_contract_terms hash of the contract that is now paid
+ * @param session_id the session that paid the contract
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_mark_contract_paid (void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const char *session_id);
+
+#endif
diff --git a/src/backenddb/pg_refund_coin.c b/src/backenddb/pg_refund_coin.c
new file mode 100644
index 00000000..3b124612
--- /dev/null
+++ b/src/backenddb/pg_refund_coin.c
@@ -0,0 +1,77 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_refund_coin.c
+ * @brief Implementation of the refund_coin function for Postgres
+ * @author Iván Ávalos
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_refund_coin.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_refund_coin (void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ struct GNUNET_TIME_Timestamp refund_timestamp,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const char *reason)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_timestamp (&refund_timestamp),
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_string (reason),
+ GNUNET_PQ_query_param_end
+ };
+ PREPARE (pg,
+ "refund_coin",
+ "INSERT INTO merchant_refunds"
+ "(order_serial"
+ ",rtransaction_id"
+ ",refund_timestamp"
+ ",coin_pub"
+ ",reason"
+ ",refund_amount_val"
+ ",refund_amount_frac"
+ ") "
+ "SELECT "
+ " order_serial"
+ ",0" /* rtransaction_id always 0 for /abort */
+ ",$3"
+ ",coin_pub"
+ ",$5"
+ ",amount_with_fee_val"
+ ",amount_with_fee_frac"
+ " FROM merchant_deposits"
+ " WHERE coin_pub=$4"
+ " AND order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "refund_coin",
+ params);
+}
diff --git a/src/backenddb/pg_refund_coin.h b/src/backenddb/pg_refund_coin.h
new file mode 100644
index 00000000..6b5c5d30
--- /dev/null
+++ b/src/backenddb/pg_refund_coin.h
@@ -0,0 +1,51 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_refund_coin.h
+ * @brief implementation of the refund_coin function for Postgres
+ * @author Iván Ávalos
+ */
+#ifndef PG_REFUND_COIN_H
+#define PG_REFUND_COIN_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Function called during aborts to refund a coin. Marks the
+ * respective coin as refunded.
+ *
+ * @param cls closure
+ * @param instance_id instance to refund payment for
+ * @param h_contract_terms hash of the contract to refund coin for
+ * @param refund_timestamp timestamp of the refund
+ * @param coin_pub public key of the coin to refund (fully)
+ * @param reason text justifying the refund
+ * @return transaction status
+ * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a coin_pub is unknown to us;
+ * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid,
+ * regardless of whether it actually increased the refund
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_refund_coin (void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ struct GNUNET_TIME_Timestamp refund_timestamp,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const char *reason);
+
+#endif
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 757a303c..3dbdae48 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -72,6 +72,15 @@
#include "pg_insert_contract_terms.h"
#include "pg_update_contract_terms.h"
#include "pg_delete_contract_terms.h"
+#include "pg_lookup_deposits.h"
+#include "pg_insert_exchange_signkey.h"
+#include "pg_insert_deposit.h"
+#include "pg_lookup_refunds.h"
+#include "pg_mark_contract_paid.h"
+#include "pg_refund_coin.h"
+#include "pg_lookup_order_status.h"
+#include "pg_lookup_order_status_by_serial.h"
+#include "pg_lookup_payment_status.h"
#include "pg_set_transfer_status_to_confirmed.h"
@@ -350,633 +359,6 @@ postgres_commit (void *cls)
/**
- * Closure for #lookup_deposits_cb().
- */
-struct LookupDepositsContext
-{
- /**
- * Function to call with results.
- */
- TALER_MERCHANTDB_DepositsCallback cb;
-
- /**
- * Closure for @e cls.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct PostgresClosure *pg;
-
- /**
- * Transaction status (set).
- */
- enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param[in,out] cls of type `struct LookupDepositsContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_deposits_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupDepositsContext *ldc = cls;
- struct PostgresClosure *pg = ldc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_Amount amount_with_fee;
- struct TALER_Amount deposit_fee;
- struct TALER_Amount refund_fee;
- struct TALER_Amount wire_fee;
- char *exchange_url;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("exchange_url",
- &exchange_url),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("deposit_fee",
- &deposit_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("refund_fee",
- &refund_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
- &wire_fee),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ldc->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
- ldc->cb (ldc->cb_cls,
- exchange_url,
- &coin_pub,
- &amount_with_fee,
- &deposit_fee,
- &refund_fee,
- &wire_fee);
- GNUNET_PQ_cleanup_result (rs);
- }
- ldc->qs = num_results;
-}
-
-
-/**
- * Lookup information about coins that were successfully deposited for a
- * given contract.
- *
- * @param cls closure
- * @param instance_id instance to lookup deposits for
- * @param h_contract_terms proposal data's hashcode
- * @param cb function to call with payment data
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_deposits (
- void *cls,
- const char *instance_id,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- TALER_MERCHANTDB_DepositsCallback cb,
- void *cb_cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_end
- };
- struct LookupDepositsContext ldc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* no preflight check here, run in its own transaction by the caller! */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Finding deposits for h_contract_terms '%s'\n",
- GNUNET_h2s (&h_contract_terms->hash));
- check_connection (pg);
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_deposits",
- params,
- &lookup_deposits_cb,
- &ldc);
- if (qs <= 0)
- return qs;
- return ldc.qs;
-}
-
-
-/**
- * Insert an exchange signing key into our database.
- *
- * @param cls closure
- * @param master_pub exchange master public key used for @a master_sig
- * @param exchange_pub exchange signing key to insert
- * @param start_date when does the signing key become valid
- * @param expire_date when does the signing key stop being used
- * @param end_date when does the signing key become void as proof
- * @param master_sig signature of @a master_pub over the @a exchange_pub and the dates
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_exchange_signkey (
- void *cls,
- const struct TALER_MasterPublicKeyP *master_pub,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- struct GNUNET_TIME_Timestamp start_date,
- struct GNUNET_TIME_Timestamp expire_date,
- struct GNUNET_TIME_Timestamp end_date,
- const struct TALER_MasterSignatureP *master_sig)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (master_pub),
- GNUNET_PQ_query_param_auto_from_type (exchange_pub),
- GNUNET_PQ_query_param_timestamp (&start_date),
- GNUNET_PQ_query_param_timestamp (&expire_date),
- GNUNET_PQ_query_param_timestamp (&end_date),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_end
- };
-
- check_connection (pg);
- postgres_preflight (pg);
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_exchange_signkey",
- params);
-
-}
-
-
-/**
- * Insert payment confirmation from the exchange into the database.
- *
- * @param cls closure
- * @param instance_id instance to lookup deposits for
- * @param deposit_timestamp time when the exchange generated the deposit confirmation
- * @param h_contract_terms proposal data's hashcode
- * @param coin_pub public key of the coin
- * @param exchange_url URL of the exchange that issued @a coin_pub
- * @param amount_with_fee amount the exchange will deposit for this coin
- * @param deposit_fee fee the exchange will charge for this coin
- * @param wire_fee wire fee the exchange charges
- * @param refund_fee fee the exchange charges to refund this coin
- * @param h_wire hash of the wire details of the target account of the merchant
- * @param exchange_sig signature from exchange that coin was accepted
- * @param exchange_pub signgin key that was used for @a exchange_sig
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_deposit (
- void *cls,
- const char *instance_id,
- struct GNUNET_TIME_Timestamp deposit_timestamp,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const char *exchange_url,
- const struct TALER_Amount *amount_with_fee,
- const struct TALER_Amount *deposit_fee,
- const struct TALER_Amount *refund_fee,
- const struct TALER_Amount *wire_fee,
- const struct TALER_MerchantWireHashP *h_wire,
- const struct TALER_ExchangeSignatureP *exchange_sig,
- const struct TALER_ExchangePublicKeyP *exchange_pub)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_timestamp (&deposit_timestamp), /* $3 */
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_string (exchange_url),
- TALER_PQ_query_param_amount (amount_with_fee), /* $6/$7 */
- TALER_PQ_query_param_amount (deposit_fee), /* $8, $9 */
- TALER_PQ_query_param_amount (refund_fee), /* $10, $11 */
- TALER_PQ_query_param_amount (wire_fee), /* $12, $13 */
- GNUNET_PQ_query_param_auto_from_type (h_wire), /* $14 */
- GNUNET_PQ_query_param_auto_from_type (exchange_sig), /* $15 */
- GNUNET_PQ_query_param_auto_from_type (exchange_pub), /* $16 */
- GNUNET_PQ_query_param_end
- };
-
- /* no preflight check here, run in transaction by caller! */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Storing deposit for instance `%s' h_contract_terms `%s', coin_pub: `%s', amount_with_fee: %s\n",
- instance_id,
- GNUNET_h2s (&h_contract_terms->hash),
- TALER_B2S (coin_pub),
- TALER_amount2s (amount_with_fee));
- check_connection (pg);
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_deposit",
- params);
-
-}
-
-
-/**
- * Closure for #lookup_refunds_cb().
- */
-struct LookupRefundsContext
-{
- /**
- * Function to call for each refund.
- */
- TALER_MERCHANTDB_RefundCallback rc;
-
- /**
- * Closure for @e rc.
- */
- void *rc_cls;
-
- /**
- * Plugin context.
- */
- struct PostgresClosure *pg;
-
- /**
- * Transaction result.
- */
- enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls of type `struct LookupRefundsContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lookup_refunds_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRefundsContext *lrc = cls;
- struct PostgresClosure *pg = lrc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_Amount refund_amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT ("refund_amount",
- &refund_amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- lrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
- return;
- }
- lrc->rc (lrc->rc_cls,
- &coin_pub,
- &refund_amount);
- GNUNET_PQ_cleanup_result (rs); /* technically useless here */
- }
- lrc->qs = num_results;
-}
-
-
-/**
- * Obtain refunds associated with a contract.
- *
- * @param cls closure, typically a connection to the db
- * @param instance_id instance to lookup refunds for
- * @param h_contract_terms hash code of the contract
- * @param rc function to call for each coin on which there is a refund
- * @param rc_cls closure for @a rc
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_refunds (
- void *cls,
- const char *instance_id,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- TALER_MERCHANTDB_RefundCallback rc,
- void *rc_cls)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_end
- };
- struct LookupRefundsContext lrc = {
- .rc = rc,
- .rc_cls = rc_cls,
- .pg = pg
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* no preflight check here, run in transaction by caller! */
- TALER_LOG_DEBUG ("Looking for refund of h_contract_terms %s at `%s'\n",
- GNUNET_h2s (&h_contract_terms->hash),
- instance_id);
- check_connection (pg);
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_refunds",
- params,
- &lookup_refunds_cb,
- &lrc);
- if (0 >= qs)
- return qs;
- return lrc.qs;
-}
-
-
-/**
- * Mark contract as paid and store the current @a session_id
- * for which the contract was paid. Deletes the underlying order
- * and marks the locked stocks of the order as sold.
- *
- * @param cls closure
- * @param instance_id instance to mark contract as paid for
- * @param h_contract_terms hash of the contract that is now paid
- * @param session_id the session that paid the contract
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_mark_contract_paid (
- void *cls,
- const char *instance_id,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- const char *session_id)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_string (session_id),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_QueryParam uparams[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* Session ID must always be given by the caller. */
- GNUNET_assert (NULL != session_id);
-
- /* no preflight check here, run in transaction by caller! */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Marking h_contract_terms '%s' of %s as paid for session `%s'\n",
- GNUNET_h2s (&h_contract_terms->hash),
- instance_id,
- session_id);
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "mark_contract_paid",
- params);
- if (qs <= 0)
- return qs;
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "mark_inventory_sold",
- uparams);
- if (qs < 0)
- return qs; /* 0: no inventory management, that's OK! */
- /* ON DELETE CASCADE deletes from merchant_order_locks */
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "delete_completed_order",
- uparams);
-}
-
-
-/**
- * Function called during aborts to refund a coin. Marks the
- * respective coin as refunded.
- *
- * @param cls closure
- * @param instance_id instance to refund payment for
- * @param h_contract_terms hash of the contract to refund coin for
- * @param refund_timestamp timestamp of the refund
- * @param coin_pub public key of the coin to refund (fully)
- * @param reason text justifying the refund
- * @return transaction status
- * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a coin_pub is unknown to us;
- * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid,
- * regardless of whether it actually increased the refund
- */
-static enum GNUNET_DB_QueryStatus
-postgres_refund_coin (void *cls,
- const char *instance_id,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- struct GNUNET_TIME_Timestamp refund_timestamp,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const char *reason)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_timestamp (&refund_timestamp),
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_string (reason),
- GNUNET_PQ_query_param_end
- };
-
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "refund_coin",
- params);
-}
-
-
-/**
- * Retrieve contract terms given its @a order_id
- *
- * @param cls closure
- * @param instance_id instance's identifier
- * @param order_id order to lookup contract for
- * @param[out] h_contract_terms set to the hash of the contract.
- * @param[out] paid set to the payment status of the contract
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_order_status (
- void *cls,
- const char *instance_id,
- const char *order_id,
- struct TALER_PrivateContractHashP *h_contract_terms,
- bool *paid)
-{
- struct PostgresClosure *pg = cls;
- uint8_t paid8;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_string (order_id),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("paid",
- &paid8),
- GNUNET_PQ_result_spec_end
- };
-
- check_connection (pg);
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_order_status",
- params,
- rs);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- *paid = (0 != paid8);
- else
- *paid = false; /* just to be safe(r) */
- return qs;
-}
-
-
-/**
- * Retrieve contract terms given its @a order_serial
- *
- * @param cls closure
- * @param instance_id instance's identifier
- * @param order_serial serial ID of the order to look up
- * @param[out] order_id set to ID of the order
- * @param[out] h_contract_terms set to the hash of the contract.
- * @param[out] paid set to the payment status of the contract
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_order_status_by_serial (void *cls,
- const char *instance_id,
- uint64_t order_serial,
- char **order_id,
- struct TALER_PrivateContractHashP *
- h_contract_terms,
- bool *paid)
-{
- struct PostgresClosure *pg = cls;
- uint8_t paid8;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_uint64 (&order_serial),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("paid",
- &paid8),
- GNUNET_PQ_result_spec_string ("order_id",
- order_id),
- GNUNET_PQ_result_spec_end
- };
-
- check_connection (pg);
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_order_status_by_serial",
- params,
- rs);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- *paid = (0 != paid8);
- else
- *paid = false; /* just to be safe(r) */
- return qs;
-}
-
-
-/**
- * Retrieve payment and wire status for a given @a order_serial and session ID.
- *
- * @param cls closure
- * @param order_serial identifies the order
- * @param session_id session for which to check the payment status, NULL for any
- * @param[out] paid set to the payment status of the contract
- * @param[out] wired set to the wire transfer status of the exchange payment
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_payment_status (void *cls,
- uint64_t order_serial,
- const char *session_id,
- bool *paid,
- bool *wired)
-{
- struct PostgresClosure *pg = cls;
- uint8_t paid8;
- uint8_t wired8;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("paid",
- &paid8),
- GNUNET_PQ_result_spec_auto_from_type ("wired",
- &wired8),
- GNUNET_PQ_result_spec_end
- };
- check_connection (pg);
- if (NULL == session_id)
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&order_serial),
- GNUNET_PQ_query_param_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_payment_status",
- params,
- rs);
- }
- else
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&order_serial),
- GNUNET_PQ_query_param_string (session_id),
- GNUNET_PQ_query_param_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_payment_status_session_id",
- params,
- rs);
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- *paid = (0 != paid8);
- *wired = (0 != wired8);
- }
- else
- {
- *paid = false; /* just to be safe(r) */
- *wired = false; /* just to be safe(r) */
- }
- return qs;
-}
-
-
-/**
* Closure for lookup_deposits_by_order_cb().
*/
struct LookupDepositsByOrderContext
@@ -5428,205 +4810,6 @@ postgres_connect (void *cls)
struct GNUNET_PQ_PreparedStatement ps[] = {
GNUNET_PQ_make_prepare ("end_transaction",
"COMMIT"),
- /* for postgres_lookup_deposits() */
- GNUNET_PQ_make_prepare ("lookup_deposits",
- "SELECT"
- " exchange_url"
- ",coin_pub"
- ",amount_with_fee_val"
- ",amount_with_fee_frac"
- ",deposit_fee_val"
- ",deposit_fee_frac"
- ",refund_fee_val"
- ",refund_fee_frac"
- ",wire_fee_val"
- ",wire_fee_frac"
- " FROM merchant_deposits"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$2"
- " AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1))"),
- /* for postgres_insert_exchange_signkey() */
- GNUNET_PQ_make_prepare ("insert_exchange_signkey",
- "INSERT INTO merchant_exchange_signing_keys"
- "(master_pub"
- ",exchange_pub"
- ",start_date"
- ",expire_date"
- ",end_date"
- ",master_sig)"
- "VALUES"
- "($1, $2, $3, $4, $5, $6)"),
- /* for postgres_insert_deposit() */
- GNUNET_PQ_make_prepare ("insert_deposit",
- "WITH md AS"
- " (SELECT account_serial, merchant_serial"
- " FROM merchant_accounts"
- " WHERE h_wire=$14"
- " AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1))"
- ", ed AS"
- " (SELECT signkey_serial"
- " FROM merchant_exchange_signing_keys"
- " WHERE exchange_pub=$16"
- " ORDER BY start_date DESC"
- " LIMIT 1)"
- "INSERT INTO merchant_deposits"
- "(order_serial"
- ",deposit_timestamp"
- ",coin_pub"
- ",exchange_url"
- ",amount_with_fee_val"
- ",amount_with_fee_frac"
- ",deposit_fee_val"
- ",deposit_fee_frac"
- ",refund_fee_val"
- ",refund_fee_frac"
- ",wire_fee_val"
- ",wire_fee_frac"
- ",exchange_sig"
- ",signkey_serial"
- ",account_serial)"
- " SELECT "
- " order_serial"
- " ,$3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $15"
- " ,ed.signkey_serial"
- " ,md.account_serial"
- " FROM merchant_contract_terms"
- " JOIN md USING (merchant_serial)"
- " FULL OUTER JOIN ed ON TRUE"
- " WHERE h_contract_terms=$2"),
- /* for postgres_lookup_refunds() */
- GNUNET_PQ_make_prepare ("lookup_refunds",
- "SELECT"
- " coin_pub"
- ",refund_amount_val"
- ",refund_amount_frac"
- " FROM merchant_refunds"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$2"
- " AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1))"),
- /* for postgres_mark_contract_paid() */
- GNUNET_PQ_make_prepare ("mark_contract_paid",
- "UPDATE merchant_contract_terms SET"
- " paid=TRUE"
- ",session_id=$3"
- " WHERE h_contract_terms=$2"
- " AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1)"),
- /* for postgres_mark_contract_paid() */
- GNUNET_PQ_make_prepare ("mark_inventory_sold",
- "UPDATE merchant_inventory SET"
- " total_sold=total_sold + order_locks.total_locked"
- " FROM (SELECT total_locked,product_serial"
- " FROM merchant_order_locks"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$2"
- " AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1))"
- " ) AS order_locks"
- " WHERE merchant_inventory.product_serial"
- " =order_locks.product_serial"),
- /* for postgres_mark_contract_paid() */
- GNUNET_PQ_make_prepare ("delete_completed_order",
- "WITH md AS"
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1) "
- "DELETE"
- " FROM merchant_orders"
- " WHERE order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " JOIN md USING (merchant_serial)"
- " WHERE h_contract_terms=$2)"),
- /* for postgres_refund_coin() */
- GNUNET_PQ_make_prepare ("refund_coin",
- "INSERT INTO merchant_refunds"
- "(order_serial"
- ",rtransaction_id"
- ",refund_timestamp"
- ",coin_pub"
- ",reason"
- ",refund_amount_val"
- ",refund_amount_frac"
- ") "
- "SELECT "
- " order_serial"
- ",0" /* rtransaction_id always 0 for /abort */
- ",$3"
- ",coin_pub"
- ",$5"
- ",amount_with_fee_val"
- ",amount_with_fee_frac"
- " FROM merchant_deposits"
- " WHERE coin_pub=$4"
- " AND order_serial="
- " (SELECT order_serial"
- " FROM merchant_contract_terms"
- " WHERE h_contract_terms=$2"
- " AND merchant_serial="
- " (SELECT merchant_serial"
- " FROM merchant_instances"
- " WHERE merchant_id=$1))"),
-
- /* for postgres_lookup_order_status() */
- GNUNET_PQ_make_prepare ("lookup_order_status",
- "SELECT"
- " h_contract_terms"
- ",paid"
- " FROM merchant_contract_terms"
- " WHERE merchant_serial="
- " (SELECT merchant_serial "
- " FROM merchant_instances"
- " WHERE merchant_id=$1)"
- " AND order_id=$2"),
-
- /* for postgres_lookup_order_status_by_serial() */
- GNUNET_PQ_make_prepare ("lookup_order_status_by_serial",
- "SELECT"
- " h_contract_terms"
- ",order_id"
- ",paid"
- " FROM merchant_contract_terms"
- " WHERE merchant_serial="
- " (SELECT merchant_serial "
- " FROM merchant_instances"
- " WHERE merchant_id=$1)"
- " AND order_serial=$2"),
-
- /* for postgres_lookup_payment_status() */
- GNUNET_PQ_make_prepare ("lookup_payment_status",
- "SELECT"
- " wired"
- ",paid"
- " FROM merchant_contract_terms"
- " WHERE order_serial=$1"),
- /* for postgres_lookup_payment_status() */
- GNUNET_PQ_make_prepare ("lookup_payment_status_session_id",
- "SELECT"
- " wired"
- ",paid"
- " FROM merchant_contract_terms"
- " WHERE order_serial=$1"
- " AND session_id=$2"),
/* for postgres_lookup_deposits_by_order() */
GNUNET_PQ_make_prepare ("lookup_deposits_by_order",
"SELECT"
@@ -6700,16 +5883,24 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
= &TMH_PG_update_contract_terms;
plugin->delete_contract_terms
= &TMH_PG_delete_contract_terms;
- plugin->lookup_deposits = &postgres_lookup_deposits;
- plugin->insert_exchange_signkey = &postgres_insert_exchange_signkey;
- plugin->insert_deposit = &postgres_insert_deposit;
- plugin->lookup_refunds = &postgres_lookup_refunds;
- plugin->mark_contract_paid = &postgres_mark_contract_paid;
- plugin->refund_coin = &postgres_refund_coin;
- plugin->lookup_order_status = &postgres_lookup_order_status;
- plugin->lookup_order_status_by_serial =
- &postgres_lookup_order_status_by_serial;
- plugin->lookup_payment_status = &postgres_lookup_payment_status;
+ plugin->lookup_deposits
+ = &TMH_PG_lookup_deposits;
+ plugin->insert_exchange_signkey
+ = &TMH_PG_insert_exchange_signkey;
+ plugin->insert_deposit
+ = &TMH_PG_insert_deposit;
+ plugin->lookup_refunds
+ = &TMH_PG_lookup_refunds;
+ plugin->mark_contract_paid
+ = &TMH_PG_mark_contract_paid;
+ plugin->refund_coin
+ = &TMH_PG_refund_coin;
+ plugin->lookup_order_status
+ = &TMH_PG_lookup_order_status;
+ plugin->lookup_order_status_by_serial
+ = &TMH_PG_lookup_order_status_by_serial;
+ plugin->lookup_payment_status
+ = &TMH_PG_lookup_payment_status;
plugin->lookup_deposits_by_order = &postgres_lookup_deposits_by_order;
plugin->lookup_transfer_details_by_order =
&postgres_lookup_transfer_details_by_order;