summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-05-01 16:12:51 +0200
committerChristian Grothoff <christian@grothoff.org>2020-05-01 16:14:51 +0200
commitd5a57b88a7ccbfdfe49378410417d170eff2f14f (patch)
treed31e1df1c9b3ea465d04ada5478f5f63d753ab88 /src/backend/taler-merchant-httpd_post-orders-ID-abort.c
parent49217808de28559964ca3f2b42e50c3990436520 (diff)
downloadmerchant-d5a57b88a7ccbfdfe49378410417d170eff2f14f.tar.gz
merchant-d5a57b88a7ccbfdfe49378410417d170eff2f14f.tar.bz2
merchant-d5a57b88a7ccbfdfe49378410417d170eff2f14f.zip
DB API for /abort
Diffstat (limited to 'src/backend/taler-merchant-httpd_post-orders-ID-abort.c')
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-abort.c259
1 files changed, 117 insertions, 142 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
index 27a83812..e6e8e406 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
@@ -704,36 +704,66 @@ begin_transaction (struct AbortContext *ac)
return;
}
- /* check payment was indeed incomplete */
- qs = TMH_db->lookup_paid_order (TMH_db->cls,
- ac->hc->instance->settings.id,
- &ac->h_contract_terms,
- NULL);
- if (0 < qs)
+ /* check payment was indeed incomplete
+ (now that we are in the transaction scope!) */
{
- /* Payment is complete, refuse to abort. */
- TMH_db->rollback (TMH_db->cls);
- resume_abort_with_error (ac,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_ABORT_ABORT_REFUND_REFUSED_ABORTMENT_COMPLETE,
- "Payment was complete, refusing to abort");
- return;
- }
- if (0 > qs)
- {
- TMH_db->rollback (TMH_db->cls);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ struct GNUNET_HashCode h_contract_terms;
+ bool paid;
+
+ qs = TMH_db->lookup_order_status (TMH_db->cls,
+ ac->hc->instance->settings.id,
+ ac->hc->infix,
+ &h_contract_terms,
+ &paid);
+ switch (qs)
{
- begin_transaction (ac);
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ /* Always report on hard error to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ TMH_db->rollback (TMH_db->cls);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ {
+ begin_transaction (ac);
+ return;
+ }
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ resume_abort_with_error (ac,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_ABORT_DB_FETCH_TRANSACTION_ERROR,
+ "Merchant database error");
+ return;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ TMH_db->rollback (TMH_db->cls);
+ resume_abort_with_error (ac,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_ABORT_CONTRACT_NOT_FOUND,
+ "Could not find contract");
+ return;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ if (paid)
+ {
+ /* Payment is complete, refuse to abort. */
+ TMH_db->rollback (TMH_db->cls);
+ resume_abort_with_error (ac,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE,
+ "Payment was complete, refusing to abort");
+ return;
+ }
+ }
+ if (0 !=
+ GNUNET_memcmp (&ac->h_contract_terms,
+ &h_contract_terms))
+ {
+ GNUNET_break_op (0);
+ resume_abort_with_error (ac,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_ABORT_CONTRACT_HASH_MISSMATCH,
+ "Provided hash does not match order on file");
return;
}
- /* Always report on hard error as well to enable diagnostics */
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
- resume_abort_with_error (ac,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_ABORT_DB_STORE_ABORT_ERROR,
- "Merchant database error");
- return;
}
/* Mark all deposits we have in our database for the order as refunded. */
@@ -802,132 +832,77 @@ parse_abort (struct MHD_Connection *connection,
struct TMH_HandlerContext *hc,
struct AbortContext *ac)
{
+ json_t *coins;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_json ("coins",
+ &coins),
+ GNUNET_JSON_spec_fixed_auto ("h_contract",
+ &ac->h_contract_terms),
+
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_json_data (connection,
+ hc->request_body,
+ spec);
+ if (GNUNET_YES != res)
+ {
+ GNUNET_break_op (0);
+ return res;
+ }
+ ac->coins_cnt = json_array_size (coins);
+ if (0 == ac->coins_cnt)
{
- json_t *coins;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("coins",
- &coins),
- GNUNET_JSON_spec_fixed_auto ("h_contract",
- &ac->h_contract_terms),
-
- GNUNET_JSON_spec_end ()
- };
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (connection,
- hc->request_body,
- spec);
- if (GNUNET_YES != res)
- {
- GNUNET_break_op (0);
- return res;
- }
- ac->coins_cnt = json_array_size (coins);
- if (0 == ac->coins_cnt)
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_ABORT_COINS_ARRAY_EMPTY,
- "coins");
- }
- /* note: 1 coin = 1 deposit confirmation expected */
- ac->pending = ac->coins_cnt;
- ac->rd = GNUNET_new_array (ac->coins_cnt,
- struct RefundDetails);
- /* This loop populates the array 'rd' in 'ac' */
- {
- unsigned int coins_index;
- json_t *coin;
- json_array_foreach (coins, coins_index, coin)
- {
- struct RefundDetails *rd = &ac->rd[coins_index];
- const char *exchange_url;
- struct GNUNET_JSON_Specification ispec[] = {
- TALER_JSON_spec_amount ("contribution",
- &rd->amount_with_fee),
- TALER_JSON_spec_amount ("refund_fee",
- &rd->refund_fee),
- GNUNET_JSON_spec_string ("exchange_url",
- &exchange_url),
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &rd->coin_pub),
- GNUNET_JSON_spec_end ()
- };
-
- res = TALER_MHD_parse_json_data (connection,
- coin,
- ispec);
- if (GNUNET_YES != res)
- {
- GNUNET_JSON_parse_free (spec);
- GNUNET_break_op (0);
- return res;
- }
- rd->exchange_url = GNUNET_strdup (exchange_url);
- rd->index = coins_index;
- rd->ac = ac;
- }
- }
GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_ABORT_COINS_ARRAY_EMPTY,
+ "coins");
}
-
- /* Check request against contract on file */
+ /* note: 1 coin = 1 deposit confirmation expected */
+ ac->pending = ac->coins_cnt;
+ ac->rd = GNUNET_new_array (ac->coins_cnt,
+ struct RefundDetails);
+ /* This loop populates the array 'rd' in 'ac' */
{
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_HashCode h_contract_terms;
-
- qs = TMH_db->lookup_contract_terms_hash (TMH_db->cls,
- hc->instance->settings.id,
- hc->infix,
- &h_contract_terms);
- if (0 > qs)
- {
- /* single, read-only SQL statements should never cause
- serialization problems */
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
- /* Always report on hard error to enable diagnostics */
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
- return (MHD_YES ==
- TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_ABORT_DB_FETCH_ABORT_ERROR,
- "Failed to obtain contract terms from DB"))
- ? GNUNET_NO
- : GNUNET_SYSERR;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- return (MHD_YES ==
- TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_ABORT_PROPOSAL_NOT_FOUND,
- "Order not found"))
- ? GNUNET_NO
- : GNUNET_SYSERR;
- }
-
- /* check client provided the right hash and is thus authorized to request aborting */
+ unsigned int coins_index;
+ json_t *coin;
+ json_array_foreach (coins, coins_index, coin)
{
- if (0 !=
- GNUNET_memcmp (&ac->h_contract_terms,
- &h_contract_terms))
+ struct RefundDetails *rd = &ac->rd[coins_index];
+ const char *exchange_url;
+ struct GNUNET_JSON_Specification ispec[] = {
+ TALER_JSON_spec_amount ("contribution",
+ &rd->amount_with_fee),
+ TALER_JSON_spec_amount ("refund_fee",
+ &rd->refund_fee),
+ GNUNET_JSON_spec_string ("exchange_url",
+ &exchange_url),
+ GNUNET_JSON_spec_fixed_auto ("coin_pub",
+ &rd->coin_pub),
+ GNUNET_JSON_spec_end ()
+ };
+
+ res = TALER_MHD_parse_json_data (connection,
+ coin,
+ ispec);
+ if (GNUNET_YES != res)
{
+ GNUNET_JSON_parse_free (spec);
GNUNET_break_op (0);
- return (MHD_YES ==
- TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_ABORT_CONTRACT_HASH_MISSMATCH,
- "Provided hash does not match order on file"))
- ? GNUNET_NO
- : GNUNET_SYSERR;
+ return res;
}
+ rd->exchange_url = GNUNET_strdup (exchange_url);
+ rd->index = coins_index;
+ rd->ac = ac;
}
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Handling /abort for order `%s' with contract hash `%s'\n",
- ac->hc->infix,
- GNUNET_h2s (&ac->h_contract_terms));
}
+ GNUNET_JSON_parse_free (spec);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling /abort for order `%s' with contract hash `%s'\n",
+ ac->hc->infix,
+ GNUNET_h2s (&ac->h_contract_terms));
return GNUNET_OK;
}