merchant

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

taler-merchant-httpd_helper.h (14099B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2021-2023 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 Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file taler-merchant-httpd_helper.h
     18  * @brief helpers for shared logic
     19  * @author Florian Dold
     20  * @author Benedikt Mueller
     21  * @author Christian Grothoff
     22  */
     23 #ifndef TALER_MERCHANT_HTTPD_HELPER_H
     24 #define TALER_MERCHANT_HTTPD_HELPER_H
     25 
     26 #define TMH_MAX_FRACTIONAL_PRECISION_LEVEL 6
     27 
     28 
     29 #include "taler-merchant-httpd.h"
     30 
     31 /**
     32  * check @a accounts for well-formedness
     33  *
     34  * @param accounts JSON array of merchant accounts (presumably)
     35  * @return true if they are all valid accounts
     36  */
     37 bool
     38 TMH_accounts_array_valid (const json_t *accounts);
     39 
     40 
     41 /**
     42  * Check if @a taxes is an array of valid Taxes in the sense of
     43  * Taler's API definition.
     44  *
     45  * @param taxes array to check
     46  * @return true if @a taxes is an array and all
     47  *         entries are valid Taxes.
     48  */
     49 bool
     50 TMH_taxes_array_valid (const json_t *taxes);
     51 
     52 
     53 /**
     54  * Check if @a location is a valid Location object in the sense of Taler's API
     55  * definition.
     56  *
     57  * @param location object to check
     58  * @return true if @a location is an object
     59  *         representing a Location.
     60  */
     61 bool
     62 TMH_location_object_valid (const json_t *location);
     63 
     64 
     65 /**
     66  * Check if @a products is an array of valid Product(s) in the sense of
     67  * Taler's API definition.
     68  *
     69  * @param products array to check
     70  * @return true if @a products is an array and all
     71  *         entries are valid Products.
     72  */
     73 bool
     74 TMH_products_array_valid (const json_t *products);
     75 
     76 
     77 /**
     78  * Parse decimal quantity expressed as string for request handling.
     79  *
     80  * @param value string to parse
     81  * @param[out] integer_part result integer component
     82  * @param[out] fractional_part result fractional component (0..MERCHANT_UNIT_FRAC_BASE-1)
     83  * @return #GNUNET_OK on success, #GNUNET_SYSERR on validation failure
     84  */
     85 enum GNUNET_GenericReturnValue
     86 TMH_parse_fractional_string (const char *value,
     87                              int64_t *integer_part,
     88                              uint32_t *fractional_part);
     89 
     90 /**
     91  * Kind of fixed-decimal value the helpers operate on.
     92  * Primarily distinguishes how special sentinel values (such as "-1"
     93  * meaning infinity for stock) must be encoded.
     94  */
     95 enum TMH_ValueKind
     96 {
     97   TMH_VK_QUANTITY,  /* -1 is illegal                    */
     98   TMH_VK_STOCK      /* -1 means "infinity"              */
     99 };
    100 
    101 /**
    102  * Extract a fixed-decimal number that may be supplied either
    103  *   - as pure integer  (e.g. "total_stock"), or
    104  *   - as decimal text (e.g. "unit_total_stock").
    105  *
    106  * Rules:
    107  *  - If both forms are missing          -> error.
    108  *  - If both are present                -> they must match and the decimal must have no fraction.
    109  *  - For kind == TMH_VK_STOCK the integer value -1 represents infinity.
    110  *
    111  * @param kind             See #TMH_ValueKind
    112  * @param allow_fractional False: any fractional part is rejected
    113  * @param int_missing      True if client omitted the integer field
    114  * @param int_raw          Raw integer (undefined if @a int_missing is true)
    115  * @param str_missing      True if client omitted the string field
    116  * @param str_raw          Raw UTF-8 string (undefined if @a str_missing is true)
    117  * @param[out] int_out     Canonicalised integer part
    118  * @param[out] frac_out    Canonicalised fractional part
    119  * @param[out] error_param Set to offending field name on failure
    120  * @param int_field        Integer field name (for error reporting)
    121  * @param str_field        String field name (for error reporting)
    122  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
    123  */
    124 enum GNUNET_GenericReturnValue
    125 TMH_process_quantity_inputs (enum TMH_ValueKind kind,
    126                              bool allow_fractional,
    127                              bool int_missing,
    128                              int64_t int_raw,
    129                              bool str_missing,
    130                              const char *str_raw,
    131                              uint64_t *int_out,
    132                              uint32_t *frac_out,
    133                              const char **error_param);
    134 
    135 /**
    136  * Lookup the defaults for @a unit within @a mi and fall back to sane
    137  * values (disallow fractional quantities, zero precision) if no data
    138  * is available.
    139  *
    140  * @param mi merchant instance whose defaults should be consulted (must not be NULL)
    141  * @param unit textual unit name (must not be NULL or empty)
    142  * @param allow_fractional updated with whether fractional quantities are allowed (must not be NULL)
    143  * @param precision_level updated with the supported precision (must not be NULL)
    144  */
    145 void
    146 TMH_quantity_defaults_from_unit (const struct TMH_MerchantInstance *mi,
    147                                  const char *unit,
    148                                  bool *allow_fractional,
    149                                  uint32_t *precision_level);
    150 
    151 /**
    152  * Query the database for precision defaults tied to @a unit within
    153  * @a mi.  Returns #GNUNET_OK even if no unit information exists, in
    154  * which case the out-parameters remain at their implicit defaults.
    155  *
    156  * @param mi merchant instance whose unit table is inspected (must not be NULL)
    157  * @param unit textual unit name (must not be NULL or empty)
    158  * @param allow_fractional updated with whether fractional quantities are allowed (must not be NULL)
    159  * @param precision_level updated with the supported precision (must not be NULL)
    160  * @return #GNUNET_OK on success, #GNUNET_SYSERR on database failure
    161  */
    162 enum GNUNET_GenericReturnValue
    163 TMH_unit_defaults_for_instance (const struct TMH_MerchantInstance *mi,
    164                                 const char *unit,
    165                                 bool *allow_fractional,
    166                                 uint32_t *precision_level);
    167 
    168 /**
    169  * Format a fixed-decimal pair into canonical string representation.
    170  * Recognises INT64_MAX / INT32_MAX as the "-1" sentinel used for
    171  * infinite stock if @a kind equals #TMH_VK_STOCK.
    172  *
    173  * @param kind specifies whether sentinel values are permitted
    174  * @param integer integer portion
    175  * @param fractional fractional portion (0..MERCHANT_UNIT_FRAC_BASE-1 or sentinel)
    176  * @param buffer output buffer
    177  * @param buffer_length length of @a buffer
    178  */
    179 void
    180 TMH_format_fractional_string (enum TMH_ValueKind kind,
    181                               uint64_t integer,
    182                               uint32_t fractional,
    183                               size_t buffer_length,
    184                               char buffer[static buffer_length]);
    185 
    186 /**
    187  * Check if @a image_data_url is a valid image
    188  * data URL. Does not validate the actual payload,
    189  * only the syntax and that it properly claims to
    190  * be an image.
    191  *
    192  * @param image_data_url string to check
    193  * @return true if @a image_data_url is a data
    194  *         URL with an "image/" mime-type
    195  */
    196 bool
    197 TMH_image_data_url_valid (const char *image_data_url);
    198 
    199 
    200 /**
    201  * Check if @a template_contract is a valid template_contract  object in the sense of Taler's API
    202  * definition.
    203  *
    204  * @param template_contract object to check
    205  * @return true if @a template_location is an object
    206  *         representing a template_location.
    207  */
    208 bool
    209 TMH_template_contract_valid (const json_t *template_contract);
    210 
    211 
    212 /**
    213  * Setup new wire method for the given @ payto_uri.
    214  *
    215  * @param payto_uri already validated payto URI
    216  * @param credit_facade_url where to download credit information for this account (can be NULL)
    217  * @param credit_facade_credentials credentials for the @a credit_facade_url
    218  * @return new wire method object, never fails
    219  */
    220 struct TMH_WireMethod *
    221 TMH_setup_wire_account (
    222   struct TALER_FullPayto payto_uri,
    223   const char *credit_facade_url,
    224   const json_t *credit_facade_credentials);
    225 
    226 
    227 /**
    228  * Test if JSON spec @a account for a wire method is equal to the given @a wm.
    229  *
    230  * @param account JSON spec for a merchant account
    231  * @param wm known wire method
    232  * @return #GNUNET_YES if both specifications are equal
    233  *  #GNUNET_NO if the specifications are for
    234  *      the same account but differ in the credit facade
    235  *  #GNUNET_SYSERR if the specs are for different accounts
    236  *     or if @a account is malformed
    237  */
    238 enum GNUNET_GenericReturnValue
    239 TMH_cmp_wire_account (
    240   const json_t *account,
    241   const struct TMH_WireMethod *wm);
    242 
    243 
    244 /**
    245  * Check that the provided authentication configuration
    246  * is valid.
    247  *
    248  * @param connection connection to use for returning errors
    249  * @param jauth JSON with authentication data
    250  * @param[out] auth_token set to the authentication token
    251  * @return #GNUNET_OK on success,
    252  *   #GNUNET_NO if an error was returned on @a connection
    253  *   #GNUNET_SYSERR if we failed to return an error on @a connection
    254  */
    255 enum GNUNET_GenericReturnValue
    256 TMH_check_auth_config (struct MHD_Connection *connection,
    257                        const json_t *jauth,
    258                        const char **auth_token);
    259 
    260 
    261 /**
    262  * Generate binary UUID from client-provided UUID-string.
    263  *
    264  * @param uuids string intpu
    265  * @param[out] uuid set to binary UUID
    266  */
    267 void
    268 TMH_uuid_from_string (const char *uuids,
    269                       struct GNUNET_Uuid *uuid);
    270 
    271 
    272 /**
    273  * Initializes a buffer with
    274  * the ``http[s]://$HOST/[$PATH/][instances/$INSTANCE/]``
    275  * string using $HOST and $PATH from @a connection.
    276  *
    277  * @param[in] connection connection to base the construction on
    278  * @param instance instance to set, NULL for none
    279  * @param[out] buf buffer to initialize
    280  * @return #GNUNET_OK on success
    281  */
    282 enum GNUNET_GenericReturnValue
    283 TMH_base_url_by_connection (struct MHD_Connection *connection,
    284                             const char *instance,
    285                             struct GNUNET_Buffer *buf);
    286 
    287 
    288 /**
    289  * Initializes a buffer with
    290  * the ``taler[+http]://$METHOD/$HOST/[instances/$INSTANCE/]``
    291  * string using $HOST from @a connection.
    292  *
    293  * @param[in] connection connection to base the construction on
    294  * @param method taler-URI method to inject
    295  * @param instance instance to set, NULL for none
    296  * @param[out] buf buffer to initialize
    297  * @return #GNUNET_OK on success
    298  */
    299 enum GNUNET_GenericReturnValue
    300 TMH_taler_uri_by_connection (struct MHD_Connection *connection,
    301                              const char *method,
    302                              const char *instance,
    303                              struct GNUNET_Buffer *buf);
    304 
    305 
    306 /**
    307  * Create a taler://pay/ URI for the given @a con and @a order_id
    308  * and @a session_id and @a instance_id.
    309  *
    310  * @param con HTTP connection
    311  * @param order_id the order id
    312  * @param session_id session, may be NULL
    313  * @param instance_id instance, may be "default"
    314  * @param claim_token claim token for the order, may be NULL
    315  * @return corresponding taler://pay/ URI, or NULL on missing "host"
    316  */
    317 char *
    318 TMH_make_taler_pay_uri (struct MHD_Connection *con,
    319                         const char *order_id,
    320                         const char *session_id,
    321                         const char *instance_id,
    322                         struct TALER_ClaimTokenP *claim_token);
    323 
    324 /**
    325  * Create a http(s) URL for the given @a con and @a order_id
    326  * and @a instance_id to display the /orders/{order_id} page.
    327  *
    328  * @param con HTTP connection
    329  * @param order_id the order id
    330  * @param session_id session, may be NULL
    331  * @param instance_id instance, may be "default"
    332  * @param claim_token claim token for the order, may be NULL
    333  * @param h_contract contract hash for authentication, may be NULL
    334  * @return corresponding http(s):// URL, or NULL on missing "host"
    335  */
    336 char *
    337 TMH_make_order_status_url (struct MHD_Connection *con,
    338                            const char *order_id,
    339                            const char *session_id,
    340                            const char *instance_id,
    341                            struct TALER_ClaimTokenP *claim_token,
    342                            struct TALER_PrivateContractHashP *h_contract);
    343 
    344 
    345 /**
    346  * Put data from an exchange's HTTP response into
    347  * a JSON reply
    348  *
    349  * @param hr a `TALER_EXCHANGE_HttpResponse`
    350  */
    351 #define TMH_pack_exchange_reply(hr) \
    352         GNUNET_JSON_pack_uint64 ("exchange_code", (hr)->ec),                \
    353         GNUNET_JSON_pack_uint64 ("exchange_http_status", (hr)->http_status), \
    354         GNUNET_JSON_pack_uint64 ("exchange_ec", (hr)->ec), /* LEGACY */  \
    355         GNUNET_JSON_pack_uint64 ("exchange_hc", (hr)->http_status), /* LEGACY */ \
    356         GNUNET_JSON_pack_allow_null ( \
    357           GNUNET_JSON_pack_object_incref ("exchange_reply", (json_t *) (hr)-> \
    358                                           reply))
    359 
    360 
    361 /**
    362  * TMH_trigger_webhook is a function that need to be use when someone
    363  * pay. Merchant need to have a notification.
    364  *
    365  * @param instance that we need to send the webhook as a notification
    366  * @param event of the webhook
    367  * @param args argument of the function
    368  */
    369 enum GNUNET_DB_QueryStatus
    370 TMH_trigger_webhook (const char *instance,
    371                      const char *action,
    372                      const json_t *args);
    373 
    374 
    375 /**
    376  * Return JSON array with all of the exchange accounts
    377  * that support the given @a wire_method.
    378  *
    379  * @param master_pub master public key to match exchange by
    380  * @param wire_method NULL for any
    381  * @return JSON array with information about all matching accounts
    382  */
    383 json_t *
    384 TMH_exchange_accounts_by_method (
    385   const struct TALER_MasterPublicKeyP *master_pub,
    386   const char *wire_method);
    387 
    388 /**
    389  * Check validity of login @a token for the given @a instance_id.
    390  *
    391  * @param token the login token given in the request
    392  * @param instance_id the instance the login is to be checked against
    393  * @param[out] as set to scope of the token if it is valid
    394  * @return TALER_EC_NONE on success
    395  */
    396 enum TALER_ErrorCode
    397 TMH_check_token (const char *token,
    398                  const char *instance_id,
    399                  enum TMH_AuthScope *as);
    400 
    401 #endif