merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_delete-private-orders-ORDER_ID.c (7770B)


      1 /*
      2   This file is part of TALER
      3   (C) 2020 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file src/backend/taler-merchant-httpd_delete-private-orders-ORDER_ID.c
     18  * @brief implement DELETE /orders/$ID
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"
     22 #include "taler-merchant-httpd_delete-private-orders-ORDER_ID.h"
     23 #include <stdint.h>
     24 #include <taler/taler_json_lib.h>
     25 #include "merchant-database/delete_contract_terms.h"
     26 #include "merchant-database/delete_order.h"
     27 #include "merchant-database/get_contract_terms.h"
     28 #include "merchant-database/get_contract_terms_status.h"
     29 #include "merchant-database/get_order.h"
     30 
     31 
     32 /**
     33  * Check if the given @a contract_terms contain external payment
     34  * entries ("amount_external"). Such orders may have been settled
     35  * outside of Taler and must not be deleted without force.
     36  *
     37  * @param contract_terms contract terms to check
     38  * @return true if external payment entries are present
     39  */
     40 static bool
     41 has_external_payments (const json_t *contract_terms)
     42 {
     43   return 0 != json_array_size (json_object_get (contract_terms,
     44                                                 "amount_external"));
     45 }
     46 
     47 
     48 /**
     49  * Handle a DELETE "/orders/$ID" request.
     50  *
     51  * @param rh context of the handler
     52  * @param connection the MHD connection to handle
     53  * @param[in,out] hc context with further information about the request
     54  * @return MHD result code
     55  */
     56 enum MHD_Result
     57 TMH_private_delete_orders_ID (const struct TMH_RequestHandler *rh,
     58                               struct MHD_Connection *connection,
     59                               struct TMH_HandlerContext *hc)
     60 {
     61   struct TMH_MerchantInstance *mi = hc->instance;
     62   enum GNUNET_DB_QueryStatus qs;
     63   bool force;
     64 
     65   (void) rh;
     66   GNUNET_assert (NULL != mi);
     67   TALER_MHD_parse_request_bool (connection,
     68                                 "force",
     69                                 false,
     70                                 &force);
     71   if (! force)
     72   {
     73     /* Orders with externally settled payments require an explicit
     74        force operation to be removed. */
     75     json_t *contract_terms = NULL;
     76     uint64_t order_serial;
     77 
     78     qs = TALER_MERCHANTDB_get_contract_terms (TMH_db,
     79                                               mi->settings.id,
     80                                               hc->infix,
     81                                               &contract_terms,
     82                                               &order_serial,
     83                                               NULL);
     84     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
     85     {
     86       struct TALER_MerchantPostDataHashP unused;
     87 
     88       qs = TALER_MERCHANTDB_get_order (TMH_db,
     89                                        mi->settings.id,
     90                                        hc->infix,
     91                                        NULL,
     92                                        &unused,
     93                                        &contract_terms);
     94     }
     95     if (0 > qs)
     96       return TALER_MHD_reply_with_error (connection,
     97                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
     98                                          TALER_EC_GENERIC_DB_FETCH_FAILED,
     99                                          "lookup order for deletion");
    100     if (NULL != contract_terms)
    101     {
    102       bool blocked = has_external_payments (contract_terms);
    103 
    104       json_decref (contract_terms);
    105       if (blocked)
    106         return TALER_MHD_reply_with_error (
    107           connection,
    108           MHD_HTTP_CONFLICT,
    109           TALER_EC_MERCHANT_PRIVATE_DELETE_ORDERS_EXTERNALLY_PAID,
    110           hc->infix);
    111     }
    112   }
    113   qs = TALER_MERCHANTDB_delete_order (TMH_db,
    114                                       mi->settings.id,
    115                                       hc->infix,
    116                                       force);
    117   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
    118     qs = TALER_MERCHANTDB_delete_contract_terms (TMH_db,
    119                                                  mi->settings.id,
    120                                                  hc->infix,
    121                                                  TMH_legal_expiration);
    122   switch (qs)
    123   {
    124   case GNUNET_DB_STATUS_HARD_ERROR:
    125     return TALER_MHD_reply_with_error (connection,
    126                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    127                                        TALER_EC_GENERIC_DB_COMMIT_FAILED,
    128                                        NULL);
    129   case GNUNET_DB_STATUS_SOFT_ERROR:
    130     GNUNET_break (0);
    131     return TALER_MHD_reply_with_error (connection,
    132                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    133                                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
    134                                        NULL);
    135   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
    136     {
    137       struct TALER_MerchantPostDataHashP unused;
    138       uint64_t order_serial;
    139       bool paid = false;
    140       bool wired = false;
    141       bool matches = false;
    142       int16_t choice_index;
    143 
    144       qs = TALER_MERCHANTDB_get_order (TMH_db,
    145                                        mi->settings.id,
    146                                        hc->infix,
    147                                        NULL,
    148                                        &unused,
    149                                        NULL);
    150       if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
    151       {
    152         qs = TALER_MERCHANTDB_get_contract_terms_status (TMH_db,
    153                                                          mi->settings.id,
    154                                                          hc->infix,
    155                                                          NULL,
    156                                                          NULL,
    157                                                          &order_serial,
    158                                                          &paid,
    159                                                          &wired,
    160                                                          &matches,
    161                                                          NULL,
    162                                                          &choice_index);
    163       }
    164       if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
    165         return TALER_MHD_reply_with_error (connection,
    166                                            MHD_HTTP_NOT_FOUND,
    167                                            TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN,
    168                                            hc->infix);
    169       if (paid)
    170         return TALER_MHD_reply_with_error (connection,
    171                                            MHD_HTTP_CONFLICT,
    172                                            TALER_EC_MERCHANT_PRIVATE_DELETE_ORDERS_ALREADY_PAID,
    173                                            hc->infix);
    174       return TALER_MHD_reply_with_error (connection,
    175                                          MHD_HTTP_CONFLICT,
    176                                          TALER_EC_MERCHANT_PRIVATE_DELETE_ORDERS_AWAITING_PAYMENT,
    177                                          hc->infix);
    178     }
    179   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
    180     return TALER_MHD_reply_static (connection,
    181                                    MHD_HTTP_NO_CONTENT,
    182                                    NULL,
    183                                    NULL,
    184                                    0);
    185   }
    186   GNUNET_assert (0);
    187   return MHD_NO;
    188 }
    189 
    190 
    191 /* end of taler-merchant-httpd_delete-private-orders-ORDER_ID.c */