merchant

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

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:
Msrc/backend/taler-merchant-httpd_contract.c | 2+-
Msrc/backend/taler-merchant-httpd_contract.h | 70++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/backend/taler-merchant-httpd_private-post-orders.c | 113++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
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++; }