From 7d81706ca0d905a2d7e8c7c18a6e2d48d0a67bae Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 7 Oct 2020 12:40:07 +0200 Subject: refuse refunds categorically if refund_delay was 0, instead of trying to give refunds anyway --- ...-merchant-httpd_private-post-orders-ID-refund.c | 96 ++++++++++++++++------ 1 file changed, 72 insertions(+), 24 deletions(-) (limited to 'src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c') diff --git a/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c b/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c index 859603bb..7af14873 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c +++ b/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c @@ -115,6 +115,70 @@ TMH_private_post_orders_ID_refund (const struct TMH_RequestHandler *rh, enum TALER_MERCHANTDB_RefundStatus rs; struct GNUNET_HashCode h_contract; + { + enum GNUNET_DB_QueryStatus qs; + json_t *contract_terms; + uint64_t order_serial; + struct GNUNET_TIME_Absolute refund_deadline; + struct GNUNET_TIME_Absolute timestamp; + + qs = TMH_db->lookup_contract_terms (TMH_db->cls, + hc->instance->settings.id, + hc->infix, + &contract_terms, + &order_serial); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_absolute_time ("refund_deadline", + &refund_deadline), + TALER_JSON_spec_absolute_time ("timestamp", + ×tamp), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_YES != + GNUNET_JSON_parse (contract_terms, + spec, + NULL, NULL)) + { + GNUNET_break (0); + GNUNET_JSON_parse_free (spec); + json_decref (contract_terms); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_INTERNAL_LOGIC_ERROR, + "Failed to parse contract terms from DB"); + } + json_decref (contract_terms); + if (timestamp.abs_value_us == refund_deadline.abs_value_us) + { + /* refund was never allowed, so we should refuse hard */ + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, +#ifndef TALER_EC_MERCHANT_REFUND_NOT_ALLOWED_BY_CONTRACT + 2609, /* remove post 0.8.0 release */ +#else + TALER_EC_MERCHANT_REFUND_NOT_ALLOWED_BY_CONTRACT, +#endif + NULL); + } + if (0 == GNUNET_TIME_absolute_get_remaining (refund_deadline).rel_value_us) + { + /* it is too late for refunds */ + /* NOTE: We MAY still be lucky that the exchange did not yet + wire the funds, so we will try to give the refund anyway */ + } + } + else + { + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_REFUND_ORDER_ID_UNKNOWN, + hc->infix); + } + } + { enum GNUNET_GenericReturnValue res; @@ -187,30 +251,14 @@ TMH_private_post_orders_ID_refund (const struct TMH_RequestHandler *rh, NULL); case TALER_MERCHANTDB_RS_NO_SUCH_ORDER: { - enum GNUNET_DB_QueryStatus qs; - json_t *contract_terms; - uint64_t order_serial; - - qs = TMH_db->lookup_contract_terms (TMH_db->cls, - hc->instance->settings.id, - hc->infix, - &contract_terms, - &order_serial); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) - { - json_decref (contract_terms); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_CONFLICT, - TALER_EC_REFUND_ORDER_ID_UNPAID, - hc->infix); - } - else - { - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_REFUND_ORDER_ID_UNKNOWN, - hc->infix); - } + /* We know the order exists from the + "lookup_contract_terms" at the beginning; + so if we get 'no such order' here, it + must be read as "no PAID order" */ + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_REFUND_ORDER_ID_UNPAID, + hc->infix); } case TALER_MERCHANTDB_RS_SUCCESS: { -- cgit v1.2.3