commit 9e2c0eef5cbead66bce50a9e0ef55cce0e440484
parent 2771060a37d31386f499d0e2be29f6394716a26b
Author: Christian Blättler <blatc2@bfh.ch>
Date: Thu, 7 Mar 2024 11:04:22 +0100
add limits datastructure, move brutto to contract instead of choice
Diffstat:
3 files changed, 115 insertions(+), 70 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_contract.c b/src/backend/taler-merchant-httpd_contract.c
@@ -159,7 +159,7 @@ TMH_serialize_contract_v0 (const struct TALER_MerchantContract *contract,
TALER_JSON_pack_amount ("max_fee",
&contract->limits->max_fee),
TALER_JSON_pack_amount ("amount",
- &choice->price),
+ &contract->brutto),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_object_incref ("extra",
(json_t *) contract->extra))
diff --git a/src/backend/taler-merchant-httpd_contract.h b/src/backend/taler-merchant-httpd_contract.h
@@ -240,14 +240,6 @@ struct TALER_MerchantContractChoice
json_t *products;
/**
- * Price to be paid for the transaction. Could be 0. The price is in addition
- * to other instruments, such as rations and tokens.
- * The exchange will subtract deposit fees from that amount
- * before transferring it to the merchant.
- */
- struct TALER_Amount price;
-
- /**
* List of inputs the wallet must provision (all of them) to satisfy the
* conditions for the contract.
*/
@@ -270,6 +262,32 @@ struct TALER_MerchantContractChoice
unsigned int outputs_len;
};
+struct TALER_MerchantContractLimits
+{
+ /**
+ * Currency these limits are for.
+ */
+ char currency[TALER_CURRENCY_LEN];
+
+ /**
+ * The hash of the merchant instance's wire details.
+ */
+ struct TALER_MerchantWireHashP h_wire;
+
+ /**
+ * Wire transfer method identifier for the wire method associated with ``h_wire``.
+ * The wallet may only select exchanges via a matching auditor if the
+ * exchange also supports this wire method.
+ * The wire transfer fees must be added based on this wire transfer method.
+ */
+ char *wire_method;
+
+ /**
+ * Maximum total deposit fee accepted by the merchant for this contract.
+ */
+ struct TALER_Amount max_fee;
+};
+
/**
* Struct to hold contract terms in v0 and v1 format. v0 contracts are mdoelled
* as a v1 contract with a single choice and no inputs and outputs. Use the
@@ -293,6 +311,14 @@ struct TALER_MerchantContract
char *merchant_base_url;
/**
+ * Price to be paid for the transaction. Could be 0. The price is in addition
+ * to other instruments, such as rations and tokens.
+ * The exchange will subtract deposit fees from that amount
+ * before transferring it to the merchant.
+ */
+ struct TALER_Amount brutto;
+
+ /**
* Timestamp of the order.
*/
struct GNUNET_TIME_Timestamp timestamp;
@@ -464,33 +490,9 @@ struct TALER_MerchantContract
unsigned int token_authorities_len;
/**
- * Fee limits and wire account details by currency.
+ * Array of fee limits and wire account details by currency.
*/
- struct
- {
- /**
- * Currency these limits are for.
- */
- char currency[TALER_CURRENCY_LEN];
-
- /**
- * The hash of the merchant instance's wire details.
- */
- struct TALER_MerchantWireHashP h_wire;
-
- /**
- * Wire transfer method identifier for the wire method associated with ``h_wire``.
- * The wallet may only select exchanges via a matching auditor if the
- * exchange also supports this wire method.
- * The wire transfer fees must be added based on this wire transfer method.
- */
- char *wire_method;
-
- /**
- * Maximum total deposit fee accepted by the merchant for this contract.
- */
- struct TALER_Amount max_fee;
- } *limits;
+ struct TALER_MerchantContractLimits *limits;
/**
* Length of the @e limits array;
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -29,6 +29,7 @@
#include <gnunet/gnunet_time_lib.h>
#include <jansson.h>
#include <string.h>
+#include <taler/taler_error_codes.h>
#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
#include "taler-merchant-httpd_private-post-orders.h"
@@ -224,10 +225,7 @@ struct OrderContext
/**
* Information set in the ORDER_PHASE_PARSE_ORDER phase.
*/
- struct
- {
- struct TALER_MerchantContract contract;
- } parse_order;
+ struct TALER_MerchantContract parse_order;
/**
* Information set in the ORDER_PHASE_MERGE_INVENTORY phase.
@@ -483,20 +481,24 @@ clean_order (void *cls)
json_decref (oc->set_exchanges.exchanges);
oc->set_exchanges.exchanges = NULL;
}
- if (NULL != oc->parse_order.fulfillment_message_i18n)
- {
- json_decref (oc->parse_order.fulfillment_message_i18n);
- oc->parse_order.fulfillment_message_i18n = NULL;
- }
- if (NULL != oc->parse_order.summary_i18n)
- {
- json_decref (oc->parse_order.summary_i18n);
- oc->parse_order.summary_i18n = NULL;
- }
- if (NULL != oc->parse_order.delivery_location)
+ /* TODO: Clean choices array */
+ for (unsigned int i = 0; i<oc->parse_order.choices_len; i++)
{
- json_decref (oc->parse_order.delivery_location);
- oc->parse_order.delivery_location = NULL;
+ if (NULL != oc->parse_order.choices[i].fulfillment_message_i18n)
+ {
+ json_decref (oc->parse_order.choices[i].fulfillment_message_i18n);
+ oc->parse_order.choices[i].fulfillment_message_i18n = NULL;
+ }
+ if (NULL != oc->parse_order.choices[i].summary_i18n)
+ {
+ json_decref (oc->parse_order.choices[i].summary_i18n);
+ oc->parse_order.choices[i].summary_i18n = NULL;
+ }
+ if (NULL != oc->parse_order.delivery_location)
+ {
+ json_decref (oc->parse_order.delivery_location);
+ oc->parse_order.delivery_location = NULL;
+ }
}
if (NULL != oc->merge_inventory.products)
{
@@ -1139,9 +1141,10 @@ serialize_order (struct OrderContext *oc)
{
const struct TALER_MERCHANTDB_InstanceSettings *settings =
&oc->hc->instance->settings;
+ enum GNUNET_GenericReturnValue ret;
- ret = TMH_serialize_contract_v0(
- oc->parse_order.contract,
+ ret = TMH_serialize_contract(
+ oc->parse_order,
oc->hc->instance,
oc->add_payment_details.wm,
oc->set_exchanges.exchanges,
@@ -1266,14 +1269,39 @@ parse_order (struct OrderContext *oc)
&version),
NULL),
GNUNET_JSON_spec_end ()
- }
+ };
enum GNUNET_GenericReturnValue ret;
ret = TALER_MHD_parse_json_data (oc->connection,
oc->parse_request.order,
spec);
+ if (GNUNET_OK != ret)
+ {
+ GNUNET_break_op (0);
+ finalize_order2 (oc,
+ ret);
+ return;
+ }
+ if (0 == strcmp("v0", version))
+ {
+ oc->parse_order.version = TALER_MCV_V0;
+ }
+ else if (0 != strcmp("v1", version))
+ {
+ oc->parse_order.version = TALER_MCV_V1;
+ }
+ else
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ reply_with_error (oc,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_VERSION_MALFORMED,
+ "invalid version specified in order, supported are 'v0' or 'v1'");
+ return;
+ }
}
/**
@@ -1284,10 +1312,15 @@ parse_order (struct OrderContext *oc)
static void
parse_order_v0 (struct OrderContext *oc)
{
+ struct TALER_MerchantContractChoice *choice;
+ struct TALER_MerchantContractLimits *limits;
+
const struct TALER_MERCHANTDB_InstanceSettings *settings =
&oc->hc->instance->settings;
const char *merchant_base_url = NULL;
const json_t *jmerchant = NULL;
+ choice = GNUNET_new (struct TALER_MerchantContractChoice);
+ limits = GNUNET_new (struct TALER_MerchantContractLimits);
/* auto_refund only needs to be type-checked,
* mostly because in GNUnet relative times can't
* be negative. */
@@ -1296,14 +1329,14 @@ parse_order_v0 (struct OrderContext *oc)
TALER_JSON_spec_amount_any ("amount",
&oc->parse_order.brutto),
GNUNET_JSON_spec_string ("summary",
- &oc->parse_order.summary),
+ &choice->summary),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_array_const ("products",
- &oc->parse_order.products),
+ &choice->products),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_json ("summary_i18n",
- &oc->parse_order.summary_i18n),
+ &choice->summary_i18n),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("order_id",
@@ -1315,15 +1348,15 @@ parse_order_v0 (struct OrderContext *oc)
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("fulfillment_message",
- &oc->parse_order.fulfillment_message),
+ &choice->fulfillment_message),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_json ("fulfillment_message_i18n",
- &oc->parse_order.fulfillment_message_i18n),
+ &choice->fulfillment_message_i18n),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("fulfillment_url",
- &oc->parse_order.fulfillment_url),
+ &choice->fulfillment_url),
NULL),
GNUNET_JSON_spec_mark_optional (
TALER_JSON_spec_web_url ("merchant_base_url",
@@ -1351,7 +1384,7 @@ parse_order_v0 (struct OrderContext *oc)
NULL),
GNUNET_JSON_spec_mark_optional (
TALER_JSON_spec_amount_any ("max_fee",
- &oc->parse_order.max_fee),
+ &limits->max_fee),
&no_fee),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_json ("delivery_location",
@@ -1399,7 +1432,7 @@ parse_order_v0 (struct OrderContext *oc)
if ( (! no_fee) &&
(GNUNET_OK !=
TALER_amount_cmp_currency (&oc->parse_order.brutto,
- &oc->parse_order.max_fee)) )
+ &limits->max_fee)) )
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@@ -1410,6 +1443,11 @@ parse_order_v0 (struct OrderContext *oc)
return;
}
+ GNUNET_snprintf (limits->currency,
+ sizeof (limits->currency),
+ "%s",
+ oc->parse_order.brutto.currency);
+
/* Add order_id if it doesn't exist. */
if (NULL == oc->parse_order.order_id)
{
@@ -1457,11 +1495,11 @@ parse_order_v0 (struct OrderContext *oc)
}
/* Patch fulfillment URL with order_id (implements #6467). */
- if (NULL != oc->parse_order.fulfillment_url)
+ if (NULL != choice->fulfillment_url)
{
const char *pos;
- pos = strstr (oc->parse_order.fulfillment_url,
+ pos = strstr (choice->fulfillment_url,
"${ORDER_ID}");
if (NULL != pos)
{
@@ -1483,14 +1521,14 @@ parse_order_v0 (struct OrderContext *oc)
GNUNET_asprintf (&nurl,
"%.*s%s%s",
/* first output URL until ${ORDER_ID} */
- (int) (pos - oc->parse_order.fulfillment_url),
- oc->parse_order.fulfillment_url,
+ (int) (pos - choice->fulfillment_url),
+ choice->fulfillment_url,
/* replace ${ORDER_ID} with the right order_id */
oc->parse_order.order_id,
/* append rest of original URL */
pos + strlen ("${ORDER_ID}"));
- oc->parse_order.fulfillment_url = GNUNET_strdup (nurl);
+ choice->fulfillment_url = GNUNET_strdup (nurl);
GNUNET_free (nurl);
}
@@ -1638,8 +1676,8 @@ parse_order_v0 (struct OrderContext *oc)
oc->parse_order.merchant_base_url = url;
}
- if ( (NULL != oc->parse_order.products) &&
- (! TMH_products_array_valid (oc->parse_order.products)) )
+ if ( (NULL != choice->products) &&
+ (! TMH_products_array_valid (choice->products)) )
{
GNUNET_break_op (0);
reply_with_error (
@@ -1673,6 +1711,11 @@ parse_order_v0 (struct OrderContext *oc)
return;
}
+ oc->parse_order.choices = choice;
+ oc->parse_order.choices_len = 1;
+ oc->parse_order.limits = limits;
+ oc->parse_order.limits_len = 1;
+
oc->phase++;
}