merchant

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

commit 5cb9ea47557c18166a1f42768e495716c2f4594b
parent e28c2fc790a07dda17de2794ce2de8a5ee422529
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Mon, 23 Jun 2025 11:43:29 +0200

modifications on the taler_merchant_pay_service.c

Diffstat:
Asrc/backenddb/merchant-0019.sql | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/taler_merchant_pay_service.c | 60+++++++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 140 insertions(+), 9 deletions(-)

diff --git a/src/backenddb/merchant-0019.sql b/src/backenddb/merchant-0019.sql @@ -0,0 +1,88 @@ +-- +-- 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/> +-- + +-- @file merchant-0019.sql +-- @brief Create table to store donau related information +-- @author Bohdan Potuzhnyi +-- @author Vlada Svirsh + +BEGIN; + +-- Check patch versioning is in place. +SELECT _v.register_patch('merchant-0019', NULL, NULL); + +SET search_path TO merchant; + +CREATE TABLE IF NOT EXISTS merchant_donau_keys +(donau_keys_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE + ,donau_url TEXT PRIMARY KEY + ,keys_json TEXT NOT NULL +); + +COMMENT ON TABLE merchant_donau_keys + IS 'Here we store the cached /keys response from Donau in JSON format'; +COMMENT ON COLUMN merchant_donau_keys.donau_keys_serial + IS 'Unique serial identifier for each cached key entry'; +COMMENT ON COLUMN merchant_donau_keys.donau_url + IS 'Base URL of Donau associated with these keys'; +COMMENT ON COLUMN merchant_donau_keys.keys_json + IS 'JSON string of the /keys as generated by Donau'; + +CREATE TABLE IF NOT EXISTS merchant_donau_instances +(donau_instances_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY + ,donau_url TEXT NOT NULL + ,charity_name TEXT NOT NULL + ,charity_pub_key BYTEA CHECK (LENGTH(charity_pub_key)=32) + ,charity_id BIGINT NOT NULL + ,charity_max_per_year taler_amount_currency NOT NULL + ,charity_receipts_to_date taler_amount_currency NOT NULL + ,current_year INT8 NOT NULL +); + +COMMENT ON TABLE merchant_donau_instances + IS 'Here we store information about individual Donau instances, including details about associated charities and donation limits'; +COMMENT ON COLUMN merchant_donau_instances.donau_instances_serial + IS 'Unique serial identifier for each Donau instance'; +COMMENT ON COLUMN merchant_donau_instances.donau_url + IS 'The URL associated with the Donau system for this instance'; +COMMENT ON COLUMN merchant_donau_instances.charity_pub_key + IS 'The public key of the charity organization linked to this instance, with a 32-byte length constraint'; +COMMENT ON COLUMN merchant_donau_instances.charity_id + IS 'The unique identifier for the charity organization linked to this Donau instance'; +COMMENT ON COLUMN merchant_donau_instances.charity_max_per_year + IS 'Maximum allowable donation amount per year for the charity associated with this instance, stored in taler_amount_currency'; +COMMENT ON COLUMN merchant_donau_instances.charity_receipts_to_date + IS 'The total amount of donations received to date for this instance, stored in taler_amount_currency'; +COMMENT ON COLUMN merchant_donau_instances.current_year + IS 'The current year for tracking donations for this instance, stored as an 8-byte integer'; + +CREATE TABLE IF NOT EXISTS merchant_order_donau +(order_donau_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY + ,order_serial BIGINT NOT NULL + REFERENCES merchant_orders (order_serial) ON DELETE CASCADE + ,donau_budis TEXT NOT NULL +); + +COMMENT ON TABLE merchant_order_donau + IS 'Table linking merchant orders with Donau BUDIS information'; +COMMENT ON COLUMN merchant_order_donau.order_donau_serial + IS 'Unique serial identifier for Donau order linkage'; +COMMENT ON COLUMN merchant_order_donau.order_serial + IS 'Foreign key linking to the corresponding merchant order'; +COMMENT ON COLUMN merchant_order_donau.donau_budis + IS 'Donau BUDIs json associated with the order'; + +COMMIT; +\ No newline at end of file diff --git a/src/lib/taler_merchant_pay_service.c b/src/lib/taler_merchant_pay_service.c @@ -91,7 +91,7 @@ struct TALER_MERCHANT_OrderPayHandle const struct TALER_MERCHANT_OutputToken *output_tokens; } output_tokens; - /* computed once we see both choice_index and token_evs(outputs in the env): */ + /* computed once we see both choice_index and tokens_evs(outputs in the env): */ json_t *wallet_data; struct GNUNET_HashCode wallet_data_hash; @@ -576,7 +576,7 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph, ph->output_tokens.output_tokens = o->details.output_tokens.output_tokens; { - /* build and store token_evs */ + /* build and store tokens_evs */ json_t *arr = json_array (); for (unsigned j = 0; j < ph->output_tokens.num_output_tokens; j++) { const struct TALER_MERCHANT_OutputToken *otk = &ph->output_tokens.output_tokens[j]; @@ -586,7 +586,7 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph, json_array_append_new (arr, je); } json_t *js = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_array_steal ("token_evs", arr) + GNUNET_JSON_pack_array_steal ("tokens_evs", arr) ); store_json_option (ph, o->ot, js); } @@ -666,11 +666,11 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph) /* --- build wallet_data hash for signing coins & tokens --- */ if (ph->has_choice_index) { - /* wallet_data = { choice_index: …, token_evs: … } */ + /* wallet_data = { choice_index: …, tokens_evs: … } */ ph->wallet_data = GNUNET_JSON_PACK ( GNUNET_JSON_pack_int64("choice_index", ph->choice_index), GNUNET_JSON_pack_allow_null( - GNUNET_JSON_pack_array_incref("token_evs", ph->body)) + GNUNET_JSON_pack_array_incref("tokens_evs", ph->body)) ); TALER_json_hash (ph->wallet_data, &ph->wallet_data_hash); } @@ -740,7 +740,7 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph) store_json_option (ph, TALER_MERCHANT_OrderPayOptionType_COINS, GNUNET_JSON_PACK ( - GNUNET_JSON_pack_array_steal ("paid_coins", arr) + GNUNET_JSON_pack_array_steal ("coins", arr) ) ); } @@ -772,12 +772,54 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph) store_json_option (ph, TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS, GNUNET_JSON_PACK ( - GNUNET_JSON_pack_array_steal ("used_tokens", arr) + GNUNET_JSON_pack_array_steal ("tokens", arr) ) ); } - //TODO: Change the usage of this function to how it is in the api_post_order_pay.c in the order_pay_frontend - return fire_request (ph); + /* --- post the request --------------------------------------------------- */ + { + /* BEGIN INLINE FIRE REQUEST (was fire_request()) */ + char *path; + GNUNET_asprintf (&path, + "orders/%s/pay", + ph->order_id); + ph->url = TALER_url_join (ph->merchant_url, + path, + NULL); + GNUNET_free (path); + + if (NULL == ph->url) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not construct request URL.\n"); + json_decref (ph->body); + GNUNET_free (ph); + return TALER_MERCHANT_OPOEC_INVALID_VALUE; + } + + CURL *eh = TALER_MERCHANT_curl_easy_get_ (ph->url); + if (GNUNET_OK != + TALER_curl_easy_post (&ph->post_ctx, + eh, + ph->body)) + { + GNUNET_break (0); + curl_easy_cleanup (eh); + json_decref (ph->body); + GNUNET_free (ph->url); + GNUNET_free (ph); + return TALER_MERCHANT_OPOEC_INVALID_VALUE; + } + + json_decref (ph->body); + ph->job = GNUNET_CURL_job_add2 (ph->ctx, + eh, + ph->post_ctx.headers, + &handle_finished, + ph); + /* END INLINE FIRE REQUEST */ + return TALER_MERCHANT_OPOEC_OK; + } }