summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_get-orders-ID.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_get-orders-ID.c')
-rw-r--r--src/backend/taler-merchant-httpd_get-orders-ID.c135
1 files changed, 104 insertions, 31 deletions
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c
index 9c60f7a9..af5513d9 100644
--- a/src/backend/taler-merchant-httpd_get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_get-orders-ID.c
@@ -120,6 +120,22 @@ struct GetOrderData
json_t *contract_terms;
/**
+ * Merchant base URL from @e contract_terms.
+ */
+ const char *merchant_base_url;
+
+ /**
+ * Public reorder URL from @e contract_terms.
+ * Could be NULL if contract does not have one.
+ */
+ const char *public_reorder_url;
+
+ /**
+ * Total amount in contract.
+ */
+ struct TALER_Amount contract_total;
+
+ /**
* Total refunds granted for this payment. Only initialized
* if @e refunded is set to true.
*/
@@ -180,6 +196,16 @@ struct GetOrderData
*/
bool generate_html;
+ /**
+ * Did we parse the contract terms?
+ */
+ bool contract_parsed;
+
+ /**
+ * Set to true if the refunds found in the DB have
+ * a different currency then the main contract.
+ */
+ bool bad_refund_currency_in_db;
};
@@ -316,6 +342,9 @@ suspend_god (struct GetOrderData *god)
json_decref (god->contract_terms);
god->fulfillment_url = NULL;
god->contract_terms = NULL;
+ god->contract_parsed = false;
+ god->merchant_base_url = NULL;
+ god->public_reorder_url = NULL;
}
GNUNET_assert (! god->suspended);
god->suspended = GNUNET_YES;
@@ -712,6 +741,16 @@ process_refunds_cb (void *cls,
TALER_B2S (coin_pub),
reason);
god->refund_pending |= pending;
+ if ( (GNUNET_OK !=
+ TALER_amount_cmp_currency (&god->refund_taken,
+ refund_amount)) ||
+ (GNUNET_OK !=
+ TALER_amount_cmp_currency (&god->refund_amount,
+ refund_amount)) )
+ {
+ god->bad_refund_currency_in_db = true;
+ return;
+ }
if (! pending)
{
GNUNET_assert (0 <=
@@ -767,7 +806,6 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
bool contract_match = false;
bool token_match = false;
bool contract_available = false;
- const char *merchant_base_url;
(void) rh;
if (NULL == god)
@@ -945,10 +983,9 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
if (NULL != god->contract_terms)
{
contract_available = true;
-
- if (GNUNET_YES == GNUNET_is_zero (&god->h_contract_terms))
+ if (GNUNET_YES ==
+ GNUNET_is_zero (&god->h_contract_terms))
{
-
if (GNUNET_OK !=
TALER_JSON_contract_hash (god->contract_terms,
&god->h_contract_terms))
@@ -959,11 +996,9 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH,
"contract terms");
}
-
}
else
{
-
struct TALER_PrivateContractHashP h;
if (GNUNET_OK !=
@@ -988,9 +1023,7 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
TALER_EC_MERCHANT_GENERIC_CONTRACT_HASH_DOES_NOT_MATCH_ORDER,
NULL);
}
-
}
-
}
if (contract_available)
@@ -1040,21 +1073,46 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
} /* end unclaimed order logic */
GNUNET_assert (NULL != god->contract_terms);
- merchant_base_url = json_string_value (json_object_get (god->contract_terms,
- "merchant_base_url"));
- if (NULL == merchant_base_url)
+ if (! god->contract_parsed)
{
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID,
- order_id);
+ struct GNUNET_JSON_Specification espec[] = {
+ TALER_JSON_spec_amount_any ("amount",
+ &god->contract_total),
+ GNUNET_JSON_spec_string ("merchant_base_url",
+ &god->merchant_base_url),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("fulfillment_url",
+ &god->fulfillment_url),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("public_reorder_url",
+ &god->public_reorder_url),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+ const char *ename;
+ unsigned int eline;
+
+ res = GNUNET_JSON_parse (god->contract_terms,
+ espec,
+ &ename,
+ &eline);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to parse contract %s in DB at field %s\n",
+ order_id,
+ ename);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID,
+ order_id);
+ }
+ god->contract_parsed = true;
}
- if (NULL == god->fulfillment_url)
- god->fulfillment_url = json_string_value (json_object_get (
- god->contract_terms,
- "fulfillment_url"));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Token match: %d, contract_available: %d, contract match: %d, claimed: %d\n",
token_match,
@@ -1085,15 +1143,11 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
if (! (token_match ||
contract_match) )
{
- const char *public_reorder_url;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Neither claim token nor contract matched\n");
- public_reorder_url = json_string_value (json_object_get (
- god->contract_terms,
- "public_reorder_url"));
/* Client has no rights to this order */
- if (NULL == public_reorder_url)
+ if (NULL == god->public_reorder_url)
{
/* We cannot give the client a new order, just fail */
if (! GNUNET_is_zero (&god->h_contract_terms))
@@ -1135,7 +1189,7 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
GNUNET_break (MHD_YES ==
MHD_add_response_header (reply,
MHD_HTTP_HEADER_LOCATION,
- public_reorder_url));
+ god->public_reorder_url));
ret = MHD_queue_response (connection,
MHD_HTTP_FOUND,
reply);
@@ -1147,7 +1201,7 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
connection,
MHD_HTTP_ACCEPTED,
GNUNET_JSON_pack_string ("public_reorder_url",
- public_reorder_url));
+ god->public_reorder_url));
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1247,13 +1301,25 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
}
}
+ if ( (god->sc.awaiting_refund) &&
+ (GNUNET_OK !=
+ TALER_amount_cmp_currency (&god->contract_total,
+ &god->sc.refund_expected)) )
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
+ god->contract_total.currency);
+ }
+
/* At this point, we know the contract was paid. Let's check for
refunds. First, clear away refunds found from previous invocations. */
GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (TMH_currency,
+ TALER_amount_set_zero (god->contract_total.currency,
&god->refund_amount));
GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (TMH_currency,
+ TALER_amount_set_zero (god->contract_total.currency,
&god->refund_taken));
qs = TMH_db->lookup_refunds_detailed (TMH_db->cls,
hc->instance->settings.id,
@@ -1268,7 +1334,14 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
TALER_EC_GENERIC_DB_FETCH_FAILED,
"lookup_refunds_detailed");
}
-
+ if (god->bad_refund_currency_in_db)
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "currency mix-up between contract price and refunds in database");
+ }
if ( ((god->sc.awaiting_refund) &&
( (! god->refunded) ||
(1 != TALER_amount_cmp (&god->refund_amount,
@@ -1308,7 +1381,7 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
char *uri;
GNUNET_assert (NULL != god->contract_terms);
- uri = make_taler_refund_uri (merchant_base_url,
+ uri = make_taler_refund_uri (god->merchant_base_url,
order_id);
if (NULL == uri)
{