/* This file is part of TALER Copyright (C) 2015-2020 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 bank's HTTP API * This is currently ONLY used to provide the "test" wire transfer protocol. * @author Christian Grothoff */ #ifndef _TALER_BANK_SERVICE_H #define _TALER_BANK_SERVICE_H #include #include #include "taler_util.h" #include "taler_error_codes.h" /** * 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 { /** * 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; }; /** * Different account types supported by payto://. */ enum TALER_PaytoAccountType { /** * Used to indicate an uninitialized struct. */ TALER_PAC_NONE = 0, /** * Account type of a bank running the x-taler-bank protocol. */ TALER_PAC_X_TALER_BANK, /** * Account identified by IBAN number. */ TALER_PAC_IBAN }; /** * Information about an account extracted from a payto://-URL. */ struct TALER_Account { /** * How this the account represented. */ enum TALER_PaytoAccountType type; /** * Internals depending on @e type. */ union { /** * Taler bank address from x-taler-bank. Set if * @e type is #TALER_AC_X_TALER_BANK. */ struct { /** * Bank account base URL. */ char *account_base_url; /** * Only the hostname of the bank. */ char *hostname; } x_taler_bank; /** * Taler bank address from iban. Set if * @e type is #TALER_AC_IBAN. */ struct { /** * IBAN number. */ char *number; } iban; } details; }; /* ********************* /admin/add/incoming *********************** */ /** * @brief A /admin/add/incoming Handle */ struct TALER_BANK_AdminAddIncomingHandle; /** * Callbacks of this type are used to serve the result of submitting * information about an incoming transaction to a bank. * * @param cls closure * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * 0 if the bank's reply is bogus (fails to follow the protocol) * @param ec detailed error code * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error * @param timestamp time when the transaction was made. * @param json detailed response from the HTTPD, or NULL if reply was not in JSON */ typedef void (*TALER_BANK_AdminAddIncomingResultCallback) (void *cls, unsigned int http_status, enum TALER_ErrorCode ec, uint64_t serial_id, struct GNUNET_TIME_Absolute timestamp, const json_t *json); /** * Notify the bank that we have received an incoming transaction * which fills a reserve. Note that this API is an administrative * API and thus not accessible to typical bank clients, but only * to the operators of the bank. * * @param ctx curl context for the event loop * @param account_base_url URL of the bank (money flows into this account) * @param auth authentication data to send to the bank * @param reserve_pub wire transfer subject for the transfer * @param amount amount that was 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). * In this case, the callback is not called. */ struct TALER_BANK_AdminAddIncomingHandle * TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx, const char *account_base_url, const struct TALER_BANK_AuthenticationData *auth, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *amount, const char *credit_account, TALER_BANK_AdminAddIncomingResultCallback res_cb, void *res_cb_cls); /** * Cancel an add incoming. This function cannot be used on a request * handle if a response is already served for it. * * @param aai the admin add incoming request handle */ void TALER_BANK_admin_add_incoming_cancel (struct TALER_BANK_AdminAddIncomingHandle *aai); /* ********************* /taler/transfer *********************** */ /** * Prepare for exeuction of a wire transfer. * * @param destination_account_url 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 buf[out] set to transaction data to persist, NULL on error * @param buf_size[out] set to number of bytes in @a buf, 0 on error */ void TALER_BANK_prepare_wire_transfer (const char *destination_account_url, 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_WireExecuteHandle; /** * Function called with the result from the execute step. * * @param cls closure * @param response_code HTTP status code * @param ec taler error code * @param row_id unique ID of the wire transfer in the bank's records * @param timestamp when did the transaction go into effect */ typedef void (*TALER_BANK_ConfirmationCallback)(void *cls, unsigned int response_code, enum TALER_ErrorCode ec, uint64_t row_id, struct GNUNET_TIME_Absolute timestamp); /** * Execute a wire transfer. * * @param ctx context for HTTP interaction * @param bank_base_url URL of the base INCLUDING account number * @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_WireExecuteHandle * TALER_BANK_execute_wire_transfer (struct GNUNET_CURL_Context *ctx, const char *bank_base_url, const struct TALER_BANK_AuthenticationData *auth, const void *buf, size_t buf_size, TALER_BANK_ConfirmationCallback 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 @e * execute_wire_transfer again for the same request as soon as * possilbe, 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). * * @param eh execution to cancel */ void TALER_BANK_execute_wire_transfer_cancel (struct TALER_BANK_WireExecuteHandle *eh); /* ********************* /taler/credits *********************** */ /** * 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 { /** * Amount that was transferred */ struct TALER_Amount amount; /** * Time of the the transfer */ struct GNUNET_TIME_Absolute execution_date; /** * Reserve public key encoded in the wire * transfer subject. */ struct TALER_ReservePublicKeyP reserve_pub; /** * payto://-URL of the source account that * send the funds. */ const char *debit_account_url; /** * payto://-URL of the target account that * received the funds. */ const char *credit_account_url; }; /** * Callbacks of this type are used to serve the result of asking * the bank for the credit transaction history. * * @param cls closure * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * 0 if the bank's reply is bogus (fails to follow the protocol), * #MHD_HTTP_NO_CONTENT if there are no more results; on success the * last callback is always of this status (even if `abs(num_results)` were * already returned). * @param ec detailed error code * @param serial_id monotonically increasing counter corresponding to the transaction * @param details details about the wire transfer * @param json detailed response from the HTTPD, or NULL if reply was not in JSON * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration */ typedef int (*TALER_BANK_CreditResultCallback) (void *cls, unsigned int http_status, enum TALER_ErrorCode ec, uint64_t serial_id, const struct TALER_BANK_CreditDetails *details, const json_t *json); /** * Request the wire credit history of an exchange's bank account. * * @param ctx curl context for the event loop * @param account_base_url URL of the base INCLUDING account number * @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 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 char *account_base_url, const struct TALER_BANK_AuthenticationData *auth, uint64_t start_row, int64_t num_results, TALER_BANK_CreditResultCallback 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 hh the history request handle */ void TALER_BANK_credit_history_cancel (struct TALER_BANK_CreditHistoryHandle *hh); /* ********************* /taler/debits *********************** */ /** * 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 { /** * Amount that was transferred */ struct TALER_Amount amount; /** * Time of the the transfer */ struct GNUNET_TIME_Absolute 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://-URL of the source account that * send the funds. */ const char *debit_account_url; /** * payto://-URL of the target account that * received the funds. */ const char *credit_account_url; }; /** * Callbacks of this type are used to serve the result of asking * the bank for the debit transaction history. * * @param cls closure * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * 0 if the bank's reply is bogus (fails to follow the protocol), * #MHD_HTTP_NO_CONTENT if there are no more results; on success the * last callback is always of this status (even if `abs(num_results)` were * already returned). * @param ec detailed error code * @param serial_id monotonically increasing counter corresponding to the transaction * @param details details about the wire transfer * @param json detailed response from the HTTPD, or NULL if reply was not in JSON * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration */ typedef int (*TALER_BANK_DebitResultCallback) (void *cls, unsigned int http_status, enum TALER_ErrorCode ec, uint64_t serial_id, const struct TALER_BANK_DebitDetails *details, const json_t *json); /** * Request the wire credit history of an exchange's bank account. * * @param ctx curl context for the event loop * @param bank_base_url URL of the base INCLUDING account number * @param auth authentication data to use * @param account_number which account number should we query * @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 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 char *bank_base_url, const struct TALER_BANK_AuthenticationData *auth, uint64_t start_row, int64_t num_results, TALER_BANK_DebitResultCallback 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 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 account data. * * @param cfg configuration to parse * @param section the section with the configuration data * @param acc[out] set to the account details * @return #GNUNET_OK on success */ int TALER_BANK_account_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, struct TALER_Account *acc); /** * Release memory allocated in @a acc. * * @param acc account to free, the pointer itself is NOT free'd. */ void TALER_BANK_account_free (struct TALER_Account *acc); /** * Parse @a payto_url and store the result in @a acc * * @param payto_url URL to parse * @param acc[in,out] account to initialize, free using #TALER_BANK_account_free() later * @return #TALER_EC_NONE if @a payto_url is well-formed */ enum TALER_ErrorCode TALER_BANK_payto_to_account (const char *payto_url, struct TALER_Account *acc); /** * Convenience method for parsing configuration section with bank * authentication data. The section must contain an option * "METHOD", plus other options that depend on the METHOD specified. * * @param cfg configuration to parse * @param section the section with the configuration data * @param auth[out] set to the configuration data found * @return #GNUNET_OK on success */ int 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 auth itself). * Dual to #TALER_BANK_auth_parse_cfg(). * * @param auth authentication data to free */ void TALER_BANK_auth_free (struct TALER_BANK_AuthenticationData *auth); #endif /* _TALER_BANK_SERVICE_H */