diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_get-orders-ID.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_get-orders-ID.c | 135 |
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) { |