summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_post-orders-ID-refund.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_post-orders-ID-refund.c')
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-refund.c101
1 files changed, 72 insertions, 29 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-refund.c b/src/backend/taler-merchant-httpd_post-orders-ID-refund.c
index cc12dc03..8c445680 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-refund.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-refund.c
@@ -130,8 +130,7 @@ struct PostRefundData
{
/**
- * Hashed version of contract terms. All zeros if
- * not provided.
+ * Hashed version of contract terms. All zeros if not provided.
*/
struct GNUNET_HashCode h_contract_terms;
@@ -215,6 +214,11 @@ struct PostRefundData
enum TALER_ErrorCode ec;
/**
+ * HTTP status to use for the reply, 0 if not yet known.
+ */
+ unsigned int http_status;
+
+ /**
* Set to true if we are dealing with an unclaimed order
* (and thus @e h_contract_terms is not set, and certain
* DB queries will not work).
@@ -340,7 +344,8 @@ exchange_operations_pending (struct PostRefundData *prd)
static void
check_resume_prd (struct PostRefundData *prd)
{
- if (exchange_operations_pending (prd))
+ if ( (TALER_EC_NONE == prd->ec) &&
+ exchange_operations_pending (prd) )
return;
GNUNET_CONTAINER_DLL_remove (prd_head,
prd_tail,
@@ -423,25 +428,34 @@ exchange_found_cb (void *cls,
bool exchange_trusted)
{
struct CoinRefund *cr = cls;
+ struct PostRefundData *prd = cr->prd;
(void) payto_uri;
+ (void) wire_fee;
+ (void) exchange_trusted;
cr->fo = NULL;
- if (TALER_EC_NONE == hr->ec)
+ if (NULL == hr)
{
- cr->rh = TALER_EXCHANGE_refund (eh,
- &cr->refund_amount,
- &cr->prd->h_contract_terms,
- &cr->coin_pub,
- cr->rtransaction_id,
- &cr->prd->hc->instance->merchant_priv,
- &refund_cb,
- cr);
+ prd->http_status = MHD_HTTP_GATEWAY_TIMEOUT;
+ prd->ec = TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT;
+ check_resume_prd (prd);
return;
}
- cr->exchange_status = hr->http_status;
- cr->exchange_code = hr->ec;
- cr->exchange_reply = json_incref ((json_t*) hr->reply);
- check_resume_prd (cr->prd);
+ if (NULL == eh)
+ {
+ prd->http_status = MHD_HTTP_BAD_GATEWAY;
+ prd->ec = TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE;
+ check_resume_prd (prd);
+ return;
+ }
+ cr->rh = TALER_EXCHANGE_refund (eh,
+ &cr->refund_amount,
+ &prd->h_contract_terms,
+ &cr->coin_pub,
+ cr->rtransaction_id,
+ &prd->hc->instance->merchant_priv,
+ &refund_cb,
+ cr);
}
@@ -569,16 +583,16 @@ TMH_post_orders_ID_refund (const struct TMH_RequestHandler *rh,
GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GET_ORDERS_DB_FETCH_CONTRACT_TERMS_ERROR,
- NULL);
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "contract terms");
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
json_decref (contract_terms);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
- TALER_EC_GET_ORDERS_ORDER_NOT_FOUND,
- NULL);
+ TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN,
+ hc->infix);
}
{
struct GNUNET_HashCode h_contract_terms;
@@ -590,21 +604,50 @@ TMH_post_orders_ID_refund (const struct TMH_RequestHandler *rh,
json_decref (contract_terms);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GET_ORDERS_FAILED_COMPUTE_PROPOSAL_HASH,
+ TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH,
NULL);
}
json_decref (contract_terms);
if (0 != GNUNET_memcmp (&h_contract_terms,
&prd->h_contract_terms))
{
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_GET_ORDER_WRONG_CONTRACT,
- NULL);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_MERCHANT_GENERIC_CONTRACT_HASH_DOES_NOT_MATCH_ORDER,
+ NULL);
}
}
}
}
+
+ if (TALER_EC_NONE != prd->ec)
+ {
+ GNUNET_break (0 != prd->http_status);
+ /* kill pending coin refund operations immediately, just to be
+ extra sure they don't modify 'prd' after we already created
+ a reply (this might not be needed, but feels safer). */
+ for (struct CoinRefund *cr = prd->cr_head;
+ NULL != cr;
+ cr = cr->next)
+ {
+ if (NULL != cr->fo)
+ {
+ TMH_EXCHANGES_find_exchange_cancel (cr->fo);
+ cr->fo = NULL;
+ }
+ if (NULL != cr->rh)
+ {
+ TALER_EXCHANGE_refund_cancel (cr->rh);
+ cr->rh = NULL;
+ }
+ }
+ return TALER_MHD_reply_with_error (connection,
+ prd->http_status,
+ prd->ec,
+ NULL);
+ }
+
{
GNUNET_assert (GNUNET_OK == TALER_amount_get_zero (TMH_currency,
&prd->refund_amount));
@@ -618,8 +661,8 @@ TMH_post_orders_ID_refund (const struct TMH_RequestHandler *rh,
GNUNET_break (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GET_ORDERS_DB_LOOKUP_ERROR,
- NULL);
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "detailed refunds");
}
}
@@ -641,8 +684,8 @@ TMH_post_orders_ID_refund (const struct TMH_RequestHandler *rh,
case GNUNET_DB_STATUS_SOFT_ERROR:
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GET_ORDERS_DB_LOOKUP_ERROR,
- NULL);
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "refund proof");
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
if (NULL == cr->exchange_reply)
{