merchant

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

commit a79281b1181c54bb6bbd491b2ff295d718aaad96
parent 70a0669ea92275d6b23d9a13503b5854f9a2ef88
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Sat, 15 Nov 2025 10:25:30 +0100

dd73: product//image

Diffstat:
Msrc/backend/Makefile.am | 2++
Msrc/backend/taler-merchant-httpd.c | 10++++++++++
Asrc/backend/taler-merchant-httpd_get-products-image.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backend/taler-merchant-httpd_get-products-image.h | 32++++++++++++++++++++++++++++++++
Msrc/backenddb/Makefile.am | 2++
Asrc/backenddb/merchant-0026.sql | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_insert_product.sql | 10+++++++++-
Asrc/backenddb/pg_lookup_product_image.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/pg_lookup_product_image.h | 33+++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_update_product.sql | 7+++++++
Msrc/backenddb/plugin_merchantdb_postgres.c | 3+++
Msrc/include/taler_merchant_service.h | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/include/taler_merchant_testing_lib.h | 131++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/include/taler_merchantdb_plugin.h | 839++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/lib/Makefile.am | 1+
Asrc/lib/merchant_api_get_product_image.c | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/testing/Makefile.am | 1+
Msrc/testing/test_merchant_api.c | 47+++++++++++++++++++++++++++++++++++++++++++----
Asrc/testing/testing_api_cmd_get_product_image.c | 217+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19 files changed, 1330 insertions(+), 480 deletions(-)

diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am @@ -74,6 +74,8 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_exchanges.c taler-merchant-httpd_exchanges.h \ taler-merchant-httpd_get-orders-ID.c \ taler-merchant-httpd_get-orders-ID.h \ + taler-merchant-httpd_get-products-image.c \ + taler-merchant-httpd_get-products-image.h \ taler-merchant-httpd_get-templates-ID.c \ taler-merchant-httpd_get-templates-ID.h \ taler-merchant-httpd_helper.c \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c @@ -32,6 +32,7 @@ #include "taler-merchant-httpd_config.h" #include "taler-merchant-httpd_exchanges.h" #include "taler-merchant-httpd_get-orders-ID.h" +#include "taler-merchant-httpd_get-products-image.h" #include "taler-merchant-httpd_get-templates-ID.h" #include "taler-merchant-httpd_helper.h" #include "taler-merchant-httpd_mhd.h" @@ -2035,6 +2036,15 @@ url_handler (void *cls, .have_id_segment = true, .handler = &TMH_get_templates_ID }, + /* GET /products/$HASH/image: */ + { + .url_prefix = "/products/", + .method = MHD_HTTP_METHOD_GET, + .have_id_segment = true, + .allow_deleted_instance = true, + .url_suffix = "image", + .handler = &TMH_get_products_image + }, /* POST /templates/$ID: */ { .url_prefix = "/templates/", diff --git a/src/backend/taler-merchant-httpd_get-products-image.c b/src/backend/taler-merchant-httpd_get-products-image.c @@ -0,0 +1,87 @@ +/* + 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 Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file taler-merchant-httpd_get-products-image.c + * @brief implement GET /products/$HASH/image + * @author Bohdan Potuzhnyi + */ +#include "platform.h" +#include "taler-merchant-httpd_get-products-image.h" +#include "taler-merchant-httpd_helper.h" +#include <taler/taler_error_codes.h> + + +MHD_RESULT +TMH_get_products_image (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + const char *image_hash = hc->infix; + char *image = NULL; + enum GNUNET_DB_QueryStatus qs; + (void) rh; + + { + /* Just simple check if the string is what we really expect */ + size_t ih_len = strlen (image_hash); + + if ( (sizeof (struct GNUNET_ShortHashCode) * 2) != ih_len) + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "image_hash"); + + for (size_t i = 0; i < ih_len; i++) + if (! isxdigit ((unsigned char) image_hash[i])) + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "image_hash"); + } + + qs = TMH_db->lookup_product_image_by_hash (TMH_db->cls, + mi->settings.id, + image_hash, + &image); + if (0 > qs) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "lookup_product_image_by_hash"); + } + if ( (0 == qs) || + (NULL == image) ) + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_MERCHANT_GENERIC_PRODUCT_UNKNOWN, + image_hash); + } + + { + MHD_RESULT ret; + + ret = TALER_MHD_REPLY_JSON_PACK (connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_string ("image", + image)); + GNUNET_free (image); + return ret; + } +} diff --git a/src/backend/taler-merchant-httpd_get-products-image.h b/src/backend/taler-merchant-httpd_get-products-image.h @@ -0,0 +1,31 @@ +/* + 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 Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file taler-merchant-httpd_get-products-image.h + * @brief implement GET /products/$HASH/image + * @author Bohdan Potuzhnyi + */ +#ifndef TALER_MERCHANT_HTTPD_GET_PRODUCTS_IMAGE_H +#define TALER_MERCHANT_HTTPD_GET_PRODUCTS_IMAGE_H + +#include "taler-merchant-httpd.h" + +MHD_RESULT +TMH_get_products_image (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); + +#endif +\ No newline at end of file diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am @@ -42,6 +42,7 @@ sql_DATA = \ merchant-0023.sql \ merchant-0024.sql \ merchant-0025.sql \ + merchant-0026.sql \ drop.sql BUILT_SOURCES = \ @@ -164,6 +165,7 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \ pg_lookup_pending_deposits.h pg_lookup_pending_deposits.c \ pg_lookup_pending_webhooks.h pg_lookup_pending_webhooks.c \ pg_lookup_product.h pg_lookup_product.c \ + pg_lookup_product_image.h pg_lookup_product_image.c \ pg_lookup_products.h pg_lookup_products.c \ pg_lookup_refund_proof.h pg_lookup_refund_proof.c \ pg_lookup_refunds.h pg_lookup_refunds.c \ diff --git a/src/backenddb/merchant-0026.sql b/src/backenddb/merchant-0026.sql @@ -0,0 +1,54 @@ +-- +-- 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-0026.sql +-- @brief add hashes for product images +-- @author Bohdan Potuzhnyi + + +BEGIN; + +-- Check patch versioning is in place. +SELECT _v.register_patch('merchant-0026', NULL, NULL); + +SET search_path TO merchant; + +CREATE EXTENSION IF NOT EXISTS pgcrypto; + +ALTER TABLE merchant_inventory + ADD COLUMN image_hash TEXT; + +COMMENT ON COLUMN merchant_inventory.image_hash + IS 'SHA-256 hash of the base64-encoded image data, used by wallets to fetch product images.'; + +UPDATE merchant_inventory + SET image_hash = CASE + WHEN (image IS NULL) OR (image = '') + THEN NULL + ELSE encode( + digest( + convert_to(image, 'UTF8'), + 'sha256' + ), + 'hex' + ) + END; + +CREATE INDEX merchant_inventory_by_image_hash + ON merchant_inventory + (merchant_serial, image_hash); + +COMMIT; diff --git a/src/backenddb/pg_insert_product.sql b/src/backenddb/pg_insert_product.sql @@ -66,12 +66,13 @@ INSERT INTO merchant_inventory ,description_i18n ,unit ,image + ,image_hash ,taxes ,price ,total_stock ,address ,next_restock - ,minimum_age + ,minimum_age ) VALUES ( my_merchant_id ,in_product_id @@ -80,6 +81,13 @@ INSERT INTO merchant_inventory ,in_description_i18n ,in_unit ,in_image + ,CASE + WHEN (in_image IS NULL) OR (in_image = '') + THEN NULL + ELSE encode(digest(convert_to(in_image, 'UTF8'), + 'sha256'), + 'hex') + END ,in_taxes ,in_price ,in_total_stock diff --git a/src/backenddb/pg_lookup_product_image.c b/src/backenddb/pg_lookup_product_image.c @@ -0,0 +1,66 @@ +/* + 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 backenddb/pg_lookup_product_image.c + * @brief Implementation of the lookup_product_image_by_hash function for Postgres + * @author Bohdan Potuzhnyi + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_pq_lib.h> +#include "pg_lookup_product_image.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_product_image_by_hash (void *cls, + const char *instance_id, + const char *image_hash, + char **image) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (image_hash), + GNUNET_PQ_query_param_end + }; + + check_connection (pg); + PREPARE ( + pg, + "lookup_product_image_by_hash", + "SELECT" + " mi.image" + " FROM merchant_inventory mi" + " JOIN merchant_instances inst" + " USING (merchant_serial)" + " WHERE inst.merchant_id=$1" + " AND mi.image_hash=$2"); + + *image = NULL; + { + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("image", + image), + GNUNET_PQ_result_spec_end + }; + + return GNUNET_PQ_eval_prepared_singleton_select ( + pg->conn, + "lookup_product_image_by_hash", + params, + rs); + } +} +\ No newline at end of file diff --git a/src/backenddb/pg_lookup_product_image.h b/src/backenddb/pg_lookup_product_image.h @@ -0,0 +1,32 @@ +/* + 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 backenddb/pg_lookup_product_image.h + * @brief declaration of lookup_product_image_by_hash for Postgres + * @author Bohdan Potuzhnyi + */ +#ifndef PG_LOOKUP_PRODUCT_IMAGE_H +#define PG_LOOKUP_PRODUCT_IMAGE_H + +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +TMH_PG_lookup_product_image_by_hash (void *cls, + const char *instance_id, + const char *image_hash, + char **image); + +#endif +\ No newline at end of file diff --git a/src/backenddb/pg_update_product.sql b/src/backenddb/pg_update_product.sql @@ -126,6 +126,13 @@ UPDATE merchant_inventory SET ,product_name=in_product_name ,unit=in_unit ,image=in_image + ,image_hash=CASE + WHEN (in_image IS NULL) OR (in_image = '') + THEN NULL + ELSE encode(digest(convert_to(in_image, 'UTF8'), + 'sha256'), + 'hex') + END ,taxes=in_taxes ,price=in_price ,total_stock=in_total_stock diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c @@ -81,6 +81,7 @@ #include "pg_lookup_products.h" #include "pg_lookup_all_products.h" #include "pg_lookup_product.h" +#include "pg_lookup_product_image.h" #include "pg_delete_product.h" #include "pg_insert_product.h" #include "pg_update_product.h" @@ -463,6 +464,8 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) = &TMH_PG_lookup_all_products; plugin->lookup_product = &TMH_PG_lookup_product; + plugin->lookup_product_image_by_hash + = &TMH_PG_lookup_product_image_by_hash; plugin->delete_product = &TMH_PG_delete_product; plugin->insert_product diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -1055,7 +1055,7 @@ TALER_MERCHANT_instance_delete_cancel ( * @param arg request to cancel. */ #define TALER_MERCHANT_instance_purge_cancel(arg) \ - TALER_MERCHANT_instance_delete_cancel (arg) + TALER_MERCHANT_instance_delete_cancel (arg) /* *************** Accounts **************** */ @@ -1713,6 +1713,82 @@ TALER_MERCHANT_product_get_cancel ( struct TALER_MERCHANT_ProductGetHandle *pgh); +/* ********************* /products/$HASH/image *********************** */ + + +/** + * Handle for a GET /products/$HASH/image operation. + */ +struct TALER_MERCHANT_ProductImageGetHandle; + + +/** + * Response to GET /products/$HASH/image operation. + */ +struct TALER_MERCHANT_ProductImageGetResponse +{ + /** + * HTTP response details + */ + struct TALER_MERCHANT_HttpResponse hr; + + union + { + /** + * Details for #MHD_HTTP_OK. + */ + struct + { + /** + * Base64-encoded data URL containing the product image. + */ + const char *image; + } ok; + } details; +}; + + +/** + * Function called with the result of the GET /products/$HASH/image operation. + * + * @param cls closure + * @param pir response details + */ +typedef void +(*TALER_MERCHANT_ProductImageGetCallback)( + void *cls, + const struct TALER_MERCHANT_ProductImageGetResponse *pir); + + +/** + * Make a GET /products/$HASH/image request. + * + * @param ctx the context + * @param backend_url HTTP base URL for the backend + * @param image_hash the image hash to fetch + * @param cb function to call with the backend's response + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_MERCHANT_ProductImageGetHandle * +TALER_MERCHANT_product_image_get ( + struct GNUNET_CURL_Context *ctx, + const char *backend_url, + const char *image_hash, + TALER_MERCHANT_ProductImageGetCallback cb, + void *cb_cls); + + +/** + * Cancel GET /products/$HASH/image operation. + * + * @param pigh operation to cancel + */ +void +TALER_MERCHANT_product_image_get_cancel ( + struct TALER_MERCHANT_ProductImageGetHandle *pigh); + + /** * Handle for a POST /products operation. */ diff --git a/src/include/taler_merchant_testing_lib.h b/src/include/taler_merchant_testing_lib.h @@ -38,7 +38,7 @@ #define MERCHANT_FAIL() \ - do {GNUNET_break (0); return NULL; } while (0) + do {GNUNET_break (0); return NULL; } while (0) /** @@ -497,6 +497,13 @@ TALER_TESTING_cmd_merchant_get_product (const char *label, unsigned int http_status, const char *product_reference); +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_product_image (const char *label, + const char *merchant_url, + const char *product_reference, + const char *image_hash, + unsigned int http_status); + /** * Define a "LOCK /products/$ID" CMD. @@ -2047,53 +2054,53 @@ TALER_TESTING_cmd_merchant_get_statisticsamount (const char *label, */ // FIXME: rename: refund_entry->refund_detail #define TALER_MERCHANT_TESTING_SIMPLE_TRAITS(op) \ - op (claim_nonce, const struct GNUNET_CRYPTO_EddsaPublicKey) \ - op (pickup_id, const struct TALER_PickupIdentifierP) \ - op (instance_name, const char) \ - op (instance_id, const char) \ - op (address, const json_t) \ - op (product_description, const char) \ - op (product_image, const char) \ - op (product_stock, const int64_t) \ - op (product_unit, const char) \ - op (product_id, const char) \ - op (reason, const char) \ - op (lock_uuid, const char) \ - op (auth_token, const char) \ - op (bearer_token, const char) \ - op (paths_length, const uint32_t) \ - op (payto_length, const uint32_t) \ - op (num_planchets, const uint32_t) \ - op (i18n_description, const json_t) \ - op (taxes, const json_t) \ - op (fee, const struct TALER_Amount) \ - op (use_stefan, const bool) \ - op (jurisdiction, const json_t) \ - op (wire_delay, const struct GNUNET_TIME_Relative) \ - op (pay_delay, const struct GNUNET_TIME_Relative) \ - op (refund_entry, const struct TALER_MERCHANT_RefundDetail) \ - op (order_terms, const json_t) \ - op (h_contract_terms, const struct TALER_PrivateContractHashP) \ - op (h_wire, const struct TALER_MerchantWireHashP) \ - op (proposal_reference, const char) \ - op (template_description, const char) \ - op (otp_device_description, const char) \ - op (otp_id, const char) \ - op (otp_key, const char) \ - op (otp_alg, const enum TALER_MerchantConfirmationAlgorithm) \ - op (template_id, const char) \ - op (template_contract, const json_t) \ - op (event_type, const char) \ - op (webhook_id, const char) \ - op (merchant_base_url, const char) \ - op (url, const char) \ - op (http_method, const char) \ - op (header_template, const char) \ - op (body_template, const char) \ - op (summary, const char) \ - op (token_family_slug, const char) \ - op (token_family_duration, const struct GNUNET_TIME_Relative) \ - op (token_family_kind, const char) + op (claim_nonce, const struct GNUNET_CRYPTO_EddsaPublicKey) \ + op (pickup_id, const struct TALER_PickupIdentifierP) \ + op (instance_name, const char) \ + op (instance_id, const char) \ + op (address, const json_t) \ + op (product_description, const char) \ + op (product_image, const char) \ + op (product_stock, const int64_t) \ + op (product_unit, const char) \ + op (product_id, const char) \ + op (reason, const char) \ + op (lock_uuid, const char) \ + op (auth_token, const char) \ + op (bearer_token, const char) \ + op (paths_length, const uint32_t) \ + op (payto_length, const uint32_t) \ + op (num_planchets, const uint32_t) \ + op (i18n_description, const json_t) \ + op (taxes, const json_t) \ + op (fee, const struct TALER_Amount) \ + op (use_stefan, const bool) \ + op (jurisdiction, const json_t) \ + op (wire_delay, const struct GNUNET_TIME_Relative) \ + op (pay_delay, const struct GNUNET_TIME_Relative) \ + op (refund_entry, const struct TALER_MERCHANT_RefundDetail) \ + op (order_terms, const json_t) \ + op (h_contract_terms, const struct TALER_PrivateContractHashP) \ + op (h_wire, const struct TALER_MerchantWireHashP) \ + op (proposal_reference, const char) \ + op (template_description, const char) \ + op (otp_device_description, const char) \ + op (otp_id, const char) \ + op (otp_key, const char) \ + op (otp_alg, const enum TALER_MerchantConfirmationAlgorithm) \ + op (template_id, const char) \ + op (template_contract, const json_t) \ + op (event_type, const char) \ + op (webhook_id, const char) \ + op (merchant_base_url, const char) \ + op (url, const char) \ + op (http_method, const char) \ + op (header_template, const char) \ + op (body_template, const char) \ + op (summary, const char) \ + op (token_family_slug, const char) \ + op (token_family_duration, const struct GNUNET_TIME_Relative) \ + op (token_family_kind, const char) /** @@ -2102,20 +2109,20 @@ TALER_TESTING_cmd_merchant_get_statisticsamount (const char *label, * @param op macro to call */ #define TALER_MERCHANT_TESTING_INDEXED_TRAITS(op) \ - op (coin_reference, const char) \ - op (paths, const char) \ - op (payto_uris, const struct TALER_FullPayto) \ - op (h_wires, const struct TALER_MerchantWireHashP) \ - op (amounts, const struct TALER_Amount) \ - op (urls, const char) \ - op (http_methods, const char) \ - op (http_header, const char) \ - op (http_body, const void) \ - op (http_body_size, const size_t) \ - op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \ - op (token_priv, const struct TALER_TokenUsePrivateKeyP) \ - op (token_issue_sig, const struct TALER_TokenIssueSignature) \ - op (token_issue_pub, const struct TALER_TokenIssuePublicKey) + op (coin_reference, const char) \ + op (paths, const char) \ + op (payto_uris, const struct TALER_FullPayto) \ + op (h_wires, const struct TALER_MerchantWireHashP) \ + op (amounts, const struct TALER_Amount) \ + op (urls, const char) \ + op (http_methods, const char) \ + op (http_header, const char) \ + op (http_body, const void) \ + op (http_body_size, const size_t) \ + op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \ + op (token_priv, const struct TALER_TokenUsePrivateKeyP) \ + op (token_issue_sig, const struct TALER_TokenIssueSignature) \ + op (token_issue_pub, const struct TALER_TokenIssuePublicKey) TALER_MERCHANT_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT) diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -1560,7 +1560,7 @@ struct TALER_MERCHANTDB_Plugin * @param cls closure */ enum GNUNET_GenericReturnValue - (*connect)(void *cls); + (*connect)(void *cls); /** * Drop merchant tables. Used for testcases and to reset the DB. @@ -1569,7 +1569,7 @@ struct TALER_MERCHANTDB_Plugin * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ enum GNUNET_GenericReturnValue - (*drop_tables)(void *cls); + (*drop_tables)(void *cls); /** * Garbage collect database. Removes unnecessary data. @@ -1578,7 +1578,7 @@ struct TALER_MERCHANTDB_Plugin * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ enum GNUNET_GenericReturnValue - (*gc)(void *cls); + (*gc)(void *cls); /** * Initialize merchant tables @@ -1587,7 +1587,7 @@ struct TALER_MERCHANTDB_Plugin * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ enum GNUNET_GenericReturnValue - (*create_tables)(void *cls); + (*create_tables)(void *cls); /** * Register callback to be invoked on events of type @a es. @@ -1650,8 +1650,8 @@ struct TALER_MERCHANTDB_Plugin * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue - (*start)(void *cls, - const char *name); + (*start)(void *cls, + const char *name); /** * Start a transaction with isolation level 'read committed'. @@ -1662,8 +1662,8 @@ struct TALER_MERCHANTDB_Plugin * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue - (*start_read_committed)(void *cls, - const char *name); + (*start_read_committed)(void *cls, + const char *name); /** * Roll back the current transaction of a database connection. @@ -1680,7 +1680,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*commit)(void *cls); + (*commit)(void *cls); /** * Lookup all of the instances this backend has configured. @@ -1691,10 +1691,10 @@ struct TALER_MERCHANTDB_Plugin * @param cb_cls closure for @a cb */ enum GNUNET_DB_QueryStatus - (*lookup_instances)(void *cls, - bool active_only, - TALER_MERCHANTDB_InstanceCallback cb, - void *cb_cls); + (*lookup_instances)(void *cls, + bool active_only, + TALER_MERCHANTDB_InstanceCallback cb, + void *cb_cls); /** * Lookup one of the instances this backend has configured. @@ -1706,11 +1706,11 @@ struct TALER_MERCHANTDB_Plugin * @param cb_cls closure for @a cb */ enum GNUNET_DB_QueryStatus - (*lookup_instance)(void *cls, - const char *id, - bool active_only, - TALER_MERCHANTDB_InstanceCallback cb, - void *cb_cls); + (*lookup_instance)(void *cls, + const char *id, + bool active_only, + TALER_MERCHANTDB_InstanceCallback cb, + void *cb_cls); /** * Lookup authentication data of an instance. @@ -1720,9 +1720,9 @@ struct TALER_MERCHANTDB_Plugin * @param[out] ias where to store the auth data */ enum GNUNET_DB_QueryStatus - (*lookup_instance_auth)(void *cls, - const char *instance_id, - struct TALER_MERCHANTDB_InstanceAuthSettings *ias); + (*lookup_instance_auth)(void *cls, + const char *instance_id, + struct TALER_MERCHANTDB_InstanceAuthSettings *ias); /** @@ -1737,12 +1737,12 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_instance)(void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_MerchantPrivateKeyP *merchant_priv, - const struct TALER_MERCHANTDB_InstanceSettings *is, - const struct TALER_MERCHANTDB_InstanceAuthSettings *ias, - bool validation_needed); + (*insert_instance)(void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + const struct TALER_MERCHANTDB_InstanceSettings *is, + const struct TALER_MERCHANTDB_InstanceAuthSettings *ias, + bool validation_needed); /** @@ -1753,7 +1753,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_account)( + (*insert_account)( void *cls, const struct TALER_MERCHANTDB_AccountDetails *account_details); @@ -1771,7 +1771,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_login_token)( + (*insert_login_token)( void *cls, const char *id, const struct TALER_MERCHANTDB_LoginTokenP *token, @@ -1792,7 +1792,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_login_token)( + (*select_login_token)( void *cls, const char *id, const struct TALER_MERCHANTDB_LoginTokenP *token, @@ -1812,12 +1812,12 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_login_tokens)(void *cls, - const char *instance_id, - uint64_t offset, - int64_t limit, - TALER_MERCHANTDB_LoginTokensCallback cb, - void *cb_cls); + (*lookup_login_tokens)(void *cls, + const char *instance_id, + uint64_t offset, + int64_t limit, + TALER_MERCHANTDB_LoginTokensCallback cb, + void *cb_cls); /** * Delete login token from database. @@ -1828,7 +1828,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*delete_login_token)( + (*delete_login_token)( void *cls, const char *id, const struct TALER_MERCHANTDB_LoginTokenP *token); @@ -1842,7 +1842,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*delete_login_token_serial)( + (*delete_login_token_serial)( void *cls, const char *id, uint64_t serial); @@ -1859,7 +1859,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_account)( + (*update_account)( void *cls, const char *id, const struct TALER_MerchantWireHashP *h_wire, @@ -1877,7 +1877,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_accounts)( + (*select_accounts)( void *cls, const char *id, TALER_MERCHANTDB_AccountCallback cb, @@ -1894,7 +1894,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_account)( + (*select_account)( void *cls, const char *id, const struct TALER_MerchantWireHashP *h_wire, @@ -1911,7 +1911,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_account_by_uri)( + (*select_account_by_uri)( void *cls, const char *id, struct TALER_FullPayto payto_uri, @@ -1926,7 +1926,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*delete_instance_private_key)( + (*delete_instance_private_key)( void *cls, const char *merchant_id); @@ -1939,8 +1939,8 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*purge_instance)(void *cls, - const char *merchant_id); + (*purge_instance)(void *cls, + const char *merchant_id); /** * Update information about an instance into our database. @@ -1950,8 +1950,8 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_instance)(void *cls, - const struct TALER_MERCHANTDB_InstanceSettings *is); + (*update_instance)(void *cls, + const struct TALER_MERCHANTDB_InstanceSettings *is); /** * Update information about an instance's authentication settings @@ -1963,7 +1963,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_instance_auth)( + (*update_instance_auth)( void *cls, const char *merchant_id, const struct TALER_MERCHANTDB_InstanceAuthSettings *ias); @@ -1977,9 +1977,9 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*inactivate_account)(void *cls, - const char *merchant_id, - const struct TALER_MerchantWireHashP *h_wire); + (*inactivate_account)(void *cls, + const char *merchant_id, + const struct TALER_MerchantWireHashP *h_wire); /** @@ -1991,9 +1991,9 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*activate_account)(void *cls, - const char *merchant_id, - const struct TALER_MerchantWireHashP *h_wire); + (*activate_account)(void *cls, + const char *merchant_id, + const struct TALER_MerchantWireHashP *h_wire); /** @@ -2010,7 +2010,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*account_kyc_get_status)( + (*account_kyc_get_status)( void *cls, const char *merchant_id, const struct TALER_MerchantWireHashP *h_wire, @@ -2039,7 +2039,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*get_kyc_status)( + (*get_kyc_status)( void *cls, struct TALER_FullPayto merchant_account_uri, const char *instance_id, @@ -2068,7 +2068,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*get_kyc_limits)( + (*get_kyc_limits)( void *cls, struct TALER_FullPayto merchant_account_uri, const char *instance_id, @@ -2097,7 +2097,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*account_kyc_set_status)( + (*account_kyc_set_status)( void *cls, const char *merchant_id, const struct TALER_MerchantWireHashP *h_wire, @@ -2125,7 +2125,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*account_kyc_set_failed)( + (*account_kyc_set_failed)( void *cls, const char *merchant_id, const struct TALER_MerchantWireHashP *h_wire, @@ -2169,15 +2169,15 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_products)(void *cls, - const char *instance_id, - uint64_t offset, - int64_t limit, - const char *category_filter, - const char *name_filter, - const char *description_filter, - TALER_MERCHANTDB_ProductsCallback cb, - void *cb_cls); + (*lookup_products)(void *cls, + const char *instance_id, + uint64_t offset, + int64_t limit, + const char *category_filter, + const char *name_filter, + const char *description_filter, + TALER_MERCHANTDB_ProductsCallback cb, + void *cb_cls); /** @@ -2190,10 +2190,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_all_products)(void *cls, - const char *instance_id, - TALER_MERCHANTDB_ProductCallback cb, - void *cb_cls); + (*lookup_all_products)(void *cls, + const char *instance_id, + TALER_MERCHANTDB_ProductCallback cb, + void *cb_cls); /** * Lookup details about a particular product. @@ -2209,12 +2209,27 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_product)(void *cls, - const char *instance_id, - const char *product_id, - struct TALER_MERCHANTDB_ProductDetails *pd, - size_t *num_categories, - uint64_t **categories); + (*lookup_product)(void *cls, + const char *instance_id, + const char *product_id, + struct TALER_MERCHANTDB_ProductDetails *pd, + size_t *num_categories, + uint64_t **categories); + + /** + * Lookup product image by its hash. + * + * @param cls closure + * @param instance_id instance to lookup products for + * @param image_hash lowercase hexadecimal representation of the SHA256 hash + * @param[out] image set to base64-encoded data URL on success, caller must free() + * @return database result code + */ + enum GNUNET_DB_QueryStatus + (*lookup_product_image_by_hash)(void *cls, + const char *instance_id, + const char *image_hash, + char **image); /** * Delete information about a product. Note that the transaction must @@ -2227,9 +2242,9 @@ struct TALER_MERCHANTDB_Plugin * if locks prevent deletion OR product unknown */ enum GNUNET_DB_QueryStatus - (*delete_product)(void *cls, - const char *instance_id, - const char *product_id); + (*delete_product)(void *cls, + const char *instance_id, + const char *product_id); /** * Insert details about a particular product. @@ -2247,15 +2262,15 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_product)(void *cls, - const char *instance_id, - const char *product_id, - const struct TALER_MERCHANTDB_ProductDetails *pd, - size_t num_cats, - const uint64_t *cats, - bool *no_instance, - bool *conflict, - ssize_t *no_cat); + (*insert_product)(void *cls, + const char *instance_id, + const char *product_id, + const struct TALER_MERCHANTDB_ProductDetails *pd, + size_t num_cats, + const uint64_t *cats, + bool *no_instance, + bool *conflict, + ssize_t *no_cat); /** * Update details about a particular product. Note that the @@ -2279,18 +2294,18 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_product)(void *cls, - const char *instance_id, - const char *product_id, - const struct TALER_MERCHANTDB_ProductDetails *pd, - size_t num_cats, - const uint64_t *cats, - bool *no_instance, - ssize_t *no_cat, - bool *no_product, - bool *lost_reduced, - bool *sold_reduced, - bool *stocked_reduced); + (*update_product)(void *cls, + const char *instance_id, + const char *product_id, + const struct TALER_MERCHANTDB_ProductDetails *pd, + size_t num_cats, + const uint64_t *cats, + bool *no_instance, + ssize_t *no_cat, + bool *no_product, + bool *lost_reduced, + bool *sold_reduced, + bool *stocked_reduced); /** * Lock stocks of a particular product. Note that the transaction must @@ -2306,12 +2321,12 @@ struct TALER_MERCHANTDB_Plugin * product is unknown OR if there insufficient stocks remaining */ enum GNUNET_DB_QueryStatus - (*lock_product)(void *cls, - const char *instance_id, - const char *product_id, - const struct GNUNET_Uuid *uuid, - uint64_t quantity, - struct GNUNET_TIME_Timestamp expiration_time); + (*lock_product)(void *cls, + const char *instance_id, + const char *product_id, + const struct GNUNET_Uuid *uuid, + uint64_t quantity, + struct GNUNET_TIME_Timestamp expiration_time); /** @@ -2323,7 +2338,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*expire_locks)(void *cls); + (*expire_locks)(void *cls); /** @@ -2338,10 +2353,10 @@ struct TALER_MERCHANTDB_Plugin * if locks prevent deletion OR order unknown */ enum GNUNET_DB_QueryStatus - (*delete_order)(void *cls, - const char *instance_id, - const char *order_id, - bool force); + (*delete_order)(void *cls, + const char *instance_id, + const char *order_id, + bool force); /** @@ -2358,12 +2373,12 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_order)(void *cls, - const char *instance_id, - const char *order_id, - struct TALER_ClaimTokenP *claim_token, - struct TALER_MerchantPostDataHashP *h_post_data, - json_t **contract_terms); + (*lookup_order)(void *cls, + const char *instance_id, + const char *order_id, + struct TALER_ClaimTokenP *claim_token, + struct TALER_MerchantPostDataHashP *h_post_data, + json_t **contract_terms); /** @@ -2377,11 +2392,11 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_order_summary)(void *cls, - const char *instance_id, - const char *order_id, - struct GNUNET_TIME_Timestamp *timestamp, - uint64_t *order_serial); + (*lookup_order_summary)(void *cls, + const char *instance_id, + const char *order_id, + struct GNUNET_TIME_Timestamp *timestamp, + uint64_t *order_serial); /** @@ -2395,11 +2410,11 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_orders)(void *cls, - const char *instance_id, - const struct TALER_MERCHANTDB_OrderFilter *of, - TALER_MERCHANTDB_OrdersCallback cb, - void *cb_cls); + (*lookup_orders)(void *cls, + const char *instance_id, + const struct TALER_MERCHANTDB_OrderFilter *of, + TALER_MERCHANTDB_OrdersCallback cb, + void *cb_cls); /** @@ -2418,16 +2433,16 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_order)(void *cls, - const char *instance_id, - const char *order_id, - const char *session_id, - const struct TALER_MerchantPostDataHashP *h_post_data, - struct GNUNET_TIME_Timestamp pay_deadline, - const struct TALER_ClaimTokenP *claim_token, - const json_t *contract_terms, - const char *pos_key, - enum TALER_MerchantConfirmationAlgorithm pos_algorithm); + (*insert_order)(void *cls, + const char *instance_id, + const char *order_id, + const char *session_id, + const struct TALER_MerchantPostDataHashP *h_post_data, + struct GNUNET_TIME_Timestamp pay_deadline, + const struct TALER_ClaimTokenP *claim_token, + const json_t *contract_terms, + const char *pos_key, + enum TALER_MerchantConfirmationAlgorithm pos_algorithm); /** @@ -2440,7 +2455,7 @@ struct TALER_MERCHANTDB_Plugin * @param blinded_sigs JSON array of blinded signatures */ enum GNUNET_DB_QueryStatus - (*insert_order_blinded_sigs)( + (*insert_order_blinded_sigs)( void *cls, const char *order_id, uint32_t i, @@ -2459,8 +2474,8 @@ struct TALER_MERCHANTDB_Plugin * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT indicates success */ enum GNUNET_DB_QueryStatus - (*unlock_inventory)(void *cls, - const struct GNUNET_Uuid *uuid); + (*unlock_inventory)(void *cls, + const struct GNUNET_Uuid *uuid); /** @@ -2476,11 +2491,11 @@ struct TALER_MERCHANTDB_Plugin * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT indicates success */ enum GNUNET_DB_QueryStatus - (*insert_order_lock)(void *cls, - const char *instance_id, - const char *order_id, - const char *product_id, - uint64_t quantity); + (*insert_order_lock)(void *cls, + const char *instance_id, + const char *order_id, + const char *product_id, + uint64_t quantity); /** @@ -2492,7 +2507,7 @@ struct TALER_MERCHANTDB_Plugin * @param cb_cls closure for @a cb */ enum GNUNET_DB_QueryStatus - (*select_order_blinded_sigs)( + (*select_order_blinded_sigs)( void *cls, const char *order_id, TALER_MERCHANTDB_BlindedSigCallback cb, @@ -2514,7 +2529,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_contract_terms2)( + (*lookup_contract_terms2)( void *cls, const char *instance_id, const char *order_id, @@ -2543,7 +2558,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_contract_terms3)( + (*lookup_contract_terms3)( void *cls, const char *instance_id, const char *order_id, @@ -2569,7 +2584,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_contract_terms)( + (*lookup_contract_terms)( void *cls, const char *instance_id, const char *order_id, @@ -2595,7 +2610,7 @@ struct TALER_MERCHANTDB_Plugin * is malformed */ enum GNUNET_DB_QueryStatus - (*insert_contract_terms)( + (*insert_contract_terms)( void *cls, const char *instance_id, const char *order_id, @@ -2619,10 +2634,10 @@ struct TALER_MERCHANTDB_Plugin * is malformed */ enum GNUNET_DB_QueryStatus - (*update_contract_terms)(void *cls, - const char *instance_id, - const char *order_id, - json_t *contract_terms); + (*update_contract_terms)(void *cls, + const char *instance_id, + const char *order_id, + json_t *contract_terms); /** @@ -2639,10 +2654,10 @@ struct TALER_MERCHANTDB_Plugin * if locks prevent deletion OR order unknown */ enum GNUNET_DB_QueryStatus - (*delete_contract_terms)(void *cls, - const char *instance_id, - const char *order_id, - struct GNUNET_TIME_Relative legal_expiration); + (*delete_contract_terms)(void *cls, + const char *instance_id, + const char *order_id, + struct GNUNET_TIME_Relative legal_expiration); /** @@ -2657,12 +2672,12 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_deposits)(void *cls, - const char *instance_id, - const struct TALER_PrivateContractHashP *h_contract_terms - , - TALER_MERCHANTDB_DepositsCallback cb, - void *cb_cls); + (*lookup_deposits)(void *cls, + const char *instance_id, + const struct TALER_PrivateContractHashP *h_contract_terms + , + TALER_MERCHANTDB_DepositsCallback cb, + void *cb_cls); /** @@ -2677,7 +2692,7 @@ struct TALER_MERCHANTDB_Plugin * @param master_sig signature of @a master_pub over the @a exchange_pub and the dates */ enum GNUNET_DB_QueryStatus - (*insert_exchange_signkey)( + (*insert_exchange_signkey)( void *cls, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_ExchangePublicKeyP *exchange_pub, @@ -2705,7 +2720,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_deposit_confirmation)( + (*insert_deposit_confirmation)( void *cls, const char *instance_id, struct GNUNET_TIME_Timestamp deposit_timestamp, @@ -2737,7 +2752,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_deposit)( + (*insert_deposit)( void *cls, uint32_t offset, uint64_t deposit_confirmation_serial_id, @@ -2760,11 +2775,11 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_refunds)(void *cls, - const char *instance_id, - const struct TALER_PrivateContractHashP *h_contract_terms, - TALER_MERCHANTDB_RefundCallback rc, - void *rc_cls); + (*lookup_refunds)(void *cls, + const char *instance_id, + const struct TALER_PrivateContractHashP *h_contract_terms, + TALER_MERCHANTDB_RefundCallback rc, + void *rc_cls); /** @@ -2777,10 +2792,10 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_spent_tokens_by_order)(void *cls, - uint64_t order_serial, - TALER_MERCHANTDB_UsedTokensCallback cb, - void *cb_cls); + (*lookup_spent_tokens_by_order)(void *cls, + uint64_t order_serial, + TALER_MERCHANTDB_UsedTokensCallback cb, + void *cb_cls); /** @@ -2795,7 +2810,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*mark_contract_paid)( + (*mark_contract_paid)( void *cls, const char *instance_id, const struct TALER_PrivateContractHashP *h_contract_terms, @@ -2819,12 +2834,12 @@ struct TALER_MERCHANTDB_Plugin * regardless of whether it actually increased the refund */ enum GNUNET_DB_QueryStatus - (*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); + (*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); /** @@ -2838,11 +2853,11 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_order_status)(void *cls, - const char *instance_id, - const char *order_id, - struct TALER_PrivateContractHashP *h_contract_terms, - bool *paid); + (*lookup_order_status)(void *cls, + const char *instance_id, + const char *order_id, + struct TALER_PrivateContractHashP *h_contract_terms, + bool *paid); /** * Retrieve contract terms given its @a order_serial @@ -2856,13 +2871,13 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*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); + (*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); /** @@ -2875,10 +2890,10 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_deposits_by_order)(void *cls, - uint64_t order_serial, - TALER_MERCHANTDB_DepositedCoinsCallback cb, - void *cb_cls); + (*lookup_deposits_by_order)(void *cls, + uint64_t order_serial, + TALER_MERCHANTDB_DepositedCoinsCallback cb, + void *cb_cls); /** @@ -2892,7 +2907,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_transfer_details_by_order)( + (*lookup_transfer_details_by_order)( void *cls, uint64_t order_serial, TALER_MERCHANTDB_OrderTransferDetailsCallback cb, @@ -2913,7 +2928,7 @@ struct TALER_MERCHANTDB_Plugin * @return database transaction status */ enum GNUNET_DB_QueryStatus - (*update_transfer_status)( + (*update_transfer_status)( void *cls, const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, @@ -2938,7 +2953,7 @@ struct TALER_MERCHANTDB_Plugin * @return database transaction status */ enum GNUNET_DB_QueryStatus - (*finalize_transfer_status)( + (*finalize_transfer_status)( void *cls, const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, @@ -2961,7 +2976,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*select_open_transfers)( + (*select_open_transfers)( void *cls, uint64_t limit, TALER_MERCHANTDB_OpenTransferCallback cb, @@ -2979,11 +2994,11 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_deposit_to_transfer)(void *cls, - uint64_t deposit_serial, - const struct TALER_MerchantWireHashP *h_wire, - const char *exchange_url, - const struct TALER_EXCHANGE_DepositData *dd); + (*insert_deposit_to_transfer)(void *cls, + uint64_t deposit_serial, + const struct TALER_MerchantWireHashP *h_wire, + const char *exchange_url, + const struct TALER_EXCHANGE_DepositData *dd); /** @@ -2994,8 +3009,8 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*mark_order_wired)(void *cls, - uint64_t order_serial); + (*mark_order_wired)(void *cls, + uint64_t order_serial); /** @@ -3021,7 +3036,7 @@ struct TALER_MERCHANTDB_Plugin * what was already refunded (idempotency!) */ enum TALER_MERCHANTDB_RefundStatus - (*increase_refund)( + (*increase_refund)( void *cls, const char *instance_id, const char *order_id, @@ -3042,7 +3057,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_refunds_detailed)( + (*lookup_refunds_detailed)( void *cls, const char *instance_id, const struct TALER_PrivateContractHashP *h_contract_terms, @@ -3059,7 +3074,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_refund_proof)( + (*insert_refund_proof)( void *cls, uint64_t refund_serial, const struct TALER_ExchangeSignatureP *exchange_sig, @@ -3078,7 +3093,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_spent_token)( + (*insert_spent_token)( void *cls, const struct TALER_PrivateContractHashP * h_contract_terms, @@ -3098,7 +3113,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_issued_token)( + (*insert_issued_token)( void *cls, const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_TokenIssuePublicKeyHashP *h_issue_pub, @@ -3115,7 +3130,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_refund_proof)( + (*lookup_refund_proof)( void *cls, uint64_t refund_serial, struct TALER_ExchangeSignatureP *exchange_sig, @@ -3136,7 +3151,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_order_by_fulfillment)( + (*lookup_order_by_fulfillment)( void *cls, const char *instance_id, const char *fulfillment_url, @@ -3154,7 +3169,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*update_wirewatch_progress)( + (*update_wirewatch_progress)( void *cls, const char *instance, struct TALER_FullPayto payto_uri, @@ -3170,7 +3185,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*select_wirewatch_accounts)( + (*select_wirewatch_accounts)( void *cls, TALER_MERCHANTDB_WirewatchWorkCallback cb, void *cb_cls); @@ -3189,7 +3204,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_transfer)( + (*insert_transfer)( void *cls, const char *instance_id, const char *exchange_url, @@ -3210,9 +3225,9 @@ struct TALER_MERCHANTDB_Plugin * if deletion is prohibited OR transfer is unknown */ enum GNUNET_DB_QueryStatus - (*delete_transfer)(void *cls, - const char *instance_id, - uint64_t transfer_serial_id); + (*delete_transfer)(void *cls, + const char *instance_id, + uint64_t transfer_serial_id); /** @@ -3226,9 +3241,9 @@ struct TALER_MERCHANTDB_Plugin * if the transfer record exists */ enum GNUNET_DB_QueryStatus - (*check_transfer_exists)(void *cls, - const char *instance_id, - uint64_t transfer_serial_id); + (*check_transfer_exists)(void *cls, + const char *instance_id, + uint64_t transfer_serial_id); /** @@ -3241,10 +3256,10 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_account)(void *cls, - const char *instance_id, - struct TALER_FullPayto payto_uri, - uint64_t *account_serial); + (*lookup_account)(void *cls, + const char *instance_id, + struct TALER_FullPayto payto_uri, + uint64_t *account_serial); /** @@ -3261,7 +3276,7 @@ struct TALER_MERCHANTDB_Plugin * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT on success */ enum GNUNET_DB_QueryStatus - (*insert_transfer_details)( + (*insert_transfer_details)( void *cls, const char *instance_id, const char *exchange_url, @@ -3285,7 +3300,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*lookup_wire_fee)( + (*lookup_wire_fee)( void *cls, const struct TALER_MasterPublicKeyP *master_pub, const char *wire_method, @@ -3309,7 +3324,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_deposits_by_contract_and_coin)( + (*lookup_deposits_by_contract_and_coin)( void *cls, const char *instance_id, const struct TALER_PrivateContractHashP *h_contract_terms, @@ -3329,7 +3344,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_transfer_summary)( + (*lookup_transfer_summary)( void *cls, const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, @@ -3348,7 +3363,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_transfer_details)( + (*lookup_transfer_details)( void *cls, const char *exchange_url, const struct TALER_WireTransferIdentifierRawP *wtid, @@ -3373,7 +3388,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_transfers)( + (*lookup_transfers)( void *cls, const char *instance_id, struct TALER_FullPayto payto_uri, @@ -3404,7 +3419,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_expected_transfers)( + (*lookup_expected_transfers)( void *cls, const char *instance_id, struct TALER_FullPayto payto_uri, @@ -3432,7 +3447,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*store_wire_fee_by_exchange)( + (*store_wire_fee_by_exchange)( void *cls, const struct TALER_MasterPublicKeyP *master_pub, const struct GNUNET_HashCode *h_wire_method, @@ -3450,7 +3465,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*delete_exchange_accounts)( + (*delete_exchange_accounts)( void *cls, const struct TALER_MasterPublicKeyP *master_pub); @@ -3465,7 +3480,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_accounts_by_exchange)( + (*select_accounts_by_exchange)( void *cls, const struct TALER_MasterPublicKeyP *master_pub, TALER_MERCHANTDB_ExchangeAccountCallback cb, @@ -3485,7 +3500,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_exchange_account)( + (*insert_exchange_account)( void *cls, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_FullPayto payto_uri, @@ -3505,10 +3520,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_templates)(void *cls, - const char *instance_id, - TALER_MERCHANTDB_TemplatesCallback cb, - void *cb_cls); + (*lookup_templates)(void *cls, + const char *instance_id, + TALER_MERCHANTDB_TemplatesCallback cb, + void *cb_cls); /** @@ -3522,10 +3537,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_template)(void *cls, - const char *instance_id, - const char *template_id, - struct TALER_MERCHANTDB_TemplateDetails *td); + (*lookup_template)(void *cls, + const char *instance_id, + const char *template_id, + struct TALER_MERCHANTDB_TemplateDetails *td); /** * Delete information about a template. @@ -3537,9 +3552,9 @@ struct TALER_MERCHANTDB_Plugin * if template unknown. */ enum GNUNET_DB_QueryStatus - (*delete_template)(void *cls, - const char *instance_id, - const char *template_id); + (*delete_template)(void *cls, + const char *instance_id, + const char *template_id); /** @@ -3553,11 +3568,11 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_template)(void *cls, - const char *instance_id, - const char *template_id, - uint64_t otp_serial_id, - const struct TALER_MERCHANTDB_TemplateDetails *td); + (*insert_template)(void *cls, + const char *instance_id, + const char *template_id, + uint64_t otp_serial_id, + const struct TALER_MERCHANTDB_TemplateDetails *td); /** @@ -3572,10 +3587,10 @@ struct TALER_MERCHANTDB_Plugin * does not yet exist. */ enum GNUNET_DB_QueryStatus - (*update_template)(void *cls, - const char *instance_id, - const char *template_id, - const struct TALER_MERCHANTDB_TemplateDetails *td); + (*update_template)(void *cls, + const char *instance_id, + const char *template_id, + const struct TALER_MERCHANTDB_TemplateDetails *td); /** @@ -3588,9 +3603,9 @@ struct TALER_MERCHANTDB_Plugin * if template unknown. */ enum GNUNET_DB_QueryStatus - (*delete_otp)(void *cls, - const char *instance_id, - const char *otp_id); + (*delete_otp)(void *cls, + const char *instance_id, + const char *otp_id); /** * Insert details about a particular OTP device. @@ -3602,10 +3617,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_otp)(void *cls, - const char *instance_id, - const char *otp_id, - const struct TALER_MERCHANTDB_OtpDeviceDetails *td); + (*insert_otp)(void *cls, + const char *instance_id, + const char *otp_id, + const struct TALER_MERCHANTDB_OtpDeviceDetails *td); /** @@ -3620,10 +3635,10 @@ struct TALER_MERCHANTDB_Plugin * does not yet exist. */ enum GNUNET_DB_QueryStatus - (*update_otp)(void *cls, - const char *instance_id, - const char *otp_id, - const struct TALER_MERCHANTDB_OtpDeviceDetails *td); + (*update_otp)(void *cls, + const char *instance_id, + const char *otp_id, + const struct TALER_MERCHANTDB_OtpDeviceDetails *td); /** * Lookup all of the OTP devices the given instance has configured. @@ -3635,10 +3650,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_otp_devices)(void *cls, - const char *instance_id, - TALER_MERCHANTDB_OtpDeviceCallback cb, - void *cb_cls); + (*lookup_otp_devices)(void *cls, + const char *instance_id, + TALER_MERCHANTDB_OtpDeviceCallback cb, + void *cb_cls); /** @@ -3652,10 +3667,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_otp)(void *cls, - const char *instance_id, - const char *otp_id, - struct TALER_MERCHANTDB_OtpDeviceDetails *td); + (*select_otp)(void *cls, + const char *instance_id, + const char *otp_id, + struct TALER_MERCHANTDB_OtpDeviceDetails *td); /** @@ -3667,10 +3682,10 @@ struct TALER_MERCHANTDB_Plugin * @param[out] serial set to the OTP device serial number * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_otp_serial)(void *cls, - const char *instance_id, - const char *otp_id, - uint64_t *serial); + (*select_otp_serial)(void *cls, + const char *instance_id, + const char *otp_id, + uint64_t *serial); /** @@ -3683,9 +3698,9 @@ struct TALER_MERCHANTDB_Plugin * if template unknown. */ enum GNUNET_DB_QueryStatus - (*delete_category)(void *cls, - const char *instance_id, - uint64_t category_id); + (*delete_category)(void *cls, + const char *instance_id, + uint64_t category_id); /** * Insert new product category. @@ -3698,11 +3713,11 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_category)(void *cls, - const char *instance_id, - const char *category_name, - const json_t *category_name_i18n, - uint64_t *category_id); + (*insert_category)(void *cls, + const char *instance_id, + const char *category_name, + const json_t *category_name_i18n, + uint64_t *category_id); /** @@ -3717,11 +3732,11 @@ struct TALER_MERCHANTDB_Plugin * does not yet exist. */ enum GNUNET_DB_QueryStatus - (*update_category)(void *cls, - const char *instance_id, - uint64_t category_id, - const char *category_name, - const json_t *category_name_i18n); + (*update_category)(void *cls, + const char *instance_id, + uint64_t category_id, + const char *category_name, + const json_t *category_name_i18n); /** * Lookup all of the product categories the given instance has configured. @@ -3733,10 +3748,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_categories)(void *cls, - const char *instance_id, - TALER_MERCHANTDB_CategoriesCallback cb, - void *cb_cls); + (*lookup_categories)(void *cls, + const char *instance_id, + TALER_MERCHANTDB_CategoriesCallback cb, + void *cb_cls); /** @@ -3752,12 +3767,12 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_category)(void *cls, - const char *instance_id, - uint64_t category_id, - struct TALER_MERCHANTDB_CategoryDetails *cd, - size_t *num_products, - char **products); + (*select_category)(void *cls, + const char *instance_id, + uint64_t category_id, + struct TALER_MERCHANTDB_CategoryDetails *cd, + size_t *num_products, + char **products); /** @@ -3771,11 +3786,11 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*select_category_by_name)(void *cls, - const char *instance_id, - const char *category_name, - json_t **name_i18n, - uint64_t *category_id); + (*select_category_by_name)(void *cls, + const char *instance_id, + const char *category_name, + json_t **name_i18n, + uint64_t *category_id); /** @@ -3788,10 +3803,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_webhooks)(void *cls, - const char *instance_id, - TALER_MERCHANTDB_WebhooksCallback cb, - void *cb_cls); + (*lookup_webhooks)(void *cls, + const char *instance_id, + TALER_MERCHANTDB_WebhooksCallback cb, + void *cb_cls); /** @@ -3805,10 +3820,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_webhook)(void *cls, - const char *instance_id, - const char *webhook_id, - struct TALER_MERCHANTDB_WebhookDetails *wb); + (*lookup_webhook)(void *cls, + const char *instance_id, + const char *webhook_id, + struct TALER_MERCHANTDB_WebhookDetails *wb); /** * Delete information about a webhook. @@ -3820,9 +3835,9 @@ struct TALER_MERCHANTDB_Plugin * if webhook unknown. */ enum GNUNET_DB_QueryStatus - (*delete_webhook)(void *cls, - const char *instance_id, - const char *webhook_id); + (*delete_webhook)(void *cls, + const char *instance_id, + const char *webhook_id); /** @@ -3835,10 +3850,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_webhook)(void *cls, - const char *instance_id, - const char *webhook_id, - const struct TALER_MERCHANTDB_WebhookDetails *wb); + (*insert_webhook)(void *cls, + const char *instance_id, + const char *webhook_id, + const struct TALER_MERCHANTDB_WebhookDetails *wb); /** @@ -3853,10 +3868,10 @@ struct TALER_MERCHANTDB_Plugin * does not yet exist. */ enum GNUNET_DB_QueryStatus - (*update_webhook)(void *cls, - const char *instance_id, - const char *webhook_id, - const struct TALER_MERCHANTDB_WebhookDetails *wb); + (*update_webhook)(void *cls, + const char *instance_id, + const char *webhook_id, + const struct TALER_MERCHANTDB_WebhookDetails *wb); /** * Lookup webhook by event @@ -3869,11 +3884,11 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_webhook_by_event)(void *cls, - const char *instance_id, - const char *event_type, - TALER_MERCHANTDB_WebhookDetailCallback cb, - void *cb_cls); + (*lookup_webhook_by_event)(void *cls, + const char *instance_id, + const char *event_type, + TALER_MERCHANTDB_WebhookDetailCallback cb, + void *cb_cls); /** * Insert webhook in the pending webhook. @@ -3888,13 +3903,13 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_pending_webhook)(void *cls, - const char *instance_id, - uint64_t webhook_serial, - const char *url, - const char *http_method, - const char *header, - const char *body); + (*insert_pending_webhook)(void *cls, + const char *instance_id, + uint64_t webhook_serial, + const char *url, + const char *http_method, + const char *header, + const char *body); /** * Lookup the webhook that need to be send in priority. These webhooks are not successfully * send. @@ -3905,9 +3920,9 @@ struct TALER_MERCHANTDB_Plugin */ // WHERE next_attempt <= now ORDER BY next_attempt ASC enum GNUNET_DB_QueryStatus - (*lookup_pending_webhooks)(void *cls, - TALER_MERCHANTDB_PendingWebhooksCallback cb, - void *cb_cls); + (*lookup_pending_webhooks)(void *cls, + TALER_MERCHANTDB_PendingWebhooksCallback cb, + void *cb_cls); /** * Lookup future webhook in the pending webhook that need to be send. @@ -3919,9 +3934,9 @@ struct TALER_MERCHANTDB_Plugin */ // ORDER BY next_attempt ASC LIMIT 1 enum GNUNET_DB_QueryStatus - (*lookup_future_webhook)(void *cls, - TALER_MERCHANTDB_PendingWebhooksCallback cb, - void *cb_cls); + (*lookup_future_webhook)(void *cls, + TALER_MERCHANTDB_PendingWebhooksCallback cb, + void *cb_cls); /** * Lookup all the webhooks in the pending webhook. @@ -3936,12 +3951,12 @@ struct TALER_MERCHANTDB_Plugin */ // WHERE webhook_pending_serial > min_row ORDER BY webhook_pending_serial ASC LIMIT max_results enum GNUNET_DB_QueryStatus - (*lookup_all_webhooks)(void *cls, - const char *instance_id, - uint64_t min_row, - uint32_t max_results, - TALER_MERCHANTDB_PendingWebhooksCallback cb, - void *cb_cls); + (*lookup_all_webhooks)(void *cls, + const char *instance_id, + uint64_t min_row, + uint32_t max_results, + TALER_MERCHANTDB_PendingWebhooksCallback cb, + void *cb_cls); /** @@ -3953,9 +3968,9 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_pending_webhook)(void *cls, - uint64_t webhook_pending_serial, - struct GNUNET_TIME_Absolute next_attempt); + (*update_pending_webhook)(void *cls, + uint64_t webhook_pending_serial, + struct GNUNET_TIME_Absolute next_attempt); // maybe add: http status of failure? @@ -3968,8 +3983,8 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*delete_pending_webhook)(void *cls, - uint64_t webhook_pending_serial); + (*delete_pending_webhook)(void *cls, + uint64_t webhook_pending_serial); /** @@ -3982,10 +3997,10 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*select_exchange_keys)(void *cls, - const char *exchange_url, - struct GNUNET_TIME_Absolute *first_retry, - struct TALER_EXCHANGE_Keys **keys); + (*select_exchange_keys)(void *cls, + const char *exchange_url, + struct GNUNET_TIME_Absolute *first_retry, + struct TALER_EXCHANGE_Keys **keys); /** @@ -3997,9 +4012,9 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_exchange_keys)(void *cls, - const struct TALER_EXCHANGE_Keys *keys, - struct GNUNET_TIME_Absolute first_retry); + (*insert_exchange_keys)(void *cls, + const struct TALER_EXCHANGE_Keys *keys, + struct GNUNET_TIME_Absolute first_retry); /** @@ -4012,10 +4027,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_token_families)(void *cls, - const char *instance_id, - TALER_MERCHANTDB_TokenFamiliesCallback cb, - void *cb_cls); + (*lookup_token_families)(void *cls, + const char *instance_id, + TALER_MERCHANTDB_TokenFamiliesCallback cb, + void *cb_cls); /** * Lookup details about a particular token family. @@ -4028,10 +4043,10 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_token_family)(void *cls, - const char *instance_id, - const char *token_family_slug, - struct TALER_MERCHANTDB_TokenFamilyDetails *details); + (*lookup_token_family)(void *cls, + const char *instance_id, + const char *token_family_slug, + struct TALER_MERCHANTDB_TokenFamilyDetails *details); /** * Delete information about a token family. @@ -4042,9 +4057,9 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*delete_token_family)(void *cls, - const char *instance_id, - const char *token_family_slug); + (*delete_token_family)(void *cls, + const char *instance_id, + const char *token_family_slug); /** * Update details about a particular token family. @@ -4057,7 +4072,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_token_family)( + (*update_token_family)( void *cls, const char *instance_id, const char *token_family_slug, @@ -4074,7 +4089,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_token_family)( + (*insert_token_family)( void *cls, const char *instance_id, const char *token_family_slug, @@ -4094,7 +4109,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_token_family_key)( + (*lookup_token_family_key)( void *cls, const char *instance_id, const char *token_family_slug, @@ -4116,7 +4131,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_token_family_keys)( + (*lookup_token_family_keys)( void *cls, const char *instance_id, const char *token_family_slug, @@ -4141,7 +4156,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*insert_token_family_key)( + (*insert_token_family_key)( void *cls, const char *merchant_id, const char *token_family_slug, @@ -4163,7 +4178,7 @@ struct TALER_MERCHANTDB_Plugin * @return transaction status */ enum GNUNET_DB_QueryStatus - (*lookup_pending_deposits)( + (*lookup_pending_deposits)( void *cls, const char *exchange_url, uint64_t limit, @@ -4186,7 +4201,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_deposit_confirmation_status)( + (*update_deposit_confirmation_status)( void *cls, uint64_t deposit_serial, bool retry_needed, @@ -4205,7 +4220,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_donau_instance_receipts_amount)( + (*update_donau_instance_receipts_amount)( void *cls, uint64_t *donau_instances_serial, const struct TALER_Amount *new_amount @@ -4232,7 +4247,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_mfa_challenge)( + (*lookup_mfa_challenge)( void *cls, uint64_t challenge_id, const struct TALER_MERCHANT_MFA_BodyHash *h_body, @@ -4262,7 +4277,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*solve_mfa_challenge)( + (*solve_mfa_challenge)( void *cls, uint64_t challenge_id, const struct TALER_MERCHANT_MFA_BodyHash *h_body, @@ -4286,7 +4301,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*update_mfa_challenge)( + (*update_mfa_challenge)( void *cls, uint64_t challenge_id, const char *code, @@ -4313,7 +4328,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*create_mfa_challenge)( + (*create_mfa_challenge)( void *cls, enum TALER_MERCHANT_MFA_CriticalOperation op, const struct TALER_MERCHANT_MFA_BodyHash *h_body, @@ -4336,7 +4351,7 @@ struct TALER_MERCHANTDB_Plugin * @param charity_id charity ID of the Donau instance */ enum GNUNET_DB_QueryStatus - (*insert_donau_instance)( + (*insert_donau_instance)( void *cls, const char *donau_url, const struct DONAU_Charity *charity, @@ -4353,7 +4368,7 @@ struct TALER_MERCHANTDB_Plugin * @param charity_id charity ID of the Donau instance */ enum GNUNET_DB_QueryStatus - (*check_donau_instance)( + (*check_donau_instance)( void *cls, const struct TALER_MerchantPublicKeyP *merchant_pub, const char *donau_url, @@ -4369,7 +4384,7 @@ struct TALER_MERCHANTDB_Plugin * @param[out] charity_id set to the charity ID of the Donau instance */ enum GNUNET_DB_QueryStatus - (*select_donau_instance_by_serial)( + (*select_donau_instance_by_serial)( void *cls, uint64_t serial, char **donau_url, @@ -4386,7 +4401,7 @@ struct TALER_MERCHANTDB_Plugin * @param cb_cls closure for @a cb */ enum GNUNET_DB_QueryStatus - (*select_donau_instances)( + (*select_donau_instances)( void *cls, const char *id, TALER_MERCHANTDB_DonauInstanceCallback cb, @@ -4402,7 +4417,7 @@ struct TALER_MERCHANTDB_Plugin * @param cb_cls closure for @a cb */ enum GNUNET_DB_QueryStatus - (*select_all_donau_instances)( + (*select_all_donau_instances)( void *cls, TALER_MERCHANTDB_DonauInstanceCallback cb, void *cb_cls); @@ -4417,7 +4432,7 @@ struct TALER_MERCHANTDB_Plugin * @param cb_cls closure for @a cb */ enum GNUNET_DB_QueryStatus - (*select_donau_instances_filtered)( + (*select_donau_instances_filtered)( void *cls, const char *currency, TALER_MERCHANTDB_DonauInstanceFilteredCallback cb, @@ -4431,7 +4446,7 @@ struct TALER_MERCHANTDB_Plugin * @param[out] keys set to the Donau keys on success */ enum GNUNET_DB_QueryStatus - (*lookup_donau_keys)( + (*lookup_donau_keys)( void *cls, const char *donau_url, struct GNUNET_TIME_Absolute *first_retry, @@ -4454,7 +4469,7 @@ struct TALER_MERCHANTDB_Plugin * Donau keys */ enum GNUNET_DB_QueryStatus - (*lookup_order_charity)( + (*lookup_order_charity)( void *cls, const char *instance_id, const char *donau_url, @@ -4473,7 +4488,7 @@ struct TALER_MERCHANTDB_Plugin * @param keys Donau keys to insert or update */ enum GNUNET_DB_QueryStatus - (*upsert_donau_keys)( + (*upsert_donau_keys)( void *cls, const struct DONAU_Keys *keys, struct GNUNET_TIME_Absolute first_retry @@ -4488,7 +4503,7 @@ struct TALER_MERCHANTDB_Plugin * @param charity_id charity ID of the Donau instance */ enum GNUNET_DB_QueryStatus - (*update_donau_instance)( + (*update_donau_instance)( void *cls, const char *donau_url, const struct DONAU_Charity *charity, @@ -4504,7 +4519,7 @@ struct TALER_MERCHANTDB_Plugin * @param charity_id charity ID of the Donau instance to delete */ enum GNUNET_DB_QueryStatus - (*delete_donau_instance)( + (*delete_donau_instance)( void *cls, const char *id, uint64_t charity_id @@ -4521,7 +4536,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_statistics_amount_by_bucket)( + (*lookup_statistics_amount_by_bucket)( void *cls, const char *instance_id, const char *slug, @@ -4540,7 +4555,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_statistics_counter_by_bucket)( + (*lookup_statistics_counter_by_bucket)( void *cls, const char *instance_id, const char *slug, @@ -4558,7 +4573,7 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_statistics_amount_by_interval)( + (*lookup_statistics_amount_by_interval)( void *cls, const char *instance_id, const char *slug, @@ -4575,12 +4590,12 @@ struct TALER_MERCHANTDB_Plugin * @return database result code */ enum GNUNET_DB_QueryStatus - (*lookup_statistics_counter_by_interval)(void *cls, - const char *instance_id, - const char *slug, - TALER_MERCHANTDB_CounterByIntervalStatisticsCallback - cb, - void *cb_cls); + (*lookup_statistics_counter_by_interval)(void *cls, + const char *instance_id, + const char *slug, + TALER_MERCHANTDB_CounterByIntervalStatisticsCallback + cb, + void *cb_cls); }; #endif diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am @@ -35,6 +35,7 @@ libtalermerchant_la_SOURCES = \ merchant_api_get_otp_device.c \ merchant_api_get_otp_devices.c \ merchant_api_get_product.c \ + merchant_api_get_product_image.c \ merchant_api_get_products.c \ merchant_api_get_statistics.c \ merchant_api_get_transfers.c \ diff --git a/src/lib/merchant_api_get_product_image.c b/src/lib/merchant_api_get_product_image.c @@ -0,0 +1,188 @@ +/* + 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 Lesser General Public License as published by the Free Software + Foundation; either version 2.1, 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along with + TALER; see the file COPYING.LGPL. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant_api_get_product_image.c + * @brief Implementation of the GET /products/$HASH/image request + * @author Bohdan Potuzhnyi + */ +#include "platform.h" +#include <curl/curl.h> +#include <jansson.h> +#include <microhttpd.h> +#include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_curl_lib.h> +#include <taler/taler_error_codes.h> +#include <taler/taler_json_lib.h> +#include "taler_merchant_service.h" +#include "merchant_api_curl_defaults.h" + + +/** + * Handle for a GET /products/$HASH/image operation. + */ +struct TALER_MERCHANT_ProductImageGetHandle +{ + /** + * The url for this request. + */ + char *url; + + /** + * Handle for the request. + */ + struct GNUNET_CURL_Job *job; + + /** + * Function to call with the result. + */ + TALER_MERCHANT_ProductImageGetCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Reference to the execution context. + */ + struct GNUNET_CURL_Context *ctx; +}; + + +/** + * Function called when we're done processing the + * HTTP GET /products/$HASH/image request. + * + * @param cls the `struct TALER_MERCHANT_ProductImageGetHandle` + * @param response_code HTTP response code, 0 on error + * @param response response body, NULL if not in JSON + */ +static void +handle_get_product_image_finished (void *cls, + long response_code, + const void *response) +{ + struct TALER_MERCHANT_ProductImageGetHandle *pigh = cls; + const json_t *json = response; + struct TALER_MERCHANT_ProductImageGetResponse pir = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json + }; + + pigh->job = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got /products/$HASH/image response with status code %u\n", + (unsigned int) response_code); + switch (response_code) + { + case MHD_HTTP_OK: + { + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("image", + &pir.details.ok.image), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK == + GNUNET_JSON_parse (json, + spec, + NULL, NULL)) + { + pigh->cb (pigh->cb_cls, + &pir); + GNUNET_JSON_parse_free (spec); + TALER_MERCHANT_product_image_get_cancel (pigh); + return; + } + pir.hr.http_status = 0; + pir.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + case MHD_HTTP_NOT_FOUND: + case MHD_HTTP_BAD_REQUEST: + pir.hr.ec = TALER_JSON_get_error_code (json); + pir.hr.hint = TALER_JSON_get_error_hint (json); + break; + default: + pir.hr.ec = TALER_JSON_get_error_code (json); + pir.hr.hint = TALER_JSON_get_error_hint (json); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u/%d\n", + (unsigned int) response_code, + (int) pir.hr.ec); + break; + } + pigh->cb (pigh->cb_cls, + &pir); + TALER_MERCHANT_product_image_get_cancel (pigh); +} + + +struct TALER_MERCHANT_ProductImageGetHandle * +TALER_MERCHANT_product_image_get ( + struct GNUNET_CURL_Context *ctx, + const char *backend_url, + const char *image_hash, + TALER_MERCHANT_ProductImageGetCallback cb, + void *cb_cls) +{ + struct TALER_MERCHANT_ProductImageGetHandle *pigh; + CURL *eh; + + pigh = GNUNET_new (struct TALER_MERCHANT_ProductImageGetHandle); + pigh->ctx = ctx; + pigh->cb = cb; + pigh->cb_cls = cb_cls; + { + char *path; + + GNUNET_asprintf (&path, + "products/%s/image", + image_hash); + pigh->url = TALER_url_join (backend_url, + path, + NULL); + GNUNET_free (path); + } + if (NULL == pigh->url) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not construct request URL.\n"); + GNUNET_free (pigh); + return NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Requesting URL '%s'\n", + pigh->url); + eh = TALER_MERCHANT_curl_easy_get_ (pigh->url); + pigh->job = GNUNET_CURL_job_add (ctx, + eh, + &handle_get_product_image_finished, + pigh); + return pigh; +} + + +void +TALER_MERCHANT_product_image_get_cancel ( + struct TALER_MERCHANT_ProductImageGetHandle *pigh) +{ + if (NULL != pigh->job) + GNUNET_CURL_job_cancel (pigh->job); + GNUNET_free (pigh->url); + GNUNET_free (pigh); +} +\ No newline at end of file diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am @@ -38,6 +38,7 @@ libtalermerchanttesting_la_SOURCES = \ testing_api_cmd_get_otp_device.c \ testing_api_cmd_get_otp_devices.c \ testing_api_cmd_get_product.c \ + testing_api_cmd_get_product_image.c \ testing_api_cmd_get_products.c \ testing_api_cmd_get_statisticsamount.c \ testing_api_cmd_get_statisticscounter.c \ diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c @@ -48,7 +48,7 @@ * commands should NOT wait for this timeout! */ #define POLL_ORDER_TIMEOUT \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * The 'poll-orders-conclude-1x' and other 'conclude' @@ -56,7 +56,7 @@ * here we use a short value! */ #define POLL_ORDER_SHORT_TIMEOUT \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) /** * Configuration file we use. One (big) configuration is used @@ -176,8 +176,8 @@ cmd_exec_wirewatch (const char *label) * @param label label to use for the command. */ #define CMD_EXEC_AGGREGATOR(label) \ - TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \ - TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file) + TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \ + TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file) /** @@ -2186,6 +2186,45 @@ run (void *cls, "product-1", MHD_HTTP_OK, "post-products-p1"), + TALER_TESTING_cmd_merchant_post_products2 ( + "post-products-img", + merchant_url, + "product-img", + "product with image", + json_pack ("{s:s}", "en", "product with image"), + "test-unit", + "EUR:1", + "data:image/jpeg;base64,RAWDATA", + json_array (), + 4, + 0, + json_pack ("{s:s}", "street", "my street"), + GNUNET_TIME_UNIT_ZERO_TS, + MHD_HTTP_NO_CONTENT), + TALER_TESTING_cmd_get_product_image ( + "get-product-image-img", + merchant_url, + "post-products-img", + "5831ca012639a29df949c3b1e5cd436bac0a5b26a5340ccd95df394b7a8742d6", + MHD_HTTP_OK), + TALER_TESTING_cmd_get_product_image ( + "get-product-image-invalid", + merchant_url, + NULL, + "not-a-valid-hash", + MHD_HTTP_BAD_REQUEST), + TALER_TESTING_cmd_get_product_image ( + "get-product-image-empty", + merchant_url, + NULL, + "", + MHD_HTTP_BAD_REQUEST), + TALER_TESTING_cmd_get_product_image ( + "get-product-image-not-found", + merchant_url, + NULL, + "5831ca012639a29df949c3b1e5cd436bac0a5b26a5340ccd95df394b7a8742d7", + MHD_HTTP_NOT_FOUND), TALER_TESTING_cmd_merchant_post_products ( "post-products-p2", merchant_url, diff --git a/src/testing/testing_api_cmd_get_product_image.c b/src/testing/testing_api_cmd_get_product_image.c @@ -0,0 +1,217 @@ +/* + 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 testing_api_cmd_get_product_image.c + * @brief command to test GET /products/$HASH/image + * @author Bohdan Potuzhnyi + */ +#include "platform.h" +#include <taler/taler_exchange_service.h> +#include <taler/taler_testing_lib.h> +#include "taler_merchant_service.h" +#include "taler_merchant_testing_lib.h" + + +/** + * State of a "GET product image" CMD. + */ +struct GetProductImageState +{ + /** + * Handle for a "GET product image" request. + */ + struct TALER_MERCHANT_ProductImageGetHandle *pigh; + + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Base URL of the merchant serving the request. + */ + const char *merchant_url; + + /** + * Reference for a POST or PATCH /products CMD (optional). + */ + const char *product_reference; + + /** + * Expected HTTP response code. + */ + unsigned int http_status; + + /** + * Expected image as a data URL. + */ + char *expected_image; + + /** + * Hash over the expected image, lowercase hex encoding. + */ + const char *image_hash; +}; + + +/** + * Callback for a /products/$HASH/image operation. + * + * @param cls closure for this function + * @param pir response details + */ +static void +get_product_image_cb (void *cls, + const struct TALER_MERCHANT_ProductImageGetResponse *pir) +{ + struct GetProductImageState *gis = cls; + + gis->pigh = NULL; + if (gis->http_status != pir->hr.http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u (%d) to command %s\n", + pir->hr.http_status, + (int) pir->hr.ec, + TALER_TESTING_interpreter_get_current_label (gis->is)); + TALER_TESTING_interpreter_fail (gis->is); + return; + } + switch (pir->hr.http_status) + { + case MHD_HTTP_OK: + if (NULL != gis->expected_image) + { + if (0 != strcmp (pir->details.ok.image, + gis->expected_image)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Product image did not match expected value\n"); + TALER_TESTING_interpreter_fail (gis->is); + return; + } + } + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Unhandled HTTP status.\n"); + } + TALER_TESTING_interpreter_next (gis->is); +} + + +/** + * Run the "GET product image" CMD. + * + * @param cls closure. + * @param cmd command being run now. + * @param is interpreter state. + */ +static void +get_product_image_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct GetProductImageState *gis = cls; + const struct TALER_TESTING_Command *product_cmd; + + gis->is = is; + gis->expected_image = NULL; + if (NULL != gis->product_reference) + { + product_cmd = TALER_TESTING_interpreter_lookup_command (is, + gis-> + product_reference); + if (NULL == product_cmd) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + const char *product_image; + + if (GNUNET_OK != + TALER_TESTING_get_trait_product_image (product_cmd, + &product_image)) + { + TALER_TESTING_interpreter_fail (is); + return; + } + gis->expected_image = GNUNET_strdup (product_image); + } + gis->pigh + = TALER_MERCHANT_product_image_get ( + TALER_TESTING_interpreter_get_context (is), + gis->merchant_url, + gis->image_hash, + &get_product_image_cb, + gis); + GNUNET_assert (NULL != gis->pigh); +} + + +/** + * Free the state of a "GET product image" CMD, and possibly + * cancel a pending operation thereof. + * + * @param cls closure. + * @param cmd command being run. + */ +static void +get_product_image_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct GetProductImageState *gis = cls; + + if (NULL != gis->pigh) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "GET /products/$HASH/image operation did not complete\n"); + TALER_MERCHANT_product_image_get_cancel (gis->pigh); + } + GNUNET_free (gis->expected_image); + GNUNET_free (gis); +} + + +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_product_image (const char *label, + const char *merchant_url, + const char *product_reference, + const char *image_hash, + unsigned int http_status) +{ + struct GetProductImageState *gis; + + gis = GNUNET_new (struct GetProductImageState); + gis->merchant_url = merchant_url; + gis->product_reference = product_reference; + gis->http_status = http_status; + gis->image_hash = image_hash; + { + struct TALER_TESTING_Command cmd = { + .cls = gis, + .label = label, + .run = &get_product_image_run, + .cleanup = &get_product_image_cleanup + }; + + return cmd; + } +}