merchant

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

merchantdb_lib.h (18881B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014, 2015, 2016, 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 Lesser 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.GPL.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 
     17 /**
     18  * @file src/include/merchantdb_lib.h
     19  * @brief database helper functions used by the merchant backend
     20  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
     21  */
     22 #ifndef TALER_MERCHANTDB_LIB_H
     23 #define TALER_MERCHANTDB_LIB_H
     24 
     25 #include <gnunet/gnunet_pq_lib.h>
     26 #include <taler/taler_util.h>
     27 
     28 /**
     29  * Handle to interact with the database.
     30  */
     31 struct TALER_MERCHANTDB_PostgresContext;
     32 
     33 GNUNET_NETWORK_STRUCT_BEGIN
     34 
     35 /**
     36  * Format of the data hashed to generate the notification
     37  * string whenever the KYC status for an account has
     38  * changed.
     39  */
     40 struct TALER_MERCHANTDB_MerchantKycStatusChangeEventP
     41 {
     42   /**
     43    * Type is TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_STATUS_CHANGED.
     44    */
     45   struct GNUNET_DB_EventHeaderP header;
     46 
     47   /**
     48    * Salted hash of the affected account.
     49    */
     50   struct TALER_MerchantWireHashP h_wire;
     51 };
     52 
     53 /**
     54  * Event triggered when an order is paid.
     55  */
     56 struct TMH_OrderPayEventP
     57 {
     58   /**
     59    * Type is #TALER_DBEVENT_MERCHANT_ORDER_PAID
     60    */
     61   struct GNUNET_DB_EventHeaderP header;
     62 
     63   /**
     64    * Always zero (for alignment).
     65    */
     66   uint32_t reserved GNUNET_PACKED;
     67 
     68   /**
     69    * Merchant's public key
     70    */
     71   struct TALER_MerchantPublicKeyP merchant_pub;
     72 
     73   /**
     74    * Hash of the order ID.
     75    */
     76   struct GNUNET_HashCode h_order_id;
     77 };
     78 
     79 
     80 GNUNET_NETWORK_STRUCT_END
     81 
     82 
     83 /**
     84  * Connect to postgresql database
     85  *
     86  * @param cfg the configuration handle
     87  * @return connection to the database; NULL upon error
     88  */
     89 struct TALER_MERCHANTDB_PostgresContext *
     90 TALER_MERCHANTDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
     91 
     92 
     93 /**
     94  * Disconnect from the database
     95  *
     96  * @param pg database handle to close
     97  */
     98 void
     99 TALER_MERCHANTDB_disconnect (struct TALER_MERCHANTDB_PostgresContext *pg);
    100 
    101 
    102 void
    103 check_connection (struct TALER_MERCHANTDB_PostgresContext *pg);
    104 
    105 
    106 /**
    107  * Possible token family kinds.
    108  */
    109 enum TALER_MERCHANTDB_TokenFamilyKind
    110 {
    111 
    112   /**
    113    * Token family representing a discount token
    114    */
    115   TALER_MERCHANTDB_TFK_Discount = 0,
    116 
    117   /**
    118    * Token family representing a subscription token
    119    */
    120   TALER_MERCHANTDB_TFK_Subscription = 1,
    121 
    122 };
    123 
    124 /**
    125  * Results from trying to increase a refund.
    126  */
    127 enum TALER_MERCHANTDB_RefundStatus
    128 {
    129 
    130   /**
    131    * Refund amount exceeds legal exchange limits.
    132    */
    133   TALER_MERCHANTDB_RS_LEGAL_FAILURE = -5,
    134 
    135   /**
    136    * Refund amount currency does not match original payment.
    137    */
    138   TALER_MERCHANTDB_RS_BAD_CURRENCY = -4,
    139 
    140   /**
    141    * Refund amount exceeds original payment.
    142    */
    143   TALER_MERCHANTDB_RS_TOO_HIGH = -3,
    144 
    145   /**
    146    * Hard database failure.
    147    */
    148   TALER_MERCHANTDB_RS_HARD_ERROR = -2,
    149 
    150   /**
    151    * Soft database failure.
    152    */
    153   TALER_MERCHANTDB_RS_SOFT_ERROR = -1,
    154 
    155   /**
    156    * Order not found.
    157    */
    158   TALER_MERCHANTDB_RS_NO_SUCH_ORDER = 0,
    159 
    160   /**
    161    * Refund is now at or above the requested amount.
    162    */
    163   TALER_MERCHANTDB_RS_SUCCESS = 1
    164 
    165 };
    166 
    167 /**
    168  * Details about an OTP device.
    169  */
    170 struct TALER_MERCHANTDB_OtpDeviceDetails
    171 {
    172 
    173   /**
    174    * Description of the device.
    175    */
    176   char *otp_description;
    177 
    178   /**
    179    * Current usage counter value.
    180    */
    181   uint64_t otp_ctr;
    182 
    183   /**
    184    * Base64-encoded key.
    185    */
    186   char *otp_key;
    187 
    188   /**
    189    * Algorithm used to compute purchase confirmations.
    190    */
    191   enum TALER_MerchantConfirmationAlgorithm otp_algorithm;
    192 };
    193 
    194 
    195 /**
    196  * Details about a template.
    197  */
    198 struct TALER_MERCHANTDB_TemplateDetails
    199 {
    200   /**
    201    * Description of the template.
    202    */
    203   char *template_description;
    204 
    205   /**
    206    * In this template contract, we can have additional information.
    207    */
    208   json_t *template_contract;
    209 
    210   /**
    211    * ID of the OTP device linked to the template, or NULL.
    212    */
    213   char *otp_id;
    214 
    215   /**
    216    * Editable default values for fields not specified
    217    * in the @e template_contract. NULL if the user
    218    * cannot edit anything.
    219    */
    220   json_t *editable_defaults;
    221 
    222 };
    223 
    224 
    225 /**
    226  * Structure to hold Donau instance details from the database.
    227  */
    228 struct TALER_MERCHANTDB_DonauInstance
    229 {
    230   /**
    231    * Donau instance serial
    232    */
    233   uint64_t donau_instance_serial;
    234 
    235   /**
    236    * The URL for the Donau instance.
    237    */
    238   char *donau_url;
    239 
    240   /**
    241    * The name of the charity associated with the Donau instance.
    242    */
    243   char *charity_name;
    244 
    245   /**
    246    * Pointer to the public key of the charity, used for cryptographic operations.
    247    * This is represented as an EDDSA public key structure.
    248    */
    249   struct DONAU_CharityPublicKeyP *charity_pub_key;
    250 
    251   /**
    252    * A unique identifier for the charity in the Donau instance.
    253    */
    254   uint64_t charity_id;
    255 
    256   /**
    257    * The maximum allowable amount for donations to this charity in the current year.
    258    * This is tracked for regulatory or internal business constraints.
    259    */
    260   struct TALER_Amount charity_max_per_year;
    261 
    262   /**
    263    * The total amount of donations received by the charity in the current year.
    264    * This field helps track progress toward the yearly donation limit.
    265    */
    266   struct TALER_Amount charity_receipts_to_date;
    267 
    268   /**
    269    * The current year being tracked for donations.
    270    * This is used to differentiate donation data between years.
    271    */
    272   int64_t current_year;
    273 
    274   /**
    275    * A JSON object containing key information specific to the Donau instance,
    276    * such as cryptographic keys or other relevant details.
    277    */
    278   json_t *donau_keys_json;
    279 };
    280 
    281 
    282 /**
    283  * Details about a product.
    284  *
    285  * FIXME: reuse TALER_MERCHANT_Product as a member in this structure!
    286  */
    287 struct TALER_MERCHANTDB_ProductDetails
    288 {
    289   /**
    290    * Name of the product.
    291    */
    292   char *product_name;
    293 
    294   /**
    295    * Description of the product.
    296    */
    297   char *description;
    298 
    299   /**
    300    * Internationalized description.
    301    */
    302   json_t *description_i18n;
    303 
    304   /**
    305    * Unit in which the product is sold.
    306    */
    307   char *unit;
    308 
    309   /**
    310    * Optional list of per-unit prices. When NULL or empty, @e price
    311    * must be used as the canonical single price.
    312    */
    313   struct TALER_Amount *price_array;
    314 
    315   /**
    316    * Number of entries in @e price_array.
    317    */
    318   size_t price_array_length;
    319 
    320   /**
    321    * Base64-encoded product image, or an empty string.
    322    */
    323   char *image;
    324 
    325   /**
    326    * Hash of the product image data, or NULL.
    327    */
    328   char *image_hash;
    329 
    330   /**
    331    * List of taxes the merchant pays for this product. Never NULL,
    332    * but can be an empty array.
    333    */
    334   json_t *taxes;
    335 
    336   /**
    337    * Number of units of the product in stock in sum in total, including all
    338    * existing sales and lost product, in product-specific units. UINT64_MAX
    339    * indicates "infinite".
    340    */
    341   uint64_t total_stock;
    342 
    343   /**
    344    * Fractional part of stock in units of 1/1000000 of the base value.
    345    */
    346   uint32_t total_stock_frac;
    347 
    348   /**
    349    * Honor fractional stock if TRUE, else only integer stock.
    350    */
    351   bool allow_fractional_quantity;
    352 
    353   /**
    354    * Precision level (number of decimal places) to apply when
    355    * fractional quantities are enabled.
    356    */
    357   uint32_t fractional_precision_level;
    358 
    359   /**
    360    * Number of units of the product in sold, in product-specific units.
    361    */
    362   uint64_t total_sold;
    363 
    364   /**
    365    * Fractional part of units sold in units of 1/1000000 of the base value.
    366    */
    367   uint32_t total_sold_frac;
    368 
    369   /**
    370    * Number of units of stock lost.
    371    */
    372   uint64_t total_lost;
    373 
    374   /**
    375    * Fractional part of lost units in units of 1/1000000 of the base value.
    376    */
    377   uint32_t total_lost_frac;
    378 
    379   /**
    380    * Identifies where the product is in stock, possibly an empty map.
    381    */
    382   json_t *address;
    383 
    384   /**
    385    * Identifies when the product will be restocked. 0 for unknown,
    386    * #GNUNET_TIME_UNIT_FOREVER_ABS for never.
    387    */
    388   struct GNUNET_TIME_Timestamp next_restock;
    389 
    390   /**
    391    * Minimum required age for consumers buying this product.
    392    * Default is 0. Only enforced of an exchange supports age
    393    * restrictions.
    394    */
    395   uint32_t minimum_age;
    396 
    397   /**
    398    * Group in which the product is in. 0 for default group.
    399    */
    400   uint64_t product_group_id;
    401 
    402   /**
    403    * Money pot into which sales of this product should go into by default.
    404    */
    405   uint64_t money_pot_id;
    406 
    407   /**
    408    * True if the price for this product is given in net,
    409    * False if its the gross price.
    410    */
    411   bool price_is_net;
    412 
    413 };
    414 
    415 
    416 /**
    417  * Details about a webhook.
    418  */
    419 struct TALER_MERCHANTDB_WebhookDetails
    420 {
    421 
    422   /**
    423    * event of the webhook.
    424    */
    425   char *event_type;
    426 
    427   /**
    428    * URL of the webhook. The customer will be redirected on this url.
    429    */
    430   char *url;
    431 
    432   /**
    433    * Http method used by the webhook.
    434    */
    435   char *http_method;
    436 
    437   /**
    438    * Header template of the webhook.
    439    */
    440   char *header_template;
    441 
    442   /**
    443    * Body template of the webhook.
    444    */
    445   char *body_template;
    446 
    447 };
    448 
    449 
    450 /**
    451  * Details about a product category.
    452  */
    453 struct TALER_MERCHANTDB_CategoryDetails
    454 {
    455 
    456   /**
    457    * Name of the category.
    458    */
    459   char *category_name;
    460 
    461   /**
    462    * Translations of the name of the category.
    463    */
    464   json_t *category_name_i18n;
    465 
    466 };
    467 
    468 
    469 /**
    470  * Details about the pending webhook.
    471  */
    472 struct TALER_MERCHANTDB_PendingWebhookDetails
    473 {
    474 
    475   /**
    476    * Identifies when we should make the next request to the webhook. 0 for unknown,
    477    * #GNUNET_TIME_UNIT_FOREVER_ABS for never.
    478    */
    479   struct GNUNET_TIME_Absolute next_attempt;
    480 
    481   /**
    482    * How often have we tried this request so far.
    483    */
    484   uint32_t retries;
    485 
    486   /**
    487    * URL of the webhook. The customer will be redirected on this url.
    488    */
    489   char *url;
    490 
    491   /**
    492    * Http method used for the webhook.
    493    */
    494   char *http_method;
    495 
    496   /**
    497    * Header of the webhook.
    498    */
    499   char *header;
    500 
    501   /**
    502    * Body of the webhook.
    503    */
    504   char *body;
    505 
    506 };
    507 
    508 
    509 /**
    510  * Details about a token family.
    511  */
    512 struct TALER_MERCHANTDB_TokenFamilyDetails
    513 {
    514   /**
    515    * Token family slug used for identification.
    516    */
    517   char *slug;
    518 
    519   /**
    520    * User readable name of the token family.
    521    */
    522   char *name;
    523 
    524   /**
    525    * Description of the token family.
    526    */
    527   char *description;
    528 
    529   /**
    530    * Internationalized token family description.
    531    */
    532   json_t *description_i18n;
    533 
    534   /**
    535    * Meta-data associated with the token family.
    536    * Includes information like "trusted_domains" or
    537    * "expected_domains", if set.
    538    */
    539   json_t *extra_data;
    540 
    541   /**
    542    * Cipher that should be used for this token family.  Note: We do not expose
    543    * this over the API and do not let clients set it. NULL for default (when
    544    * calling database).
    545    */
    546   char *cipher_spec;
    547 
    548   /**
    549    * Start time of the token family duration.
    550    */
    551   struct GNUNET_TIME_Timestamp valid_after;
    552 
    553   /**
    554    * End time of the token family duration.
    555    */
    556   struct GNUNET_TIME_Timestamp valid_before;
    557 
    558   /**
    559    * Validity duration of the token family. Must be larger or
    560    * equal to @a rounding plus @a start_offset_s.
    561    */
    562   struct GNUNET_TIME_Relative duration;
    563 
    564   /**
    565    * Rounding duration of the token family.
    566    */
    567   struct GNUNET_TIME_Relative validity_granularity;
    568 
    569   /**
    570    * Offset (in seconds) to subtract from the rounded
    571    * validity start period.
    572    */
    573   struct GNUNET_TIME_Relative start_offset;
    574 
    575   /**
    576    * Token family kind.
    577    */
    578   enum TALER_MERCHANTDB_TokenFamilyKind kind;
    579 
    580   /**
    581    * Counter for each issued token of this family.
    582    */
    583   uint64_t issued;
    584 
    585   /**
    586    * Counter for each used token of this family.
    587    */
    588   uint64_t used;
    589 };
    590 
    591 
    592 /**
    593  * Minimal product details for inventory templates.
    594  */
    595 struct TALER_MERCHANTDB_InventoryProductDetails
    596 {
    597   /**
    598    * Name of the product.
    599    */
    600   char *product_name;
    601 
    602   /**
    603    * Description of the product.
    604    */
    605   char *description;
    606 
    607   /**
    608    * Internationalized description.
    609    */
    610   json_t *description_i18n;
    611 
    612   /**
    613    * Unit in which the product is sold.
    614    */
    615   char *unit;
    616 
    617   /**
    618    * List of per-unit prices.
    619    */
    620   struct TALER_Amount *price_array;
    621 
    622   /**
    623    * Number of entries in @e price_array.
    624    */
    625   size_t price_array_length;
    626 
    627   /**
    628    * Hash of the product image data, or NULL.
    629    */
    630   char *image_hash;
    631 
    632   /**
    633    * Honor fractional stock if TRUE, else only integer stock.
    634    */
    635   bool allow_fractional_quantity;
    636 
    637   /**
    638    * Precision level (number of decimal places) to apply when
    639    * fractional quantities are enabled.
    640    */
    641   uint32_t fractional_precision_level;
    642 
    643   /**
    644    * Remaining units after sold/lost/locked deductions.
    645    */
    646   uint64_t remaining_stock;
    647 
    648   /**
    649    * Fractional part of remaining units in units of 1/1000000 of the base value.
    650    */
    651   uint32_t remaining_stock_frac;
    652 
    653   /**
    654    * List of taxes the merchant pays for this product. Never NULL,
    655    * but can be an empty array.
    656    */
    657   json_t *taxes;
    658 };
    659 
    660 
    661 /**
    662  * Details about an inventory measurement unit.
    663  */
    664 struct TALER_MERCHANTDB_UnitDetails
    665 {
    666 
    667   /**
    668    * Database serial.
    669    */
    670   uint64_t unit_serial;
    671 
    672   /**
    673    * Backend identifier used in product payloads.
    674    */
    675   char *unit;
    676 
    677   /**
    678    * Default long label (fallback string).
    679    */
    680   char *unit_name_long;
    681 
    682   /**
    683    * Default short label (fallback string).
    684    */
    685   char *unit_name_short;
    686 
    687   /**
    688    * Internationalised long labels.
    689    */
    690   json_t *unit_name_long_i18n;
    691 
    692   /**
    693    * Internationalised short labels.
    694    */
    695   json_t *unit_name_short_i18n;
    696 
    697   /**
    698    * Whether fractional quantities are enabled by default.
    699    */
    700   bool unit_allow_fraction;
    701 
    702   /**
    703    * Maximum number of fractional digits honoured by default.
    704    */
    705   uint32_t unit_precision_level;
    706 
    707   /**
    708    * Hidden from selectors when false.
    709    */
    710   bool unit_active;
    711 
    712   /**
    713    * Built-in units cannot be deleted.
    714    */
    715   bool unit_builtin;
    716 };
    717 
    718 
    719 /**
    720  * Details about a wire account of the merchant.
    721  */
    722 struct TALER_MERCHANTDB_AccountDetails
    723 {
    724   /**
    725    * Hash of the wire details (@e payto_uri and @e salt).
    726    */
    727   struct TALER_MerchantWireHashP h_wire;
    728 
    729   /**
    730    * Salt value used for hashing @e payto_uri.
    731    */
    732   struct TALER_WireSaltP salt;
    733 
    734   /**
    735    * Instance ID. Do not free (may be aliased with
    736    * the instance ID given in the query!).
    737    * FIXME: set in all functions involving this struct!
    738    */
    739   const char *instance_id;
    740 
    741   /**
    742    * Actual account address as a payto://-URI.
    743    */
    744   struct TALER_FullPayto payto_uri;
    745 
    746   /**
    747    * Where can the taler-merchant-wirewatch helper
    748    * download information about incoming transfers?
    749    * NULL if not available.
    750    */
    751   char *credit_facade_url;
    752 
    753   /**
    754    * JSON with credentials to use to access the
    755    * @e credit_facade_url.
    756    */
    757   json_t *credit_facade_credentials;
    758 
    759   /**
    760    * Additional meta data to include in wire transfers to this
    761    * account. Can be NULL if not used.
    762    */
    763   char *extra_wire_subject_metadata;
    764 
    765   /**
    766    * Is the account set for active use in new contracts?
    767    */
    768   bool active;
    769 
    770 };
    771 
    772 
    773 /**
    774  * Binary login token. Just a vanilla token made out
    775  * of random bits.
    776  */
    777 struct TALER_MERCHANTDB_LoginTokenP
    778 {
    779   /**
    780    * 32 bytes of entropy.
    781    */
    782   uint64_t data[32 / 8];
    783 };
    784 
    785 /**
    786  * Authentication settings for an instance.
    787  */
    788 struct TALER_MERCHANTDB_InstanceAuthSettings
    789 {
    790   /**
    791    * Hash used for authentication.  All zero if authentication is off.
    792    */
    793   struct TALER_MerchantAuthenticationHashP auth_hash;
    794 
    795   /**
    796    * Salt used to hash the "Authentication" header, the result must then
    797    * match the @e auth_hash.
    798    */
    799   struct TALER_MerchantAuthenticationSaltP auth_salt;
    800 };
    801 
    802 
    803 /**
    804  * General settings for an instance.
    805  */
    806 struct TALER_MERCHANTDB_InstanceSettings
    807 {
    808   /**
    809    * prefix for the instance under "/instances/"
    810    */
    811   char *id;
    812 
    813   /**
    814    * legal name of the instance
    815    */
    816   char *name;
    817 
    818   /**
    819    * merchant's site url
    820    */
    821   char *website;
    822 
    823   /**
    824    * email contact for password reset / possibly admin / customers
    825    */
    826   char *email;
    827 
    828   /**
    829    * phone contact for password reset / possibly admin / customers
    830    */
    831   char *phone;
    832 
    833   /**
    834    * merchant's logo data uri
    835    */
    836   char *logo;
    837 
    838   /**
    839    * Address of the business
    840    */
    841   json_t *address;
    842 
    843   /**
    844    * jurisdiction of the business
    845    */
    846   json_t *jurisdiction;
    847 
    848   /**
    849    * Use STEFAN curves to determine acceptable
    850    * fees by default (otherwise: accept no fees by default).
    851    */
    852   bool use_stefan;
    853 
    854   /**
    855    * True of @e phone was validated.
    856    */
    857   bool phone_validated;
    858 
    859   /**
    860    * True of @e email was validated.
    861    */
    862   bool email_validated;
    863 
    864   /**
    865    * If the frontend does NOT specify an execution date, how long should
    866    * we tell the exchange to wait to aggregate transactions before
    867    * executing the wire transfer?  This delay is added to the current
    868    * time when we generate the advisory execution time for the exchange.
    869    */
    870   struct GNUNET_TIME_Relative default_wire_transfer_delay;
    871 
    872   /**
    873    * If the frontend does NOT specify a payment deadline, how long should
    874    * offers we make be valid by default?
    875    */
    876   struct GNUNET_TIME_Relative default_pay_delay;
    877 
    878   /**
    879    * If the frontend does NOT specify a refund deadline, how long should
    880    * refunds be possible?
    881    */
    882   struct GNUNET_TIME_Relative default_refund_delay;
    883 
    884   /**
    885    * How much should we round up the wire transfer deadline computed by
    886    * adding the @e default_wire_transfer_delay to the refund deadline.
    887    */
    888   enum GNUNET_TIME_RounderInterval default_wire_transfer_rounding_interval;
    889 
    890 };
    891 
    892 
    893 /**
    894  * Free members of @a pd, but not @a pd itself.
    895  *
    896  * @param[in] pd product details to clean up
    897  */
    898 void
    899 TALER_MERCHANTDB_product_details_free (
    900   struct TALER_MERCHANTDB_ProductDetails *pd);
    901 
    902 
    903 /**
    904  * Free members of @a tp, but not @a tp itself.
    905  *
    906  * @param[in] tp template details to clean up
    907  */
    908 void
    909 TALER_MERCHANTDB_template_details_free (
    910   struct TALER_MERCHANTDB_TemplateDetails *tp);
    911 
    912 
    913 /**
    914  * Free members of @a wb, but not @a wb itself.
    915  *
    916  * @param[in] wb webhook details to clean up
    917  */
    918 void
    919 TALER_MERCHANTDB_webhook_details_free (
    920   struct TALER_MERCHANTDB_WebhookDetails *wb);
    921 
    922 /**
    923  * Free members of @a pwb, but not @a pwb itself.
    924  *
    925  * @param[in] pwb pending webhook details to clean up
    926  */
    927 void
    928 TALER_MERCHANTDB_pending_webhook_details_free (
    929   struct TALER_MERCHANTDB_PendingWebhookDetails *pwb);
    930 
    931 
    932 /**
    933  * Free members of @a tf, but not @a tf itself.
    934  *
    935  * @param[in] tf token family details to clean up
    936  */
    937 void
    938 TALER_MERCHANTDB_token_family_details_free (
    939   struct TALER_MERCHANTDB_TokenFamilyDetails *tf);
    940 
    941 
    942 /**
    943  * Free members of @a cd, but not @a cd itself.
    944  *
    945  * @param[in] cd token family details to clean up
    946  */
    947 void
    948 TALER_MERCHANTDB_category_details_free (
    949   struct TALER_MERCHANTDB_CategoryDetails *cd);
    950 
    951 /**
    952  * Free members of @a ud, but not @a ud itself.
    953  *
    954  * @param[in] ud unit details to clean up
    955  */
    956 void
    957 TALER_MERCHANTDB_unit_details_free (
    958   struct TALER_MERCHANTDB_UnitDetails *ud);
    959 
    960 #endif  /* MERCHANT_DB_H */
    961 
    962 /* end of taler_merchantdb_lib.h */