merchant

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

commit 50e0bdbfa81107a525f8f708d82d050e485700cb
parent 80b8e221fe2233050e33400fac032d37ac73f731
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Thu, 14 Aug 2025 17:04:01 +0200

preliminary work on #9434

Diffstat:
Msrc/backenddb/merchant-0022.sql | 3+++
Msrc/backenddb/pg_insert_issued_token.c | 47+++++++++++++++++++++++++++++++----------------
Asrc/backenddb/pg_insert_issued_token.sql | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_insert_spent_token.c | 47++++++++++++++++++++++++++++++-----------------
Asrc/backenddb/pg_insert_spent_token.sql | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_lookup_spent_tokens_by_order.c | 8++++----
Msrc/backenddb/procedures.sql.in | 2++
7 files changed, 210 insertions(+), 37 deletions(-)

diff --git a/src/backenddb/merchant-0022.sql b/src/backenddb/merchant-0022.sql @@ -30,6 +30,9 @@ SELECT _v.register_patch('merchant-0022', NULL, NULL); SET search_path TO merchant; +ALTER TABLE merchant_used_tokens + DROP COLUMN merchant_serial; + ALTER TABLE merchant_instances ADD COLUMN phone_number TEXT DEFAULT NULL, ADD COLUMN phone_validated BOOL NOT NULL DEFAULT FALSE, diff --git a/src/backenddb/pg_insert_issued_token.c b/src/backenddb/pg_insert_issued_token.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2024 Taler Systems SA + Copyright (C) 2024, 2025 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 @@ -35,29 +35,44 @@ TMH_PG_insert_issued_token (void *cls, blind_sig) { struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (h_issue_pub), GNUNET_PQ_query_param_auto_from_type (h_contract_terms), GNUNET_PQ_query_param_blinded_sig (blind_sig->signature), GNUNET_PQ_query_param_end }; + bool no_fam; + bool existed; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_no_family", + &no_fam), + GNUNET_PQ_result_spec_bool ("out_existed", + &existed), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; check_connection (pg); PREPARE (pg, "issued_token_insert", - "INSERT INTO merchant_issued_tokens" - "(token_family_key_serial" - ",h_contract_terms" - ",blind_sig)" - " SELECT token_family_key_serial, $2, $3" - " FROM merchant_token_families" - " JOIN merchant_token_family_keys" - " USING (token_family_serial)" - " WHERE h_pub = $1"); - - /* FIXME-#9434: Increase issued counter on merchant_token_family table. */ - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "issued_token_insert", - params); + "SELECT" + " ,out_no_family" + " ,out_existed" + " FROM merchant_do_insert_issued_token" + " ($1, $2, $3);"); + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "issued_token_insert", + params, + rs); + if (qs < 0) + return qs; + if (no_fam) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (existed) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return qs; } diff --git a/src/backenddb/pg_insert_issued_token.sql b/src/backenddb/pg_insert_issued_token.sql @@ -0,0 +1,67 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2025 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/> +-- + + +DROP FUNCTION IF EXISTS merchant_do_insert_issued_token; +CREATE FUNCTION merchant_do_insert_issued_token ( + IN in_h_issue_pub BYTEA, + IN in_h_contract_terms BYTEA, + IN in_blind_sig BYTEA, + OUT out_no_family BOOL, + OUT out_existed BOOL) +LANGUAGE plpgsql +AS $$ +DECLARE + my_tfk_serial INT8; +BEGIN + +SELECT mtf.token_family_key_serial + INTO my_tfk_serial + FROM merchant_token_families mtf + JOIN merchant_token_family_keys mtfk + USING (token_family_serial) + WHERE mtfk.h_pub = in_h_issue_pub; + +IF NOT FOUND +THEN + out_no_family = TRUE; + out_existed = FALSE; + return; +END IF; + +out_no_family = FALSE; + +INSERT INTO merchant_issued_tokens + (token_family_key_serial + ,h_contract_terms + ,blind_sig + ) VALUES + (my_tfk_serial + ,in_h_contract_terms + ,in_blind_sig) + ON CONFLICT DO NOTHING; + +IF NOT FOUND +THEN + out_existed = TRUE; + return; +END IF; + +UPDATE merchant_token_families + SET issued=issued+1 + WHERE token_family_key_serial=my_tfk_serial; + +END $$; diff --git a/src/backenddb/pg_insert_spent_token.c b/src/backenddb/pg_insert_spent_token.c @@ -44,25 +44,38 @@ TMH_PG_insert_spent_token ( GNUNET_PQ_query_param_unblinded_sig (issue_sig->signature), GNUNET_PQ_query_param_end }; + bool no_fam; + bool existed; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("out_no_family", + &no_fam), + GNUNET_PQ_result_spec_bool ("out_existed", + &existed), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; check_connection (pg); PREPARE (pg, "spent_token_insert", - "INSERT INTO merchant_used_tokens" - "(merchant_serial" /* FIXME-#9434: Remove merchant_serial field from the db, it's already given by token_family.merchant_serial. */ - ",token_family_key_serial" - ",h_contract_terms" - ",token_pub" - ",token_sig" - ",blind_sig)" - " SELECT merchant_serial, token_family_key_serial, $2, $3, $4, $5" - " FROM merchant_token_families" - " JOIN merchant_token_family_keys" - " USING (token_family_serial)" - " WHERE h_pub = $1"); - - /* FIXME-#9434: Increase used counter on merchant_token_family table. */ - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "spent_token_insert", - params); + "SELECT" + " ,out_no_family" + " ,out_existed" + " FROM merchant_do_insert_spent_token" + "($1, $2, $3, $4, $5);"); + qs = GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "spent_token_insert", + params, + rs); + if (qs < 0) + return qs; + if (no_fam) + { + GNUNET_break (0); + return GNUNET_DB_STATUS_HARD_ERROR; + } + if (existed) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return qs; } diff --git a/src/backenddb/pg_insert_spent_token.sql b/src/backenddb/pg_insert_spent_token.sql @@ -0,0 +1,73 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2025 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/> +-- + + +DROP FUNCTION IF EXISTS merchant_do_insert_spent_token; +CREATE FUNCTION merchant_do_insert_spent_token ( + IN in_h_contract_terms BYTEA, + IN in_h_issue_pub BYTEA, + IN in_use_pub BYTEA, + IN in_use_sig BYTEA, + IN in_issue_sig BYTEA, + OUT out_no_family BOOL, + OUT out_existed BOOL) +LANGUAGE plpgsql +AS $$ +DECLARE + my_tfk_serial INT8; +BEGIN + +SELECT mtf.token_family_key_serial + INTO my_tfk_serial + FROM merchant_token_families mtf + JOIN merchant_token_family_keys mtfk + USING (token_family_serial) + WHERE mtfk.h_pub = in_h_issue_pub; + +IF NOT FOUND +THEN + out_no_family = TRUE; + out_existed = FALSE; + return; +END IF; + +out_no_family = FALSE; + +INSERT INTO merchant_used_tokens + (token_family_key_serial + ,h_contract_terms + ,token_pub + ,token_sig + ,blind_sig + ) VALUES + (my_tfk_serial + ,in_h_contract_terms + ,in_use_pub + ,in_use_sig + ,in_issue_sig) + ON CONFLICT DO NOTHING; + +IF NOT FOUND +THEN + out_existed = TRUE; + return; +END IF; + +UPDATE merchant_token_families + SET redeemed=redeemed+1 + WHERE token_family_key_serial=my_tfk_serial; + +END $$; diff --git a/src/backenddb/pg_lookup_spent_tokens_by_order.c b/src/backenddb/pg_lookup_spent_tokens_by_order.c @@ -64,8 +64,8 @@ struct LookupSpentTokensByOrderContext */ static void lookup_spent_tokens_by_order_cb (void *cls, - PGresult *result, - unsigned int num_results) + PGresult *result, + unsigned int num_results) { struct LookupSpentTokensByOrderContext *ctx = cls; @@ -88,8 +88,8 @@ lookup_spent_tokens_by_order_cb (void *cls, &use_pub), GNUNET_PQ_result_spec_auto_from_type ("token_sig", &use_sig), - // GNUNET_PQ_result_spec_unblinded_sig ("blind_sig", - // &issue_sig), + GNUNET_PQ_result_spec_unblinded_sig ("blind_sig", + &issue_sig.signature), GNUNET_PQ_result_spec_end }; diff --git a/src/backenddb/procedures.sql.in b/src/backenddb/procedures.sql.in @@ -20,6 +20,8 @@ SET search_path TO merchant; #include "pg_insert_deposit_to_transfer.sql" #include "pg_insert_product.sql" +#include "pg_insert_issued_token.sql" +#include "pg_insert_spent_token.sql" #include "pg_insert_transfer_details.sql" #include "pg_update_product.sql" #include "pg_account_kyc_set_status.sql"