summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorChristian Blättler <blatc2@bfh.ch>2023-12-12 10:12:14 +0100
committerChristian Grothoff <grothoff@gnunet.org>2023-12-23 00:09:54 +0800
commit129380c78c4fa631a2b1aeb0197255afdb5b469f (patch)
treea8e121251f8446d563307badcb65b7608e453775 /src/backend
parent0699871850011f41dedda515cc3438ec54791f89 (diff)
downloadmerchant-129380c78c4fa631a2b1aeb0197255afdb5b469f.tar.gz
merchant-129380c78c4fa631a2b1aeb0197255afdb5b469f.tar.bz2
merchant-129380c78c4fa631a2b1aeb0197255afdb5b469f.zip
start with post orders handler refactoring
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/taler-merchant-httpd_private-post-orders.c1038
1 files changed, 612 insertions, 426 deletions
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c
index 31b99536..8a2acb5d 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.c
+++ b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -24,7 +24,9 @@
* @author Marcello Stanisci
*/
#include "platform.h"
+#include <gnunet/gnunet_json_lib.h>
#include <jansson.h>
+#include <string.h>
#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
#include "taler-merchant-httpd_private-post-orders.h"
@@ -132,135 +134,302 @@ struct RekeyExchange
*/
struct OrderContext
{
-
/**
- * Connection of the request.
+ * Information set in the ORDER_PHASE_INIT phase.
*/
- struct MHD_Connection *connection;
+ struct {
+ /**
+ * Order field of the request
+ */
+ json_t *order;
- /**
- * Kept in a DLL while suspended.
- */
- struct OrderContext *next;
+ /**
+ * Set to how long refunds will be allowed.
+ */
+ struct GNUNET_TIME_Relative refund_delay;
- /**
- * Kept in a DLL while suspended.
- */
- struct OrderContext *prev;
+ /**
+ * RFC8905 payment target type to find a matching merchant account
+ */
+ const char *payment_target;
- /**
- * Handler context for the request.
- */
- struct TMH_HandlerContext *hc;
+ /**
+ * Shared key to use with @e pos_algorithm.
+ */
+ const char *pos_key;
- /**
- * Hash of the POST request data, used to detect
- * idempotent requests.
- */
- struct TALER_MerchantPostDataHashP h_post_data;
+ /**
+ * Selected algorithm (by template) when we are to
+ * generate an OTP code for payment confirmation.
+ */
+ enum TALER_MerchantConfirmationAlgorithm pos_algorithm;
- /**
- * Payment deadline.
- */
- struct GNUNET_TIME_Timestamp pay_deadline;
+ /**
+ * Hash of the POST request data, used to detect
+ * idempotent requests.
+ */
+ struct TALER_MerchantPostDataHashP h_post_data;
- /**
- * Set to how long refunds will be allowed.
- */
- struct GNUNET_TIME_Relative refund_delay;
+ /**
+ * Length of the @e inventory_products array.
+ */
+ unsigned int inventory_products_length;
- /**
- * Order we are building (modified as we process
- * the request).
- */
- json_t *order;
+ /**
+ * Array of inventory products in the @e order.
+ */
+ struct InventoryProduct *inventory_products;
- /**
- * Maximum fee for @e order based on STEFAN curves.
- * Used to set @e max_fee if not provided as part of
- * @e order.
- */
- struct TALER_Amount max_stefan_fee;
+ /**
+ * Length of the @e uuids array.
+ */
+ unsigned int uuids_length;
- /**
- * Maximum fee as given by the client request.
- */
- struct TALER_Amount max_fee;
+ /**
+ * array of UUIDs used to reserve products from @a inventory_products.
+ */
+ struct GNUNET_Uuid *uuids;
- /**
- * Gross amount value of the contract. Used to
- * compute @e max_stefan_fee.
- */
- struct TALER_Amount brutto;
+ /**
+ * Claim token for the request.
+ */
+ struct TALER_ClaimTokenP claim_token;
- /**
- * Array of exchanges we find acceptable for this
- * order.
- */
- json_t *exchanges;
+ } init;
- /**
- * RFC8905 payment target type to find a matching merchant account
- */
- const char *payment_target;
/**
- * Wire method (and our bank account) we have selected
- * to be included for this order.
+ * Information set in the ORDER_PHASE_MERGE_INVENTORY phase.
*/
- const struct TMH_WireMethod *wm;
+ struct {
+ /**
+ * Merged array of products in the @e order.
+ */
+ json_t *products;
+ } merge_inventory;
/**
- * Forced requests to /keys to update our exchange
- * information.
+ * Information set in the ORDER_PHASE_ADD_PAYMENT_DETAILS phase.
*/
- struct RekeyExchange *pending_reload_head;
+ struct {
+ /**
+ * Wire method (and our bank account) we have selected
+ * to be included for this order.
+ */
+ const struct TMH_WireMethod *wm;
+ } add_payment_details;
/**
- * Forced requests to /keys to update our exchange
- * information.
+ * Information set in the ORDER_PHASE_PATCH_ORDER phase.
*/
- struct RekeyExchange *pending_reload_tail;
+ struct {
+ /**
+ * Our order ID.
+ */
+ const char *order_id;
- /**
- * Claim token for the request.
- */
- struct TALER_ClaimTokenP claim_token;
+ /**
+ * Summary of the order.
+ */
+ const char *summary;
+
+ /**
+ * Internationalized summary.
+ */
+ json_t *summary_i18n;
+
+ /**
+ * URL where the same contract could be ordered again (if available).
+ */
+ const char *public_reorder_url;
+
+ /**
+ * URL that will show that the order was successful
+ * after it has been paid for.
+ */
+ const char *fulfillment_url;
+
+ /**
+ * Message shown to the customer after paying for the order.
+ * Either fulfillment_url or fulfillment_message must be specified.
+ */
+ const char *fulfillment_message;
+
+ /**
+ * Map from IETF BCP 47 language tags to localized fulfillment messages.
+ */
+ json_t *fulfillment_message_i18n;
+
+ /**
+ * Merchant base URL.
+ */
+ const char *merchant_base_url;
+
+ /**
+ * Timestamp of the order.
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+ /**
+ * Deadline for refunds.
+ */
+ struct GNUNET_TIME_Timestamp refund_deadline;
+
+ /**
+ * Delivery date.
+ */
+ struct GNUNET_TIME_Timestamp delivery_date;
+
+ /**
+ * Payment deadline.
+ */
+ struct GNUNET_TIME_Timestamp pay_deadline;
+
+ /**
+ * Wire transfer deadline.
+ */
+ struct GNUNET_TIME_Timestamp wire_deadline;
+
+ /**
+ * TODO: Maybe remove this and set it from settings where we serialize
+ * the order to JSON?
+ *
+ * Information like name, website, email, etc. about the merchant.
+ */
+ json_t *merchant;
+
+ /**
+ * TODO: Maybe remove this and set it from settings where we serialize
+ * the order to JSON?
+ *
+ * Merchant's public key
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+
+ /**
+ * Gross amount value of the contract. Used to
+ * compute @e max_stefan_fee.
+ */
+ struct TALER_Amount brutto;
+
+ /**
+ * Maximum fee as given by the client request.
+ */
+ struct TALER_Amount max_fee;
+
+ /**
+ * Delivery location.
+ */
+ const json_t *delivery_location;
+
+ /**
+ * Specifies for how long the wallet should try to get an
+ * automatic refund for the purchase.
+ */
+ struct GNUNET_TIME_Relative auto_refund;
+
+ /**
+ * Nonce generated by the wallet and echoed by the merchant
+ * in this field when the proposal is generated.
+ */
+ const char *nonce;
+
+ /**
+ * Extra data that is only interpreted by the merchant frontend.
+ */
+ json_t *extra;
+
+ } patch_order;
/**
- * Length of the @e inventory_products array.
+ * Information set in the ORDER_PHASE_SET_EXCHANGES phase.
*/
- unsigned int inventory_products_length;
+ struct {
+ /**
+ * Array of exchanges we find acceptable for this
+ * order.
+ */
+ json_t *exchanges;
+
+ /**
+ * Forced requests to /keys to update our exchange
+ * information.
+ */
+ struct RekeyExchange *pending_reload_head;
+
+ /**
+ * Forced requests to /keys to update our exchange
+ * information.
+ */
+ struct RekeyExchange *pending_reload_tail;
+
+ /**
+ * Did we previously force reloading of /keys from
+ * all exchanges? Set to 'true' to prevent us from
+ * doing it again (and again...).
+ */
+ bool forced_reload;
+
+ /**
+ * Set to true once we are sure that we have at
+ * least one good exchange.
+ */
+ bool exchange_good;
+
+ /**
+ * Maximum fee for @e order based on STEFAN curves.
+ * Used to set @e max_fee if not provided as part of
+ * @e order.
+ */
+ struct TALER_Amount max_stefan_fee;
+ } set_exchanges;
/**
- * Array of inventory products in the @e order.
+ * Information set in the ORDER_PHASE_SET_MAX_FEE phase.
*/
- struct InventoryProduct *inventory_products;
+ struct {
+ /**
+ * Maximum fee
+ */
+ struct TALER_Amount max_fee;
+ } set_max_fee;
/**
- * array of UUIDs used to reserve products from @a inventory_products.
+ * Information set in the ORDER_PHASE_EXECUTE_ORDER phase.
*/
- struct GNUNET_Uuid *uuids;
+ struct {
+ /**
+ * Which product (by offset) is out of stock, UINT_MAX if all were in-stock.
+ */
+ unsigned int out_of_stock_index;
+ } execute_order;
+
+ struct {
+ /**
+ * Contract terms to store in the database.
+ */
+ json_t *contract;
+ } serialize_order;
/**
- * Shared key to use with @e pos_algorithm.
+ * Connection of the request.
*/
- const char *pos_key;
+ struct MHD_Connection *connection;
/**
- * Our order ID. Pointer into @e order.
+ * Kept in a DLL while suspended.
*/
- const char *order_id;
+ struct OrderContext *next;
/**
- * which product (by offset) is out of stock, UINT_MAX if all were in-stock
+ * Kept in a DLL while suspended.
*/
- unsigned int out_of_stock_index;
+ struct OrderContext *prev;
/**
- * Length of the @e uuids array.
+ * Handler context for the request.
*/
- unsigned int uuids_length;
+ struct TMH_HandlerContext *hc;
/**
* #GNUNET_YES if suspended.
@@ -268,12 +437,6 @@ struct OrderContext
enum GNUNET_GenericReturnValue suspended;
/**
- * Selected algorithm (by template) when we are to
- * generate an OTP code for payment confirmation.
- */
- enum TALER_MerchantConfirmationAlgorithm pos_algorithm;
-
- /**
* Current phase of setting up the order.
*/
enum
@@ -284,6 +447,7 @@ struct OrderContext
ORDER_PHASE_PATCH_ORDER,
ORDER_PHASE_SET_EXCHANGES,
ORDER_PHASE_SET_MAX_FEE,
+ ORDER_PHASE_SERIALIZE_ORDER,
ORDER_PHASE_CHECK_CONTRACT,
ORDER_PHASE_EXECUTE_ORDER,
@@ -298,18 +462,6 @@ struct OrderContext
ORDER_PHASE_FINISHED_MHD_NO
} phase;
- /**
- * Set to true once we are sure that we have at
- * least one good exchange.
- */
- bool exchange_good;
-
- /**
- * Did we previously force reloading of /keys from
- * all exchanges? Set to 'true' to prevent us from
- * doing it again (and again...).
- */
- bool forced_reload;
};
@@ -413,27 +565,29 @@ clean_order (void *cls)
struct OrderContext *oc = cls;
struct RekeyExchange *rx;
- while (NULL != (rx = oc->pending_reload_head))
+ while (NULL != (rx = oc->set_exchanges.pending_reload_head))
{
- GNUNET_CONTAINER_DLL_remove (oc->pending_reload_head,
- oc->pending_reload_tail,
+ GNUNET_CONTAINER_DLL_remove (oc->set_exchanges.pending_reload_head,
+ oc->set_exchanges.pending_reload_tail,
rx);
TMH_EXCHANGES_keys4exchange_cancel (rx->fo);
GNUNET_free (rx->url);
GNUNET_free (rx);
}
- if (NULL != oc->exchanges)
+ if (NULL != oc->set_exchanges.exchanges)
{
- json_decref (oc->exchanges);
- oc->exchanges = NULL;
+ json_decref (oc->set_exchanges.exchanges);
+ oc->set_exchanges.exchanges = NULL;
}
- GNUNET_array_grow (oc->inventory_products,
- oc->inventory_products_length,
+ GNUNET_array_grow (oc->init.inventory_products,
+ oc->init.inventory_products_length,
0);
- GNUNET_array_grow (oc->uuids,
- oc->uuids_length,
+ GNUNET_array_grow (oc->init.uuids,
+ oc->init.uuids_length,
0);
- json_decref (oc->order);
+ json_decref (oc->init.order);
+ /* TODO: Check that all other fields are cleaned up! */
+ json_decref (oc->serialize_order.contract);
GNUNET_free (oc);
}
@@ -461,14 +615,14 @@ execute_transaction (struct OrderContext *oc)
/* Setup order */
qs = TMH_db->insert_order (TMH_db->cls,
oc->hc->instance->settings.id,
- oc->order_id,
+ oc->patch_order.order_id,
NULL /* session ID! FIXME: protocol v6! */,
- &oc->h_post_data,
- oc->pay_deadline,
- &oc->claim_token,
- oc->order, /* called 'contract terms' at database. */
- oc->pos_key,
- oc->pos_algorithm);
+ &oc->init.h_post_data,
+ oc->patch_order.pay_deadline,
+ &oc->init.claim_token,
+ oc->serialize_order.contract, /* called 'contract terms' at database. */
+ oc->init.pos_key,
+ oc->init.pos_algorithm);
if (qs <= 0)
{
/* qs == 0: probably instance does not exist (anymore) */
@@ -476,10 +630,10 @@ execute_transaction (struct OrderContext *oc)
return qs;
}
/* Migrate locks from UUIDs to new order: first release old locks */
- for (unsigned int i = 0; i<oc->uuids_length; i++)
+ for (unsigned int i = 0; i<oc->init.uuids_length; i++)
{
qs = TMH_db->unlock_inventory (TMH_db->cls,
- &oc->uuids[i]);
+ &oc->init.uuids[i]);
if (qs < 0)
{
TMH_db->rollback (TMH_db->cls);
@@ -492,14 +646,14 @@ execute_transaction (struct OrderContext *oc)
(note: this can basically ONLY fail on serializability OR
because the UUID locks were insufficient for the desired
quantities). */
- for (unsigned int i = 0; i<oc->inventory_products_length; i++)
+ for (unsigned int i = 0; i<oc->init.inventory_products_length; i++)
{
qs = TMH_db->insert_order_lock (
TMH_db->cls,
oc->hc->instance->settings.id,
- oc->order_id,
- oc->inventory_products[i].product_id,
- oc->inventory_products[i].quantity);
+ oc->patch_order.order_id,
+ oc->init.inventory_products[i].product_id,
+ oc->init.inventory_products[i].quantity);
if (qs < 0)
{
TMH_db->rollback (TMH_db->cls);
@@ -509,17 +663,17 @@ execute_transaction (struct OrderContext *oc)
{
/* qs == 0: lock acquisition failed due to insufficient stocks */
TMH_db->rollback (TMH_db->cls);
- oc->out_of_stock_index = i; /* indicate which product is causing the issue */
+ oc->execute_order.out_of_stock_index = i; /* indicate which product is causing the issue */
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
}
- oc->out_of_stock_index = UINT_MAX;
+ oc->execute_order.out_of_stock_index = UINT_MAX;
/* Get the order serial and timestamp for the order we just created to
update long-poll clients. */
qs = TMH_db->lookup_order_summary (TMH_db->cls,
oc->hc->instance->settings.id,
- oc->order_id,
+ oc->patch_order.order_id,
&timestamp,
&order_serial);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
@@ -552,63 +706,64 @@ execute_order (struct OrderContext *oc)
{
const struct TALER_MERCHANTDB_InstanceSettings *settings =
&oc->hc->instance->settings;
- const char *summary;
- const char *fulfillment_msg = NULL;
- const json_t *products;
- const json_t *merchant;
- struct GNUNET_TIME_Timestamp timestamp;
- struct GNUNET_TIME_Timestamp refund_deadline = { 0 };
- struct GNUNET_TIME_Timestamp wire_transfer_deadline;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("order_id",
- &oc->order_id),
- TALER_JSON_spec_i18n_str ("summary",
- &summary),
+ // const char *summary;
+ // const char *fulfillment_msg = NULL;
+ // const json_t *products;
+ // This was never actually used, not even checked if it is well-formed.
+ // const json_t *merchant;
+ // struct GNUNET_TIME_Timestamp timestamp;
+ // struct GNUNET_TIME_Timestamp refund_deadline = { 0 };
+ // struct GNUNET_TIME_Timestamp wire_transfer_deadline;
+ // struct GNUNET_JSON_Specification spec[] = {
+ // GNUNET_JSON_spec_string ("order_id",
+ // &oc->patch_order.order_id),
+ // TALER_JSON_spec_i18n_str ("summary",
+ // &summary),
/**
* The following entries we don't actually need,
* except to check that the order is well-formed */
- GNUNET_JSON_spec_array_const ("products",
- &products),
- GNUNET_JSON_spec_object_const ("merchant",
- &merchant),
- GNUNET_JSON_spec_mark_optional (
- TALER_JSON_spec_i18n_str ("fulfillment_message",
- &fulfillment_msg),
- NULL),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &timestamp),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_timestamp ("refund_deadline",
- &refund_deadline),
- NULL),
- GNUNET_JSON_spec_timestamp ("pay_deadline",
- &oc->pay_deadline),
- GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
- &wire_transfer_deadline),
- GNUNET_JSON_spec_end ()
- };
+ // GNUNET_JSON_spec_array_const ("products",
+ // &products),
+ // GNUNET_JSON_spec_object_const ("merchant",
+ // &merchant),
+ // GNUNET_JSON_spec_mark_optional (
+ // TALER_JSON_spec_i18n_str ("fulfillment_message",
+ // &fulfillment_msg),
+ // NULL),
+ // GNUNET_JSON_spec_timestamp ("timestamp",
+ // &timestamp),
+ // GNUNET_JSON_spec_mark_optional (
+ // GNUNET_JSON_spec_timestamp ("refund_deadline",
+ // &refund_deadline),
+ // NULL),
+ // GNUNET_JSON_spec_timestamp ("pay_deadline",
+ // &oc->patch_order.pay_deadline),
+ // GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
+ // &wire_transfer_deadline),
+ // GNUNET_JSON_spec_end ()
+ // };
enum GNUNET_DB_QueryStatus qs;
/* extract fields we need to sign separately */
- {
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (oc->connection,
- oc->order,
- spec);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- finalize_order2 (oc,
- res);
- return;
- }
- }
+ // {
+ // enum GNUNET_GenericReturnValue res;
+
+ // res = TALER_MHD_parse_json_data (oc->connection,
+ // oc->order,
+ // spec);
+ // if (GNUNET_OK != res)
+ // {
+ // GNUNET_break_op (0);
+ // finalize_order2 (oc,
+ // res);
+ // return;
+ // }
+ // }
/* check product list in contract is well-formed */
- if (! TMH_products_array_valid (products))
+ if (! TMH_products_array_valid (oc->merge_inventory.products))
{
- GNUNET_JSON_parse_free (spec);
+ // GNUNET_JSON_parse_free (spec);
GNUNET_break_op (0);
reply_with_error (oc,
MHD_HTTP_BAD_REQUEST,
@@ -626,7 +781,7 @@ execute_order (struct OrderContext *oc)
TMH_db->preflight (TMH_db->cls);
qs = TMH_db->lookup_order (TMH_db->cls,
oc->hc->instance->settings.id,
- oc->order_id,
+ oc->patch_order.order_id,
&token,
&orig_post,
&contract_terms);
@@ -635,7 +790,7 @@ execute_order (struct OrderContext *oc)
{
GNUNET_break (0);
TMH_db->rollback (TMH_db->cls);
- GNUNET_JSON_parse_free (spec);
+ // GNUNET_JSON_parse_free (spec);
reply_with_error (oc,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_FETCH_FAILED,
@@ -650,7 +805,7 @@ execute_order (struct OrderContext *oc)
/* Comparing the contract terms is sufficient because all the other
params get added to it at some point. */
if (0 == GNUNET_memcmp (&orig_post,
- &oc->h_post_data))
+ &oc->init.h_post_data))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Order creation idempotent\n");
@@ -658,7 +813,7 @@ execute_order (struct OrderContext *oc)
oc->connection,
MHD_HTTP_OK,
GNUNET_JSON_pack_string ("order_id",
- oc->order_id),
+ oc->patch_order.order_id),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_data_varsize (
"token",
@@ -666,7 +821,7 @@ execute_order (struct OrderContext *oc)
? NULL
: &token,
sizeof (token))));
- GNUNET_JSON_parse_free (spec);
+ // GNUNET_JSON_parse_free (spec);
finalize_order (oc,
ret);
return;
@@ -677,14 +832,14 @@ execute_order (struct OrderContext *oc)
oc,
MHD_HTTP_CONFLICT,
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS,
- oc->order_id);
- GNUNET_JSON_parse_free (spec);
+ oc->patch_order.order_id);
+ // GNUNET_JSON_parse_free (spec);
return;
}
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Executing database transaction to create order '%s' for instance '%s'\n",
- oc->order_id,
+ oc->patch_order.order_id,
settings->id);
for (unsigned int i = 0; i<MAX_RETRIES; i++)
{
@@ -695,7 +850,7 @@ execute_order (struct OrderContext *oc)
}
if (0 >= qs)
{
- GNUNET_JSON_parse_free (spec);
+ // GNUNET_JSON_parse_free (spec);
/* Special report if retries insufficient */
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
{
@@ -714,7 +869,7 @@ execute_order (struct OrderContext *oc)
oc,
MHD_HTTP_CONFLICT,
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS,
- oc->order_id);
+ oc->patch_order.order_id);
return;
}
/* Other hard transaction error (disk full, etc.) */
@@ -728,7 +883,7 @@ execute_order (struct OrderContext *oc)
}
/* DB transaction succeeded, check for out-of-stock */
- if (oc->out_of_stock_index < UINT_MAX)
+ if (oc->execute_order.out_of_stock_index < UINT_MAX)
{
/* We had a product that has insufficient quantities,
generate the details for the response. */
@@ -741,9 +896,9 @@ execute_order (struct OrderContext *oc)
qs = TMH_db->lookup_product (
TMH_db->cls,
oc->hc->instance->settings.id,
- oc->inventory_products[oc->out_of_stock_index].product_id,
+ oc->init.inventory_products[oc->execute_order.out_of_stock_index].product_id,
&pd);
- GNUNET_JSON_parse_free (spec);
+ // GNUNET_JSON_parse_free (spec);
switch (qs)
{
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
@@ -754,10 +909,10 @@ execute_order (struct OrderContext *oc)
MHD_HTTP_GONE,
GNUNET_JSON_pack_string (
"product_id",
- oc->inventory_products[oc->out_of_stock_index].product_id),
+ oc->init.inventory_products[oc->execute_order.out_of_stock_index].product_id),
GNUNET_JSON_pack_uint64 (
"requested_quantity",
- oc->inventory_products[oc->out_of_stock_index].quantity),
+ oc->init.inventory_products[oc->execute_order.out_of_stock_index].quantity),
GNUNET_JSON_pack_uint64 (
"available_quantity",
pd.total_stock - pd.total_sold - pd.total_lost),
@@ -778,11 +933,11 @@ execute_order (struct OrderContext *oc)
MHD_HTTP_GONE,
GNUNET_JSON_pack_string (
"product_id",
- oc->inventory_products[oc->out_of_stock_index].
+ oc->init.inventory_products[oc->execute_order.out_of_stock_index].
product_id),
GNUNET_JSON_pack_uint64 (
"requested_quantity",
- oc->inventory_products[oc->out_of_stock_index].
+ oc->init.inventory_products[oc->execute_order.out_of_stock_index].
quantity),
GNUNET_JSON_pack_uint64 (
"available_quantity",
@@ -820,15 +975,15 @@ execute_order (struct OrderContext *oc)
oc->connection,
MHD_HTTP_OK,
GNUNET_JSON_pack_string ("order_id",
- oc->order_id),
+ oc->patch_order.order_id),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_data_varsize (
"token",
- GNUNET_is_zero (&oc->claim_token)
+ GNUNET_is_zero (&oc->init.claim_token)
? NULL
- : &oc->claim_token,
- sizeof (oc->claim_token))));
- GNUNET_JSON_parse_free (spec);
+ : &oc->init.claim_token,
+ sizeof (oc->init.claim_token))));
+ // GNUNET_JSON_parse_free (spec);
finalize_order (oc,
ret);
}
@@ -845,7 +1000,7 @@ check_contract (struct OrderContext *oc)
{
struct TALER_PrivateContractHashP h_control;
- switch (TALER_JSON_contract_hash (oc->order,
+ switch (TALER_JSON_contract_hash (oc->serialize_order.contract,
&h_control))
{
case GNUNET_SYSERR:
@@ -886,33 +1041,33 @@ update_stefan (struct OrderContext *oc,
if (GNUNET_SYSERR !=
TALER_EXCHANGE_keys_stefan_b2n (keys,
- &oc->brutto,
+ &oc->patch_order.brutto,
&net))
{
struct TALER_Amount fee;
TALER_EXCHANGE_keys_stefan_round (keys,
&net);
- if (-1 == TALER_amount_cmp (&oc->brutto,
+ if (-1 == TALER_amount_cmp (&oc->patch_order.brutto,
&net))
{
/* brutto < netto! */
/* => after rounding, there is no real difference */
- net = oc->brutto;
+ net = oc->patch_order.brutto;
}
GNUNET_assert (0 <=
TALER_amount_subtract (&fee,
- &oc->brutto,
+ &oc->patch_order.brutto,
&net));
if ( (GNUNET_OK !=
- TALER_amount_is_valid (&oc->max_stefan_fee)) ||
- (-1 == TALER_amount_cmp (&oc->max_stefan_fee,
+ TALER_amount_is_valid (&oc->set_exchanges.max_stefan_fee)) ||
+ (-1 == TALER_amount_cmp (&oc->set_exchanges.max_stefan_fee,
&fee)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Updated STEFAN-based fee to %s\n",
TALER_amount2s (&fee));
- oc->max_stefan_fee = fee;
+ oc->set_exchanges.max_stefan_fee = fee;
}
}
}
@@ -937,7 +1092,7 @@ get_acceptable (void *cls,
enum GNUNET_GenericReturnValue res;
res = TMH_exchange_check_debit (exchange,
- oc->wm);
+ oc->add_payment_details.wm);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Exchange %s evaluated at %d\n",
url,
@@ -946,16 +1101,16 @@ get_acceptable (void *cls,
{
case GNUNET_OK:
priority = 1024; /* high */
- oc->exchange_good = true;
+ oc->set_exchanges.exchange_good = true;
break;
case GNUNET_NO:
- if (oc->forced_reload)
+ if (oc->set_exchanges.forced_reload)
priority = 0; /* fresh negative response */
else
priority = 512; /* stale negative response */
break;
case GNUNET_SYSERR:
- if (oc->forced_reload)
+ if (oc->set_exchanges.forced_reload)
priority = 256; /* fresh, no accounts yet */
else
priority = 768; /* stale, no accounts yet */
@@ -970,7 +1125,7 @@ get_acceptable (void *cls,
TMH_EXCHANGES_get_master_pub (exchange)));
GNUNET_assert (NULL != j_exchange);
GNUNET_assert (0 ==
- json_array_append_new (oc->exchanges,
+ json_array_append_new (oc->set_exchanges.exchanges,
j_exchange));
}
@@ -986,7 +1141,7 @@ resume_with_keys (struct OrderContext *oc)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Resuming order processing after /keys downloads (now have %u accounts)\n",
- (unsigned int) json_array_size (oc->exchanges));
+ (unsigned int) json_array_size (oc->set_exchanges.exchanges));
GNUNET_assert (GNUNET_YES == oc->suspended);
GNUNET_CONTAINER_DLL_remove (oc_head,
oc_tail,
@@ -1017,8 +1172,8 @@ keys_cb (
&oc->hc->instance->settings;
rx->fo = NULL;
- GNUNET_CONTAINER_DLL_remove (oc->pending_reload_head,
- oc->pending_reload_tail,
+ GNUNET_CONTAINER_DLL_remove (oc->set_exchanges.pending_reload_head,
+ oc->set_exchanges.pending_reload_tail,
rx);
if (NULL == keys)
{
@@ -1033,7 +1188,7 @@ keys_cb (
rx->url);
if ( (settings->use_stefan) &&
(GNUNET_OK !=
- TALER_amount_is_valid (&oc->max_fee)) )
+ TALER_amount_is_valid (&oc->patch_order.max_fee)) )
update_stefan (oc,
keys);
get_acceptable (oc,
@@ -1042,7 +1197,7 @@ keys_cb (
}
GNUNET_free (rx->url);
GNUNET_free (rx);
- if (NULL != oc->pending_reload_head)
+ if (NULL != oc->set_exchanges.pending_reload_head)
return;
resume_with_keys (oc);
}
@@ -1068,21 +1223,91 @@ get_exchange_keys (void *cls,
rx = GNUNET_new (struct RekeyExchange);
rx->oc = oc;
rx->url = GNUNET_strdup (url);
- GNUNET_CONTAINER_DLL_insert (oc->pending_reload_head,
- oc->pending_reload_tail,
+ GNUNET_CONTAINER_DLL_insert (oc->set_exchanges.pending_reload_head,
+ oc->set_exchanges.pending_reload_tail,
rx);
- if (oc->forced_reload)
+ if (oc->set_exchanges.forced_reload)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Forcing download of %skeys\n",
url);
rx->fo = TMH_EXCHANGES_keys4exchange (url,
- oc->forced_reload,
+ oc->set_exchanges.forced_reload,
&keys_cb,
rx);
}
/**
+ * Serialize @a oc->init.order into @a oc->execute_order.contract_terms.
+ *
+ * @param[in,out] oc order context
+ */
+static void
+serialize_order (struct OrderContext *oc)
+{
+ /* TODO: add public_reorder_url
+ fulfillment_message
+ fulfillment_message_i18n
+ nonce
+ extra (?)
+ */
+
+ oc->serialize_order.contract = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("summary",
+ oc->patch_order.summary),
+ GNUNET_JSON_pack_object_steal ("summary_i18n",
+ oc->patch_order.summary_i18n),
+ GNUNET_JSON_pack_string ("public_reorder_url",
+ oc->patch_order.public_reorder_url),
+ GNUNET_JSON_pack_string ("fulfillment_message",
+ oc->patch_order.fulfillment_message),
+ GNUNET_JSON_pack_object_steal ("fulfillment_message_i18n",
+ oc->patch_order.fulfillment_message_i18n),
+ GNUNET_JSON_pack_object_steal ("products",
+ oc->merge_inventory.products),
+ GNUNET_JSON_pack_data_auto ("h_wire",
+ &oc->add_payment_details.wm->h_wire),
+ GNUNET_JSON_pack_string ("wire_method",
+ oc->add_payment_details.wm->wire_method),
+ GNUNET_JSON_pack_string ("order_id",
+ oc->patch_order.order_id),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("fulfillment_url",
+ oc->patch_order.fulfillment_url)),
+ GNUNET_JSON_pack_timestamp ("timestamp",
+ oc->patch_order.timestamp),
+ GNUNET_JSON_pack_timestamp ("refund_deadline",
+ oc->patch_order.refund_deadline),
+ GNUNET_JSON_pack_timestamp ("pay_deadline",
+ oc->patch_order.pay_deadline),
+ GNUNET_JSON_pack_timestamp ("wire_transfer_deadline",
+ oc->patch_order.wire_deadline),
+ GNUNET_JSON_pack_time_rel ("auto_refund",
+ oc->patch_order.auto_refund),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_timestamp ("delivery_date",
+ oc->patch_order.delivery_date)),
+ GNUNET_JSON_pack_string ("merchant_base_url",
+ oc->patch_order.merchant_base_url),
+ GNUNET_JSON_pack_object_steal ("merchant",
+ oc->patch_order.merchant),
+ GNUNET_JSON_pack_data_auto ("merchant_pub",
+ &oc->hc->instance->merchant_pub),
+ GNUNET_JSON_pack_array_steal ("exchanges",
+ oc->set_exchanges.exchanges),
+ TALER_JSON_pack_amount ("max_fee",
+ &oc->set_max_fee.max_fee),
+ TALER_JSON_pack_amount ("amount",
+ &oc->patch_order.brutto),
+ GNUNET_JSON_pack_string ("nonce",
+ oc->patch_order.nonce),
+ GNUNET_JSON_pack_object_steal ("extra",
+ oc->patch_order.extra)
+ );
+}
+
+
+/**
* Set max_fee in @a oc based on STEFAN value if
* not yet present.
*
@@ -1095,23 +1320,19 @@ set_max_fee (struct OrderContext *oc)
&oc->hc->instance->settings;
if (GNUNET_OK !=
- TALER_amount_is_valid (&oc->max_fee))
+ TALER_amount_is_valid (&oc->patch_order.max_fee))
{
struct TALER_Amount stefan;
if ( (settings->use_stefan) &&
(GNUNET_OK ==
- TALER_amount_is_valid (&oc->max_stefan_fee)) )
- stefan = oc->max_stefan_fee;
+ TALER_amount_is_valid (&oc->set_exchanges.max_stefan_fee)) )
+ stefan = oc->set_exchanges.max_stefan_fee;
else
GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (oc->brutto.currency,
+ TALER_amount_set_zero (oc->patch_order.brutto.currency,
&stefan));
- GNUNET_assert (0 ==
- json_object_set_new (
- oc->order,
- "max_fee",
- TALER_JSON_from_amount (&stefan)));
+ oc->set_max_fee.max_fee = stefan;
}
oc->phase++;
}
@@ -1129,28 +1350,28 @@ set_exchanges (struct OrderContext *oc)
/* Note: re-building 'oc->exchanges' every time here might be a tad
expensive; could likely consider caching the result if it starts to
matter. */
- if (NULL == oc->exchanges)
+ if (NULL == oc->set_exchanges.exchanges)
{
- oc->exchanges = json_array ();
+ oc->set_exchanges.exchanges = json_array ();
TMH_exchange_get_trusted (&get_exchange_keys,
oc);
}
- else if (! oc->exchange_good)
+ else if (! oc->set_exchanges.exchange_good)
{
- if (! oc->forced_reload)
+ if (! oc->set_exchanges.forced_reload)
{
- oc->forced_reload = true;
+ oc->set_exchanges.forced_reload = true;
GNUNET_assert (0 ==
- json_array_clear (oc->exchanges));
+ json_array_clear (oc->set_exchanges.exchanges));
TMH_exchange_get_trusted (&get_exchange_keys,
oc);
}
}
- if (NULL != oc->pending_reload_head)
+ if (NULL != oc->set_exchanges.pending_reload_head)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Still trying to (re)load %skeys\n",
- oc->pending_reload_head->url);
+ oc->set_exchanges.pending_reload_head->url);
MHD_suspend_connection (oc->connection);
oc->suspended = GNUNET_YES;
GNUNET_CONTAINER_DLL_insert (oc_head,
@@ -1158,7 +1379,7 @@ set_exchanges (struct OrderContext *oc)
oc);
return true; /* reloads pending */
}
- if (0 == json_array_size (oc->exchanges))
+ if (0 == json_array_size (oc->set_exchanges.exchanges))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Cannot create order: lacking trusted exchanges\n");
@@ -1166,19 +1387,14 @@ set_exchanges (struct OrderContext *oc)
oc,
MHD_HTTP_CONFLICT,
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD,
- oc->wm->wire_method);
+ oc->add_payment_details.wm->wire_method);
return false;
}
- if (! oc->exchange_good)
+ if (! oc->set_exchanges.exchange_good)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Creating order, but possibly without usable trusted exchanges\n");
}
- /* 'set' is correct here: reference in oc->exchanges released in cleanup_order() */
- GNUNET_assert (0 ==
- json_object_set (oc->order,
- "exchanges",
- oc->exchanges));
oc->phase++;
return false;
}
@@ -1195,28 +1411,45 @@ patch_order (struct OrderContext *oc)
{
const struct TALER_MERCHANTDB_InstanceSettings *settings =
&oc->hc->instance->settings;
- const char *order_id = NULL;
- const char *fulfillment_url = NULL;
- const char *merchant_base_url = NULL;
+
+ /* Setting default values of patch_order, maybe not needed (?) */
+ oc->patch_order.order_id = NULL;
+ oc->patch_order.fulfillment_url = NULL;
+ oc->patch_order.merchant_base_url = NULL;
+ oc->patch_order.timestamp = GNUNET_TIME_UNIT_ZERO_TS;
+ oc->patch_order.refund_deadline = GNUNET_TIME_UNIT_FOREVER_TS;
+ oc->patch_order.pay_deadline = GNUNET_TIME_UNIT_ZERO_TS;
+ oc->patch_order.wire_deadline = GNUNET_TIME_UNIT_FOREVER_TS;
+ oc->patch_order.delivery_location = NULL;
+
+
const json_t *jmerchant = NULL;
- const json_t *delivery_location = NULL;
- struct GNUNET_TIME_Timestamp timestamp
- = GNUNET_TIME_UNIT_ZERO_TS;
- struct GNUNET_TIME_Timestamp delivery_date
- = GNUNET_TIME_UNIT_ZERO_TS;
- struct GNUNET_TIME_Timestamp refund_deadline
- = GNUNET_TIME_UNIT_FOREVER_TS;
- struct GNUNET_TIME_Timestamp wire_deadline
- = GNUNET_TIME_UNIT_FOREVER_TS;
/* auto_refund only needs to be type-checked,
* mostly because in GNUnet relative times can't
* be negative. */
- struct GNUNET_TIME_Relative auto_refund;
bool no_fee;
struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string("summary",
+ &oc->patch_order.summary),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("summary_i18n",
+ &oc->patch_order.summary_i18n),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("public_reorder_url",
+ &oc->patch_order.public_reorder_url),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string("fulfillment_message",
+ &oc->patch_order.fulfillment_message),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("fulfillment_message_i18n",
+ &oc->patch_order.fulfillment_message_i18n),
+ NULL),
GNUNET_JSON_spec_mark_optional (
TALER_JSON_spec_web_url ("merchant_base_url",
- &merchant_base_url),
+ &oc->patch_order.merchant_base_url),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_object_const ("merchant",
@@ -1224,52 +1457,60 @@ patch_order (struct OrderContext *oc)
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("order_id",
- &order_id),
+ &oc->patch_order.order_id),
NULL),
TALER_JSON_spec_amount_any ("amount",
- &oc->brutto),
+ &oc->patch_order.brutto),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("fulfillment_url",
- &fulfillment_url),
+ &oc->patch_order.fulfillment_url),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("timestamp",
- &timestamp),
+ &oc->patch_order.timestamp),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("refund_deadline",
- &refund_deadline),
+ &oc->patch_order.refund_deadline),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("pay_deadline",
- &oc->pay_deadline),
+ &oc->patch_order.pay_deadline),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
- &wire_deadline),
+ &oc->patch_order.wire_deadline),
NULL),
GNUNET_JSON_spec_mark_optional (
TALER_JSON_spec_amount_any ("max_fee",
- &oc->max_fee),
+ &oc->patch_order.max_fee),
&no_fee),
GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_object_const ("delivery_location",
+ &oc->patch_order.delivery_location),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_timestamp ("delivery_date",
- &delivery_date),
+ &oc->patch_order.delivery_date),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("nonce",
+ &oc->patch_order.nonce),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_relative_time ("auto_refund",
- &auto_refund),
+ &oc->patch_order.auto_refund),
NULL),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_object_const ("delivery_location",
- &delivery_location),
+ GNUNET_JSON_spec_json ("extra",
+ &oc->patch_order.extra),
NULL),
GNUNET_JSON_spec_end ()
};
enum GNUNET_GenericReturnValue ret;
ret = TALER_MHD_parse_json_data (oc->connection,
- oc->order,
+ oc->init.order,
spec);
if (GNUNET_OK != ret)
{
@@ -1278,7 +1519,7 @@ patch_order (struct OrderContext *oc)
ret);
return;
}
- if (! TMH_test_exchange_configured_for_currency (oc->brutto.currency))
+ if (! TMH_test_exchange_configured_for_currency (oc->patch_order.brutto.currency))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@@ -1290,8 +1531,8 @@ patch_order (struct OrderContext *oc)
}
if ( (! no_fee) &&
(GNUNET_OK !=
- TALER_amount_cmp_currency (&oc->brutto,
- &oc->max_fee)) )
+ TALER_amount_cmp_currency (&oc->patch_order.brutto,
+ &oc->patch_order.max_fee)) )
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@@ -1303,7 +1544,7 @@ patch_order (struct OrderContext *oc)
}
/* Add order_id if it doesn't exist. */
- if (NULL == order_id)
+ if (NULL == oc->patch_order.order_id)
{
char buf[256];
time_t timer;
@@ -1311,7 +1552,6 @@ patch_order (struct OrderContext *oc)
size_t off;
uint64_t rand;
char *last;
- json_t *jbuf;
time (&timer);
tm_info = localtime (&timer);
@@ -1340,25 +1580,21 @@ patch_order (struct OrderContext *oc)
sizeof (buf) - off);
GNUNET_assert (NULL != last);
*last = '\0';
- jbuf = json_string (buf);
- GNUNET_assert (NULL != jbuf);
+
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Assigning order ID `%s' server-side\n",
buf);
- GNUNET_break (0 ==
- json_object_set_new (oc->order,
- "order_id",
- jbuf));
- order_id = json_string_value (jbuf);
- GNUNET_assert (NULL != order_id);
+
+ oc->patch_order.order_id = GNUNET_strdup (buf);
+ GNUNET_assert (NULL != oc->patch_order.order_id);
}
/* Patch fulfillment URL with order_id (implements #6467). */
- if (NULL != fulfillment_url)
+ if (NULL != oc->patch_order.fulfillment_url)
{
const char *pos;
- pos = strstr (fulfillment_url,
+ pos = strstr (oc->patch_order.fulfillment_url,
"${ORDER_ID}");
if (NULL != pos)
{
@@ -1380,17 +1616,15 @@ patch_order (struct OrderContext *oc)
GNUNET_asprintf (&nurl,
"%.*s%s%s",
/* first output URL until ${ORDER_ID} */
- (int) (pos - fulfillment_url),
- fulfillment_url,
+ (int) (pos - oc->patch_order.fulfillment_url),
+ oc->patch_order.fulfillment_url,
/* replace ${ORDER_ID} with the right order_id */
- order_id,
+ oc->patch_order.order_id,
/* append rest of original URL */
pos + strlen ("${ORDER_ID}"));
- /* replace in JSON of the order */
- GNUNET_break (0 ==
- json_object_set_new (oc->order,
- "fulfillment_url",
- json_string (nurl)));
+
+ oc->patch_order.fulfillment_url = GNUNET_strdup (nurl);
+
GNUNET_free (nurl);
}
}
@@ -1401,35 +1635,28 @@ patch_order (struct OrderContext *oc)
struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
/* Add timestamp if it doesn't exist (or is zero) */
- if (GNUNET_TIME_absolute_is_zero (timestamp.abs_time))
+ if (GNUNET_TIME_absolute_is_zero (oc->patch_order.timestamp.abs_time))
{
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "timestamp",
- GNUNET_JSON_from_timestamp (now)));
+ oc->patch_order.timestamp = now;
}
/* If no refund_deadline given, set one based on refund_delay. */
- if (GNUNET_TIME_absolute_is_never (refund_deadline.abs_time))
+ if (GNUNET_TIME_absolute_is_never (oc->patch_order.refund_deadline.abs_time))
{
- if (GNUNET_TIME_relative_is_zero (oc->refund_delay))
+ if (GNUNET_TIME_relative_is_zero (oc->init.refund_delay))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Refund delay is zero, no refunds are possible for this order\n");
- refund_deadline = GNUNET_TIME_UNIT_ZERO_TS;
+ oc->patch_order.refund_deadline = GNUNET_TIME_UNIT_ZERO_TS;
}
else
{
- refund_deadline = GNUNET_TIME_relative_to_timestamp (oc->refund_delay);
+ oc->patch_order.refund_deadline = GNUNET_TIME_relative_to_timestamp (oc->init.refund_delay);
}
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "refund_deadline",
- GNUNET_JSON_from_timestamp (
- refund_deadline)));
}
- if ( (! GNUNET_TIME_absolute_is_zero (delivery_date.abs_time)) &&
- (GNUNET_TIME_absolute_is_past (delivery_date.abs_time)) )
+
+ if ( (! GNUNET_TIME_absolute_is_zero (oc->patch_order.delivery_date.abs_time)) &&
+ (GNUNET_TIME_absolute_is_past (oc->patch_order.delivery_date.abs_time)) )
{
GNUNET_break_op (0);
reply_with_error (
@@ -1441,17 +1668,12 @@ patch_order (struct OrderContext *oc)
}
}
- if (GNUNET_TIME_absolute_is_zero (oc->pay_deadline.abs_time))
+ if (GNUNET_TIME_absolute_is_zero (oc->patch_order.pay_deadline.abs_time))
{
- oc->pay_deadline = GNUNET_TIME_relative_to_timestamp (
+ oc->patch_order.pay_deadline = GNUNET_TIME_relative_to_timestamp (
settings->default_pay_delay);
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "pay_deadline",
- GNUNET_JSON_from_timestamp (
- oc->pay_deadline)));
}
- else if (GNUNET_TIME_absolute_is_past (oc->pay_deadline.abs_time))
+ else if (GNUNET_TIME_absolute_is_past (oc->patch_order.pay_deadline.abs_time))
{
GNUNET_break_op (0);
reply_with_error (
@@ -1461,8 +1683,9 @@ patch_order (struct OrderContext *oc)
NULL);
return;
}
- if ( (! GNUNET_TIME_absolute_is_zero (refund_deadline.abs_time)) &&
- (GNUNET_TIME_absolute_is_past (refund_deadline.abs_time)) )
+
+ if ( (! GNUNET_TIME_absolute_is_zero (oc->patch_order.refund_deadline.abs_time)) &&
+ (GNUNET_TIME_absolute_is_past (oc->patch_order.refund_deadline.abs_time)) )
{
GNUNET_break_op (0);
reply_with_error (
@@ -1473,16 +1696,16 @@ patch_order (struct OrderContext *oc)
return;
}
- if (GNUNET_TIME_absolute_is_never (wire_deadline.abs_time))
+ if (GNUNET_TIME_absolute_is_never (oc->patch_order.wire_deadline.abs_time))
{
struct GNUNET_TIME_Timestamp t;
t = GNUNET_TIME_relative_to_timestamp (
GNUNET_TIME_relative_max (settings->default_wire_transfer_delay,
- oc->refund_delay));
- wire_deadline = GNUNET_TIME_timestamp_max (refund_deadline,
+ oc->init.refund_delay));
+ oc->patch_order.wire_deadline = GNUNET_TIME_timestamp_max (oc->patch_order.refund_deadline,
t);
- if (GNUNET_TIME_absolute_is_never (wire_deadline.abs_time))
+ if (GNUNET_TIME_absolute_is_never (oc->patch_order.wire_deadline.abs_time))
{
GNUNET_break_op (0);
reply_with_error (
@@ -1492,15 +1715,10 @@ patch_order (struct OrderContext *oc)
"order:wire_transfer_deadline");
return;
}
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "wire_transfer_deadline",
- GNUNET_JSON_from_timestamp (
- wire_deadline)));
}
- if (GNUNET_TIME_timestamp_cmp (wire_deadline,
+ if (GNUNET_TIME_timestamp_cmp (oc->patch_order.wire_deadline,
<,
- refund_deadline))
+ oc->patch_order.refund_deadline))
{
GNUNET_break_op (0);
reply_with_error (
@@ -1511,7 +1729,7 @@ patch_order (struct OrderContext *oc)
return;
}
- if (NULL == merchant_base_url)
+ if (NULL == oc->patch_order.merchant_base_url)
{
char *url;
@@ -1527,14 +1745,11 @@ patch_order (struct OrderContext *oc)
"order:merchant_base_url");
return;
}
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "merchant_base_url",
- json_string (url)));
+ oc->patch_order.merchant_base_url = GNUNET_strdup (url);
GNUNET_free (url);
}
- else if (('\0' == *merchant_base_url) ||
- ('/' != merchant_base_url[strlen (merchant_base_url) - 1]))
+ else if (('\0' == *oc->patch_order.merchant_base_url) ||
+ ('/' != oc->patch_order.merchant_base_url[strlen (oc->patch_order.merchant_base_url) - 1]))
{
GNUNET_break_op (0);
reply_with_error (
@@ -1558,9 +1773,7 @@ patch_order (struct OrderContext *oc)
}
{
- json_t *jm;
-
- jm = GNUNET_JSON_PACK (
+ oc->patch_order.merchant = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("name",
settings->name),
GNUNET_JSON_pack_allow_null (
@@ -1572,7 +1785,7 @@ patch_order (struct OrderContext *oc)
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("logo",
settings->logo)));
- GNUNET_assert (NULL != jm);
+ GNUNET_assert (NULL != oc->patch_order.merchant);
{
json_t *loca;
@@ -1582,7 +1795,7 @@ patch_order (struct OrderContext *oc)
{
loca = json_deep_copy (loca);
GNUNET_assert (0 ==
- json_object_set_new (jm,
+ json_object_set_new (oc->patch_order.merchant,
"address",
loca));
}
@@ -1596,36 +1809,29 @@ patch_order (struct OrderContext *oc)
{
locj = json_deep_copy (locj);
GNUNET_assert (0 ==
- json_object_set_new (jm,
+ json_object_set_new (oc->patch_order.merchant,
"jurisdiction",
locj));
}
}
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "merchant",
- jm));
}
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "merchant_pub",
- GNUNET_JSON_from_data_auto (
- &oc->hc->instance->merchant_pub)));
-
- if (GNUNET_OK !=
- TALER_JSON_contract_seed_forgettable (oc->order))
- {
- reply_with_error (
- oc,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_JSON_INVALID,
- "could not compute hash of order due to bogus forgettable fields");
- return;
- }
-
- if ( (NULL != delivery_location) &&
- (! TMH_location_object_valid (delivery_location)) )
+ oc->patch_order.merchant_pub = oc->hc->instance->merchant_pub;
+
+ /* TODO: Not sure yet how to properly handle this in the refactored code */
+ // if (GNUNET_OK !=
+ // TALER_JSON_contract_seed_forgettable (oc->order))
+ // {
+ // reply_with_error (
+ // oc,
+ // MHD_HTTP_BAD_REQUEST,
+ // TALER_EC_GENERIC_JSON_INVALID,
+ // "could not compute hash of order due to bogus forgettable fields");
+ // return;
+ // }
+
+ if ( (NULL != oc->patch_order.delivery_location) &&
+ (! TMH_location_object_valid (oc->patch_order.delivery_location)) )
{
GNUNET_break_op (0);
reply_with_error (oc,
@@ -1634,6 +1840,7 @@ patch_order (struct OrderContext *oc)
"delivery_location");
return;
}
+
oc->phase++;
}
@@ -1654,8 +1861,8 @@ add_payment_details (struct OrderContext *oc)
/* Locate wire method that has a matching payment target */
while ( (NULL != wm) &&
( (! wm->active) ||
- ( (NULL != oc->payment_target) &&
- (0 != strcasecmp (oc->payment_target,
+ ( (NULL != oc->init.payment_target) &&
+ (0 != strcasecmp (oc->init.payment_target,
wm->wire_method) ) ) ) )
wm = wm->next;
if (NULL == wm)
@@ -1666,19 +1873,10 @@ add_payment_details (struct OrderContext *oc)
reply_with_error (oc,
MHD_HTTP_NOT_FOUND,
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE,
- oc->payment_target);
+ oc->init.payment_target);
return;
}
- oc->wm = wm;
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "h_wire",
- GNUNET_JSON_from_data_auto (
- &wm->h_wire)));
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "wire_method",
- json_string (wm->wire_method)));
+ oc->add_payment_details.wm = wm;
oc->phase++;
}
@@ -1698,16 +1896,13 @@ merge_inventory (struct OrderContext *oc)
* order.products => contains products that are not from the backend-managed inventory.
*/
{
- json_t *jprod = json_object_get (oc->order,
+ oc->merge_inventory.products = json_object_get (oc->init.order,
"products");
- if (NULL == jprod)
+ if (NULL == oc->merge_inventory.products)
{
- GNUNET_assert (0 ==
- json_object_set_new (oc->order,
- "products",
- json_array ()));
+ oc->merge_inventory.products = json_array ();
}
- else if (! TMH_products_array_valid (jprod))
+ else if (! TMH_products_array_valid (oc->merge_inventory.products))
{
reply_with_error (oc,
MHD_HTTP_BAD_REQUEST,
@@ -1719,17 +1914,15 @@ merge_inventory (struct OrderContext *oc)
/* Populate products from inventory product array and database */
{
- json_t *np = json_array ();
-
- GNUNET_assert (NULL != np);
- for (unsigned int i = 0; i<oc->inventory_products_length; i++)
+ GNUNET_assert (NULL != oc->merge_inventory.products);
+ for (unsigned int i = 0; i<oc->init.inventory_products_length; i++)
{
struct TALER_MERCHANTDB_ProductDetails pd;
enum GNUNET_DB_QueryStatus qs;
qs = TMH_db->lookup_product (TMH_db->cls,
oc->hc->instance->settings.id,
- oc->inventory_products[i].product_id,
+ oc->init.inventory_products[i].product_id,
&pd);
if (qs <= 0)
{
@@ -1751,7 +1944,7 @@ merge_inventory (struct OrderContext *oc)
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Product %s from order unknown\n",
- oc->inventory_products[i].product_id);
+ oc->init.inventory_products[i].product_id);
http_status = MHD_HTTP_NOT_FOUND;
ec = TALER_EC_MERCHANT_GENERIC_PRODUCT_UNKNOWN;
break;
@@ -1759,11 +1952,11 @@ merge_inventory (struct OrderContext *oc)
/* case listed to make compilers happy */
GNUNET_assert (0);
}
- json_decref (np);
+ json_decref (oc->merge_inventory.products);
reply_with_error (oc,
http_status,
ec,
- oc->inventory_products[i].product_id);
+ oc->init.inventory_products[i].product_id);
return;
}
{
@@ -1784,10 +1977,10 @@ merge_inventory (struct OrderContext *oc)
pd.image),
GNUNET_JSON_pack_uint64 (
"quantity",
- oc->inventory_products[i].quantity));
+ oc->init.inventory_products[i].quantity));
GNUNET_assert (NULL != p);
GNUNET_assert (0 ==
- json_array_append_new (np,
+ json_array_append_new (oc->merge_inventory.products,
p));
}
GNUNET_free (pd.description);
@@ -1795,16 +1988,6 @@ merge_inventory (struct OrderContext *oc)
GNUNET_free (pd.image);
json_decref (pd.address);
}
- /* merge into existing products list */
- {
- json_t *xp;
-
- xp = json_object_get (oc->order,
- "products");
- GNUNET_assert (NULL != xp);
- json_array_extend (xp, np);
- json_decref (np);
- }
}
oc->phase++;
}
@@ -1824,14 +2007,14 @@ parse_order_request (struct OrderContext *oc)
bool create_token = true; /* default */
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("order",
- &oc->order),
+ &oc->init.order),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_relative_time ("refund_delay",
- &oc->refund_delay),
+ &oc->init.refund_delay),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("payment_target",
- &oc->payment_target),
+ &oc->init.payment_target),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_array_const ("inventory_products",
@@ -1865,7 +2048,7 @@ parse_order_request (struct OrderContext *oc)
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Refund delay is %s\n",
- GNUNET_TIME_relative2s (oc->refund_delay,
+ GNUNET_TIME_relative2s (oc->init.refund_delay,
false));
TMH_db->expire_locks (TMH_db->cls);
if (NULL != otp_id)
@@ -1902,14 +2085,14 @@ parse_order_request (struct OrderContext *oc)
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
break;
}
- oc->pos_key = td.otp_key;
- oc->pos_algorithm = td.otp_algorithm;
+ oc->init.pos_key = td.otp_key;
+ oc->init.pos_algorithm = td.otp_algorithm;
}
if (create_token)
{
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &oc->claim_token,
- sizeof (oc->claim_token));
+ &oc->init.claim_token,
+ sizeof (oc->init.claim_token));
}
/* Compute h_post_data (for idempotency check) */
{
@@ -1932,19 +2115,19 @@ parse_order_request (struct OrderContext *oc)
}
GNUNET_CRYPTO_hash (req_body_enc,
strlen (req_body_enc),
- &oc->h_post_data.hash);
+ &oc->init.h_post_data.hash);
GNUNET_free (req_body_enc);
}
/* parse the inventory_products (optionally given) */
if (NULL != ip)
{
- GNUNET_array_grow (oc->inventory_products,
- oc->inventory_products_length,
+ GNUNET_array_grow (oc->init.inventory_products,
+ oc->init.inventory_products_length,
json_array_size (ip));
- for (unsigned int i = 0; i<oc->inventory_products_length; i++)
+ for (unsigned int i = 0; i<oc->init.inventory_products_length; i++)
{
- struct InventoryProduct *ipr = &oc->inventory_products[i];
+ struct InventoryProduct *ipr = &oc->init.inventory_products[i];
const char *error_name;
unsigned int error_line;
struct GNUNET_JSON_Specification ispec[] = {
@@ -1980,10 +2163,10 @@ parse_order_request (struct OrderContext *oc)
/* parse the lock_uuids (optionally given) */
if (NULL != uuid)
{
- GNUNET_array_grow (oc->uuids,
- oc->uuids_length,
+ GNUNET_array_grow (oc->init.uuids,
+ oc->init.uuids_length,
json_array_size (uuid));
- for (unsigned int i = 0; i<oc->uuids_length; i++)
+ for (unsigned int i = 0; i<oc->init.uuids_length; i++)
{
json_t *ui = json_array_get (uuid,
i);
@@ -2001,7 +2184,7 @@ parse_order_request (struct OrderContext *oc)
return;
}
TMH_uuid_from_string (json_string_value (ui),
- &oc->uuids[i]);
+ &oc->init.uuids[i]);
}
}
oc->phase++;
@@ -2050,6 +2233,9 @@ TMH_private_post_orders (
case ORDER_PHASE_SET_MAX_FEE:
set_max_fee (oc);
break;
+ case ORDER_PHASE_SERIALIZE_ORDER:
+ serialize_order (oc);
+ break;
case ORDER_PHASE_CHECK_CONTRACT:
check_contract (oc);
break;