/* This file is part of TALER Copyright (C) 2015-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with TALER; see the file COPYING. If not, see */ /** * @file include/taler_bank_service.h * @brief C interface of libtalerbank, a C library to use the Taler Wire gateway HTTP API * See https://docs.taler.net/core/api-wire.html * @author Christian Grothoff */ #ifndef _TALER_BANK_SERVICE_H #define _TALER_BANK_SERVICE_H #include #include #include "taler_util.h" #include "taler_error_codes.h" /** * Version of the Bank API, in hex. * Thus 0.12.0-0 = 0x000C0000. */ #define TALER_BANK_SERVICE_API_VERSION 0x000C0000 /** * Authentication method types. */ enum TALER_BANK_AuthenticationMethod { /** * No authentication. */ TALER_BANK_AUTH_NONE, /** * Basic authentication with cleartext username and password. */ TALER_BANK_AUTH_BASIC, }; /** * Information used to authenticate to the bank. */ struct TALER_BANK_AuthenticationData { /** * Base URL we use to talk to the wire gateway, * which talks to the bank for us. */ char *wire_gateway_url; /** * Which authentication method should we use? */ enum TALER_BANK_AuthenticationMethod method; /** * Further details as per @e method. */ union { /** * Details for #TALER_BANK_AUTH_BASIC. */ struct { /** * Username to use. */ char *username; /** * Password to use. */ char *password; } basic; } details; }; /* ********************* /admin/add-incoming *********************** */ /** * @brief A /admin/add-incoming Handle */ struct TALER_BANK_AdminAddIncomingHandle; /** * Response details for a history request. */ struct TALER_BANK_AdminAddIncomingResponse { /** * HTTP status. */ unsigned int http_status; /** * Taler error code, #TALER_EC_NONE on success. */ enum TALER_ErrorCode ec; /** * Full response, NULL if body was not in JSON format. */ const json_t *response; /** * Details returned depending on the @e http_status. */ union { /** * Details if status was #MHD_HTTP_OK */ struct { /** * unique ID of the wire transfer in the bank's records */ uint64_t serial_id; /** * time when the transaction was made. */ struct GNUNET_TIME_Timestamp timestamp; } ok; } details; }; /** * Callbacks of this type are used to return the result of submitting * a request to transfer funds to the exchange. * * @param cls closure * @param air response details */ typedef void (*TALER_BANK_AdminAddIncomingCallback) ( void *cls, const struct TALER_BANK_AdminAddIncomingResponse *air); /** * Perform a wire transfer from some account to the exchange to fill a * reserve. Note that this API is usually only used for testing (with * fakebank) and thus may not be accessible in a production setting. * * @param ctx curl context for the event loop * @param auth authentication data to send to the bank * @param reserve_pub wire transfer subject for the transfer * @param amount amount that is to be deposited * @param debit_account account to deposit from (payto URI, but used as 'payfrom') * @param res_cb the callback to call when the final result for this request is available * @param res_cb_cls closure for the above callback * @return NULL * if the inputs are invalid (i.e. invalid amount) or internal errors. * In this case, the callback is not called. */ struct TALER_BANK_AdminAddIncomingHandle * TALER_BANK_admin_add_incoming ( struct GNUNET_CURL_Context *ctx, const struct TALER_BANK_AuthenticationData *auth, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *amount, const char *debit_account, TALER_BANK_AdminAddIncomingCallback res_cb, void *res_cb_cls); /** * Cancel an add incoming operation. This function cannot be used on a * request handle if a response is already served for it. * * @param[in] aai the admin add incoming request handle */ void TALER_BANK_admin_add_incoming_cancel ( struct TALER_BANK_AdminAddIncomingHandle *aai); /** * @brief A /admin/add-kycauth Handle */ struct TALER_BANK_AdminAddKycauthHandle; /** * Response details for a history request. */ struct TALER_BANK_AdminAddKycauthResponse { /** * HTTP status. */ unsigned int http_status; /** * Taler error code, #TALER_EC_NONE on success. */ enum TALER_ErrorCode ec; /** * Full response, NULL if body was not in JSON format. */ const json_t *response; /** * Details returned depending on the @e http_status. */ union { /** * Details if status was #MHD_HTTP_OK */ struct { /** * unique ID of the wire transfer in the bank's records */ uint64_t serial_id; /** * time when the transaction was made. */ struct GNUNET_TIME_Timestamp timestamp; } ok; } details; }; /** * Callbacks of this type are used to return the result of submitting * a request to transfer funds to the exchange. * * @param cls closure * @param air response details */ typedef void (*TALER_BANK_AdminAddKycauthCallback) ( void *cls, const struct TALER_BANK_AdminAddKycauthResponse *air); /** * Perform a wire transfer from some account to the exchange to register a * public key for KYC authentication of the origin account. Note that this * API is usually only used for testing (with fakebank) and thus may not be * accessible in a production setting. * * @param ctx curl context for the event loop * @param auth authentication data to send to the bank * @param account_pub wire transfer subject for the transfer * @param amount amount that is to be deposited * @param debit_account account to deposit from (payto URI, but used as 'payfrom') * @param res_cb the callback to call when the final result for this request is available * @param res_cb_cls closure for the above callback * @return NULL * if the inputs are invalid (i.e. invalid amount) or internal errors. * In this case, the callback is not called. */ struct TALER_BANK_AdminAddKycauthHandle * TALER_BANK_admin_add_kycauth ( struct GNUNET_CURL_Context *ctx, const struct TALER_BANK_AuthenticationData *auth, const union TALER_AccountPublicKeyP *account_pub, const struct TALER_Amount *amount, const char *debit_account, TALER_BANK_AdminAddKycauthCallback res_cb, void *res_cb_cls); /** * Cancel an add kycauth operation. This function cannot be used on a * request handle if a response is already served for it. * * @param[in] aai the admin add kycauth request handle */ void TALER_BANK_admin_add_kycauth_cancel ( struct TALER_BANK_AdminAddKycauthHandle *aai); /* ********************* /transfer *********************** */ /** * Prepare for execution of a wire transfer from the exchange to some * merchant. * * @param destination_account_payto_uri payto:// URL identifying where to send the money * @param amount amount to transfer, already rounded * @param exchange_base_url base URL of this exchange (included in subject * to facilitate use of tracking API by merchant backend) * @param wtid wire transfer identifier to use * @param[out] buf set to transaction data to persist, NULL on error * @param[out] buf_size set to number of bytes in @a buf, 0 on error */ void TALER_BANK_prepare_transfer ( const char *destination_account_payto_uri, const struct TALER_Amount *amount, const char *exchange_base_url, const struct TALER_WireTransferIdentifierRawP *wtid, void **buf, size_t *buf_size); /** * Handle for active wire transfer. */ struct TALER_BANK_TransferHandle; /** * Response details for a history request. */ struct TALER_BANK_TransferResponse { /** * HTTP status. */ unsigned int http_status; /** * Taler error code, #TALER_EC_NONE on success. */ enum TALER_ErrorCode ec; /** * Full response, NULL if body was not in JSON format. */ const json_t *response; /** * Details returned depending on the @e http_status. */ union { /** * Details if status was #MHD_HTTP_OK */ struct { /** * unique ID of the wire transfer in the bank's records */ uint64_t row_id; /** * when did the transaction go into effect */ struct GNUNET_TIME_Timestamp timestamp; } ok; } details; }; /** * Function called with the result from the execute step. * * @param cls closure * @param tr response details */ typedef void (*TALER_BANK_TransferCallback)( void *cls, const struct TALER_BANK_TransferResponse *tr); /** * Execute a wire transfer from the exchange to some merchant. * * @param ctx context for HTTP interaction * @param auth authentication data to authenticate with the bank * @param buf buffer with the prepared execution details * @param buf_size number of bytes in @a buf * @param cc function to call upon success * @param cc_cls closure for @a cc * @return NULL on error */ struct TALER_BANK_TransferHandle * TALER_BANK_transfer ( struct GNUNET_CURL_Context *ctx, const struct TALER_BANK_AuthenticationData *auth, const void *buf, size_t buf_size, TALER_BANK_TransferCallback cc, void *cc_cls); /** * Abort execution of a wire transfer. For example, because we are shutting * down. Note that if an execution is aborted, it may or may not still * succeed. * * The caller MUST run #TALER_BANK_transfer() again for the same request as * soon as possible, to ensure that the request either ultimately succeeds or * ultimately fails. Until this has been done, the transaction is in limbo * (i.e. may or may not have been committed). * * This function cannot be used on a request handle if a response is already * served for it. * * @param[in] th handle of the wire transfer request to cancel */ void TALER_BANK_transfer_cancel ( struct TALER_BANK_TransferHandle *th); /* ********************* /history/incoming *********************** */ /** * Different types of wire transfers that might be * credited to an exchange account. */ enum TALER_BANK_CreditType { /** * Common wire transfer into a reserve account. */ TALER_BANK_CT_RESERVE, /** * KYC authentication wire transfer with an account * public key. */ TALER_BANK_CT_KYCAUTH, /** * WAD transfer between exchanges. */ TALER_BANK_CT_WAD }; /** * Handle for querying the bank for transactions * made to the exchange. */ struct TALER_BANK_CreditHistoryHandle; /** * Details about a wire transfer to the exchange. */ struct TALER_BANK_CreditDetails { /** * Type of the wire transfer. */ enum TALER_BANK_CreditType type; /** * Serial ID of the wire transfer. */ uint64_t serial_id; /** * Amount that was transferred */ struct TALER_Amount amount; /** * Time of the the transfer */ struct GNUNET_TIME_Timestamp execution_date; /** * payto://-URL of the source account that send the funds. */ const char *debit_account_uri; /** * Details that depend on the @e type. */ union { /** * Details for @e type #TALER_BANK_CT_RESERVE. */ struct { /** * Reserve public key encoded in the wire transfer subject. */ struct TALER_ReservePublicKeyP reserve_pub; } reserve; /** * Details for @e type #TALER_BANK_CT_KYCAUTH. */ struct { /** * Public key to associate with the owner of the * origin bank account. */ union TALER_AccountPublicKeyP account_pub; } kycauth; /** * Details for @e type #TALER_BANK_CT_WAD. */ struct { /** * WAD identifier for the transfer. */ struct TALER_WadIdentifierP wad_id; /** * Base URL of the exchange originating the transfer. */ const char *origin_exchange_url; } wad; } details; }; /** * Response details for a history request. */ struct TALER_BANK_CreditHistoryResponse { /** * HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both * successful replies, but @e details will only contain @e success information * if this is set to #MHD_HTTP_OK. */ unsigned int http_status; /** * Taler error code, #TALER_EC_NONE on success. */ enum TALER_ErrorCode ec; /** * Full response, NULL if body was not in JSON format. */ const json_t *response; /** * Details returned depending on the @e http_status. */ union { /** * Details if status was #MHD_HTTP_OK */ struct { /** * payto://-URL of the target account that received the funds. */ const char *credit_account_uri; /** * Array of transactions received. */ const struct TALER_BANK_CreditDetails *details; /** * Length of the @e details array. */ unsigned int details_length; } ok; } details; }; /** * Callbacks of this type are used to serve the result of asking * the bank for the credit transaction history. * * @param cls closure * @param reply details about the response */ typedef void (*TALER_BANK_CreditHistoryCallback)( void *cls, const struct TALER_BANK_CreditHistoryResponse *reply); /** * Request the wire credit history of an exchange's bank account. * * @param ctx curl context for the event loop * @param auth authentication data to use * @param start_row from which row on do we want to get results, use UINT64_MAX for the latest; exclusive * @param num_results how many results do we want; negative numbers to go into the past, * positive numbers to go into the future starting at @a start_row; * must not be zero. * @param timeout how long the client is willing to wait for more results * (only useful if @a num_results is positive) * @param hres_cb the callback to call with the transaction history * @param hres_cb_cls closure for the above callback * @return NULL * if the inputs are invalid (i.e. zero value for @e num_results). * In this case, the callback is not called. */ struct TALER_BANK_CreditHistoryHandle * TALER_BANK_credit_history ( struct GNUNET_CURL_Context *ctx, const struct TALER_BANK_AuthenticationData *auth, uint64_t start_row, int64_t num_results, struct GNUNET_TIME_Relative timeout, TALER_BANK_CreditHistoryCallback hres_cb, void *hres_cb_cls); /** * Cancel an history request. This function cannot be used on a request * handle if the last response (anything with a status code other than * 200) is already served for it. * * @param[in] hh the history request handle */ void TALER_BANK_credit_history_cancel ( struct TALER_BANK_CreditHistoryHandle *hh); /* ********************* /history/outgoing *********************** */ /** * Handle for querying the bank for transactions * made from the exchange to merchants. */ struct TALER_BANK_DebitHistoryHandle; /** * Details about a wire transfer made by the exchange * to a merchant. */ struct TALER_BANK_DebitDetails { /** * Serial ID of the wire transfer. */ uint64_t serial_id; /** * Amount that was transferred */ struct TALER_Amount amount; /** * Time of the the transfer */ struct GNUNET_TIME_Timestamp execution_date; /** * Wire transfer identifier used by the exchange. */ struct TALER_WireTransferIdentifierRawP wtid; /** * Exchange's base URL as given in the wire transfer. */ const char *exchange_base_url; /** * payto://-URI of the target account that received the funds. */ const char *credit_account_uri; }; /** * Response details for a history request. */ struct TALER_BANK_DebitHistoryResponse { /** * HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both * successful replies, but @e details will only contain @e success information * if this is set to #MHD_HTTP_OK. */ unsigned int http_status; /** * Taler error code, #TALER_EC_NONE on success. */ enum TALER_ErrorCode ec; /** * Full response, NULL if body was not in JSON format. */ const json_t *response; /** * Details returned depending on the @e http_status. */ union { /** * Details if status was #MHD_HTTP_OK */ struct { /** * payto://-URI of the source account that send the funds. */ const char *debit_account_uri; /** * Array of transactions initiated. */ const struct TALER_BANK_DebitDetails *details; /** * Length of the @e details array. */ unsigned int details_length; } ok; } details; }; /** * Callbacks of this type are used to serve the result of asking * the bank for the debit transaction history. * * @param cls closure * @param reply details about the response */ typedef void (*TALER_BANK_DebitHistoryCallback)( void *cls, const struct TALER_BANK_DebitHistoryResponse *reply); /** * Request the wire credit history of an exchange's bank account. * * @param ctx curl context for the event loop * @param auth authentication data to use * @param start_row from which row on do we want to get results, use UINT64_MAX for the latest; exclusive * @param num_results how many results do we want; negative numbers to go into the past, * positive numbers to go into the future starting at @a start_row; * must not be zero. * @param timeout how long the client is willing to wait for more results * (only useful if @a num_results is positive) * @param hres_cb the callback to call with the transaction history * @param hres_cb_cls closure for the above callback * @return NULL * if the inputs are invalid (i.e. zero value for @e num_results). * In this case, the callback is not called. */ struct TALER_BANK_DebitHistoryHandle * TALER_BANK_debit_history ( struct GNUNET_CURL_Context *ctx, const struct TALER_BANK_AuthenticationData *auth, uint64_t start_row, int64_t num_results, struct GNUNET_TIME_Relative timeout, TALER_BANK_DebitHistoryCallback hres_cb, void *hres_cb_cls); /** * Cancel an history request. This function cannot be used on a request * handle if the last response (anything with a status code other than * 200) is already served for it. * * @param[in] hh the history request handle */ void TALER_BANK_debit_history_cancel ( struct TALER_BANK_DebitHistoryHandle *hh); /* ******************** Convenience functions **************** */ /** * Convenience method for parsing configuration section with bank * authentication data. * * @param cfg configuration to parse * @param section the section with the configuration data * @param[out] auth set to the configuration data found * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue TALER_BANK_auth_parse_cfg ( const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, struct TALER_BANK_AuthenticationData *auth); /** * Free memory inside of @a auth (but not @a auth itself). * Dual to #TALER_BANK_auth_parse_cfg(). * * @param[in,out] auth authentication data to free */ void TALER_BANK_auth_free ( struct TALER_BANK_AuthenticationData *auth); #endif /* _TALER_BANK_SERVICE_H */